mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-12-23 22:49:28 -05:00
Churn
Signed-off-by: Tad <tad@spotco.us>
This commit is contained in:
parent
337ae6012d
commit
724b742b64
@ -21,10 +21,10 @@ Change-Id: I907877608f4672f24c002e630e58bf9133937a5e
|
||||
1 file changed, 10 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/stack/gatt/gatt_cl.cc b/stack/gatt/gatt_cl.cc
|
||||
index dca49738c..2650a307a 100644
|
||||
index 014240888..203808806 100644
|
||||
--- a/stack/gatt/gatt_cl.cc
|
||||
+++ b/stack/gatt/gatt_cl.cc
|
||||
@@ -297,7 +297,7 @@ void gatt_send_queue_write_cancel(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
|
||||
@@ -291,7 +291,7 @@ void gatt_send_queue_write_cancel(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
|
||||
bool gatt_check_write_long_terminate(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
|
||||
tGATT_VALUE* p_rsp_value) {
|
||||
tGATT_VALUE* p_attr = (tGATT_VALUE*)p_clcb->p_attr_buf;
|
||||
@ -33,7 +33,7 @@ index dca49738c..2650a307a 100644
|
||||
tGATT_EXEC_FLAG flag = GATT_PREP_WRITE_EXEC;
|
||||
|
||||
VLOG(1) << __func__;
|
||||
@@ -310,19 +310,18 @@ bool gatt_check_write_long_terminate(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
|
||||
@@ -304,19 +304,18 @@ bool gatt_check_write_long_terminate(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
|
||||
/* data does not match */
|
||||
p_clcb->status = GATT_ERROR;
|
||||
flag = GATT_PREP_WRITE_CANCEL;
|
||||
@ -57,7 +57,7 @@ index dca49738c..2650a307a 100644
|
||||
}
|
||||
|
||||
/** Send prepare write */
|
||||
@@ -586,15 +585,15 @@ void gatt_process_prep_write_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
|
||||
@@ -583,15 +582,15 @@ void gatt_process_prep_write_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
|
||||
|
||||
memcpy(value.value, p, value.len);
|
||||
|
||||
|
@ -20,10 +20,10 @@ Change-Id: I085ecfa1a9ba098ecbfecbd3cb3e263ae13f9724
|
||||
1 file changed, 6 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/stack/gatt/gatt_cl.cc b/stack/gatt/gatt_cl.cc
|
||||
index db41c5f9f..f7f11b7a9 100644
|
||||
index 203808806..49ccc7e52 100644
|
||||
--- a/stack/gatt/gatt_cl.cc
|
||||
+++ b/stack/gatt/gatt_cl.cc
|
||||
@@ -586,12 +586,17 @@ void gatt_process_prep_write_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
|
||||
@@ -582,12 +582,17 @@ void gatt_process_prep_write_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
|
||||
|
||||
memcpy(value.value, p, value.len);
|
||||
|
||||
|
@ -21,7 +21,7 @@ Change-Id: I907877608f4672f24c002e630e58bf9133937a5e
|
||||
1 file changed, 10 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/stack/gatt/gatt_cl.cc b/stack/gatt/gatt_cl.cc
|
||||
index dca49738c..2650a307a 100644
|
||||
index f8d5bab92..16a7171f6 100644
|
||||
--- a/stack/gatt/gatt_cl.cc
|
||||
+++ b/stack/gatt/gatt_cl.cc
|
||||
@@ -297,7 +297,7 @@ void gatt_send_queue_write_cancel(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
|
||||
@ -57,7 +57,7 @@ index dca49738c..2650a307a 100644
|
||||
}
|
||||
|
||||
/** Send prepare write */
|
||||
@@ -586,15 +585,15 @@ void gatt_process_prep_write_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
|
||||
@@ -587,15 +586,15 @@ void gatt_process_prep_write_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
|
||||
|
||||
memcpy(value.value, p, value.len);
|
||||
|
||||
|
@ -20,7 +20,7 @@ Change-Id: I085ecfa1a9ba098ecbfecbd3cb3e263ae13f9724
|
||||
1 file changed, 6 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/stack/gatt/gatt_cl.cc b/stack/gatt/gatt_cl.cc
|
||||
index db41c5f9f..f7f11b7a9 100644
|
||||
index 16a7171f6..5e4837020 100644
|
||||
--- a/stack/gatt/gatt_cl.cc
|
||||
+++ b/stack/gatt/gatt_cl.cc
|
||||
@@ -586,12 +586,17 @@ void gatt_process_prep_write_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
|
||||
|
@ -1,4 +1,4 @@
|
||||
From 50f60add5c547b8c9bc4462bd2fc2840d8fc4525 Mon Sep 17 00:00:00 2001
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Vincent Rabaud <vrabaud@google.com>
|
||||
Date: Thu, 7 Sep 2023 21:16:03 +0200
|
||||
Subject: [PATCH] Fix OOB write in BuildHuffmanTable.
|
||||
@ -21,7 +21,7 @@ Change-Id: I31c36dbf3aa78d35ecf38706b50464fd3d375741
|
||||
4 files changed, 129 insertions(+), 43 deletions(-)
|
||||
|
||||
diff --git a/src/dec/vp8l_dec.c b/src/dec/vp8l_dec.c
|
||||
index 93615d4ed2..0d38314db8 100644
|
||||
index 93615d4e..0d38314d 100644
|
||||
--- a/src/dec/vp8l_dec.c
|
||||
+++ b/src/dec/vp8l_dec.c
|
||||
@@ -253,11 +253,11 @@ static int ReadHuffmanCodeLengths(
|
||||
@ -169,7 +169,7 @@ index 93615d4ed2..0d38314db8 100644
|
||||
assert(dec->hdr_.num_htree_groups_ > 0);
|
||||
|
||||
diff --git a/src/dec/vp8li_dec.h b/src/dec/vp8li_dec.h
|
||||
index 72b2e86120..32540a4b88 100644
|
||||
index 72b2e861..32540a4b 100644
|
||||
--- a/src/dec/vp8li_dec.h
|
||||
+++ b/src/dec/vp8li_dec.h
|
||||
@@ -51,7 +51,7 @@ typedef struct {
|
||||
@ -182,7 +182,7 @@ index 72b2e86120..32540a4b88 100644
|
||||
|
||||
typedef struct VP8LDecoder VP8LDecoder;
|
||||
diff --git a/src/utils/huffman_utils.c b/src/utils/huffman_utils.c
|
||||
index 0cba0fbb7d..9efd6283ac 100644
|
||||
index 0cba0fbb..9efd6283 100644
|
||||
--- a/src/utils/huffman_utils.c
|
||||
+++ b/src/utils/huffman_utils.c
|
||||
@@ -177,21 +177,24 @@ static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
|
||||
@ -313,7 +313,7 @@ index 0cba0fbb7d..9efd6283ac 100644
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/utils/huffman_utils.h b/src/utils/huffman_utils.h
|
||||
index 13b7ad1ac4..98415c5328 100644
|
||||
index 13b7ad1a..98415c53 100644
|
||||
--- a/src/utils/huffman_utils.h
|
||||
+++ b/src/utils/huffman_utils.h
|
||||
@@ -43,6 +43,29 @@ typedef struct {
|
||||
|
@ -1,4 +1,4 @@
|
||||
From 20ceff7eb3ccb679bd299f3d481309e10cbf2616 Mon Sep 17 00:00:00 2001
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Vincent Rabaud <vrabaud@google.com>
|
||||
Date: Thu, 7 Sep 2023 21:16:03 +0200
|
||||
Subject: [PATCH] Fix OOB write in BuildHuffmanTable.
|
||||
@ -21,7 +21,7 @@ Change-Id: I31c36dbf3aa78d35ecf38706b50464fd3d375741
|
||||
4 files changed, 129 insertions(+), 43 deletions(-)
|
||||
|
||||
diff --git a/src/dec/vp8l_dec.c b/src/dec/vp8l_dec.c
|
||||
index 2d603b4379..09a0eeccf1 100644
|
||||
index 2d603b4..09a0eec 100644
|
||||
--- a/src/dec/vp8l_dec.c
|
||||
+++ b/src/dec/vp8l_dec.c
|
||||
@@ -253,11 +253,11 @@ static int ReadHuffmanCodeLengths(
|
||||
@ -169,7 +169,7 @@ index 2d603b4379..09a0eeccf1 100644
|
||||
assert(dec->hdr_.num_htree_groups_ > 0);
|
||||
|
||||
diff --git a/src/dec/vp8li_dec.h b/src/dec/vp8li_dec.h
|
||||
index 72b2e86120..32540a4b88 100644
|
||||
index 72b2e86..32540a4 100644
|
||||
--- a/src/dec/vp8li_dec.h
|
||||
+++ b/src/dec/vp8li_dec.h
|
||||
@@ -51,7 +51,7 @@ typedef struct {
|
||||
@ -182,7 +182,7 @@ index 72b2e86120..32540a4b88 100644
|
||||
|
||||
typedef struct VP8LDecoder VP8LDecoder;
|
||||
diff --git a/src/utils/huffman_utils.c b/src/utils/huffman_utils.c
|
||||
index 0cba0fbb7d..9efd6283ac 100644
|
||||
index 0cba0fb..9efd628 100644
|
||||
--- a/src/utils/huffman_utils.c
|
||||
+++ b/src/utils/huffman_utils.c
|
||||
@@ -177,21 +177,24 @@ static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
|
||||
@ -313,7 +313,7 @@ index 0cba0fbb7d..9efd6283ac 100644
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/utils/huffman_utils.h b/src/utils/huffman_utils.h
|
||||
index 13b7ad1ac4..98415c5328 100644
|
||||
index 13b7ad1..98415c5 100644
|
||||
--- a/src/utils/huffman_utils.h
|
||||
+++ b/src/utils/huffman_utils.h
|
||||
@@ -43,6 +43,29 @@ typedef struct {
|
||||
|
@ -1,32 +0,0 @@
|
||||
From 00a42241007a2c2a03b97656c958236091553b80 Mon Sep 17 00:00:00 2001
|
||||
From: Shruti Bihani <shrutibihani@google.com>
|
||||
Date: Thu, 6 Jul 2023 08:41:56 +0000
|
||||
Subject: [PATCH] Fix Segv on unknown address error flagged by fuzzer test.
|
||||
|
||||
The error is thrown when the destructor tries to free pointer memory.
|
||||
This is happening for cases where the pointer was not initialized. Initializing it to a default value fixes the error.
|
||||
|
||||
Bug: 245135112
|
||||
Test: Build mtp_host_property_fuzzer and run on the target device
|
||||
(cherry picked from commit 3afa6e80e8568fe63f893fa354bc79ef91d3dcc0)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:99d0823ca2b8275f000a437150fb8d1938b1b31a)
|
||||
Merged-In: I255cd68b7641e96ac47ab81479b9b46b78c15580
|
||||
Change-Id: I255cd68b7641e96ac47ab81479b9b46b78c15580
|
||||
---
|
||||
media/mtp/MtpProperty.h | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/media/mtp/MtpProperty.h b/media/mtp/MtpProperty.h
|
||||
index 36d736065f..2bdbfd3262 100644
|
||||
--- a/media/mtp/MtpProperty.h
|
||||
+++ b/media/mtp/MtpProperty.h
|
||||
@@ -26,6 +26,9 @@ namespace android {
|
||||
class MtpDataPacket;
|
||||
|
||||
struct MtpPropertyValue {
|
||||
+ // pointer str initialized to NULL so that free operation
|
||||
+ // is not called for pre-assigned value
|
||||
+ MtpPropertyValue() : str (NULL) {}
|
||||
union {
|
||||
int8_t i8;
|
||||
uint8_t u8;
|
@ -1,41 +0,0 @@
|
||||
From ce2776f4ca4fba080bd64bffa2c8fa2d0188bd45 Mon Sep 17 00:00:00 2001
|
||||
From: Hui Peng <phui@google.com>
|
||||
Date: Thu, 27 Apr 2023 00:50:26 +0000
|
||||
Subject: [PATCH] Fix a type confusion bug in bta_av_setconfig_rej
|
||||
|
||||
tBTA_AV_CI_SETCONFIG is treated as tBTA_AV_STR_MSG
|
||||
in bta_av_setconfig_rej, resulting OOB access.
|
||||
|
||||
Bug: 260230151
|
||||
Test: manual
|
||||
Ignore-AOSP-First: security
|
||||
Tag: #security
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:bbd88e88ce749aab87178e189a05e5a356d0631c)
|
||||
Merged-In: I78a1ee50dea0113381e51f8521711d758dc759cf
|
||||
Change-Id: I78a1ee50dea0113381e51f8521711d758dc759cf
|
||||
---
|
||||
system/bta/av/bta_av_aact.cc | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/system/bta/av/bta_av_aact.cc b/system/bta/av/bta_av_aact.cc
|
||||
index d0db36ea3e..39f95e5040 100644
|
||||
--- a/system/bta/av/bta_av_aact.cc
|
||||
+++ b/system/bta/av/bta_av_aact.cc
|
||||
@@ -1740,14 +1740,14 @@ void bta_av_getcap_results(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
|
||||
******************************************************************************/
|
||||
void bta_av_setconfig_rej(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
|
||||
tBTA_AV_REJECT reject;
|
||||
- uint8_t avdt_handle = p_data->ci_setconfig.avdt_handle;
|
||||
|
||||
- bta_av_adjust_seps_idx(p_scb, avdt_handle);
|
||||
+ bta_av_adjust_seps_idx(p_scb, p_scb->avdt_handle);
|
||||
+
|
||||
LOG_INFO("%s: sep_idx=%d avdt_handle=%d bta_handle=0x%x", __func__,
|
||||
p_scb->sep_idx, p_scb->avdt_handle, p_scb->hndl);
|
||||
AVDT_ConfigRsp(p_scb->avdt_handle, p_scb->avdt_label, AVDT_ERR_UNSUP_CFG, 0);
|
||||
|
||||
- reject.bd_addr = p_data->str_msg.bd_addr;
|
||||
+ reject.bd_addr = p_scb->PeerAddress();
|
||||
reject.hndl = p_scb->hndl;
|
||||
|
||||
tBTA_AV bta_av_data;
|
@ -1,83 +0,0 @@
|
||||
From 585f583ef5e6c2446df7700d8959774771d2a9d8 Mon Sep 17 00:00:00 2001
|
||||
From: Hui Peng <phui@google.com>
|
||||
Date: Thu, 11 May 2023 01:10:04 +0000
|
||||
Subject: [PATCH] Fix multiple OOB bugs resulted from tx mtu in EATT
|
||||
|
||||
The tx mtu in EATT can be controlled by remote device. With malicious
|
||||
mtu values, it is possible to trigger integer overflow and
|
||||
OOB write at multiple places (see the bug below).
|
||||
|
||||
This fix enforces a max tx mtu in EATT.
|
||||
|
||||
Bug: 271335899
|
||||
Test: manual
|
||||
Ignore-AOSP-First: security
|
||||
Tag: #security
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:ea76b7d99e6366e2043c5621eda630d559104d36)
|
||||
Merged-In: Ia06c9a17f2daa5ce4c32cffa536777f47774cf31
|
||||
Change-Id: Ia06c9a17f2daa5ce4c32cffa536777f47774cf31
|
||||
---
|
||||
system/stack/eatt/eatt.h | 9 +++++++--
|
||||
system/stack/eatt/eatt_impl.h | 2 +-
|
||||
2 files changed, 8 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/system/stack/eatt/eatt.h b/system/stack/eatt/eatt.h
|
||||
index 6ef3d3359a..1310f65480 100644
|
||||
--- a/system/stack/eatt/eatt.h
|
||||
+++ b/system/stack/eatt/eatt.h
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
+#include <algorithm>
|
||||
#include <deque>
|
||||
|
||||
#include "stack/gatt/gatt_int.h"
|
||||
@@ -24,6 +25,7 @@
|
||||
|
||||
#define EATT_MIN_MTU_MPS (64)
|
||||
#define EATT_DEFAULT_MTU (256)
|
||||
+#define EATT_MAX_TX_MTU (1024)
|
||||
#define EATT_ALL_CIDS (0xFFFF)
|
||||
|
||||
namespace bluetooth {
|
||||
@@ -59,13 +61,13 @@ class EattChannel {
|
||||
EattChannel(RawAddress& bda, uint16_t cid, uint16_t tx_mtu, uint16_t rx_mtu)
|
||||
: bda_(bda),
|
||||
cid_(cid),
|
||||
- tx_mtu_(tx_mtu),
|
||||
rx_mtu_(rx_mtu),
|
||||
state_(EattChannelState::EATT_CHANNEL_PENDING),
|
||||
indicate_handle_(0),
|
||||
ind_ack_timer_(NULL),
|
||||
ind_confirmation_timer_(NULL) {
|
||||
cl_cmd_q_ = std::deque<tGATT_CMD_Q>();
|
||||
+ EattChannelSetTxMTU(tx_mtu);
|
||||
}
|
||||
|
||||
~EattChannel() {
|
||||
@@ -94,7 +96,10 @@ class EattChannel {
|
||||
}
|
||||
state_ = state;
|
||||
}
|
||||
- void EattChannelSetTxMTU(uint16_t tx_mtu) { this->tx_mtu_ = tx_mtu; }
|
||||
+
|
||||
+ void EattChannelSetTxMTU(uint16_t tx_mtu) {
|
||||
+ this->tx_mtu_ = std::min<uint16_t>(tx_mtu, EATT_MAX_TX_MTU);
|
||||
+ }
|
||||
};
|
||||
|
||||
/* Interface class */
|
||||
diff --git a/system/stack/eatt/eatt_impl.h b/system/stack/eatt/eatt_impl.h
|
||||
index 998fc10905..c5a78550ce 100644
|
||||
--- a/system/stack/eatt/eatt_impl.h
|
||||
+++ b/system/stack/eatt/eatt_impl.h
|
||||
@@ -447,7 +447,7 @@ struct eatt_impl {
|
||||
if (is_local_cfg)
|
||||
channel->rx_mtu_ = p_cfg->mtu;
|
||||
else
|
||||
- channel->tx_mtu_ = p_cfg->mtu;
|
||||
+ channel->EattChannelSetTxMTU(p_cfg->mtu);
|
||||
|
||||
/* Go back to open state */
|
||||
channel->EattChannelSetState(EattChannelState::EATT_CHANNEL_OPENED);
|
@ -1,37 +0,0 @@
|
||||
From c9905e7968f603014d8ebd631393f9ba1ffd98c9 Mon Sep 17 00:00:00 2001
|
||||
From: Hui Peng <phui@google.com>
|
||||
Date: Wed, 10 May 2023 23:34:20 +0000
|
||||
Subject: [PATCH] Fix an integer overflow bug in avdt_msg_asmbl
|
||||
|
||||
Bug: 280633699
|
||||
Test: manual
|
||||
Ignore-AOSP-First: security
|
||||
Tag: #security
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:bf9449a704c2983861dbe0ede9ab660e42826179)
|
||||
Merged-In: Iaa4d603921fc4ffb8cfb5783f99ec0963affd6a2
|
||||
Change-Id: Iaa4d603921fc4ffb8cfb5783f99ec0963affd6a2
|
||||
---
|
||||
system/stack/avdt/avdt_msg.cc | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/system/stack/avdt/avdt_msg.cc b/system/stack/avdt/avdt_msg.cc
|
||||
index f9f3f7e1e0..0baf5f1f35 100644
|
||||
--- a/system/stack/avdt/avdt_msg.cc
|
||||
+++ b/system/stack/avdt/avdt_msg.cc
|
||||
@@ -1285,14 +1285,14 @@ BT_HDR* avdt_msg_asmbl(AvdtpCcb* p_ccb, BT_HDR* p_buf) {
|
||||
* NOTE: The buffer is allocated above at the beginning of the
|
||||
* reassembly, and is always of size BT_DEFAULT_BUFFER_SIZE.
|
||||
*/
|
||||
- uint16_t buf_len = BT_DEFAULT_BUFFER_SIZE - sizeof(BT_HDR);
|
||||
+ size_t buf_len = BT_DEFAULT_BUFFER_SIZE - sizeof(BT_HDR);
|
||||
|
||||
/* adjust offset and len of fragment for header byte */
|
||||
p_buf->offset += AVDT_LEN_TYPE_CONT;
|
||||
p_buf->len -= AVDT_LEN_TYPE_CONT;
|
||||
|
||||
/* verify length */
|
||||
- if ((p_ccb->p_rx_msg->offset + p_buf->len) > buf_len) {
|
||||
+ if (((size_t) p_ccb->p_rx_msg->offset + (size_t) p_buf->len) > buf_len) {
|
||||
/* won't fit; free everything */
|
||||
AVDT_TRACE_WARNING("%s: Fragmented message too big!", __func__);
|
||||
osi_free_and_reset((void**)&p_ccb->p_rx_msg);
|
@ -1,66 +0,0 @@
|
||||
From c93ec045f59462f2fb64242da1a119a7b49c3d50 Mon Sep 17 00:00:00 2001
|
||||
From: Brian Delwiche <delwiche@google.com>
|
||||
Date: Tue, 18 Apr 2023 23:58:50 +0000
|
||||
Subject: [PATCH] Fix integer overflow in build_read_multi_rsp
|
||||
|
||||
Local variables tracking structure size in build_read_multi_rsp are of
|
||||
uint16 type but accept a full uint16 range from function arguments while
|
||||
appending a fixed-length offset. This can lead to an integer overflow
|
||||
and unexpected behavior.
|
||||
|
||||
Change the locals to size_t, and add a check during reasssignment.
|
||||
|
||||
Bug: 273966636
|
||||
Test: atest bluetooth_test_gd_unit, net_test_stack_btm
|
||||
Tag: #security
|
||||
Ignore-AOSP-First: Security
|
||||
(cherry picked from commit 70a4d628fa016a9487fae07f211644b95e1f0000)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:badb8ffce06b517cbcfdbfa68cb7b7e02d22494a)
|
||||
Merged-In: I3a74bdb0d003cb6bf4f282615be8c68836676715
|
||||
Change-Id: I3a74bdb0d003cb6bf4f282615be8c68836676715
|
||||
---
|
||||
system/stack/gatt/gatt_sr.cc | 17 ++++++++++++-----
|
||||
1 file changed, 12 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/system/stack/gatt/gatt_sr.cc b/system/stack/gatt/gatt_sr.cc
|
||||
index 9f48d830d5..f2a3e22414 100644
|
||||
--- a/system/stack/gatt/gatt_sr.cc
|
||||
+++ b/system/stack/gatt/gatt_sr.cc
|
||||
@@ -142,7 +142,8 @@ void gatt_dequeue_sr_cmd(tGATT_TCB& tcb, uint16_t cid) {
|
||||
}
|
||||
|
||||
static void build_read_multi_rsp(tGATT_SR_CMD* p_cmd, uint16_t mtu) {
|
||||
- uint16_t ii, total_len, len;
|
||||
+ uint16_t ii;
|
||||
+ size_t total_len, len;
|
||||
uint8_t* p;
|
||||
bool is_overflow = false;
|
||||
|
||||
@@ -187,7 +188,7 @@ static void build_read_multi_rsp(tGATT_SR_CMD* p_cmd, uint16_t mtu) {
|
||||
len = p_rsp->attr_value.len - (total_len - mtu);
|
||||
is_overflow = true;
|
||||
VLOG(1) << StringPrintf(
|
||||
- "multi read overflow available len=%d val_len=%d", len,
|
||||
+ "multi read overflow available len=%zu val_len=%d", len,
|
||||
p_rsp->attr_value.len);
|
||||
} else {
|
||||
len = p_rsp->attr_value.len;
|
||||
@@ -199,9 +200,15 @@ static void build_read_multi_rsp(tGATT_SR_CMD* p_cmd, uint16_t mtu) {
|
||||
}
|
||||
|
||||
if (p_rsp->attr_value.handle == p_cmd->multi_req.handles[ii]) {
|
||||
- memcpy(p, p_rsp->attr_value.value, len);
|
||||
- if (!is_overflow) p += len;
|
||||
- p_buf->len += len;
|
||||
+ // check for possible integer overflow
|
||||
+ if (p_buf->len + len <= UINT16_MAX) {
|
||||
+ memcpy(p, p_rsp->attr_value.value, len);
|
||||
+ if (!is_overflow) p += len;
|
||||
+ p_buf->len += len;
|
||||
+ } else {
|
||||
+ p_cmd->status = GATT_NOT_FOUND;
|
||||
+ break;
|
||||
+ }
|
||||
} else {
|
||||
p_cmd->status = GATT_NOT_FOUND;
|
||||
break;
|
@ -1,40 +0,0 @@
|
||||
From 89fb17d17249382f8bd5c4c9b0912447ea7ff676 Mon Sep 17 00:00:00 2001
|
||||
From: Brian Delwiche <delwiche@google.com>
|
||||
Date: Wed, 1 Mar 2023 00:22:59 +0000
|
||||
Subject: [PATCH] Fix potential abort in btu_av_act.cc
|
||||
|
||||
Partner analysis shows that bta_av_rc_msg does not respect handling
|
||||
established for a null browse packet, instead dispatching the null
|
||||
pointer to bta_av_rc_free_browse_msg. Strictly speaking this does
|
||||
not cause a UAF, as osi_free_and_reset will find the null and abort,
|
||||
but it will lead to improper program termination.
|
||||
|
||||
Handle the case instead.
|
||||
|
||||
Bug: 269253349
|
||||
Test: atest bluetooth_test_gd_unit
|
||||
Tag: #security
|
||||
Ignore-AOSP-First: Security
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:d3ee136851de30261e56c62fbb488541dc564b94)
|
||||
Merged-In: I14dc4910476c733b246bcf7ff292afe9b7c0cc3d
|
||||
Change-Id: I14dc4910476c733b246bcf7ff292afe9b7c0cc3d
|
||||
---
|
||||
system/bta/av/bta_av_act.cc | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/system/bta/av/bta_av_act.cc b/system/bta/av/bta_av_act.cc
|
||||
index be199a4da3..357ca0ecf6 100644
|
||||
--- a/system/bta/av/bta_av_act.cc
|
||||
+++ b/system/bta/av/bta_av_act.cc
|
||||
@@ -1001,7 +1001,10 @@ void bta_av_rc_msg(tBTA_AV_CB* p_cb, tBTA_AV_DATA* p_data) {
|
||||
av.remote_cmd.rc_handle = p_data->rc_msg.handle;
|
||||
(*p_cb->p_cback)(evt, &av);
|
||||
/* If browsing message, then free the browse message buffer */
|
||||
- bta_av_rc_free_browse_msg(p_cb, p_data);
|
||||
+ if (p_data->rc_msg.opcode == AVRC_OP_BROWSE &&
|
||||
+ p_data->rc_msg.msg.browse.p_browse_pkt != NULL) {
|
||||
+ bta_av_rc_free_browse_msg(p_cb, p_data);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
@ -1,44 +0,0 @@
|
||||
From 14aed2455e4e800e4bde6175ad3c4910ffcf7b0e Mon Sep 17 00:00:00 2001
|
||||
From: Brian Delwiche <delwiche@google.com>
|
||||
Date: Tue, 11 Apr 2023 23:05:45 +0000
|
||||
Subject: [PATCH] Fix UAF in gatt_cl.cc
|
||||
|
||||
gatt_cl.cc accesses a header field after the buffer holding it may have
|
||||
been freed.
|
||||
|
||||
Track the relevant state as a local variable instead.
|
||||
|
||||
Bug: 274617156
|
||||
Test: atest: bluetooth, validated against fuzzer
|
||||
Tag: #security
|
||||
Ignore-AOSP-First: Security
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:cbaa83627b328eee8f2e26188909a5ebfb0388d5)
|
||||
Merged-In: I085ecfa1a9ba098ecbfecbd3cb3e263ae13f9724
|
||||
Change-Id: I085ecfa1a9ba098ecbfecbd3cb3e263ae13f9724
|
||||
---
|
||||
system/stack/gatt/gatt_cl.cc | 7 ++++++-
|
||||
1 file changed, 6 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/system/stack/gatt/gatt_cl.cc b/system/stack/gatt/gatt_cl.cc
|
||||
index d026633ccd..029e5cba45 100644
|
||||
--- a/system/stack/gatt/gatt_cl.cc
|
||||
+++ b/system/stack/gatt/gatt_cl.cc
|
||||
@@ -609,12 +609,17 @@ void gatt_process_prep_write_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
|
||||
|
||||
memcpy(value.value, p, value.len);
|
||||
|
||||
+ bool subtype_is_write_prepare = (p_clcb->op_subtype == GATT_WRITE_PREPARE);
|
||||
+
|
||||
if (!gatt_check_write_long_terminate(tcb, p_clcb, &value)) {
|
||||
gatt_send_prepare_write(tcb, p_clcb);
|
||||
return;
|
||||
}
|
||||
|
||||
- if (p_clcb->op_subtype == GATT_WRITE_PREPARE) {
|
||||
+ // We now know that we have not terminated, or else we would have returned
|
||||
+ // early. We free the buffer only if the subtype is not equal to
|
||||
+ // GATT_WRITE_PREPARE, so checking here is adequate to prevent UAF.
|
||||
+ if (subtype_is_write_prepare) {
|
||||
/* application should verify handle offset
|
||||
and value are matched or not */
|
||||
gatt_end_operation(p_clcb, p_clcb->status, &value);
|
@ -1,37 +0,0 @@
|
||||
From cd438ebc524bc27b6200c70ccb6ed9f8d0271a10 Mon Sep 17 00:00:00 2001
|
||||
From: Hui Peng <phui@google.com>
|
||||
Date: Wed, 19 Jul 2023 18:14:59 +0000
|
||||
Subject: [PATCH] Revert "Fix a type confusion bug in bta_av_setconfig_rej"
|
||||
|
||||
This reverts commit bbd88e88ce749aab87178e189a05e5a356d0631c.
|
||||
|
||||
Reason for revert: b/281788858
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:c3356f17866099405ef6c01244211af4bd93db2c)
|
||||
Merged-In: I0f45c87ba5f0b2c84843e568ca117439b42d1ed3
|
||||
Change-Id: I0f45c87ba5f0b2c84843e568ca117439b42d1ed3
|
||||
---
|
||||
system/bta/av/bta_av_aact.cc | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/system/bta/av/bta_av_aact.cc b/system/bta/av/bta_av_aact.cc
|
||||
index 39f95e5040..d0db36ea3e 100644
|
||||
--- a/system/bta/av/bta_av_aact.cc
|
||||
+++ b/system/bta/av/bta_av_aact.cc
|
||||
@@ -1740,14 +1740,14 @@ void bta_av_getcap_results(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
|
||||
******************************************************************************/
|
||||
void bta_av_setconfig_rej(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
|
||||
tBTA_AV_REJECT reject;
|
||||
+ uint8_t avdt_handle = p_data->ci_setconfig.avdt_handle;
|
||||
|
||||
- bta_av_adjust_seps_idx(p_scb, p_scb->avdt_handle);
|
||||
-
|
||||
+ bta_av_adjust_seps_idx(p_scb, avdt_handle);
|
||||
LOG_INFO("%s: sep_idx=%d avdt_handle=%d bta_handle=0x%x", __func__,
|
||||
p_scb->sep_idx, p_scb->avdt_handle, p_scb->hndl);
|
||||
AVDT_ConfigRsp(p_scb->avdt_handle, p_scb->avdt_label, AVDT_ERR_UNSUP_CFG, 0);
|
||||
|
||||
- reject.bd_addr = p_scb->PeerAddress();
|
||||
+ reject.bd_addr = p_data->str_msg.bd_addr;
|
||||
reject.hndl = p_scb->hndl;
|
||||
|
||||
tBTA_AV bta_av_data;
|
@ -1,85 +0,0 @@
|
||||
From df4a9362cd39867ca7deee537934649bd6a2589f Mon Sep 17 00:00:00 2001
|
||||
From: Ioana Alexandru <aioana@google.com>
|
||||
Date: Mon, 3 Jul 2023 16:29:47 +0000
|
||||
Subject: [PATCH] DO NOT MERGE Revert "Verify URI permissions for
|
||||
EXTRA_REMOTE_INPUT_HISTORY_ITEMS."
|
||||
|
||||
This reverts commit 43b1711332763788c7abf05c3baa931296c45bbb.
|
||||
|
||||
Reason for revert: regression reported at b/289223315
|
||||
|
||||
Bug: 289223315
|
||||
Bug: 276729064
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:bdc9b977e376fb3b6047530a179d00fd77f2aec1)
|
||||
Merged-In: I101938fbc51592537023345ba1e642827510981b
|
||||
Change-Id: I101938fbc51592537023345ba1e642827510981b
|
||||
---
|
||||
core/java/android/app/Notification.java | 11 -----------
|
||||
.../notification/NotificationManagerServiceTest.java | 11 -----------
|
||||
2 files changed, 22 deletions(-)
|
||||
|
||||
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
|
||||
index 8a730fb0deaa..6efb83cb3d93 100644
|
||||
--- a/core/java/android/app/Notification.java
|
||||
+++ b/core/java/android/app/Notification.java
|
||||
@@ -2857,17 +2857,6 @@ public void visitUris(@NonNull Consumer<Uri> visitor) {
|
||||
if (person != null) {
|
||||
visitor.accept(person.getIconUri());
|
||||
}
|
||||
-
|
||||
- final RemoteInputHistoryItem[] history = (RemoteInputHistoryItem[])
|
||||
- extras.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS);
|
||||
- if (history != null) {
|
||||
- for (int i = 0; i < history.length; i++) {
|
||||
- RemoteInputHistoryItem item = history[i];
|
||||
- if (item.getUri() != null) {
|
||||
- visitor.accept(item.getUri());
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
}
|
||||
|
||||
if (isStyle(MessagingStyle.class) && extras != null) {
|
||||
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
|
||||
index 2fa14a7c93c6..718d9c50c6b2 100755
|
||||
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
|
||||
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
|
||||
@@ -128,7 +128,6 @@
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Person;
|
||||
import android.app.RemoteInput;
|
||||
-import android.app.RemoteInputHistoryItem;
|
||||
import android.app.StatsManager;
|
||||
import android.app.admin.DevicePolicyManagerInternal;
|
||||
import android.app.usage.UsageStatsManagerInternal;
|
||||
@@ -5391,12 +5390,6 @@ public void testVisitUris() throws Exception {
|
||||
.setName("People List Person 2")
|
||||
.setIcon(personIcon3)
|
||||
.build();
|
||||
- final Uri historyUri1 = Uri.parse("content://com.example/history1");
|
||||
- final Uri historyUri2 = Uri.parse("content://com.example/history2");
|
||||
- final RemoteInputHistoryItem historyItem1 = new RemoteInputHistoryItem(null, historyUri1,
|
||||
- "a");
|
||||
- final RemoteInputHistoryItem historyItem2 = new RemoteInputHistoryItem(null, historyUri2,
|
||||
- "b");
|
||||
|
||||
Bundle extras = new Bundle();
|
||||
extras.putParcelable(Notification.EXTRA_AUDIO_CONTENTS_URI, audioContents);
|
||||
@@ -5404,8 +5397,6 @@ public void testVisitUris() throws Exception {
|
||||
extras.putParcelable(Notification.EXTRA_MESSAGING_PERSON, person1);
|
||||
extras.putParcelableArrayList(Notification.EXTRA_PEOPLE_LIST,
|
||||
new ArrayList<>(Arrays.asList(person2, person3)));
|
||||
- extras.putParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS,
|
||||
- new RemoteInputHistoryItem[]{historyItem1, historyItem2});
|
||||
|
||||
Notification n = new Notification.Builder(mContext, "a")
|
||||
.setContentTitle("notification with uris")
|
||||
@@ -5423,8 +5414,6 @@ public void testVisitUris() throws Exception {
|
||||
verify(visitor, times(1)).accept(eq(personIcon1.getUri()));
|
||||
verify(visitor, times(1)).accept(eq(personIcon2.getUri()));
|
||||
verify(visitor, times(1)).accept(eq(personIcon3.getUri()));
|
||||
- verify(visitor, times(1)).accept(eq(historyUri1));
|
||||
- verify(visitor, times(1)).accept(eq(historyUri2));
|
||||
}
|
||||
|
||||
@Test
|
@ -1,45 +0,0 @@
|
||||
From b55563bb9d534210c3f4c5e21ba07a63360c2094 Mon Sep 17 00:00:00 2001
|
||||
From: Achim Thesmann <achim@google.com>
|
||||
Date: Tue, 23 May 2023 00:26:33 +0000
|
||||
Subject: [PATCH] Ignore virtual presentation windows - RESTRICT AUTOMERGE
|
||||
|
||||
Windows of TYPE_PRESENTATION on virtual displays should not be counted
|
||||
as visible windows to determine if BAL is allowed.
|
||||
|
||||
Test: manual test, atest BackgroundActivityLaunchTest
|
||||
Bug: 264029851, 205130886
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:4c40b187cd5277c27d20758c675865bf89180c7a)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:5bf9607bec3f1224158cfcff7dd91ac558b46c0f)
|
||||
Merged-In: I08b16ba1c155e951286ddc22019180cbd6334dfa
|
||||
Change-Id: I08b16ba1c155e951286ddc22019180cbd6334dfa
|
||||
---
|
||||
.../core/java/com/android/server/wm/WindowState.java | 12 ++++++++++--
|
||||
1 file changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
|
||||
index 95fea0ee22f5..66213cc6403d 100644
|
||||
--- a/services/core/java/com/android/server/wm/WindowState.java
|
||||
+++ b/services/core/java/com/android/server/wm/WindowState.java
|
||||
@@ -3596,12 +3596,20 @@ void onSurfaceShownChanged(boolean shown) {
|
||||
// apps won't always be considered as foreground state.
|
||||
// Exclude private presentations as they can only be shown on private virtual displays and
|
||||
// shouldn't be the cause of an app be considered foreground.
|
||||
- if (mAttrs.type >= FIRST_SYSTEM_WINDOW && mAttrs.type != TYPE_TOAST
|
||||
- && mAttrs.type != TYPE_PRIVATE_PRESENTATION) {
|
||||
+ // Exclude presentations on virtual displays as they are not actually visible.
|
||||
+ if (mAttrs.type >= FIRST_SYSTEM_WINDOW
|
||||
+ && mAttrs.type != TYPE_TOAST
|
||||
+ && mAttrs.type != TYPE_PRIVATE_PRESENTATION
|
||||
+ && !(mAttrs.type == TYPE_PRESENTATION && isOnVirtualDisplay())
|
||||
+ ) {
|
||||
mWmService.mAtmService.mActiveUids.onNonAppSurfaceVisibilityChanged(mOwnerUid, shown);
|
||||
}
|
||||
}
|
||||
|
||||
+ private boolean isOnVirtualDisplay() {
|
||||
+ return getDisplayContent().mDisplay.getType() == Display.TYPE_VIRTUAL;
|
||||
+ }
|
||||
+
|
||||
private void logExclusionRestrictions(int side) {
|
||||
if (!logsGestureExclusionRestrictions(this)
|
||||
|| SystemClock.uptimeMillis() < mLastExclusionLogUptimeMillis[side]
|
@ -1,140 +0,0 @@
|
||||
From a80971a28168f2667a2821d008964ba001cad059 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Mat=C3=ADas=20Hern=C3=A1ndez?= <matiashe@google.com>
|
||||
Date: Thu, 15 Jun 2023 18:31:34 +0200
|
||||
Subject: [PATCH] Forbid granting access to NLSes with too-long component names
|
||||
|
||||
This makes the limitation, which was previously only checked on the Settings UI, enforced everywhere.
|
||||
|
||||
Fixes: 260570119
|
||||
Fixes: 286043036
|
||||
Test: atest + manually
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:6fcdbd0c6efc67b014b8e1b43c5ec233f912ee8b)
|
||||
Merged-In: I4c25d80978cb37a8fa1531f5045259d25ac64692
|
||||
Change-Id: I4c25d80978cb37a8fa1531f5045259d25ac64692
|
||||
---
|
||||
.../java/android/app/NotificationManager.java | 6 +++++
|
||||
.../RestrictedSwitchPreference.java | 8 ++++--
|
||||
.../NotificationManagerService.java | 5 ++++
|
||||
.../android/server/vr/VrManagerService.java | 6 ++++-
|
||||
.../NotificationManagerServiceTest.java | 25 +++++++++++++++++++
|
||||
5 files changed, 47 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
|
||||
index 3506c41310a3..2807b0b4b682 100644
|
||||
--- a/core/java/android/app/NotificationManager.java
|
||||
+++ b/core/java/android/app/NotificationManager.java
|
||||
@@ -575,6 +575,12 @@ public class NotificationManager {
|
||||
*/
|
||||
public static final int BUBBLE_PREFERENCE_SELECTED = 2;
|
||||
|
||||
+ /**
|
||||
+ * Maximum length of the component name of a registered NotificationListenerService.
|
||||
+ * @hide
|
||||
+ */
|
||||
+ public static int MAX_SERVICE_COMPONENT_NAME_LENGTH = 500;
|
||||
+
|
||||
@UnsupportedAppUsage
|
||||
private static INotificationManager sService;
|
||||
|
||||
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
|
||||
index b5e4fa38d244..af06d7304160 100644
|
||||
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
|
||||
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
|
||||
@@ -243,7 +243,9 @@ public String getPackageName() {
|
||||
return mHelper != null ? mHelper.packageName : null;
|
||||
}
|
||||
|
||||
- public void updateState(@NonNull String packageName, int uid, boolean isEnabled) {
|
||||
+ /** Updates enabled state based on associated package. */
|
||||
+ public void updateState(
|
||||
+ @NonNull String packageName, int uid, boolean isEnableAllowed, boolean isEnabled) {
|
||||
mHelper.updatePackageDetails(packageName, uid);
|
||||
if (mAppOpsManager == null) {
|
||||
mAppOpsManager = getContext().getSystemService(AppOpsManager.class);
|
||||
@@ -254,7 +256,9 @@ public void updateState(@NonNull String packageName, int uid, boolean isEnabled)
|
||||
final boolean ecmEnabled = getContext().getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_enhancedConfirmationModeEnabled);
|
||||
final boolean appOpsAllowed = !ecmEnabled || mode == AppOpsManager.MODE_ALLOWED;
|
||||
- if (isEnabled) {
|
||||
+ if (!isEnableAllowed && !isEnabled) {
|
||||
+ setEnabled(false);
|
||||
+ } else if (isEnabled) {
|
||||
setEnabled(true);
|
||||
} else if (appOpsAllowed && isDisabledByAppOps()) {
|
||||
setEnabled(true);
|
||||
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
|
||||
index 51db4b820aad..286782c60c66 100755
|
||||
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
|
||||
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
|
||||
@@ -5529,6 +5529,11 @@ public void setNotificationListenerAccessGrantedForUser(ComponentName listener,
|
||||
boolean granted, boolean userSet) {
|
||||
Objects.requireNonNull(listener);
|
||||
checkNotificationListenerAccess();
|
||||
+ if (granted && listener.flattenToString().length()
|
||||
+ > NotificationManager.MAX_SERVICE_COMPONENT_NAME_LENGTH) {
|
||||
+ throw new IllegalArgumentException(
|
||||
+ "Component name too long: " + listener.flattenToString());
|
||||
+ }
|
||||
if (!userSet && isNotificationListenerAccessUserSet(listener)) {
|
||||
// Don't override user's choice
|
||||
return;
|
||||
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
|
||||
index b296ef2a1443..1ff01a6c70bf 100644
|
||||
--- a/services/core/java/com/android/server/vr/VrManagerService.java
|
||||
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
|
||||
@@ -1049,7 +1049,11 @@ private void grantNotificationListenerAccess(String pkg, int userId) {
|
||||
|
||||
for (ComponentName c : possibleServices) {
|
||||
if (Objects.equals(c.getPackageName(), pkg)) {
|
||||
- nm.setNotificationListenerAccessGrantedForUser(c, userId, true);
|
||||
+ try {
|
||||
+ nm.setNotificationListenerAccessGrantedForUser(c, userId, true);
|
||||
+ } catch (Exception e) {
|
||||
+ Slog.w(TAG, "Could not grant NLS access to package " + pkg, e);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
|
||||
index 718d9c50c6b2..24fff1279a4e 100755
|
||||
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
|
||||
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
|
||||
@@ -84,6 +84,7 @@
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static junit.framework.Assert.fail;
|
||||
|
||||
+import static org.junit.Assert.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.isNull;
|
||||
import static org.mockito.Matchers.anyBoolean;
|
||||
import static org.mockito.Matchers.anyLong;
|
||||
@@ -3846,6 +3847,30 @@ public void testSetListenerAccessForUser() throws Exception {
|
||||
any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
|
||||
}
|
||||
|
||||
+ @Test
|
||||
+ public void testSetListenerAccessForUser_grantWithNameTooLong_throws() {
|
||||
+ UserHandle user = UserHandle.of(mContext.getUserId() + 10);
|
||||
+ ComponentName c = new ComponentName("com.example.package",
|
||||
+ com.google.common.base.Strings.repeat("Blah", 150));
|
||||
+
|
||||
+ assertThrows(IllegalArgumentException.class,
|
||||
+ () -> mBinderService.setNotificationListenerAccessGrantedForUser(
|
||||
+ c, user.getIdentifier(), /* enabled= */ true, true));
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testSetListenerAccessForUser_revokeWithNameTooLong_okay() throws Exception {
|
||||
+ UserHandle user = UserHandle.of(mContext.getUserId() + 10);
|
||||
+ ComponentName c = new ComponentName("com.example.package",
|
||||
+ com.google.common.base.Strings.repeat("Blah", 150));
|
||||
+
|
||||
+ mBinderService.setNotificationListenerAccessGrantedForUser(
|
||||
+ c, user.getIdentifier(), /* enabled= */ false, true);
|
||||
+
|
||||
+ verify(mListeners).setPackageOrComponentEnabled(
|
||||
+ c.flattenToString(), user.getIdentifier(), true, /* enabled= */ false, true);
|
||||
+ }
|
||||
+
|
||||
@Test
|
||||
public void testSetAssistantAccessForUser() throws Exception {
|
||||
UserInfo ui = new UserInfo();
|
@ -1,529 +0,0 @@
|
||||
From 7e173b43837c419a7cb77f5758191a557fdc76fa Mon Sep 17 00:00:00 2001
|
||||
From: Miranda Kephart <mkephart@google.com>
|
||||
Date: Fri, 28 Apr 2023 10:58:46 -0400
|
||||
Subject: [PATCH] [DO NOT MERGE] Update quickshare intent rather than
|
||||
recreating
|
||||
|
||||
Currently, we extract the quickshare intent and re-wrap it as a new
|
||||
PendingIntent once we get the screenshot URI. This is insecure as
|
||||
it leads to executing the original with SysUI's permissions, which
|
||||
the app may not have. This change switches to using Intent.fillin
|
||||
to add the URI, keeping the original PendingIntent and original
|
||||
permission set.
|
||||
|
||||
Bug: 278720336
|
||||
Test: manual (to test successful quickshare), atest
|
||||
SaveImageInBackgroundTaskTest (to verify original pending intent
|
||||
unchanged)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:02938e8ccae910d96578475a19dff0a5e746b03d)
|
||||
Merged-In: Icad3d5f939fcfb894e2038948954bc2735dbe326
|
||||
Change-Id: Icad3d5f939fcfb894e2038948954bc2735dbe326
|
||||
---
|
||||
.../screenshot/SaveImageInBackgroundTask.java | 113 ++++---
|
||||
.../screenshot/ScreenshotController.java | 1 +
|
||||
.../screenshot/SmartActionsReceiver.java | 7 +-
|
||||
.../SaveImageInBackgroundTaskTest.kt | 282 ++++++++++++++++++
|
||||
4 files changed, 353 insertions(+), 50 deletions(-)
|
||||
create mode 100644 packages/SystemUI/tests/src/com/android/systemui/screenshot/SaveImageInBackgroundTaskTest.kt
|
||||
|
||||
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
|
||||
index bf5fbd223186..49989273d012 100644
|
||||
--- a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
|
||||
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
|
||||
@@ -21,6 +21,7 @@
|
||||
import static com.android.systemui.screenshot.LogConfig.DEBUG_STORAGE;
|
||||
import static com.android.systemui.screenshot.LogConfig.logTag;
|
||||
import static com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider.ScreenshotSmartActionType;
|
||||
+import static com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider.ScreenshotSmartActionType.QUICK_SHARE_ACTION;
|
||||
|
||||
import android.app.ActivityTaskManager;
|
||||
import android.app.Notification;
|
||||
@@ -141,7 +142,12 @@ protected Void doInBackground(Void... paramsUnused) {
|
||||
// Since Quick Share target recommendation does not rely on image URL, it is
|
||||
// queried and surfaced before image compress/export. Action intent would not be
|
||||
// used, because it does not contain image URL.
|
||||
- queryQuickShareAction(image, user);
|
||||
+ Notification.Action quickShare =
|
||||
+ queryQuickShareAction(mScreenshotId, image, user, null);
|
||||
+ if (quickShare != null) {
|
||||
+ mQuickShareData.quickShareAction = quickShare;
|
||||
+ mParams.mQuickShareActionsReadyListener.onActionsReady(mQuickShareData);
|
||||
+ }
|
||||
}
|
||||
|
||||
// Call synchronously here since already on a background thread.
|
||||
@@ -180,8 +186,8 @@ protected Void doInBackground(Void... paramsUnused) {
|
||||
smartActionsEnabled);
|
||||
mImageData.deleteAction = createDeleteAction(mContext, mContext.getResources(), uri,
|
||||
smartActionsEnabled);
|
||||
- mImageData.quickShareAction = createQuickShareAction(mContext,
|
||||
- mQuickShareData.quickShareAction, uri);
|
||||
+ mImageData.quickShareAction = createQuickShareAction(
|
||||
+ mQuickShareData.quickShareAction, mScreenshotId, uri, mImageTime, image, user);
|
||||
mImageData.subject = getSubjectString();
|
||||
|
||||
mParams.mActionsReadyListener.onActionsReady(mImageData);
|
||||
@@ -423,75 +429,86 @@ private static void addIntentExtras(String screenshotId, Intent intent, String a
|
||||
}
|
||||
|
||||
/**
|
||||
- * Populate image uri into intent of Quick Share action.
|
||||
+ * Wrap the quickshare intent and populate the fillin intent with the URI
|
||||
*/
|
||||
@VisibleForTesting
|
||||
- private Notification.Action createQuickShareAction(Context context, Notification.Action action,
|
||||
- Uri uri) {
|
||||
- if (action == null) {
|
||||
+ Notification.Action createQuickShareAction(
|
||||
+ Notification.Action quickShare, String screenshotId, Uri uri, long imageTime,
|
||||
+ Bitmap image, UserHandle user) {
|
||||
+ if (quickShare == null) {
|
||||
return null;
|
||||
+ } else if (quickShare.actionIntent.isImmutable()) {
|
||||
+ Notification.Action quickShareWithUri =
|
||||
+ queryQuickShareAction(screenshotId, image, user, uri);
|
||||
+ if (quickShareWithUri == null
|
||||
+ || !quickShareWithUri.title.toString().contentEquals(quickShare.title)) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ quickShare = quickShareWithUri;
|
||||
}
|
||||
- // Populate image URI into Quick Share chip intent
|
||||
- Intent sharingIntent = action.actionIntent.getIntent();
|
||||
- sharingIntent.setType("image/png");
|
||||
- sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
|
||||
- String subjectDate = DateFormat.getDateTimeInstance().format(new Date(mImageTime));
|
||||
+
|
||||
+ Intent wrappedIntent = new Intent(mContext, SmartActionsReceiver.class)
|
||||
+ .putExtra(ScreenshotController.EXTRA_ACTION_INTENT, quickShare.actionIntent)
|
||||
+ .putExtra(ScreenshotController.EXTRA_ACTION_INTENT_FILLIN,
|
||||
+ createFillInIntent(uri, imageTime))
|
||||
+ .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
|
||||
+ Bundle extras = quickShare.getExtras();
|
||||
+ String actionType = extras.getString(
|
||||
+ ScreenshotNotificationSmartActionsProvider.ACTION_TYPE,
|
||||
+ ScreenshotNotificationSmartActionsProvider.DEFAULT_ACTION_TYPE);
|
||||
+ addIntentExtras(screenshotId, wrappedIntent, actionType, true);
|
||||
+ PendingIntent broadcastIntent =
|
||||
+ PendingIntent.getBroadcast(mContext, mRandom.nextInt(), wrappedIntent,
|
||||
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
||||
+ return new Notification.Action.Builder(quickShare.getIcon(), quickShare.title,
|
||||
+ broadcastIntent)
|
||||
+ .setContextual(true)
|
||||
+ .addExtras(extras)
|
||||
+ .build();
|
||||
+ }
|
||||
+
|
||||
+ private Intent createFillInIntent(Uri uri, long imageTime) {
|
||||
+ Intent fillIn = new Intent();
|
||||
+ fillIn.setType("image/png");
|
||||
+ fillIn.putExtra(Intent.EXTRA_STREAM, uri);
|
||||
+ String subjectDate = DateFormat.getDateTimeInstance().format(new Date(imageTime));
|
||||
String subject = String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate);
|
||||
- sharingIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
|
||||
+ fillIn.putExtra(Intent.EXTRA_SUBJECT, subject);
|
||||
// Include URI in ClipData also, so that grantPermission picks it up.
|
||||
// We don't use setData here because some apps interpret this as "to:".
|
||||
- ClipData clipdata = new ClipData(new ClipDescription("content",
|
||||
- new String[]{"image/png"}),
|
||||
+ ClipData clipData = new ClipData(
|
||||
+ new ClipDescription("content", new String[]{"image/png"}),
|
||||
new ClipData.Item(uri));
|
||||
- sharingIntent.setClipData(clipdata);
|
||||
- sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
- PendingIntent updatedPendingIntent = PendingIntent.getActivity(
|
||||
- context, 0, sharingIntent,
|
||||
- PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
||||
-
|
||||
- // Proxy smart actions through {@link SmartActionsReceiver} for logging smart actions.
|
||||
- Bundle extras = action.getExtras();
|
||||
- String actionType = extras.getString(
|
||||
- ScreenshotNotificationSmartActionsProvider.ACTION_TYPE,
|
||||
- ScreenshotNotificationSmartActionsProvider.DEFAULT_ACTION_TYPE);
|
||||
- Intent intent = new Intent(context, SmartActionsReceiver.class)
|
||||
- .putExtra(ScreenshotController.EXTRA_ACTION_INTENT, updatedPendingIntent)
|
||||
- .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
|
||||
- // We only query for quick share actions when smart actions are enabled, so we can assert
|
||||
- // that it's true here.
|
||||
- addIntentExtras(mScreenshotId, intent, actionType, true /* smartActionsEnabled */);
|
||||
- PendingIntent broadcastIntent = PendingIntent.getBroadcast(context,
|
||||
- mRandom.nextInt(),
|
||||
- intent,
|
||||
- PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
||||
- return new Notification.Action.Builder(action.getIcon(), action.title,
|
||||
- broadcastIntent).setContextual(true).addExtras(extras).build();
|
||||
+ fillIn.setClipData(clipData);
|
||||
+ fillIn.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
+ return fillIn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query and surface Quick Share chip if it is available. Action intent would not be used,
|
||||
* because it does not contain image URL which would be populated in {@link
|
||||
- * #createQuickShareAction(Context, Notification.Action, Uri)}
|
||||
+ * #createQuickShareAction(Notification.Action, String, Uri, long, Bitmap, UserHandle)}
|
||||
*/
|
||||
- private void queryQuickShareAction(Bitmap image, UserHandle user) {
|
||||
+
|
||||
+ @VisibleForTesting
|
||||
+ Notification.Action queryQuickShareAction(
|
||||
+ String screenshotId, Bitmap image, UserHandle user, Uri uri) {
|
||||
CompletableFuture<List<Notification.Action>> quickShareActionsFuture =
|
||||
mScreenshotSmartActions.getSmartActionsFuture(
|
||||
- mScreenshotId, null, image, mSmartActionsProvider,
|
||||
- ScreenshotSmartActionType.QUICK_SHARE_ACTION,
|
||||
- true /* smartActionsEnabled */, user);
|
||||
+ screenshotId, uri, image, mSmartActionsProvider, QUICK_SHARE_ACTION,
|
||||
+ true, user);
|
||||
int timeoutMs = DeviceConfig.getInt(
|
||||
DeviceConfig.NAMESPACE_SYSTEMUI,
|
||||
SystemUiDeviceConfigFlags.SCREENSHOT_NOTIFICATION_QUICK_SHARE_ACTIONS_TIMEOUT_MS,
|
||||
500);
|
||||
List<Notification.Action> quickShareActions =
|
||||
mScreenshotSmartActions.getSmartActions(
|
||||
- mScreenshotId, quickShareActionsFuture, timeoutMs,
|
||||
- mSmartActionsProvider,
|
||||
- ScreenshotSmartActionType.QUICK_SHARE_ACTION);
|
||||
+ screenshotId, quickShareActionsFuture, timeoutMs,
|
||||
+ mSmartActionsProvider, QUICK_SHARE_ACTION);
|
||||
if (!quickShareActions.isEmpty()) {
|
||||
- mQuickShareData.quickShareAction = quickShareActions.get(0);
|
||||
- mParams.mQuickShareActionsReadyListener.onActionsReady(mQuickShareData);
|
||||
+ return quickShareActions.get(0);
|
||||
}
|
||||
+ return null;
|
||||
}
|
||||
|
||||
private String getSubjectString() {
|
||||
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
|
||||
index 2e51cefb2c4b..8b0e7ff51aa8 100644
|
||||
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
|
||||
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
|
||||
@@ -246,6 +246,7 @@ interface TransitionDestination {
|
||||
static final String EXTRA_SMART_ACTIONS_ENABLED = "android:smart_actions_enabled";
|
||||
static final String EXTRA_OVERRIDE_TRANSITION = "android:screenshot_override_transition";
|
||||
static final String EXTRA_ACTION_INTENT = "android:screenshot_action_intent";
|
||||
+ static final String EXTRA_ACTION_INTENT_FILLIN = "android:screenshot_action_intent_fillin";
|
||||
|
||||
static final String SCREENSHOT_URI_ID = "android:screenshot_uri_id";
|
||||
static final String EXTRA_CANCEL_NOTIFICATION = "android:screenshot_cancel_notification";
|
||||
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsReceiver.java b/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsReceiver.java
|
||||
index 45af1874e9db..9761f5931193 100644
|
||||
--- a/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsReceiver.java
|
||||
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsReceiver.java
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
import static com.android.systemui.screenshot.LogConfig.DEBUG_ACTIONS;
|
||||
import static com.android.systemui.screenshot.ScreenshotController.EXTRA_ACTION_INTENT;
|
||||
+import static com.android.systemui.screenshot.ScreenshotController.EXTRA_ACTION_INTENT_FILLIN;
|
||||
import static com.android.systemui.screenshot.ScreenshotController.EXTRA_ACTION_TYPE;
|
||||
import static com.android.systemui.screenshot.ScreenshotController.EXTRA_ID;
|
||||
|
||||
@@ -46,7 +47,9 @@ public class SmartActionsReceiver extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
- PendingIntent pendingIntent = intent.getParcelableExtra(EXTRA_ACTION_INTENT);
|
||||
+ PendingIntent pendingIntent =
|
||||
+ intent.getParcelableExtra(EXTRA_ACTION_INTENT, PendingIntent.class);
|
||||
+ Intent fillIn = intent.getParcelableExtra(EXTRA_ACTION_INTENT_FILLIN, Intent.class);
|
||||
String actionType = intent.getStringExtra(EXTRA_ACTION_TYPE);
|
||||
if (DEBUG_ACTIONS) {
|
||||
Log.d(TAG, "Executing smart action [" + actionType + "]:" + pendingIntent.getIntent());
|
||||
@@ -54,7 +57,7 @@ public void onReceive(Context context, Intent intent) {
|
||||
ActivityOptions opts = ActivityOptions.makeBasic();
|
||||
|
||||
try {
|
||||
- pendingIntent.send(context, 0, null, null, null, null, opts.toBundle());
|
||||
+ pendingIntent.send(context, 0, fillIn, null, null, null, opts.toBundle());
|
||||
} catch (PendingIntent.CanceledException e) {
|
||||
Log.e(TAG, "Pending intent canceled", e);
|
||||
}
|
||||
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/SaveImageInBackgroundTaskTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/SaveImageInBackgroundTaskTest.kt
|
||||
new file mode 100644
|
||||
index 000000000000..03f8c9394218
|
||||
--- /dev/null
|
||||
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/SaveImageInBackgroundTaskTest.kt
|
||||
@@ -0,0 +1,282 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2023 The Android Open Source Project
|
||||
+ *
|
||||
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
+ * you may not use this file except in compliance with the License.
|
||||
+ * You may obtain a copy of the License at
|
||||
+ *
|
||||
+ * http://www.apache.org/licenses/LICENSE-2.0
|
||||
+ *
|
||||
+ * Unless required by applicable law or agreed to in writing, software
|
||||
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
+ * See the License for the specific language governing permissions and
|
||||
+ * limitations under the License.
|
||||
+ */
|
||||
+
|
||||
+package com.android.systemui.screenshot
|
||||
+
|
||||
+import android.app.Notification
|
||||
+import android.app.PendingIntent
|
||||
+import android.content.ComponentName
|
||||
+import android.content.Intent
|
||||
+import android.graphics.Bitmap
|
||||
+import android.graphics.drawable.Icon
|
||||
+import android.net.Uri
|
||||
+import android.os.UserHandle
|
||||
+import android.testing.AndroidTestingRunner
|
||||
+import androidx.test.filters.SmallTest
|
||||
+
|
||||
+import com.android.systemui.SysuiTestCase
|
||||
+import com.android.systemui.screenshot.ScreenshotController.SaveImageInBackgroundData
|
||||
+import com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider.ScreenshotSmartActionType
|
||||
+import com.android.systemui.util.mockito.any
|
||||
+import com.android.systemui.util.mockito.eq
|
||||
+import com.android.systemui.util.mockito.mock
|
||||
+import java.util.concurrent.CompletableFuture
|
||||
+import java.util.function.Supplier
|
||||
+import org.junit.Assert.assertEquals
|
||||
+import org.junit.Assert.assertNull
|
||||
+import org.junit.Before
|
||||
+import org.junit.runner.RunWith
|
||||
+import org.junit.Test
|
||||
+import org.mockito.Mockito
|
||||
+
|
||||
+@SmallTest
|
||||
+@RunWith(AndroidTestingRunner::class)
|
||||
+class SaveImageInBackgroundTaskTest : SysuiTestCase() {
|
||||
+ private val imageExporter = mock<ImageExporter>()
|
||||
+ private val smartActions = mock<ScreenshotSmartActions>()
|
||||
+ private val saveImageData = SaveImageInBackgroundData()
|
||||
+ private val sharedTransitionSupplier =
|
||||
+ mock<Supplier<ScreenshotController.SavedImageData.ActionTransition>>()
|
||||
+ private val testScreenshotId: String = "testScreenshotId"
|
||||
+ private val testBitmap = mock<Bitmap>()
|
||||
+ private val testUser = UserHandle.getUserHandleForUid(0)
|
||||
+ private val testIcon = mock<Icon>()
|
||||
+ private val testImageTime = 1234.toLong()
|
||||
+
|
||||
+ private val smartActionsUriFuture = mock<CompletableFuture<List<Notification.Action>>>()
|
||||
+ private val smartActionsFuture = mock<CompletableFuture<List<Notification.Action>>>()
|
||||
+
|
||||
+ private val testUri: Uri = Uri.parse("testUri")
|
||||
+ private val intent =
|
||||
+ Intent(Intent.ACTION_SEND)
|
||||
+ .setComponent(
|
||||
+ ComponentName.unflattenFromString(
|
||||
+ "com.google.android.test/com.google.android.test.TestActivity"
|
||||
+ )
|
||||
+ )
|
||||
+ private val immutablePendingIntent =
|
||||
+ PendingIntent.getBroadcast(
|
||||
+ mContext,
|
||||
+ 0,
|
||||
+ intent,
|
||||
+ PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||
+ )
|
||||
+ private val mutablePendingIntent =
|
||||
+ PendingIntent.getBroadcast(
|
||||
+ mContext,
|
||||
+ 0,
|
||||
+ intent,
|
||||
+ PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_MUTABLE
|
||||
+ )
|
||||
+
|
||||
+ private val saveImageTask =
|
||||
+ SaveImageInBackgroundTask(
|
||||
+ mContext,
|
||||
+ imageExporter,
|
||||
+ smartActions,
|
||||
+ saveImageData,
|
||||
+ sharedTransitionSupplier,
|
||||
+ )
|
||||
+
|
||||
+ @Before
|
||||
+ fun setup() {
|
||||
+ Mockito.`when`(
|
||||
+ smartActions.getSmartActionsFuture(
|
||||
+ eq(testScreenshotId),
|
||||
+ any(Uri::class.java),
|
||||
+ eq(testBitmap),
|
||||
+ any(ScreenshotNotificationSmartActionsProvider::class.java),
|
||||
+ any(ScreenshotSmartActionType::class.java),
|
||||
+ any(Boolean::class.java),
|
||||
+ eq(testUser)
|
||||
+ )
|
||||
+ )
|
||||
+ .thenReturn(smartActionsUriFuture)
|
||||
+ Mockito.`when`(
|
||||
+ smartActions.getSmartActionsFuture(
|
||||
+ eq(testScreenshotId),
|
||||
+ eq(null),
|
||||
+ eq(testBitmap),
|
||||
+ any(ScreenshotNotificationSmartActionsProvider::class.java),
|
||||
+ any(ScreenshotSmartActionType::class.java),
|
||||
+ any(Boolean::class.java),
|
||||
+ eq(testUser)
|
||||
+ )
|
||||
+ )
|
||||
+ .thenReturn(smartActionsFuture)
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ fun testQueryQuickShare_noAction() {
|
||||
+ Mockito.`when`(
|
||||
+ smartActions.getSmartActions(
|
||||
+ eq(testScreenshotId),
|
||||
+ eq(smartActionsFuture),
|
||||
+ any(Int::class.java),
|
||||
+ any(ScreenshotNotificationSmartActionsProvider::class.java),
|
||||
+ eq(ScreenshotSmartActionType.QUICK_SHARE_ACTION)
|
||||
+ )
|
||||
+ )
|
||||
+ .thenReturn(ArrayList<Notification.Action>())
|
||||
+
|
||||
+ val quickShareAction =
|
||||
+ saveImageTask.queryQuickShareAction(testScreenshotId, testBitmap, testUser, testUri)
|
||||
+
|
||||
+ assertNull(quickShareAction)
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ fun testQueryQuickShare_withActions() {
|
||||
+ val actions = ArrayList<Notification.Action>()
|
||||
+ actions.add(constructAction("Action One", mutablePendingIntent))
|
||||
+ actions.add(constructAction("Action Two", mutablePendingIntent))
|
||||
+ Mockito.`when`(
|
||||
+ smartActions.getSmartActions(
|
||||
+ eq(testScreenshotId),
|
||||
+ eq(smartActionsUriFuture),
|
||||
+ any(Int::class.java),
|
||||
+ any(ScreenshotNotificationSmartActionsProvider::class.java),
|
||||
+ eq(ScreenshotSmartActionType.QUICK_SHARE_ACTION)
|
||||
+ )
|
||||
+ )
|
||||
+ .thenReturn(actions)
|
||||
+
|
||||
+ val quickShareAction =
|
||||
+ saveImageTask.queryQuickShareAction(testScreenshotId, testBitmap, testUser, testUri)!!
|
||||
+
|
||||
+ assertEquals("Action One", quickShareAction.title)
|
||||
+ assertEquals(mutablePendingIntent, quickShareAction.actionIntent)
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ fun testCreateQuickShareAction_originalWasNull_returnsNull() {
|
||||
+ val quickShareAction =
|
||||
+ saveImageTask.createQuickShareAction(
|
||||
+ null,
|
||||
+ testScreenshotId,
|
||||
+ testUri,
|
||||
+ testImageTime,
|
||||
+ testBitmap,
|
||||
+ testUser
|
||||
+ )
|
||||
+
|
||||
+ assertNull(quickShareAction)
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ fun testCreateQuickShareAction_immutableIntentDifferentAction_returnsNull() {
|
||||
+ val actions = ArrayList<Notification.Action>()
|
||||
+ actions.add(constructAction("New Test Action", immutablePendingIntent))
|
||||
+ Mockito.`when`(
|
||||
+ smartActions.getSmartActions(
|
||||
+ eq(testScreenshotId),
|
||||
+ eq(smartActionsUriFuture),
|
||||
+ any(Int::class.java),
|
||||
+ any(ScreenshotNotificationSmartActionsProvider::class.java),
|
||||
+ eq(ScreenshotSmartActionType.QUICK_SHARE_ACTION)
|
||||
+ )
|
||||
+ )
|
||||
+ .thenReturn(actions)
|
||||
+ val origAction = constructAction("Old Test Action", immutablePendingIntent)
|
||||
+
|
||||
+ val quickShareAction =
|
||||
+ saveImageTask.createQuickShareAction(
|
||||
+ origAction,
|
||||
+ testScreenshotId,
|
||||
+ testUri,
|
||||
+ testImageTime,
|
||||
+ testBitmap,
|
||||
+ testUser,
|
||||
+ )
|
||||
+
|
||||
+ assertNull(quickShareAction)
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ fun testCreateQuickShareAction_mutableIntent_returnsSafeIntent() {
|
||||
+ val actions = ArrayList<Notification.Action>()
|
||||
+ val action = constructAction("Action One", mutablePendingIntent)
|
||||
+ actions.add(action)
|
||||
+ Mockito.`when`(
|
||||
+ smartActions.getSmartActions(
|
||||
+ eq(testScreenshotId),
|
||||
+ eq(smartActionsUriFuture),
|
||||
+ any(Int::class.java),
|
||||
+ any(ScreenshotNotificationSmartActionsProvider::class.java),
|
||||
+ eq(ScreenshotSmartActionType.QUICK_SHARE_ACTION)
|
||||
+ )
|
||||
+ )
|
||||
+ .thenReturn(actions)
|
||||
+
|
||||
+ val quickShareAction =
|
||||
+ saveImageTask.createQuickShareAction(
|
||||
+ constructAction("Test Action", mutablePendingIntent),
|
||||
+ testScreenshotId,
|
||||
+ testUri,
|
||||
+ testImageTime,
|
||||
+ testBitmap,
|
||||
+ testUser
|
||||
+ )
|
||||
+ val quickSharePendingIntent =
|
||||
+ quickShareAction.actionIntent.intent.extras!!.getParcelable(
|
||||
+ ScreenshotController.EXTRA_ACTION_INTENT,
|
||||
+ PendingIntent::class.java
|
||||
+ )
|
||||
+
|
||||
+ assertEquals("Test Action", quickShareAction.title)
|
||||
+ assertEquals(mutablePendingIntent, quickSharePendingIntent)
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ fun testCreateQuickShareAction_immutableIntent_returnsSafeIntent() {
|
||||
+ val actions = ArrayList<Notification.Action>()
|
||||
+ val action = constructAction("Test Action", immutablePendingIntent)
|
||||
+ actions.add(action)
|
||||
+ Mockito.`when`(
|
||||
+ smartActions.getSmartActions(
|
||||
+ eq(testScreenshotId),
|
||||
+ eq(smartActionsUriFuture),
|
||||
+ any(Int::class.java),
|
||||
+ any(ScreenshotNotificationSmartActionsProvider::class.java),
|
||||
+ eq(ScreenshotSmartActionType.QUICK_SHARE_ACTION)
|
||||
+ )
|
||||
+ )
|
||||
+ .thenReturn(actions)
|
||||
+
|
||||
+ val quickShareAction =
|
||||
+ saveImageTask.createQuickShareAction(
|
||||
+ constructAction("Test Action", immutablePendingIntent),
|
||||
+ testScreenshotId,
|
||||
+ testUri,
|
||||
+ testImageTime,
|
||||
+ testBitmap,
|
||||
+ testUser,
|
||||
+ )!!
|
||||
+
|
||||
+ assertEquals("Test Action", quickShareAction.title)
|
||||
+ assertEquals(
|
||||
+ immutablePendingIntent,
|
||||
+ quickShareAction.actionIntent.intent.extras!!.getParcelable(
|
||||
+ ScreenshotController.EXTRA_ACTION_INTENT,
|
||||
+ PendingIntent::class.java
|
||||
+ )
|
||||
+ )
|
||||
+ }
|
||||
+
|
||||
+ private fun constructAction(title: String, intent: PendingIntent): Notification.Action {
|
||||
+ return Notification.Action.Builder(testIcon, title, intent).build()
|
||||
+ }
|
||||
+}
|
@ -1,30 +0,0 @@
|
||||
From 44191b1c6b55d9e09d8b5fca96176035abc18c31 Mon Sep 17 00:00:00 2001
|
||||
From: Dmitry Dementyev <dementyev@google.com>
|
||||
Date: Wed, 5 Jul 2023 10:45:04 -0700
|
||||
Subject: [PATCH] Update AccountManagerService checkKeyIntentParceledCorrectly.
|
||||
|
||||
Bug: 265798288
|
||||
Test: manual
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:8476b140eed0235df4e8f07d94420a1471191b55)
|
||||
Merged-In: Ia2030a9dc371dccadd4e188a529351ac4232bb4f
|
||||
Change-Id: Ia2030a9dc371dccadd4e188a529351ac4232bb4f
|
||||
---
|
||||
.../com/android/server/accounts/AccountManagerService.java | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
|
||||
index 1dc0942ceac5..7a51f5155a98 100644
|
||||
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
|
||||
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
|
||||
@@ -4932,7 +4932,10 @@ private boolean checkKeyIntentParceledCorrectly(Bundle bundle) {
|
||||
p.setDataPosition(0);
|
||||
Bundle simulateBundle = p.readBundle();
|
||||
p.recycle();
|
||||
- Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT, Intent.class);
|
||||
+ Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT);
|
||||
+ if (intent != null && intent.getClass() != Intent.class) {
|
||||
+ return false;
|
||||
+ }
|
||||
Intent simulateIntent = simulateBundle.getParcelable(AccountManager.KEY_INTENT,
|
||||
Intent.class);
|
||||
if (intent == null) {
|
@ -1,216 +0,0 @@
|
||||
From 8dc8dfe572ce5e4bcb64418275b6d8c4e05284ac Mon Sep 17 00:00:00 2001
|
||||
From: Beth Thibodeau <ethibodeau@google.com>
|
||||
Date: Thu, 22 Jun 2023 18:26:44 -0500
|
||||
Subject: [PATCH] Improve user handling when querying for resumable media
|
||||
|
||||
- Before trying to query recent media from a saved component, check
|
||||
whether the current user actually has that component installed
|
||||
- Track user when creating the MediaBrowser, in case the user changes
|
||||
before the MBS returns a result
|
||||
|
||||
Test: atest MediaResumeListenerTest
|
||||
Bug: 284297711
|
||||
(cherry picked from commit e566a250ad61e269119b475c7ebdae6ca962c4a7)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:d61741288b4d7614e4677428aac6418f6f1d79f0)
|
||||
Merged-In: I838ff0e125acadabc8436a00dbff707cc4be6249
|
||||
Change-Id: I838ff0e125acadabc8436a00dbff707cc4be6249
|
||||
---
|
||||
.../controls/resume/MediaResumeListener.kt | 54 ++++++++++++-------
|
||||
.../controls/resume/ResumeMediaBrowser.java | 15 +++++-
|
||||
.../resume/ResumeMediaBrowserFactory.java | 7 ++-
|
||||
3 files changed, 55 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt b/packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt
|
||||
index b0389b50cd7d..813ca17422ec 100644
|
||||
--- a/packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt
|
||||
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt
|
||||
@@ -122,18 +122,18 @@ constructor(
|
||||
Log.e(TAG, "Error getting package information", e)
|
||||
}
|
||||
|
||||
- Log.d(TAG, "Adding resume controls $desc")
|
||||
- mediaDataManager.addResumptionControls(
|
||||
- currentUserId,
|
||||
- desc,
|
||||
- resumeAction,
|
||||
- token,
|
||||
- appName.toString(),
|
||||
- appIntent,
|
||||
- component.packageName
|
||||
- )
|
||||
- }
|
||||
+ Log.d(TAG, "Adding resume controls for ${browser.userId}: $desc")
|
||||
+ mediaDataManager.addResumptionControls(
|
||||
+ browser.userId,
|
||||
+ desc,
|
||||
+ resumeAction,
|
||||
+ token,
|
||||
+ appName.toString(),
|
||||
+ appIntent,
|
||||
+ component.packageName
|
||||
+ )
|
||||
}
|
||||
+ }
|
||||
|
||||
init {
|
||||
if (useMediaResumption) {
|
||||
@@ -196,7 +196,11 @@ constructor(
|
||||
}
|
||||
resumeComponents.add(component to lastPlayed)
|
||||
}
|
||||
- Log.d(TAG, "loaded resume components ${resumeComponents.toArray().contentToString()}")
|
||||
+ Log.d(
|
||||
+ TAG,
|
||||
+ "loaded resume components for $currentUserId: " +
|
||||
+ "${resumeComponents.toArray().contentToString()}"
|
||||
+ )
|
||||
|
||||
if (needsUpdate) {
|
||||
// Save any missing times that we had to fill in
|
||||
@@ -210,11 +214,21 @@ constructor(
|
||||
return
|
||||
}
|
||||
|
||||
+ val pm = context.packageManager
|
||||
val now = systemClock.currentTimeMillis()
|
||||
resumeComponents.forEach {
|
||||
if (now.minus(it.second) <= RESUME_MEDIA_TIMEOUT) {
|
||||
- val browser = mediaBrowserFactory.create(mediaBrowserCallback, it.first)
|
||||
- browser.findRecentMedia()
|
||||
+ // Verify that the service exists for this user
|
||||
+ val intent = Intent(MediaBrowserService.SERVICE_INTERFACE)
|
||||
+ intent.component = it.first
|
||||
+ val inf = pm.resolveServiceAsUser(intent, 0, currentUserId)
|
||||
+ if (inf != null) {
|
||||
+ val browser =
|
||||
+ mediaBrowserFactory.create(mediaBrowserCallback, it.first, currentUserId)
|
||||
+ browser.findRecentMedia()
|
||||
+ } else {
|
||||
+ Log.d(TAG, "User $currentUserId does not have component ${it.first}")
|
||||
+ }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -244,7 +258,7 @@ constructor(
|
||||
Log.d(TAG, "Checking for service component for " + data.packageName)
|
||||
val pm = context.packageManager
|
||||
val serviceIntent = Intent(MediaBrowserService.SERVICE_INTERFACE)
|
||||
- val resumeInfo = pm.queryIntentServices(serviceIntent, 0)
|
||||
+ val resumeInfo = pm.queryIntentServicesAsUser(serviceIntent, 0, currentUserId)
|
||||
|
||||
val inf = resumeInfo?.filter { it.serviceInfo.packageName == data.packageName }
|
||||
if (inf != null && inf.size > 0) {
|
||||
@@ -280,13 +294,17 @@ constructor(
|
||||
browser: ResumeMediaBrowser
|
||||
) {
|
||||
// Since this is a test, just save the component for later
|
||||
- Log.d(TAG, "Can get resumable media from $componentName")
|
||||
+ Log.d(
|
||||
+ TAG,
|
||||
+ "Can get resumable media for ${browser.userId} from $componentName"
|
||||
+ )
|
||||
mediaDataManager.setResumeAction(key, getResumeAction(componentName))
|
||||
updateResumptionList(componentName)
|
||||
mediaBrowser = null
|
||||
}
|
||||
},
|
||||
- componentName
|
||||
+ componentName,
|
||||
+ currentUserId
|
||||
)
|
||||
mediaBrowser?.testConnection()
|
||||
}
|
||||
@@ -326,7 +344,7 @@ constructor(
|
||||
/** Get a runnable which will resume media playback */
|
||||
private fun getResumeAction(componentName: ComponentName): Runnable {
|
||||
return Runnable {
|
||||
- mediaBrowser = mediaBrowserFactory.create(null, componentName)
|
||||
+ mediaBrowser = mediaBrowserFactory.create(null, componentName, currentUserId)
|
||||
mediaBrowser?.restart()
|
||||
}
|
||||
}
|
||||
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowser.java b/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowser.java
|
||||
index d460b5b5d782..ceaccafd8f40 100644
|
||||
--- a/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowser.java
|
||||
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowser.java
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.systemui.media.controls.resume;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
+import android.annotation.UserIdInt;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
@@ -53,6 +54,7 @@ public class ResumeMediaBrowser {
|
||||
private final ResumeMediaBrowserLogger mLogger;
|
||||
private final ComponentName mComponentName;
|
||||
private final MediaController.Callback mMediaControllerCallback = new SessionDestroyCallback();
|
||||
+ @UserIdInt private final int mUserId;
|
||||
|
||||
private MediaBrowser mMediaBrowser;
|
||||
@Nullable private MediaController mMediaController;
|
||||
@@ -62,18 +64,21 @@ public class ResumeMediaBrowser {
|
||||
* @param context the context
|
||||
* @param callback used to report media items found
|
||||
* @param componentName Component name of the MediaBrowserService this browser will connect to
|
||||
+ * @param userId ID of the current user
|
||||
*/
|
||||
public ResumeMediaBrowser(
|
||||
Context context,
|
||||
@Nullable Callback callback,
|
||||
ComponentName componentName,
|
||||
MediaBrowserFactory browserFactory,
|
||||
- ResumeMediaBrowserLogger logger) {
|
||||
+ ResumeMediaBrowserLogger logger,
|
||||
+ @UserIdInt int userId) {
|
||||
mContext = context;
|
||||
mCallback = callback;
|
||||
mComponentName = componentName;
|
||||
mBrowserFactory = browserFactory;
|
||||
mLogger = logger;
|
||||
+ mUserId = userId;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -284,6 +289,14 @@ protected MediaController createMediaController(MediaSession.Token token) {
|
||||
return new MediaController(mContext, token);
|
||||
}
|
||||
|
||||
+ /**
|
||||
+ * Get the ID of the user associated with this broswer
|
||||
+ * @return the user ID
|
||||
+ */
|
||||
+ public @UserIdInt int getUserId() {
|
||||
+ return mUserId;
|
||||
+ }
|
||||
+
|
||||
/**
|
||||
* Get the media session token
|
||||
* @return the token, or null if the MediaBrowser is null or disconnected
|
||||
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserFactory.java b/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserFactory.java
|
||||
index c558227df0b5..e37419127f5b 100644
|
||||
--- a/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserFactory.java
|
||||
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserFactory.java
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.systemui.media.controls.resume;
|
||||
|
||||
+import android.annotation.UserIdInt;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
|
||||
@@ -42,10 +43,12 @@ public ResumeMediaBrowserFactory(
|
||||
*
|
||||
* @param callback will be called on connection or error, and addTrack when media item found
|
||||
* @param componentName component to browse
|
||||
+ * @param userId ID of the current user
|
||||
* @return
|
||||
*/
|
||||
public ResumeMediaBrowser create(ResumeMediaBrowser.Callback callback,
|
||||
- ComponentName componentName) {
|
||||
- return new ResumeMediaBrowser(mContext, callback, componentName, mBrowserFactory, mLogger);
|
||||
+ ComponentName componentName, @UserIdInt int userId) {
|
||||
+ return new ResumeMediaBrowser(mContext, callback, componentName, mBrowserFactory, mLogger,
|
||||
+ userId);
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
From dfeb4270b8ecad08bc5361f122af9453881a5987 Mon Sep 17 00:00:00 2001
|
||||
From: Pinyao Ting <pinyaoting@google.com>
|
||||
Date: Thu, 1 Jun 2023 18:12:44 -0700
|
||||
Subject: [PATCH] Fix permission issue in legacy shortcut
|
||||
|
||||
When building legacy shortcut, Launcher calls
|
||||
PackageManager#resolveActivity to retrieve necessary permission to
|
||||
launch the intent.
|
||||
|
||||
However, when the source app wraps an arbitrary intent within
|
||||
Intent#createChooser, the existing logic will fail because launching
|
||||
Chooser doesn't require additional permission.
|
||||
|
||||
This CL fixes the security vulnerability by performing the permission
|
||||
check against the intent that is wrapped within.
|
||||
|
||||
Bug: 270152142
|
||||
Test: manual
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:c53818a16b4322a823497726ac7e7a44501b4442)
|
||||
Merged-In: If35344c08975e35085c7c2b9b814a3c457a144b0
|
||||
Change-Id: If35344c08975e35085c7c2b9b814a3c457a144b0
|
||||
---
|
||||
.../android/launcher3/util/PackageManagerHelper.java | 12 ++++++++++++
|
||||
1 file changed, 12 insertions(+)
|
||||
|
||||
diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java
|
||||
index a6a2751dc7..586e0c9e89 100644
|
||||
--- a/src/com/android/launcher3/util/PackageManagerHelper.java
|
||||
+++ b/src/com/android/launcher3/util/PackageManagerHelper.java
|
||||
@@ -145,6 +145,18 @@ public static boolean isAppSuspended(ApplicationInfo info) {
|
||||
* any permissions
|
||||
*/
|
||||
public boolean hasPermissionForActivity(Intent intent, String srcPackage) {
|
||||
+ // b/270152142
|
||||
+ if (Intent.ACTION_CHOOSER.equals(intent.getAction())) {
|
||||
+ final Bundle extras = intent.getExtras();
|
||||
+ if (extras == null) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ // If given intent is ACTION_CHOOSER, verify srcPackage has permission over EXTRA_INTENT
|
||||
+ intent = (Intent) extras.getParcelable(Intent.EXTRA_INTENT);
|
||||
+ if (intent == null) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
ResolveInfo target = mPm.resolveActivity(intent, 0);
|
||||
if (target == null) {
|
||||
// Not a valid target
|
@ -1,98 +0,0 @@
|
||||
From c16e6e78c1c8ba40f8c2ff6a4d87afe44590eb7f Mon Sep 17 00:00:00 2001
|
||||
From: Krishang Garodia <krishang@google.com>
|
||||
Date: Mon, 19 Jun 2023 11:43:45 +0000
|
||||
Subject: [PATCH] Remove invalid surrogates during bindSelection
|
||||
|
||||
Test: atest MediaProviderTests
|
||||
Bug: 223793631
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:108f736d0ec6e974c3f947e7e568845b7e039a0a)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:a48b01f78f28fc642b144c673bfcd12ae78c5a73)
|
||||
Merged-In: I18b879f1a51394b4739225ec88b862fd6d0d5526
|
||||
Change-Id: I18b879f1a51394b4739225ec88b862fd6d0d5526
|
||||
---
|
||||
.../providers/media/util/DatabaseUtils.java | 36 +++++++++++++++++--
|
||||
.../media/util/DatabaseUtilsTest.java | 10 ++++++
|
||||
2 files changed, 44 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/com/android/providers/media/util/DatabaseUtils.java b/src/com/android/providers/media/util/DatabaseUtils.java
|
||||
index 55efafc7f..53ecf964e 100644
|
||||
--- a/src/com/android/providers/media/util/DatabaseUtils.java
|
||||
+++ b/src/com/android/providers/media/util/DatabaseUtils.java
|
||||
@@ -127,8 +127,9 @@ public class DatabaseUtils {
|
||||
res.append(((Boolean) arg).booleanValue() ? 1 : 0);
|
||||
} else {
|
||||
res.append('\'');
|
||||
- // Escape single quote character while appending the string.
|
||||
- res.append(arg.toString().replace("'", "''"));
|
||||
+ // Escape single quote character while appending the string and reject
|
||||
+ // invalid unicode.
|
||||
+ res.append(escapeSingleQuoteAndRejectInvalidUnicode(arg.toString()));
|
||||
res.append('\'');
|
||||
}
|
||||
break;
|
||||
@@ -142,6 +143,37 @@ public class DatabaseUtils {
|
||||
return res.toString();
|
||||
}
|
||||
|
||||
+ private static String escapeSingleQuoteAndRejectInvalidUnicode(@NonNull String target) {
|
||||
+ final int len = target.length();
|
||||
+ final StringBuilder res = new StringBuilder(len);
|
||||
+ boolean lastHigh = false;
|
||||
+
|
||||
+ for (int i = 0; i < len; ) {
|
||||
+ final char c = target.charAt(i++);
|
||||
+
|
||||
+ if (lastHigh != Character.isLowSurrogate(c)) {
|
||||
+ Log.e(TAG, "Invalid surrogate in string " + target);
|
||||
+ throw new IllegalArgumentException("Invalid surrogate in string " + target);
|
||||
+ }
|
||||
+
|
||||
+ lastHigh = Character.isHighSurrogate(c);
|
||||
+
|
||||
+ // Escape the single quotes by duplicating them
|
||||
+ if (c == '\'') {
|
||||
+ res.append(c);
|
||||
+ }
|
||||
+
|
||||
+ res.append(c);
|
||||
+ }
|
||||
+
|
||||
+ if (lastHigh) {
|
||||
+ Log.e(TAG, "Invalid surrogate in string " + target);
|
||||
+ throw new IllegalArgumentException("Invalid surrogate in string " + target);
|
||||
+ }
|
||||
+
|
||||
+ return res.toString();
|
||||
+ }
|
||||
+
|
||||
/**
|
||||
* Returns data type of the given object's value.
|
||||
*<p>
|
||||
diff --git a/tests/src/com/android/providers/media/util/DatabaseUtilsTest.java b/tests/src/com/android/providers/media/util/DatabaseUtilsTest.java
|
||||
index 685d89704..a90787589 100644
|
||||
--- a/tests/src/com/android/providers/media/util/DatabaseUtilsTest.java
|
||||
+++ b/tests/src/com/android/providers/media/util/DatabaseUtilsTest.java
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
+import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
@@ -126,6 +127,15 @@ public void testBindSelection_singleQuoteCharacter() throws Exception {
|
||||
bindSelection("DATA=?", "Fo''o"));
|
||||
}
|
||||
|
||||
+ @Test
|
||||
+ public void testBindSelection_RejectInvalidUnicode() {
|
||||
+ assertThrows(IllegalArgumentException.class, () -> bindSelection("DATA=?", "Fo\uD83Do"));
|
||||
+ assertThrows(IllegalArgumentException.class, () -> bindSelection("DATA=?", "Fo\uDE00o"));
|
||||
+ assertEquals("DATA='Fo\uD83D\uDE00o'", bindSelection("DATA=?", "Fo\uD83D\uDE00o"));
|
||||
+ assertThrows(
|
||||
+ IllegalArgumentException.class, () -> bindSelection("DATA=?", "Fo\uDE00\uD83Do"));
|
||||
+ }
|
||||
+
|
||||
@Test
|
||||
public void testResolveQueryArgs_GroupBy() throws Exception {
|
||||
args.putStringArray(QUERY_ARG_GROUP_COLUMNS, new String[] { "foo", "bar" });
|
@ -1,41 +0,0 @@
|
||||
From d5771450d7b2acde9fa051dedbb6c115b001d48b Mon Sep 17 00:00:00 2001
|
||||
From: Dipankar Bhardwaj <dipankarb@google.com>
|
||||
Date: Thu, 6 Jul 2023 10:01:20 +0000
|
||||
Subject: [PATCH] Canonicalize file path for insertion by legacy apps
|
||||
|
||||
Apps with legacy external storage can try to create entries in MP for
|
||||
file paths in other apps external private directories by using a
|
||||
non-canonical path in insertion calls.
|
||||
|
||||
Test: atest LegacyStorageHostTest#testInsertToOtherAppPrivateDirFails
|
||||
Bug: 276898626
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:3c0f583f5dc3f4d395fa2423ab72dbd902c0c6c8)
|
||||
Merged-In: If4c941c8156f19459b3ec6cbaf705824ecc2ba77
|
||||
Change-Id: If4c941c8156f19459b3ec6cbaf705824ecc2ba77
|
||||
---
|
||||
src/com/android/providers/media/util/FileUtils.java | 10 +++++++++-
|
||||
1 file changed, 9 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/com/android/providers/media/util/FileUtils.java b/src/com/android/providers/media/util/FileUtils.java
|
||||
index 2e2a3e761..097eca8c9 100644
|
||||
--- a/src/com/android/providers/media/util/FileUtils.java
|
||||
+++ b/src/com/android/providers/media/util/FileUtils.java
|
||||
@@ -1324,9 +1324,17 @@ public static void computeValuesFromData(@NonNull ContentValues values, boolean
|
||||
values.remove(MediaColumns.BUCKET_ID);
|
||||
values.remove(MediaColumns.BUCKET_DISPLAY_NAME);
|
||||
|
||||
- final String data = values.getAsString(MediaColumns.DATA);
|
||||
+ String data = values.getAsString(MediaColumns.DATA);
|
||||
if (TextUtils.isEmpty(data)) return;
|
||||
|
||||
+ try {
|
||||
+ data = new File(data).getCanonicalPath();
|
||||
+ values.put(MediaColumns.DATA, data);
|
||||
+ } catch (IOException e) {
|
||||
+ throw new IllegalArgumentException(
|
||||
+ String.format(Locale.ROOT, "Invalid file path:%s in request.", data));
|
||||
+ }
|
||||
+
|
||||
final File file = new File(data);
|
||||
final File fileLower = new File(data.toLowerCase(Locale.ROOT));
|
||||
|
@ -1,34 +0,0 @@
|
||||
From b1993f6cec45bc638ea1d2875c91d069e89ca57e Mon Sep 17 00:00:00 2001
|
||||
From: Devin Moore <devinmoore@google.com>
|
||||
Date: Tue, 25 Apr 2023 00:17:13 +0000
|
||||
Subject: [PATCH] Allow sensors list to be empty
|
||||
|
||||
Test: atest VtsHalSensorManagerV1_0TargetTest
|
||||
Bug: 278013275
|
||||
Bug: 269014004
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:49600b10aa5675d4e7e985203d69f252ead13e45)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:d9e0d0ad7cb94b2b2d83066685cee45d76381355)
|
||||
Merged-In: I091f57de9570b0ace3a8da76f16fe0e83f0aa624
|
||||
Change-Id: I091f57de9570b0ace3a8da76f16fe0e83f0aa624
|
||||
---
|
||||
libs/sensor/SensorManager.cpp | 7 ++-----
|
||||
1 file changed, 2 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/libs/sensor/SensorManager.cpp b/libs/sensor/SensorManager.cpp
|
||||
index 40061cde61..9f814f1c48 100644
|
||||
--- a/libs/sensor/SensorManager.cpp
|
||||
+++ b/libs/sensor/SensorManager.cpp
|
||||
@@ -176,11 +176,8 @@ status_t SensorManager::assertStateLocked() {
|
||||
|
||||
mSensors = mSensorServer->getSensorList(mOpPackageName);
|
||||
size_t count = mSensors.size();
|
||||
- if (count == 0) {
|
||||
- ALOGE("Failed to get Sensor list");
|
||||
- mSensorServer.clear();
|
||||
- return UNKNOWN_ERROR;
|
||||
- }
|
||||
+ // If count is 0, mSensorList will be non-null. This is old
|
||||
+ // existing behavior and callers expect this.
|
||||
mSensorList =
|
||||
static_cast<Sensor const**>(malloc(count * sizeof(Sensor*)));
|
||||
LOG_ALWAYS_FATAL_IF(mSensorList == nullptr, "mSensorList NULL");
|
@ -1,47 +0,0 @@
|
||||
From 27e7cdc4e5748e2ad85552433cf9c120fd7a936b Mon Sep 17 00:00:00 2001
|
||||
From: Alisher Alikhodjaev <alisher@google.com>
|
||||
Date: Wed, 10 May 2023 18:27:42 -0700
|
||||
Subject: [PATCH] Ensure that SecureNFC setting cannot be bypassed
|
||||
|
||||
Bug: 268038643
|
||||
Test: ctsverifier
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:6cb53d963d376b97963120a4d2c7df961789e428)
|
||||
Merged-In: I53a45c3600dc6bba7009921ca5135ee37b5edfd0
|
||||
Change-Id: I53a45c3600dc6bba7009921ca5135ee37b5edfd0
|
||||
---
|
||||
src/com/android/nfc/NfcService.java | 6 ++++++
|
||||
src/com/android/nfc/cardemulation/HostEmulationManager.java | 4 +++-
|
||||
2 files changed, 9 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java
|
||||
index a1b28e97..2305922a 100644
|
||||
--- a/src/com/android/nfc/NfcService.java
|
||||
+++ b/src/com/android/nfc/NfcService.java
|
||||
@@ -1166,6 +1166,12 @@ void enforceBeamShareActivityPolicy(Context context, UserHandle uh) {
|
||||
}
|
||||
}
|
||||
|
||||
+ public boolean isSecureNfcEnabled() {
|
||||
+ synchronized (NfcService.this) {
|
||||
+ return mIsSecureNfcEnabled;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
final class NfcAdapterService extends INfcAdapter.Stub {
|
||||
@Override
|
||||
public boolean enable() throws RemoteException {
|
||||
diff --git a/src/com/android/nfc/cardemulation/HostEmulationManager.java b/src/com/android/nfc/cardemulation/HostEmulationManager.java
|
||||
index 81462024..8849cca5 100644
|
||||
--- a/src/com/android/nfc/cardemulation/HostEmulationManager.java
|
||||
+++ b/src/com/android/nfc/cardemulation/HostEmulationManager.java
|
||||
@@ -188,7 +188,9 @@ public void onHostEmulationData(byte[] data) {
|
||||
// Resolve to default
|
||||
// Check if resolvedService requires unlock
|
||||
ApduServiceInfo defaultServiceInfo = resolveInfo.defaultService;
|
||||
- if (defaultServiceInfo.requiresUnlock() && mKeyguard.isKeyguardLocked()) {
|
||||
+ if ((defaultServiceInfo.requiresUnlock()
|
||||
+ || NfcService.getInstance().isSecureNfcEnabled())
|
||||
+ && mKeyguard.isKeyguardLocked()) {
|
||||
NfcService.getInstance().sendRequireUnlockIntent();
|
||||
NfcService.getInstance().sendData(AID_NOT_FOUND);
|
||||
if (DBG) Log.d(TAG, "requiresUnlock()! show toast");
|
@ -1,31 +0,0 @@
|
||||
From a1370bd00c106e4d172dc68638778fa111f6ecbe Mon Sep 17 00:00:00 2001
|
||||
From: Ian Hua <ianhua@google.com>
|
||||
Date: Thu, 6 Jul 2023 10:05:36 +0000
|
||||
Subject: [PATCH] Fix out of Bounds Read in convertSubgraphFromHAL in
|
||||
ShimConverter.cpp in libneuralnetworks_shim_static
|
||||
|
||||
Bug: 269270167
|
||||
Test: N/A
|
||||
(cherry picked from commit 4bf7bb6b50b412678a681d29f7ced70a4d737762)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:244ac21307a785d49930d4c7e289b74856fa9647)
|
||||
Merged-In: I33272284b965efcbb531f64cbf838a0d59c28e00
|
||||
Change-Id: I33272284b965efcbb531f64cbf838a0d59c28e00
|
||||
---
|
||||
shim_and_sl/ShimConverter.cpp | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/shim_and_sl/ShimConverter.cpp b/shim_and_sl/ShimConverter.cpp
|
||||
index 1ed0e31cf..4830c5d05 100644
|
||||
--- a/shim_and_sl/ShimConverter.cpp
|
||||
+++ b/shim_and_sl/ShimConverter.cpp
|
||||
@@ -150,6 +150,10 @@ ANeuralNetworksModel* convertSubgraphFromHAL(
|
||||
break;
|
||||
}
|
||||
case OperandLifeTime::CONSTANT_POOL: {
|
||||
+ if (operand.location.poolIndex >= memoryPools.size()) {
|
||||
+ *errorStatus = ErrorStatus::INVALID_ARGUMENT;
|
||||
+ return nullptr;
|
||||
+ }
|
||||
resultModel.setOperandValueFromMemory(
|
||||
i, memoryPools[operand.location.poolIndex].get(), operand.location.offset,
|
||||
operand.location.length);
|
@ -1,262 +0,0 @@
|
||||
From 21623d1f437beb59ceee1fc88cd07d48e3f6a13e Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Mat=C3=ADas=20Hern=C3=A1ndez?= <matiashe@google.com>
|
||||
Date: Mon, 5 Jun 2023 18:24:04 +0200
|
||||
Subject: [PATCH] Don't hide approved NLSes in Settings
|
||||
|
||||
Note that an NLS that shouldn't be approvable (because its name is too long) but was already approved (either before the max length check was introduced, or through other means) will disappear from the list if the user revokes its access. This might be somewhat confusing, but since this is a very-edge case already it's fine.
|
||||
|
||||
Bug: 282932362
|
||||
Test: manual
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:ff255c6eda1528f01a167a9a65b7f8e414d28584)
|
||||
Merged-In: I4c9faea68e6d16b1a4ec7f472b5433cac1704c06
|
||||
Change-Id: I4c9faea68e6d16b1a4ec7f472b5433cac1704c06
|
||||
---
|
||||
.../NotificationAccessSettings.java | 25 +--
|
||||
.../notification/NotificationBackend.java | 3 +
|
||||
.../NotificationAccessSettingsTest.java | 144 ++++++++++++++++++
|
||||
3 files changed, 160 insertions(+), 12 deletions(-)
|
||||
create mode 100644 tests/robotests/src/com/android/settings/notification/NotificationAccessSettingsTest.java
|
||||
|
||||
diff --git a/src/com/android/settings/notification/NotificationAccessSettings.java b/src/com/android/settings/notification/NotificationAccessSettings.java
|
||||
index 56d3f0e445..369c4f6dfa 100644
|
||||
--- a/src/com/android/settings/notification/NotificationAccessSettings.java
|
||||
+++ b/src/com/android/settings/notification/NotificationAccessSettings.java
|
||||
@@ -43,6 +43,7 @@
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
+import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.applications.AppInfoBase;
|
||||
@@ -63,8 +64,8 @@
|
||||
@SearchIndexable
|
||||
public class NotificationAccessSettings extends EmptyTextSettings {
|
||||
private static final String TAG = "NotifAccessSettings";
|
||||
- private static final String ALLOWED_KEY = "allowed";
|
||||
- private static final String NOT_ALLOWED_KEY = "not_allowed";
|
||||
+ static final String ALLOWED_KEY = "allowed";
|
||||
+ static final String NOT_ALLOWED_KEY = "not_allowed";
|
||||
private static final int MAX_CN_LENGTH = 500;
|
||||
|
||||
private static final ManagedServiceSettings.Config CONFIG =
|
||||
@@ -80,9 +81,9 @@ public class NotificationAccessSettings extends EmptyTextSettings {
|
||||
.setEmptyText(R.string.no_notification_listeners)
|
||||
.build();
|
||||
|
||||
- private NotificationManager mNm;
|
||||
+ @VisibleForTesting NotificationManager mNm;
|
||||
protected Context mContext;
|
||||
- private PackageManager mPm;
|
||||
+ @VisibleForTesting PackageManager mPm;
|
||||
private DevicePolicyManager mDpm;
|
||||
private ServiceListing mServiceListing;
|
||||
private IconDrawableFactory mIconDrawableFactory;
|
||||
@@ -102,12 +103,6 @@ public void onCreate(Bundle icicle) {
|
||||
.setNoun(CONFIG.noun)
|
||||
.setSetting(CONFIG.setting)
|
||||
.setTag(CONFIG.tag)
|
||||
- .setValidator(info -> {
|
||||
- if (info.getComponentName().flattenToString().length() > MAX_CN_LENGTH) {
|
||||
- return false;
|
||||
- }
|
||||
- return true;
|
||||
- })
|
||||
.build();
|
||||
mServiceListing.addCallback(this::updateList);
|
||||
|
||||
@@ -140,7 +135,8 @@ public void onPause() {
|
||||
mServiceListing.setListening(false);
|
||||
}
|
||||
|
||||
- private void updateList(List<ServiceInfo> services) {
|
||||
+ @VisibleForTesting
|
||||
+ void updateList(List<ServiceInfo> services) {
|
||||
final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
|
||||
final int managedProfileId = Utils.getManagedProfileId(um, UserHandle.myUserId());
|
||||
|
||||
@@ -153,6 +149,11 @@ private void updateList(List<ServiceInfo> services) {
|
||||
services.sort(new PackageItemInfo.DisplayNameComparator(mPm));
|
||||
for (ServiceInfo service : services) {
|
||||
final ComponentName cn = new ComponentName(service.packageName, service.name);
|
||||
+ boolean isAllowed = mNm.isNotificationListenerAccessGranted(cn);
|
||||
+ if (!isAllowed && cn.flattenToString().length() > MAX_CN_LENGTH) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
CharSequence title = null;
|
||||
try {
|
||||
title = mPm.getApplicationInfoAsUser(
|
||||
@@ -200,7 +201,7 @@ private void updateList(List<ServiceInfo> services) {
|
||||
return true;
|
||||
});
|
||||
pref.setKey(cn.flattenToString());
|
||||
- if (mNm.isNotificationListenerAccessGranted(cn)) {
|
||||
+ if (isAllowed) {
|
||||
allowedCategory.addPreference(pref);
|
||||
} else {
|
||||
notAllowedCategory.addPreference(pref);
|
||||
diff --git a/src/com/android/settings/notification/NotificationBackend.java b/src/com/android/settings/notification/NotificationBackend.java
|
||||
index 68f5d081d1..589d455428 100644
|
||||
--- a/src/com/android/settings/notification/NotificationBackend.java
|
||||
+++ b/src/com/android/settings/notification/NotificationBackend.java
|
||||
@@ -133,6 +133,9 @@ void recordCanBeBlocked(PackageInfo app, AppRow row) {
|
||||
|
||||
static public CharSequence getDeviceList(ICompanionDeviceManager cdm, LocalBluetoothManager lbm,
|
||||
String pkg, int userId) {
|
||||
+ if (cdm == null) {
|
||||
+ return "";
|
||||
+ }
|
||||
boolean multiple = false;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
diff --git a/tests/robotests/src/com/android/settings/notification/NotificationAccessSettingsTest.java b/tests/robotests/src/com/android/settings/notification/NotificationAccessSettingsTest.java
|
||||
new file mode 100644
|
||||
index 0000000000..e644c2975b
|
||||
--- /dev/null
|
||||
+++ b/tests/robotests/src/com/android/settings/notification/NotificationAccessSettingsTest.java
|
||||
@@ -0,0 +1,144 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2023 The Android Open Source Project
|
||||
+ *
|
||||
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
+ * you may not use this file except in compliance with the License.
|
||||
+ * You may obtain a copy of the License at
|
||||
+ *
|
||||
+ * http://www.apache.org/licenses/LICENSE-2.0
|
||||
+ *
|
||||
+ * Unless required by applicable law or agreed to in writing, software
|
||||
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
+ * See the License for the specific language governing permissions and
|
||||
+ * limitations under the License.
|
||||
+ */
|
||||
+
|
||||
+package com.android.settings.notification;
|
||||
+
|
||||
+import static com.android.settings.notification.NotificationAccessSettings.ALLOWED_KEY;
|
||||
+import static com.android.settings.notification.NotificationAccessSettings.NOT_ALLOWED_KEY;
|
||||
+
|
||||
+import static com.google.common.base.Preconditions.checkNotNull;
|
||||
+import static com.google.common.truth.Truth.assertThat;
|
||||
+
|
||||
+import static org.mockito.ArgumentMatchers.any;
|
||||
+import static org.mockito.ArgumentMatchers.anyInt;
|
||||
+import static org.mockito.Mockito.mock;
|
||||
+import static org.mockito.Mockito.when;
|
||||
+
|
||||
+import android.app.NotificationManager;
|
||||
+import android.content.ComponentName;
|
||||
+import android.content.Context;
|
||||
+import android.content.pm.ApplicationInfo;
|
||||
+import android.content.pm.PackageManager;
|
||||
+import android.content.pm.ServiceInfo;
|
||||
+
|
||||
+import androidx.fragment.app.FragmentActivity;
|
||||
+import androidx.preference.PreferenceCategory;
|
||||
+import androidx.preference.PreferenceScreen;
|
||||
+
|
||||
+import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
|
||||
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
+
|
||||
+import com.google.common.base.Strings;
|
||||
+
|
||||
+import org.junit.Before;
|
||||
+import org.junit.Test;
|
||||
+import org.junit.runner.RunWith;
|
||||
+import org.mockito.Mock;
|
||||
+import org.mockito.MockitoAnnotations;
|
||||
+import org.mockito.stubbing.Answer;
|
||||
+import org.robolectric.Robolectric;
|
||||
+import org.robolectric.RobolectricTestRunner;
|
||||
+import org.robolectric.RuntimeEnvironment;
|
||||
+import org.robolectric.annotation.Config;
|
||||
+import org.robolectric.shadows.ShadowApplication;
|
||||
+
|
||||
+import java.util.ArrayList;
|
||||
+
|
||||
+@RunWith(RobolectricTestRunner.class)
|
||||
+@Config(shadows = {ShadowBluetoothUtils.class})
|
||||
+public class NotificationAccessSettingsTest {
|
||||
+
|
||||
+ private Context mContext;
|
||||
+ private NotificationAccessSettings mAccessSettings;
|
||||
+ @Mock
|
||||
+ private NotificationManager mNotificationManager;
|
||||
+ @Mock
|
||||
+ private PackageManager mPackageManager;
|
||||
+
|
||||
+ @Before
|
||||
+ public void setUp() throws Exception {
|
||||
+ MockitoAnnotations.initMocks(this);
|
||||
+
|
||||
+ mContext = RuntimeEnvironment.application;
|
||||
+ ShadowApplication shadowApp = ShadowApplication.getInstance();
|
||||
+ shadowApp.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
|
||||
+
|
||||
+ mAccessSettings = new NotificationAccessSettings();
|
||||
+ FragmentActivity activity = Robolectric.buildActivity(FragmentActivity.class).setup().get();
|
||||
+ activity.getSupportFragmentManager().beginTransaction().add(mAccessSettings, null).commit();
|
||||
+
|
||||
+ when(mPackageManager.getApplicationInfoAsUser(any(), anyInt(), anyInt())).then(
|
||||
+ (Answer<ApplicationInfo>) invocation -> {
|
||||
+ ApplicationInfo appInfo = mock(ApplicationInfo.class);
|
||||
+ when(appInfo.loadLabel(any())).thenReturn(invocation.getArgument(0));
|
||||
+ return appInfo;
|
||||
+ });
|
||||
+
|
||||
+ mAccessSettings.mNm = mNotificationManager;
|
||||
+ mAccessSettings.mPm = mPackageManager;
|
||||
+ ShadowBluetoothUtils.sLocalBluetoothManager = mock(LocalBluetoothManager.class);
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void updateList_enabledLongName_shown() {
|
||||
+ ComponentName longCn = new ComponentName("test.pkg1",
|
||||
+ Strings.repeat("Blah", 200) + "Service");
|
||||
+ ComponentName shortCn = new ComponentName("test.pkg2", "ReasonableService");
|
||||
+ ArrayList<ServiceInfo> services = new ArrayList<>();
|
||||
+ services.add(newServiceInfo(longCn.getPackageName(), longCn.getClassName(), 1));
|
||||
+ services.add(newServiceInfo(shortCn.getPackageName(), shortCn.getClassName(), 2));
|
||||
+ when(mNotificationManager.isNotificationListenerAccessGranted(any())).thenReturn(true);
|
||||
+
|
||||
+ mAccessSettings.updateList(services);
|
||||
+
|
||||
+ PreferenceScreen screen = mAccessSettings.getPreferenceScreen();
|
||||
+ PreferenceCategory allowed = checkNotNull(screen.findPreference(ALLOWED_KEY));
|
||||
+ PreferenceCategory notAllowed = checkNotNull(screen.findPreference(NOT_ALLOWED_KEY));
|
||||
+ assertThat(allowed.getPreferenceCount()).isEqualTo(2);
|
||||
+ assertThat(allowed.getPreference(0).getKey()).isEqualTo(longCn.flattenToString());
|
||||
+ assertThat(allowed.getPreference(1).getKey()).isEqualTo(shortCn.flattenToString());
|
||||
+ assertThat(notAllowed.getPreferenceCount()).isEqualTo(0);
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void updateList_disabledLongName_notShown() {
|
||||
+ ComponentName longCn = new ComponentName("test.pkg1",
|
||||
+ Strings.repeat("Blah", 200) + "Service");
|
||||
+ ComponentName shortCn = new ComponentName("test.pkg2", "ReasonableService");
|
||||
+ ArrayList<ServiceInfo> services = new ArrayList<>();
|
||||
+ services.add(newServiceInfo(longCn.getPackageName(), longCn.getClassName(), 1));
|
||||
+ services.add(newServiceInfo(shortCn.getPackageName(), shortCn.getClassName(), 2));
|
||||
+ when(mNotificationManager.isNotificationListenerAccessGranted(any())).thenReturn(false);
|
||||
+
|
||||
+ mAccessSettings.updateList(services);
|
||||
+
|
||||
+ PreferenceScreen screen = mAccessSettings.getPreferenceScreen();
|
||||
+ PreferenceCategory allowed = checkNotNull(screen.findPreference(ALLOWED_KEY));
|
||||
+ PreferenceCategory notAllowed = checkNotNull(screen.findPreference(NOT_ALLOWED_KEY));
|
||||
+ assertThat(allowed.getPreferenceCount()).isEqualTo(0);
|
||||
+ assertThat(notAllowed.getPreferenceCount()).isEqualTo(1);
|
||||
+ assertThat(notAllowed.getPreference(0).getKey()).isEqualTo(shortCn.flattenToString());
|
||||
+ }
|
||||
+
|
||||
+ private static ServiceInfo newServiceInfo(String packageName, String serviceName, int uid) {
|
||||
+ ServiceInfo serviceInfo = new ServiceInfo();
|
||||
+ serviceInfo.packageName = packageName;
|
||||
+ serviceInfo.name = serviceName;
|
||||
+ serviceInfo.applicationInfo = new ApplicationInfo();
|
||||
+ serviceInfo.applicationInfo.uid = uid;
|
||||
+ return serviceInfo;
|
||||
+ }
|
||||
+}
|
@ -1,124 +0,0 @@
|
||||
From fa5ec443d94922424112fe8a7c7f9d3b36dca67d Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Mat=C3=ADas=20Hern=C3=A1ndez?= <matiashe@google.com>
|
||||
Date: Thu, 15 Jun 2023 18:37:52 +0200
|
||||
Subject: [PATCH] Settings: don't try to allow NLSes with too-long component
|
||||
names
|
||||
|
||||
* NotificationAccessConfirmationActivity (triggered through CompanionDeviceManager) -> Don't show the dialog, bail out early similarly to other invalid inputs.
|
||||
* NotificationAccessSettings (from Special App Access) -> No changes, but use the canonical constant now.
|
||||
* ApprovalPreferenceController (used in NotificationAccessDetails) -> Disable the toggle, unless the NLS was previously approved (in which case it can still be removed).
|
||||
|
||||
Fixes: 260570119
|
||||
Fixes: 286043036
|
||||
Test: atest + manually
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:b88fbf932a1631792a422f8ac34e83e1d6ae74d7)
|
||||
Merged-In: Ifc048311746c027e3683cdcf65f1079d04cf7c56
|
||||
Change-Id: Ifc048311746c027e3683cdcf65f1079d04cf7c56
|
||||
---
|
||||
.../ApprovalPreferenceController.java | 5 +++-
|
||||
...otificationAccessConfirmationActivity.java | 4 ++-
|
||||
.../NotificationAccessSettings.java | 4 +--
|
||||
.../ApprovalPreferenceControllerTest.java | 30 +++++++++++++++++++
|
||||
4 files changed, 39 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceController.java b/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceController.java
|
||||
index 0767e65bbcb..6bee62cc688 100644
|
||||
--- a/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceController.java
|
||||
+++ b/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceController.java
|
||||
@@ -81,6 +81,8 @@ public void updateState(Preference pref) {
|
||||
final RestrictedSwitchPreference preference =
|
||||
(RestrictedSwitchPreference) pref;
|
||||
final CharSequence label = mPkgInfo.applicationInfo.loadLabel(mPm);
|
||||
+ final boolean isAllowedCn = mCn.flattenToShortString().length()
|
||||
+ <= NotificationManager.MAX_SERVICE_COMPONENT_NAME_LENGTH;
|
||||
final boolean isEnabled = isServiceEnabled(mCn);
|
||||
preference.setChecked(isEnabled);
|
||||
preference.setOnPreferenceChangeListener((p, newValue) -> {
|
||||
@@ -105,7 +107,8 @@ public void updateState(Preference pref) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
- preference.updateState(mCn.getPackageName(), mPkgInfo.applicationInfo.uid, isEnabled);
|
||||
+ preference.updateState(
|
||||
+ mCn.getPackageName(), mPkgInfo.applicationInfo.uid, isAllowedCn, isEnabled);
|
||||
}
|
||||
|
||||
public void disable(final ComponentName cn) {
|
||||
diff --git a/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java b/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java
|
||||
index dfe6df2a5ca..a6b565ae6ba 100644
|
||||
--- a/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java
|
||||
+++ b/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java
|
||||
@@ -67,7 +67,9 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
mUserId = getIntent().getIntExtra(EXTRA_USER_ID, UserHandle.USER_NULL);
|
||||
CharSequence mAppLabel;
|
||||
|
||||
- if (mComponentName == null || mComponentName.getPackageName() == null) {
|
||||
+ if (mComponentName == null || mComponentName.getPackageName() == null
|
||||
+ || mComponentName.flattenToString().length()
|
||||
+ > NotificationManager.MAX_SERVICE_COMPONENT_NAME_LENGTH) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
diff --git a/src/com/android/settings/notification/NotificationAccessSettings.java b/src/com/android/settings/notification/NotificationAccessSettings.java
|
||||
index 369c4f6dfaf..e2ef0ddccb4 100644
|
||||
--- a/src/com/android/settings/notification/NotificationAccessSettings.java
|
||||
+++ b/src/com/android/settings/notification/NotificationAccessSettings.java
|
||||
@@ -66,7 +66,6 @@ public class NotificationAccessSettings extends EmptyTextSettings {
|
||||
private static final String TAG = "NotifAccessSettings";
|
||||
static final String ALLOWED_KEY = "allowed";
|
||||
static final String NOT_ALLOWED_KEY = "not_allowed";
|
||||
- private static final int MAX_CN_LENGTH = 500;
|
||||
|
||||
private static final ManagedServiceSettings.Config CONFIG =
|
||||
new ManagedServiceSettings.Config.Builder()
|
||||
@@ -150,7 +149,8 @@ void updateList(List<ServiceInfo> services) {
|
||||
for (ServiceInfo service : services) {
|
||||
final ComponentName cn = new ComponentName(service.packageName, service.name);
|
||||
boolean isAllowed = mNm.isNotificationListenerAccessGranted(cn);
|
||||
- if (!isAllowed && cn.flattenToString().length() > MAX_CN_LENGTH) {
|
||||
+ if (!isAllowed && cn.flattenToString().length()
|
||||
+ > NotificationManager.MAX_SERVICE_COMPONENT_NAME_LENGTH) {
|
||||
continue;
|
||||
}
|
||||
|
||||
diff --git a/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceControllerTest.java b/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceControllerTest.java
|
||||
index 249b713987c..4601a1cfbaa 100644
|
||||
--- a/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceControllerTest.java
|
||||
+++ b/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceControllerTest.java
|
||||
@@ -83,6 +83,36 @@ public void setUp() {
|
||||
|
||||
}
|
||||
|
||||
+ @Test
|
||||
+ public void updateState_enabled() {
|
||||
+ when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString())).thenReturn(
|
||||
+ AppOpsManager.MODE_ALLOWED);
|
||||
+ when(mNm.isNotificationListenerAccessGranted(mCn)).thenReturn(true);
|
||||
+ RestrictedSwitchPreference pref = new RestrictedSwitchPreference(
|
||||
+ mContext);
|
||||
+ pref.setAppOps(mAppOpsManager);
|
||||
+
|
||||
+ mController.updateState(pref);
|
||||
+
|
||||
+ assertThat(pref.isEnabled()).isTrue();
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void updateState_invalidCn_disabled() {
|
||||
+ ComponentName longCn = new ComponentName("com.example.package",
|
||||
+ com.google.common.base.Strings.repeat("Blah", 150));
|
||||
+ mController.setCn(longCn);
|
||||
+ when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString())).thenReturn(
|
||||
+ AppOpsManager.MODE_ALLOWED);
|
||||
+ RestrictedSwitchPreference pref = new RestrictedSwitchPreference(
|
||||
+ mContext);
|
||||
+ pref.setAppOps(mAppOpsManager);
|
||||
+
|
||||
+ mController.updateState(pref);
|
||||
+
|
||||
+ assertThat(pref.isEnabled()).isFalse();
|
||||
+ }
|
||||
+
|
||||
@Test
|
||||
public void updateState_checked() {
|
||||
when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString())).thenReturn(
|
@ -1,228 +0,0 @@
|
||||
From ba4da9c7b3a711a5e1c73dcf361b0c14fe02ebf4 Mon Sep 17 00:00:00 2001
|
||||
From: Taran Singh <tarandeep@google.com>
|
||||
Date: Fri, 19 May 2023 23:17:47 +0000
|
||||
Subject: [PATCH] DO NOT MERGE: Prevent non-system IME from becoming device
|
||||
admin
|
||||
|
||||
Currently selected IME can inject KeyEvent on DeviceAdminAdd screen to
|
||||
activate itself as device admin and cause various DoS attacks.
|
||||
|
||||
This CL ensures KeyEvent on "Activate" button can only come from system
|
||||
apps.
|
||||
|
||||
Bug: 280793427
|
||||
Test: atest DeviceAdminActivationTest
|
||||
(cherry picked from commit 70a501d02e0a6aefd874767a15378ba998759373)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:0976cd789d3bfb593e73237b5b0adc39933a1c1c)
|
||||
Merged-In: I6470d1684d707f4b1e86f8b456be0b4e0af5f188
|
||||
Change-Id: I6470d1684d707f4b1e86f8b456be0b4e0af5f188
|
||||
---
|
||||
.../deviceadmin/DeviceAdminAdd.java | 129 +++++++++---------
|
||||
1 file changed, 68 insertions(+), 61 deletions(-)
|
||||
|
||||
diff --git a/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminAdd.java b/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminAdd.java
|
||||
index fa76a948c06..5746d13666a 100644
|
||||
--- a/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminAdd.java
|
||||
+++ b/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminAdd.java
|
||||
@@ -66,6 +66,7 @@
|
||||
import android.util.EventLog;
|
||||
import android.util.Log;
|
||||
import android.view.Display;
|
||||
+import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -156,12 +157,12 @@ protected void onCreate(Bundle icicle) {
|
||||
|
||||
mHandler = new Handler(getMainLooper());
|
||||
|
||||
- mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
|
||||
- mAppOps = (AppOpsManager)getSystemService(Context.APP_OPS_SERVICE);
|
||||
- mLayoutInflaternflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
+ mDPM = getSystemService(DevicePolicyManager.class);
|
||||
+ mAppOps = getSystemService(AppOpsManager.class);
|
||||
+ mLayoutInflaternflater = getSystemService(LayoutInflater.class);
|
||||
PackageManager packageManager = getPackageManager();
|
||||
|
||||
- if ((getIntent().getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
|
||||
+ if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
|
||||
Log.w(TAG, "Cannot start ADD_DEVICE_ADMIN as a new task");
|
||||
finish();
|
||||
return;
|
||||
@@ -171,7 +172,7 @@ protected void onCreate(Bundle icicle) {
|
||||
EXTRA_CALLED_FROM_SUPPORT_DIALOG, false);
|
||||
|
||||
String action = getIntent().getAction();
|
||||
- ComponentName who = (ComponentName)getIntent().getParcelableExtra(
|
||||
+ ComponentName who = (ComponentName) getIntent().getParcelableExtra(
|
||||
DevicePolicyManager.EXTRA_DEVICE_ADMIN);
|
||||
if (who == null) {
|
||||
String packageName = getIntent().getStringExtra(EXTRA_DEVICE_ADMIN_PACKAGE_NAME);
|
||||
@@ -229,7 +230,7 @@ protected void onCreate(Bundle icicle) {
|
||||
PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS);
|
||||
int count = avail == null ? 0 : avail.size();
|
||||
boolean found = false;
|
||||
- for (int i=0; i<count; i++) {
|
||||
+ for (int i = 0; i < count; i++) {
|
||||
ResolveInfo ri = avail.get(i);
|
||||
if (ai.packageName.equals(ri.activityInfo.packageName)
|
||||
&& ai.name.equals(ri.activityInfo.name)) {
|
||||
@@ -345,22 +346,22 @@ public void onDismiss(DialogInterface dialogInterface) {
|
||||
mAdminWarning = dialog.findViewById(R.id.admin_warning_simplified);
|
||||
mAdminWarning.setText(
|
||||
mDPM.getResources().getString(NEW_DEVICE_ADMIN_WARNING_SIMPLIFIED, () ->
|
||||
- getString(R.string.device_admin_warning_simplified,
|
||||
- mProfileOwnerName), mProfileOwnerName));
|
||||
+ getString(R.string.device_admin_warning_simplified,
|
||||
+ mProfileOwnerName), mProfileOwnerName));
|
||||
return;
|
||||
}
|
||||
setContentView(R.layout.device_admin_add);
|
||||
|
||||
- mAdminIcon = (ImageView)findViewById(R.id.admin_icon);
|
||||
- mAdminName = (TextView)findViewById(R.id.admin_name);
|
||||
- mAdminDescription = (TextView)findViewById(R.id.admin_description);
|
||||
+ mAdminIcon = (ImageView) findViewById(R.id.admin_icon);
|
||||
+ mAdminName = (TextView) findViewById(R.id.admin_name);
|
||||
+ mAdminDescription = (TextView) findViewById(R.id.admin_description);
|
||||
mProfileOwnerWarning = (TextView) findViewById(R.id.profile_owner_warning);
|
||||
|
||||
mProfileOwnerWarning.setText(
|
||||
mDPM.getResources().getString(SET_PROFILE_OWNER_POSTSETUP_WARNING,
|
||||
() -> getString(R.string.adding_profile_owner_warning)));
|
||||
|
||||
- mAddMsg = (TextView)findViewById(R.id.add_msg);
|
||||
+ mAddMsg = (TextView) findViewById(R.id.add_msg);
|
||||
mAddMsgExpander = (ImageView) findViewById(R.id.add_msg_expander);
|
||||
final View.OnClickListener onClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
@@ -381,7 +382,7 @@ public void onGlobalLayout() {
|
||||
boolean hideMsgExpander = mAddMsg.getLineCount() <= maxLines;
|
||||
mAddMsgExpander.setVisibility(hideMsgExpander ? View.GONE : View.VISIBLE);
|
||||
if (hideMsgExpander) {
|
||||
- ((View)mAddMsgExpander.getParent()).invalidate();
|
||||
+ ((View) mAddMsgExpander.getParent()).invalidate();
|
||||
}
|
||||
mAddMsg.getViewTreeObserver().removeOnGlobalLayoutListener(this);
|
||||
}
|
||||
@@ -399,7 +400,7 @@ public void onGlobalLayout() {
|
||||
mCancelButton.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
EventLog.writeEvent(EventLogTags.EXP_DET_DEVICE_ADMIN_DECLINED_BY_USER,
|
||||
- mDeviceAdmin.getActivityInfo().applicationInfo.uid);
|
||||
+ mDeviceAdmin.getActivityInfo().applicationInfo.uid);
|
||||
finish();
|
||||
}
|
||||
});
|
||||
@@ -421,58 +422,64 @@ public void onClick(View v) {
|
||||
|
||||
final View restrictedAction = findViewById(R.id.restricted_action);
|
||||
restrictedAction.setFilterTouchesWhenObscured(true);
|
||||
- restrictedAction.setOnClickListener(new View.OnClickListener() {
|
||||
- public void onClick(View v) {
|
||||
- if (!mActionButton.isEnabled()) {
|
||||
- showPolicyTransparencyDialogIfRequired();
|
||||
- return;
|
||||
- }
|
||||
- if (mAdding) {
|
||||
- addAndFinish();
|
||||
- } else if (isManagedProfile(mDeviceAdmin)
|
||||
- && mDeviceAdmin.getComponent().equals(mDPM.getProfileOwner())) {
|
||||
- final int userId = UserHandle.myUserId();
|
||||
- UserDialogs.createRemoveDialog(DeviceAdminAdd.this, userId,
|
||||
- new DialogInterface.OnClickListener() {
|
||||
- @Override
|
||||
- public void onClick(DialogInterface dialog, int which) {
|
||||
- UserManager um = UserManager.get(DeviceAdminAdd.this);
|
||||
- um.removeUser(userId);
|
||||
- finish();
|
||||
- }
|
||||
+
|
||||
+ final View.OnClickListener restrictedActionClickListener = v -> {
|
||||
+ if (!mActionButton.isEnabled()) {
|
||||
+ showPolicyTransparencyDialogIfRequired();
|
||||
+ return;
|
||||
+ }
|
||||
+ if (mAdding) {
|
||||
+ addAndFinish();
|
||||
+ } else if (isManagedProfile(mDeviceAdmin)
|
||||
+ && mDeviceAdmin.getComponent().equals(mDPM.getProfileOwner())) {
|
||||
+ final int userId = UserHandle.myUserId();
|
||||
+ UserDialogs.createRemoveDialog(DeviceAdminAdd.this, userId,
|
||||
+ new DialogInterface.OnClickListener() {
|
||||
+ @Override
|
||||
+ public void onClick(DialogInterface dialog, int which) {
|
||||
+ UserManager um = UserManager.get(DeviceAdminAdd.this);
|
||||
+ um.removeUser(userId);
|
||||
+ finish();
|
||||
}
|
||||
- ).show();
|
||||
- } else if (mUninstalling) {
|
||||
- mDPM.uninstallPackageWithActiveAdmins(mDeviceAdmin.getPackageName());
|
||||
- finish();
|
||||
- } else if (!mWaitingForRemoveMsg) {
|
||||
- try {
|
||||
- // Don't allow the admin to put a dialog up in front
|
||||
- // of us while we interact with the user.
|
||||
- ActivityManager.getService().stopAppSwitches();
|
||||
- } catch (RemoteException e) {
|
||||
- }
|
||||
- mWaitingForRemoveMsg = true;
|
||||
- mDPM.getRemoveWarning(mDeviceAdmin.getComponent(),
|
||||
- new RemoteCallback(new RemoteCallback.OnResultListener() {
|
||||
- @Override
|
||||
- public void onResult(Bundle result) {
|
||||
- CharSequence msg = result != null
|
||||
- ? result.getCharSequence(
|
||||
- DeviceAdminReceiver.EXTRA_DISABLE_WARNING)
|
||||
- : null;
|
||||
- continueRemoveAction(msg);
|
||||
- }
|
||||
- }, mHandler));
|
||||
- // Don't want to wait too long.
|
||||
- getWindow().getDecorView().getHandler().postDelayed(new Runnable() {
|
||||
- @Override public void run() {
|
||||
- continueRemoveAction(null);
|
||||
}
|
||||
- }, 2*1000);
|
||||
+ ).show();
|
||||
+ } else if (mUninstalling) {
|
||||
+ mDPM.uninstallPackageWithActiveAdmins(mDeviceAdmin.getPackageName());
|
||||
+ finish();
|
||||
+ } else if (!mWaitingForRemoveMsg) {
|
||||
+ try {
|
||||
+ // Don't allow the admin to put a dialog up in front
|
||||
+ // of us while we interact with the user.
|
||||
+ ActivityManager.getService().stopAppSwitches();
|
||||
+ } catch (RemoteException e) {
|
||||
}
|
||||
+ mWaitingForRemoveMsg = true;
|
||||
+ mDPM.getRemoveWarning(mDeviceAdmin.getComponent(),
|
||||
+ new RemoteCallback(new RemoteCallback.OnResultListener() {
|
||||
+ @Override
|
||||
+ public void onResult(Bundle result) {
|
||||
+ CharSequence msg = result != null
|
||||
+ ? result.getCharSequence(
|
||||
+ DeviceAdminReceiver.EXTRA_DISABLE_WARNING)
|
||||
+ : null;
|
||||
+ continueRemoveAction(msg);
|
||||
+ }
|
||||
+ }, mHandler));
|
||||
+ // Don't want to wait too long.
|
||||
+ getWindow().getDecorView().getHandler().postDelayed(
|
||||
+ () -> continueRemoveAction(null), 2 * 1000);
|
||||
+ }
|
||||
+ };
|
||||
+ restrictedAction.setOnKeyListener((view, keyCode, keyEvent) -> {
|
||||
+ if ((keyEvent.getFlags() & KeyEvent.FLAG_FROM_SYSTEM) == 0) {
|
||||
+ Log.e(TAG, "Can not activate device-admin with KeyEvent from non-system app.");
|
||||
+ // Consume event to suppress click.
|
||||
+ return true;
|
||||
}
|
||||
+ // Fallback to view click handler.
|
||||
+ return false;
|
||||
});
|
||||
+ restrictedAction.setOnClickListener(restrictedActionClickListener);
|
||||
}
|
||||
|
||||
/**
|
@ -1,168 +0,0 @@
|
||||
From b96ee4a2d1ec8c552af40820077fe85f9b2fa01f Mon Sep 17 00:00:00 2001
|
||||
From: Ashish Kumar <akgaurav@google.com>
|
||||
Date: Fri, 26 May 2023 14:18:46 +0000
|
||||
Subject: [PATCH] Fixed leak of cross user data in multiple settings.
|
||||
|
||||
- Any app is allowed to receive GET_CONTENT intent. Using this, an user puts back in the intent an uri with data of another user.
|
||||
- Telephony service has INTERACT_ACROSS_USER permission. Using this, it reads and shows the deta to the evil user.
|
||||
|
||||
Fix: When telephony service gets the intent result, it checks if the uri is from the current user or not.
|
||||
|
||||
Bug: b/256591023 , b/256819787
|
||||
|
||||
Test: The malicious behaviour was not being reproduced. Unable to import contact from other users data.
|
||||
Test2: Able to import contact from the primary user or uri with no user id
|
||||
(These settings are not available for secondary users)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:ab593467e900d4a6d25a34024a06195ae863f6dc)
|
||||
Merged-In: I1e3a643f17948153aecc1d0df9ffd9619ad678c1
|
||||
Change-Id: I1e3a643f17948153aecc1d0df9ffd9619ad678c1
|
||||
---
|
||||
src/com/android/phone/CdmaCallForwardOptions.java | 12 ++++++++++++
|
||||
.../android/phone/GsmUmtsCallForwardOptions.java | 12 ++++++++++++
|
||||
.../phone/settings/VoicemailSettingsActivity.java | 14 ++++++++++++++
|
||||
.../phone/settings/fdn/EditFdnContactScreen.java | 11 +++++++++++
|
||||
4 files changed, 49 insertions(+)
|
||||
|
||||
diff --git a/src/com/android/phone/CdmaCallForwardOptions.java b/src/com/android/phone/CdmaCallForwardOptions.java
|
||||
index a8d2e93d69..d70e7099b4 100644
|
||||
--- a/src/com/android/phone/CdmaCallForwardOptions.java
|
||||
+++ b/src/com/android/phone/CdmaCallForwardOptions.java
|
||||
@@ -17,10 +17,13 @@
|
||||
package com.android.phone;
|
||||
|
||||
import android.app.ActionBar;
|
||||
+import android.content.ContentProvider;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import android.os.PersistableBundle;
|
||||
+import android.os.Process;
|
||||
+import android.os.UserHandle;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.telephony.CarrierConfigManager;
|
||||
@@ -212,6 +215,15 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
}
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
+ // check if the URI returned by the user belongs to the user
|
||||
+ final int currentUser = UserHandle.getUserId(Process.myUid());
|
||||
+ if (currentUser
|
||||
+ != ContentProvider.getUserIdFromUri(data.getData(), currentUser)) {
|
||||
+
|
||||
+ Log.w(LOG_TAG, "onActivityResult: Contact data of different user, "
|
||||
+ + "cannot access");
|
||||
+ return;
|
||||
+ }
|
||||
cursor = getContentResolver().query(data.getData(),
|
||||
NUM_PROJECTION, null, null, null);
|
||||
if ((cursor == null) || (!cursor.moveToFirst())) {
|
||||
diff --git a/src/com/android/phone/GsmUmtsCallForwardOptions.java b/src/com/android/phone/GsmUmtsCallForwardOptions.java
|
||||
index fda0ea5265..db830deb66 100644
|
||||
--- a/src/com/android/phone/GsmUmtsCallForwardOptions.java
|
||||
+++ b/src/com/android/phone/GsmUmtsCallForwardOptions.java
|
||||
@@ -1,10 +1,13 @@
|
||||
package com.android.phone;
|
||||
|
||||
import android.app.ActionBar;
|
||||
+import android.content.ContentProvider;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import android.os.PersistableBundle;
|
||||
+import android.os.Process;
|
||||
+import android.os.UserHandle;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.telephony.CarrierConfigManager;
|
||||
@@ -203,6 +206,15 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
}
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
+ // check if the URI returned by the user belongs to the user
|
||||
+ final int currentUser = UserHandle.getUserId(Process.myUid());
|
||||
+ if (currentUser
|
||||
+ != ContentProvider.getUserIdFromUri(data.getData(), currentUser)) {
|
||||
+
|
||||
+ Log.w(LOG_TAG, "onActivityResult: Contact data of different user, "
|
||||
+ + "cannot access");
|
||||
+ return;
|
||||
+ }
|
||||
cursor = getContentResolver().query(data.getData(),
|
||||
NUM_PROJECTION, null, null, null);
|
||||
if ((cursor == null) || (!cursor.moveToFirst())) {
|
||||
diff --git a/src/com/android/phone/settings/VoicemailSettingsActivity.java b/src/com/android/phone/settings/VoicemailSettingsActivity.java
|
||||
index 02bf4b25d8..c940748a35 100644
|
||||
--- a/src/com/android/phone/settings/VoicemailSettingsActivity.java
|
||||
+++ b/src/com/android/phone/settings/VoicemailSettingsActivity.java
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.phone.settings;
|
||||
|
||||
import android.app.Dialog;
|
||||
+import android.content.ContentProvider;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
@@ -25,6 +26,8 @@
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.PersistableBundle;
|
||||
+import android.os.Process;
|
||||
+import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceActivity;
|
||||
@@ -520,6 +523,17 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
+ // check if the URI returned by the user belongs to the user
|
||||
+ final int currentUser = UserHandle.getUserId(Process.myUid());
|
||||
+ if (currentUser
|
||||
+ != ContentProvider.getUserIdFromUri(data.getData(), currentUser)) {
|
||||
+
|
||||
+ if (DBG) {
|
||||
+ log("onActivityResult: Contact data of different user, "
|
||||
+ + "cannot access");
|
||||
+ }
|
||||
+ return;
|
||||
+ }
|
||||
cursor = getContentResolver().query(data.getData(),
|
||||
new String[] { CommonDataKinds.Phone.NUMBER }, null, null, null);
|
||||
if ((cursor == null) || (!cursor.moveToFirst())) {
|
||||
diff --git a/src/com/android/phone/settings/fdn/EditFdnContactScreen.java b/src/com/android/phone/settings/fdn/EditFdnContactScreen.java
|
||||
index 468d38f65d..0884e1262d 100644
|
||||
--- a/src/com/android/phone/settings/fdn/EditFdnContactScreen.java
|
||||
+++ b/src/com/android/phone/settings/fdn/EditFdnContactScreen.java
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
import static android.app.Activity.RESULT_OK;
|
||||
|
||||
+import android.content.ContentProvider;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
@@ -26,6 +27,8 @@
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.PersistableBundle;
|
||||
+import android.os.Process;
|
||||
+import android.os.UserHandle;
|
||||
import android.provider.ContactsContract.CommonDataKinds;
|
||||
import android.telephony.CarrierConfigManager;
|
||||
import android.telephony.PhoneNumberUtils;
|
||||
@@ -137,6 +140,14 @@ protected void onActivityResult(int requestCode, int resultCode, Intent intent)
|
||||
}
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
+ // check if the URI returned by the user belongs to the user
|
||||
+ final int currentUser = UserHandle.getUserId(Process.myUid());
|
||||
+ if (currentUser
|
||||
+ != ContentProvider.getUserIdFromUri(intent.getData(), currentUser)) {
|
||||
+ Log.w(LOG_TAG, "onActivityResult: Contact data of different user, "
|
||||
+ + "cannot access");
|
||||
+ return;
|
||||
+ }
|
||||
cursor = getContentResolver().query(intent.getData(),
|
||||
NUM_PROJECTION, null, null, null);
|
||||
if ((cursor == null) || (!cursor.moveToFirst())) {
|
@ -85,10 +85,9 @@ patchWorkspaceReal() {
|
||||
verifyAllPlatformTags;
|
||||
gpgVerifyGitHead "$DOS_BUILD_BASE/external/chromium-webview";
|
||||
|
||||
source build/envsetup.sh;
|
||||
#source build/envsetup.sh;
|
||||
#repopick -ift twelve-bt-sbc-hd-dualchannel;
|
||||
#repopick -it twelve-colors;
|
||||
repopick -it S_asb_2023-09;
|
||||
|
||||
sh "$DOS_SCRIPTS/Patch.sh";
|
||||
sh "$DOS_SCRIPTS_COMMON/Enable_Verity.sh";
|
||||
|
@ -127,12 +127,7 @@ if enterAndClear "external/webp"; then
|
||||
applyPatch "$DOS_PATCHES/android_external_webp/CVE-2023-4863.patch"; #Fix OOB write in BuildHuffmanTable.
|
||||
fi;
|
||||
|
||||
if enterAndClear "frameworks/av"; then
|
||||
git am $DOS_PATCHES/ASB2023-09/av-*.patch;
|
||||
fi;
|
||||
|
||||
if enterAndClear "frameworks/base"; then
|
||||
git am $DOS_PATCHES/ASB2023-09/fwb-*.patch;
|
||||
git revert --no-edit d36faad3267522c6d3ff91ba9dcca8f6274bccd1; #Reverts "JobScheduler: Respect allow-in-power-save perm" in favor of below patch
|
||||
git revert --no-edit 90d6826548189ca850d91692e71fcc1be426f453; #Reverts "Remove sensitive info from SUPL requests" in favor of below patch
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_base/0007-Always_Restict_Serial.patch"; #Always restrict access to Build.SERIAL (GrapheneOS)
|
||||
@ -223,7 +218,6 @@ applyPatch "$DOS_PATCHES/android_frameworks_libs_systemui/0001-Icon_Cache.patch"
|
||||
fi;
|
||||
|
||||
if enterAndClear "frameworks/native"; then
|
||||
git am $DOS_PATCHES/ASB2023-09/native-*.patch;
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_native/0001-Sensors_Permission.patch"; #Require OTHER_SENSORS permission for sensors (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_native/0001-Sensors_Permission-a1.patch"; #Protect step sensors with OTHER_SENSORS permission for targetSdk<29 apps (GrapheneOS)
|
||||
fi;
|
||||
@ -304,7 +298,6 @@ cp -f "$DOS_PATCHES_COMMON/contributors.db" assets/contributors.db; #Update cont
|
||||
fi;
|
||||
|
||||
if enterAndClear "packages/apps/Nfc"; then
|
||||
git am $DOS_PATCHES/ASB2023-09/nfc-*.patch;
|
||||
if [ "$DOS_GRAPHENE_CONSTIFY" = true ]; then applyPatch "$DOS_PATCHES/android_packages_apps_Nfc/0001-constify_JNINativeMethod.patch"; fi; #Constify JNINativeMethod tables (GrapheneOS)
|
||||
fi;
|
||||
|
||||
@ -313,7 +306,6 @@ applyPatch "$DOS_PATCHES/android_packages_apps_OpenEUICC/0001-hacky-fix.patch";
|
||||
fi;
|
||||
|
||||
if enterAndClear "packages/apps/Settings"; then
|
||||
git am $DOS_PATCHES/ASB2023-09/settings-*.patch;
|
||||
git revert --no-edit 41b4ed345a91da1dd46c00ee11a151c2b5ff4f43;
|
||||
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/0004-Private_DNS.patch"; #More 'Private DNS' options (heavily based off of a CalyxOS patch)
|
||||
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/0005-Automatic_Reboot.patch"; #Timeout for reboot (GrapheneOS)
|
||||
@ -342,7 +334,6 @@ git revert --no-edit fcf658d2005dc557a95d5a7fb89cb90d06b31d33; #grant permission
|
||||
fi;
|
||||
|
||||
if enterAndClear "packages/apps/Trebuchet"; then
|
||||
git am $DOS_PATCHES/ASB2023-09/launcher-*.patch;
|
||||
cp $DOS_BUILD_BASE/vendor/divested/overlay/common/packages/apps/Trebuchet/res/xml/default_workspace_*.xml res/xml/; #XXX: Likely no longer needed
|
||||
fi;
|
||||
|
||||
@ -358,10 +349,6 @@ applyPatch "$DOS_PATCHES/android_packages_inputmethods_LatinIME/0001-Voice.patch
|
||||
applyPatch "$DOS_PATCHES/android_packages_inputmethods_LatinIME/0002-Disable_Personalization.patch"; #Disable personalization dictionary by default (GrapheneOS)
|
||||
fi;
|
||||
|
||||
if enterAndClear "packages/modules/Bluetooth"; then
|
||||
git am $DOS_PATCHES/ASB2023-09/bt-*.patch;
|
||||
fi;
|
||||
|
||||
if enterAndClear "packages/modules/Connectivity"; then
|
||||
applyPatch "$DOS_PATCHES/android_packages_modules_Connectivity/0001-Network_Permission-1.patch"; #Skip reportNetworkConnectivity() when permission is revoked (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_packages_modules_Connectivity/0001-Network_Permission-2.patch"; #Enforce INTERNET permission per-uid instead of per-appId (GrapheneOS)
|
||||
@ -380,10 +367,6 @@ if enterAndClear "packages/modules/NetworkStack"; then
|
||||
applyPatch "$DOS_PATCHES/android_packages_modules_NetworkStack/0001-Random_MAC.patch"; #Avoid reusing DHCP state for full MAC randomization (GrapheneOS)
|
||||
fi;
|
||||
|
||||
if enterAndClear "packages/modules/NeuralNetworks"; then
|
||||
git am $DOS_PATCHES/ASB2023-09/nn-*.patch;
|
||||
fi;
|
||||
|
||||
if enterAndClear "packages/modules/Permission"; then
|
||||
applyPatch "$DOS_PATCHES/android_packages_modules_Permission/0004-Special_Permissions-1.patch"; #Add special handling for INTERNET/OTHER_SENSORS (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_packages_modules_Permission/0004-Special_Permissions-2.patch"; #Fix usage UI summary for Network/Sensors (GrapheneOS)
|
||||
@ -400,18 +383,10 @@ if enterAndClear "packages/providers/DownloadProvider"; then
|
||||
applyPatch "$DOS_PATCHES/android_packages_providers_DownloadProvider/0001-Network_Permission.patch"; #Expose the NETWORK permission (GrapheneOS)
|
||||
fi;
|
||||
|
||||
if enterAndClear "packages/providers/MediaProvider"; then
|
||||
git am $DOS_PATCHES/ASB2023-09/media-*.patch;
|
||||
fi;
|
||||
|
||||
#if enterAndClear "packages/providers/TelephonyProvider"; then
|
||||
#cp $DOS_PATCHES_COMMON/android_packages_providers_TelephonyProvider/carrier_list.* assets/latest_carrier_id/;
|
||||
#fi;
|
||||
|
||||
if enterAndClear "packages/services/Telephony"; then
|
||||
git am $DOS_PATCHES/ASB2023-09/telephony-*.patch;
|
||||
fi;
|
||||
|
||||
if enterAndClear "system/ca-certificates"; then
|
||||
rm -rf files; #Remove old certs
|
||||
cp -r "$DOS_PATCHES_COMMON/android_system_ca-certificates/files" .; #Copy the new ones into place
|
||||
|
Loading…
Reference in New Issue
Block a user