Skip to content

Commit 3e09cce

Browse files
Android Build Coastguard Workerdoryiii
authored andcommitted
Merge cherrypicks of ['googleplex-android-review.googlesource.com/23476871', 'googleplex-android-review.googlesource.com/23733070', 'googleplex-android-review.googlesource.com/23474146', 'googleplex-android-review.googlesource.com/23905843', 'googleplex-android-review.googlesource.com/23905120', 'googleplex-android-review.googlesource.com/23834726'] into security-aosp-tm-release.
Change-Id: I1c7b53328eea2729a45e9a9fe000606df017518a
2 parents 3752277 + c1cf4b9 commit 3e09cce

File tree

16 files changed

+543
-70
lines changed

16 files changed

+543
-70
lines changed

core/java/android/app/NotificationManager.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,12 @@ public class NotificationManager {
562562
*/
563563
public static final int BUBBLE_PREFERENCE_SELECTED = 2;
564564

565+
/**
566+
* Maximum length of the component name of a registered NotificationListenerService.
567+
* @hide
568+
*/
569+
public static int MAX_SERVICE_COMPONENT_NAME_LENGTH = 500;
570+
565571
@UnsupportedAppUsage
566572
private static INotificationManager sService;
567573

packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,9 @@ public String getPackageName() {
243243
return mHelper != null ? mHelper.packageName : null;
244244
}
245245

246-
public void updateState(@NonNull String packageName, int uid, boolean isEnabled) {
246+
/** Updates enabled state based on associated package. */
247+
public void updateState(
248+
@NonNull String packageName, int uid, boolean isEnableAllowed, boolean isEnabled) {
247249
mHelper.updatePackageDetails(packageName, uid);
248250
if (mAppOpsManager == null) {
249251
mAppOpsManager = getContext().getSystemService(AppOpsManager.class);
@@ -254,7 +256,9 @@ public void updateState(@NonNull String packageName, int uid, boolean isEnabled)
254256
final boolean ecmEnabled = getContext().getResources().getBoolean(
255257
com.android.internal.R.bool.config_enhancedConfirmationModeEnabled);
256258
final boolean appOpsAllowed = !ecmEnabled || mode == AppOpsManager.MODE_ALLOWED;
257-
if (isEnabled) {
259+
if (!isEnableAllowed && !isEnabled) {
260+
setEnabled(false);
261+
} else if (isEnabled) {
258262
setEnabled(true);
259263
} else if (appOpsAllowed && isDisabledByAppOps()) {
260264
setEnabled(true);

packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,16 @@ class MediaResumeListener @Inject constructor(
101101
Log.e(TAG, "Error getting package information", e)
102102
}
103103

104-
Log.d(TAG, "Adding resume controls $desc")
105-
mediaDataManager.addResumptionControls(currentUserId, desc, resumeAction, token,
106-
appName.toString(), appIntent, component.packageName)
104+
Log.d(TAG, "Adding resume controls for ${browser.userId}: $desc")
105+
mediaDataManager.addResumptionControls(
106+
browser.userId,
107+
desc,
108+
resumeAction,
109+
token,
110+
appName.toString(),
111+
appIntent,
112+
component.packageName
113+
)
107114
}
108115
}
109116

@@ -158,7 +165,11 @@ class MediaResumeListener @Inject constructor(
158165
}
159166
resumeComponents.add(component to lastPlayed)
160167
}
161-
Log.d(TAG, "loaded resume components ${resumeComponents.toArray().contentToString()}")
168+
Log.d(
169+
TAG,
170+
"loaded resume components for $currentUserId: " +
171+
"${resumeComponents.toArray().contentToString()}"
172+
)
162173

163174
if (needsUpdate) {
164175
// Save any missing times that we had to fill in
@@ -174,11 +185,21 @@ class MediaResumeListener @Inject constructor(
174185
return
175186
}
176187

188+
val pm = context.packageManager
177189
val now = systemClock.currentTimeMillis()
178190
resumeComponents.forEach {
179191
if (now.minus(it.second) <= RESUME_MEDIA_TIMEOUT) {
180-
val browser = mediaBrowserFactory.create(mediaBrowserCallback, it.first)
181-
browser.findRecentMedia()
192+
// Verify that the service exists for this user
193+
val intent = Intent(MediaBrowserService.SERVICE_INTERFACE)
194+
intent.component = it.first
195+
val inf = pm.resolveServiceAsUser(intent, 0, currentUserId)
196+
if (inf != null) {
197+
val browser =
198+
mediaBrowserFactory.create(mediaBrowserCallback, it.first, currentUserId)
199+
browser.findRecentMedia()
200+
} else {
201+
Log.d(TAG, "User $currentUserId does not have component ${it.first}")
202+
}
182203
}
183204
}
184205
}
@@ -202,7 +223,7 @@ class MediaResumeListener @Inject constructor(
202223
Log.d(TAG, "Checking for service component for " + data.packageName)
203224
val pm = context.packageManager
204225
val serviceIntent = Intent(MediaBrowserService.SERVICE_INTERFACE)
205-
val resumeInfo = pm.queryIntentServices(serviceIntent, 0)
226+
val resumeInfo = pm.queryIntentServicesAsUser(serviceIntent, 0, currentUserId)
206227

207228
val inf = resumeInfo?.filter {
208229
it.serviceInfo.packageName == data.packageName
@@ -244,13 +265,18 @@ class MediaResumeListener @Inject constructor(
244265
browser: ResumeMediaBrowser
245266
) {
246267
// Since this is a test, just save the component for later
247-
Log.d(TAG, "Can get resumable media from $componentName")
268+
Log.d(
269+
TAG,
270+
"Can get resumable media for ${browser.userId} from $componentName"
271+
)
248272
mediaDataManager.setResumeAction(key, getResumeAction(componentName))
249273
updateResumptionList(componentName)
250274
mediaBrowser = null
251275
}
252276
},
253-
componentName)
277+
componentName,
278+
currentUserId
279+
)
254280
mediaBrowser?.testConnection()
255281
}
256282

@@ -290,7 +316,7 @@ class MediaResumeListener @Inject constructor(
290316
*/
291317
private fun getResumeAction(componentName: ComponentName): Runnable {
292318
return Runnable {
293-
mediaBrowser = mediaBrowserFactory.create(null, componentName)
319+
mediaBrowser = mediaBrowserFactory.create(null, componentName, currentUserId)
294320
mediaBrowser?.restart()
295321
}
296322
}

packages/SystemUI/src/com/android/systemui/media/ResumeMediaBrowser.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.android.systemui.media;
1818

1919
import android.annotation.Nullable;
20+
import android.annotation.UserIdInt;
2021
import android.app.PendingIntent;
2122
import android.content.ComponentName;
2223
import android.content.Context;
@@ -53,6 +54,7 @@ public class ResumeMediaBrowser {
5354
private final ResumeMediaBrowserLogger mLogger;
5455
private final ComponentName mComponentName;
5556
private final MediaController.Callback mMediaControllerCallback = new SessionDestroyCallback();
57+
@UserIdInt private final int mUserId;
5658

5759
private MediaBrowser mMediaBrowser;
5860
@Nullable private MediaController mMediaController;
@@ -62,18 +64,21 @@ public class ResumeMediaBrowser {
6264
* @param context the context
6365
* @param callback used to report media items found
6466
* @param componentName Component name of the MediaBrowserService this browser will connect to
67+
* @param userId ID of the current user
6568
*/
6669
public ResumeMediaBrowser(
6770
Context context,
6871
@Nullable Callback callback,
6972
ComponentName componentName,
7073
MediaBrowserFactory browserFactory,
71-
ResumeMediaBrowserLogger logger) {
74+
ResumeMediaBrowserLogger logger,
75+
@UserIdInt int userId) {
7276
mContext = context;
7377
mCallback = callback;
7478
mComponentName = componentName;
7579
mBrowserFactory = browserFactory;
7680
mLogger = logger;
81+
mUserId = userId;
7782
}
7883

7984
/**
@@ -275,6 +280,14 @@ protected MediaController createMediaController(MediaSession.Token token) {
275280
return new MediaController(mContext, token);
276281
}
277282

283+
/**
284+
* Get the ID of the user associated with this broswer
285+
* @return the user ID
286+
*/
287+
public @UserIdInt int getUserId() {
288+
return mUserId;
289+
}
290+
278291
/**
279292
* Get the media session token
280293
* @return the token, or null if the MediaBrowser is null or disconnected

packages/SystemUI/src/com/android/systemui/media/ResumeMediaBrowserFactory.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.android.systemui.media;
1818

19+
import android.annotation.UserIdInt;
1920
import android.content.ComponentName;
2021
import android.content.Context;
2122

@@ -42,10 +43,12 @@ public ResumeMediaBrowserFactory(
4243
*
4344
* @param callback will be called on connection or error, and addTrack when media item found
4445
* @param componentName component to browse
46+
* @param userId ID of the current user
4547
* @return
4648
*/
4749
public ResumeMediaBrowser create(ResumeMediaBrowser.Callback callback,
48-
ComponentName componentName) {
49-
return new ResumeMediaBrowser(mContext, callback, componentName, mBrowserFactory, mLogger);
50+
ComponentName componentName, @UserIdInt int userId) {
51+
return new ResumeMediaBrowser(mContext, callback, componentName, mBrowserFactory, mLogger,
52+
userId);
5053
}
5154
}

packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java

Lines changed: 63 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,12 @@ protected Void doInBackground(Void... paramsUnused) {
135135
// Since Quick Share target recommendation does not rely on image URL, it is
136136
// queried and surfaced before image compress/export. Action intent would not be
137137
// used, because it does not contain image URL.
138-
queryQuickShareAction(image, user);
138+
Notification.Action quickShare =
139+
queryQuickShareAction(mScreenshotId, image, user, null);
140+
if (quickShare != null) {
141+
mQuickShareData.quickShareAction = quickShare;
142+
mParams.mQuickShareActionsReadyListener.onActionsReady(mQuickShareData);
143+
}
139144
}
140145

141146
// Call synchronously here since already on a background thread.
@@ -168,8 +173,9 @@ protected Void doInBackground(Void... paramsUnused) {
168173
mImageData.shareTransition = createShareAction(mContext, mContext.getResources(), uri);
169174
mImageData.editTransition = createEditAction(mContext, mContext.getResources(), uri);
170175
mImageData.deleteAction = createDeleteAction(mContext, mContext.getResources(), uri);
171-
mImageData.quickShareAction = createQuickShareAction(mContext,
172-
mQuickShareData.quickShareAction, uri);
176+
mImageData.quickShareAction = createQuickShareAction(
177+
mQuickShareData.quickShareAction, mScreenshotId, uri, mImageTime, image,
178+
user);
173179

174180
mParams.mActionsReadyListener.onActionsReady(mImageData);
175181
if (DEBUG_CALLBACK) {
@@ -409,71 +415,85 @@ private static void addIntentExtras(String screenshotId, Intent intent, String a
409415
}
410416

411417
/**
412-
* Populate image uri into intent of Quick Share action.
418+
* Wrap the quickshare intent and populate the fillin intent with the URI
413419
*/
414420
@VisibleForTesting
415-
private Notification.Action createQuickShareAction(Context context, Notification.Action action,
416-
Uri uri) {
417-
if (action == null) {
421+
Notification.Action createQuickShareAction(
422+
Notification.Action quickShare, String screenshotId, Uri uri, long imageTime,
423+
Bitmap image, UserHandle user) {
424+
if (quickShare == null) {
418425
return null;
426+
} else if (quickShare.actionIntent.isImmutable()) {
427+
Notification.Action quickShareWithUri =
428+
queryQuickShareAction(screenshotId, image, user, uri);
429+
if (quickShareWithUri == null
430+
|| !quickShareWithUri.title.toString().contentEquals(quickShare.title)) {
431+
return null;
432+
}
433+
quickShare = quickShareWithUri;
419434
}
420-
// Populate image URI into Quick Share chip intent
421-
Intent sharingIntent = action.actionIntent.getIntent();
422-
sharingIntent.setType("image/png");
423-
sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
424-
String subjectDate = DateFormat.getDateTimeInstance().format(new Date(mImageTime));
435+
436+
Intent wrappedIntent = new Intent(mContext, SmartActionsReceiver.class)
437+
.putExtra(ScreenshotController.EXTRA_ACTION_INTENT, quickShare.actionIntent)
438+
.putExtra(ScreenshotController.EXTRA_ACTION_INTENT_FILLIN,
439+
createFillInIntent(uri, imageTime))
440+
.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
441+
Bundle extras = quickShare.getExtras();
442+
String actionType = extras.getString(
443+
ScreenshotNotificationSmartActionsProvider.ACTION_TYPE,
444+
ScreenshotNotificationSmartActionsProvider.DEFAULT_ACTION_TYPE);
445+
addIntentExtras(screenshotId, wrappedIntent, actionType, mSmartActionsEnabled);
446+
PendingIntent broadcastIntent =
447+
PendingIntent.getBroadcast(mContext, mRandom.nextInt(), wrappedIntent,
448+
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
449+
return new Notification.Action.Builder(quickShare.getIcon(), quickShare.title,
450+
broadcastIntent)
451+
.setContextual(true)
452+
.addExtras(extras)
453+
.build();
454+
}
455+
456+
private Intent createFillInIntent(Uri uri, long imageTime) {
457+
Intent fillIn = new Intent();
458+
fillIn.setType("image/png");
459+
fillIn.putExtra(Intent.EXTRA_STREAM, uri);
460+
String subjectDate = DateFormat.getDateTimeInstance().format(new Date(imageTime));
425461
String subject = String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate);
426-
sharingIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
462+
fillIn.putExtra(Intent.EXTRA_SUBJECT, subject);
427463
// Include URI in ClipData also, so that grantPermission picks it up.
428464
// We don't use setData here because some apps interpret this as "to:".
429-
ClipData clipdata = new ClipData(new ClipDescription("content",
430-
new String[]{"image/png"}),
465+
ClipData clipData = new ClipData(
466+
new ClipDescription("content", new String[]{"image/png"}),
431467
new ClipData.Item(uri));
432-
sharingIntent.setClipData(clipdata);
433-
sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
434-
PendingIntent updatedPendingIntent = PendingIntent.getActivity(
435-
context, 0, sharingIntent,
436-
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
437-
438-
// Proxy smart actions through {@link SmartActionsReceiver} for logging smart actions.
439-
Bundle extras = action.getExtras();
440-
String actionType = extras.getString(
441-
ScreenshotNotificationSmartActionsProvider.ACTION_TYPE,
442-
ScreenshotNotificationSmartActionsProvider.DEFAULT_ACTION_TYPE);
443-
Intent intent = new Intent(context, SmartActionsReceiver.class)
444-
.putExtra(ScreenshotController.EXTRA_ACTION_INTENT, updatedPendingIntent)
445-
.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
446-
addIntentExtras(mScreenshotId, intent, actionType, mSmartActionsEnabled);
447-
PendingIntent broadcastIntent = PendingIntent.getBroadcast(context,
448-
mRandom.nextInt(),
449-
intent,
450-
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
451-
return new Notification.Action.Builder(action.getIcon(), action.title,
452-
broadcastIntent).setContextual(true).addExtras(extras).build();
468+
fillIn.setClipData(clipData);
469+
fillIn.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
470+
return fillIn;
453471
}
454472

455473
/**
456474
* Query and surface Quick Share chip if it is available. Action intent would not be used,
457475
* because it does not contain image URL which would be populated in {@link
458-
* #createQuickShareAction(Context, Notification.Action, Uri)}
476+
* #createQuickShareAction(Notification.Action, String, Uri, long, Bitmap, UserHandle)}
459477
*/
460-
private void queryQuickShareAction(Bitmap image, UserHandle user) {
478+
479+
@VisibleForTesting
480+
Notification.Action queryQuickShareAction(
481+
String screenshotId, Bitmap image, UserHandle user, Uri uri) {
461482
CompletableFuture<List<Notification.Action>> quickShareActionsFuture =
462483
mScreenshotSmartActions.getSmartActionsFuture(
463-
mScreenshotId, null, image, mSmartActionsProvider,
464-
QUICK_SHARE_ACTION,
484+
screenshotId, uri, image, mSmartActionsProvider, QUICK_SHARE_ACTION,
465485
mSmartActionsEnabled, user);
466486
int timeoutMs = DeviceConfig.getInt(
467487
DeviceConfig.NAMESPACE_SYSTEMUI,
468488
SystemUiDeviceConfigFlags.SCREENSHOT_NOTIFICATION_QUICK_SHARE_ACTIONS_TIMEOUT_MS,
469489
500);
470490
List<Notification.Action> quickShareActions =
471491
mScreenshotSmartActions.getSmartActions(
472-
mScreenshotId, quickShareActionsFuture, timeoutMs,
492+
screenshotId, quickShareActionsFuture, timeoutMs,
473493
mSmartActionsProvider, QUICK_SHARE_ACTION);
474494
if (!quickShareActions.isEmpty()) {
475-
mQuickShareData.quickShareAction = quickShareActions.get(0);
476-
mParams.mQuickShareActionsReadyListener.onActionsReady(mQuickShareData);
495+
return quickShareActions.get(0);
477496
}
497+
return null;
478498
}
479499
}

packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ interface TransitionDestination {
234234
static final String EXTRA_SMART_ACTIONS_ENABLED = "android:smart_actions_enabled";
235235
static final String EXTRA_OVERRIDE_TRANSITION = "android:screenshot_override_transition";
236236
static final String EXTRA_ACTION_INTENT = "android:screenshot_action_intent";
237+
static final String EXTRA_ACTION_INTENT_FILLIN = "android:screenshot_action_intent_fillin";
237238

238239
static final String SCREENSHOT_URI_ID = "android:screenshot_uri_id";
239240
static final String EXTRA_CANCEL_NOTIFICATION = "android:screenshot_cancel_notification";

packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsReceiver.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import static com.android.systemui.screenshot.LogConfig.DEBUG_ACTIONS;
2020
import static com.android.systemui.screenshot.ScreenshotController.EXTRA_ACTION_INTENT;
21+
import static com.android.systemui.screenshot.ScreenshotController.EXTRA_ACTION_INTENT_FILLIN;
2122
import static com.android.systemui.screenshot.ScreenshotController.EXTRA_ACTION_TYPE;
2223
import static com.android.systemui.screenshot.ScreenshotController.EXTRA_ID;
2324

@@ -46,15 +47,17 @@ public class SmartActionsReceiver extends BroadcastReceiver {
4647

4748
@Override
4849
public void onReceive(Context context, Intent intent) {
49-
PendingIntent pendingIntent = intent.getParcelableExtra(EXTRA_ACTION_INTENT);
50+
PendingIntent pendingIntent =
51+
intent.getParcelableExtra(EXTRA_ACTION_INTENT, PendingIntent.class);
52+
Intent fillIn = intent.getParcelableExtra(EXTRA_ACTION_INTENT_FILLIN, Intent.class);
5053
String actionType = intent.getStringExtra(EXTRA_ACTION_TYPE);
5154
if (DEBUG_ACTIONS) {
5255
Log.d(TAG, "Executing smart action [" + actionType + "]:" + pendingIntent.getIntent());
5356
}
5457
ActivityOptions opts = ActivityOptions.makeBasic();
5558

5659
try {
57-
pendingIntent.send(context, 0, null, null, null, null, opts.toBundle());
60+
pendingIntent.send(context, 0, fillIn, null, null, null, opts.toBundle());
5861
} catch (PendingIntent.CanceledException e) {
5962
Log.e(TAG, "Pending intent canceled", e);
6063
}

0 commit comments

Comments
 (0)