Skip to content

Commit 50cdf7c

Browse files
author
Dianne Hackborn
committed
Fix issue #7214090: Need to be able to post notifications to all users
Also fix a bunch of system services that should be doing this. And while doing that, found I needed to fix PendingIntent to evaluate USER_CURRENT at the point of sending, not creation. Note that this may end up with us having some notification shown to non-primary users that lead to settings UI that should only be for the primary user (such as the vpn notification). I'm not sure what to do about this, maybe we need a different UI to come up there or something, but showing the actual notification for those users at least seems less broken than not telling them at all. Change-Id: Iffc51e2d7c847e3d05064d292ab93937646a1ab7
1 parent 6b3292c commit 50cdf7c

File tree

17 files changed

+125
-65
lines changed

17 files changed

+125
-65
lines changed

core/java/android/accounts/AccountManagerService.java

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -647,16 +647,17 @@ public void removeAccount(IAccountManagerResponse response, Account account) {
647647
if (response == null) throw new IllegalArgumentException("response is null");
648648
if (account == null) throw new IllegalArgumentException("account is null");
649649
checkManageAccountsPermission();
650+
UserHandle user = Binder.getCallingUserHandle();
650651
UserAccounts accounts = getUserAccountsForCaller();
651652
long identityToken = clearCallingIdentity();
652653

653-
cancelNotification(getSigninRequiredNotificationId(accounts, account));
654+
cancelNotification(getSigninRequiredNotificationId(accounts, account), user);
654655
synchronized(accounts.credentialsPermissionNotificationIds) {
655656
for (Pair<Pair<Account, String>, Integer> pair:
656657
accounts.credentialsPermissionNotificationIds.keySet()) {
657658
if (account.equals(pair.first.first)) {
658659
int id = accounts.credentialsPermissionNotificationIds.get(pair);
659-
cancelNotification(id);
660+
cancelNotification(id, user);
660661
}
661662
}
662663
}
@@ -789,7 +790,8 @@ private boolean saveAuthTokenToDatabase(UserAccounts accounts, Account account,
789790
if (account == null || type == null) {
790791
return false;
791792
}
792-
cancelNotification(getSigninRequiredNotificationId(accounts, account));
793+
cancelNotification(getSigninRequiredNotificationId(accounts, account),
794+
new UserHandle(accounts.userId));
793795
synchronized (accounts.cacheLock) {
794796
final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
795797
db.beginTransaction();
@@ -1173,11 +1175,12 @@ private void createNoCredentialsPermissionNotification(Account account, Intent i
11731175
title = titleAndSubtitle.substring(0, index);
11741176
subtitle = titleAndSubtitle.substring(index + 1);
11751177
}
1178+
UserHandle user = new UserHandle(userId);
11761179
n.setLatestEventInfo(mContext, title, subtitle,
11771180
PendingIntent.getActivityAsUser(mContext, 0, intent,
1178-
PendingIntent.FLAG_CANCEL_CURRENT,
1179-
null, new UserHandle(userId)));
1180-
installNotification(getCredentialPermissionNotificationId(account, authTokenType, uid), n);
1181+
PendingIntent.FLAG_CANCEL_CURRENT, null, user));
1182+
installNotification(getCredentialPermissionNotificationId(
1183+
account, authTokenType, uid), n, user);
11811184
}
11821185

11831186
String getAccountLabel(String accountType) {
@@ -1763,7 +1766,8 @@ public void onResult(Bundle result) {
17631766
String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
17641767
if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) {
17651768
Account account = new Account(accountName, accountType);
1766-
cancelNotification(getSigninRequiredNotificationId(mAccounts, account));
1769+
cancelNotification(getSigninRequiredNotificationId(mAccounts, account),
1770+
new UserHandle(mAccounts.userId));
17671771
}
17681772
}
17691773
IAccountManagerResponse response;
@@ -2101,30 +2105,32 @@ private void doNotification(UserAccounts accounts, Account account, CharSequence
21012105
intent.addCategory(String.valueOf(notificationId));
21022106
Notification n = new Notification(android.R.drawable.stat_sys_warning, null,
21032107
0 /* when */);
2108+
UserHandle user = new UserHandle(userId);
21042109
final String notificationTitleFormat =
21052110
mContext.getText(R.string.notification_title).toString();
21062111
n.setLatestEventInfo(mContext,
21072112
String.format(notificationTitleFormat, account.name),
21082113
message, PendingIntent.getActivityAsUser(
21092114
mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT,
2110-
null, new UserHandle(userId)));
2111-
installNotification(notificationId, n);
2115+
null, user));
2116+
installNotification(notificationId, n, user);
21122117
}
21132118
} finally {
21142119
restoreCallingIdentity(identityToken);
21152120
}
21162121
}
21172122

2118-
protected void installNotification(final int notificationId, final Notification n) {
2123+
protected void installNotification(final int notificationId, final Notification n,
2124+
UserHandle user) {
21192125
((NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE))
2120-
.notify(notificationId, n);
2126+
.notifyAsUser(null, notificationId, n, user);
21212127
}
21222128

2123-
protected void cancelNotification(int id) {
2129+
protected void cancelNotification(int id, UserHandle user) {
21242130
long identityToken = clearCallingIdentity();
21252131
try {
21262132
((NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE))
2127-
.cancel(id);
2133+
.cancelAsUser(null, id, user);
21282134
} finally {
21292135
restoreCallingIdentity(identityToken);
21302136
}
@@ -2289,7 +2295,8 @@ private void grantAppPermission(Account account, String authTokenType, int uid)
22892295
} finally {
22902296
db.endTransaction();
22912297
}
2292-
cancelNotification(getCredentialPermissionNotificationId(account, authTokenType, uid));
2298+
cancelNotification(getCredentialPermissionNotificationId(account, authTokenType, uid),
2299+
new UserHandle(accounts.userId));
22932300
}
22942301
}
22952302

@@ -2323,7 +2330,8 @@ private void revokeAppPermission(Account account, String authTokenType, int uid)
23232330
} finally {
23242331
db.endTransaction();
23252332
}
2326-
cancelNotification(getCredentialPermissionNotificationId(account, authTokenType, uid));
2333+
cancelNotification(getCredentialPermissionNotificationId(account, authTokenType, uid),
2334+
new UserHandle(accounts.userId));
23272335
}
23282336
}
23292337

core/java/android/app/PendingIntent.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,8 @@ public static PendingIntent getActivity(Context context, int requestCode,
265265

266266
/**
267267
* @hide
268+
* Note that UserHandle.CURRENT will be interpreted at the time the
269+
* activity is started, not when the pending intent is created.
268270
*/
269271
public static PendingIntent getActivityAsUser(Context context, int requestCode,
270272
Intent intent, int flags, Bundle options, UserHandle user) {
@@ -417,7 +419,11 @@ public static PendingIntent getBroadcast(Context context, int requestCode,
417419
new UserHandle(UserHandle.myUserId()));
418420
}
419421

420-
/** @hide */
422+
/**
423+
* @hide
424+
* Note that UserHandle.CURRENT will be interpreted at the time the
425+
* broadcast is sent, not when the pending intent is created.
426+
*/
421427
public static PendingIntent getBroadcastAsUser(Context context, int requestCode,
422428
Intent intent, int flags, UserHandle userHandle) {
423429
String packageName = context.getPackageName();

core/java/com/android/internal/statusbar/StatusBarNotification.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public class StatusBarNotification implements Parcelable {
4848
public final int score;
4949
public final UserHandle user;
5050

51+
/** This is temporarily needed for the JB MR1 PDK. */
5152
@Deprecated
5253
public StatusBarNotification(String pkg, int id, String tag, int uid, int initialPid, int score,
5354
Notification notification) {
@@ -143,6 +144,6 @@ public boolean isClearable() {
143144

144145
/** Returns a userHandle for the instance of the app that posted this notification. */
145146
public int getUserId() {
146-
return UserHandle.getUserId(this.uid);
147+
return this.user.getIdentifier();
147148
}
148149
}

core/tests/coretests/src/android/accounts/AccountManagerServiceTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import android.content.pm.RegisteredServicesCacheListener;
2424
import android.os.Bundle;
2525
import android.os.Handler;
26+
import android.os.UserHandle;
2627
import android.test.AndroidTestCase;
2728
import android.test.IsolatedContext;
2829
import android.test.RenamingDelegatingContext;
@@ -243,11 +244,11 @@ public MyAccountManagerService(Context context, PackageManager packageManager,
243244
}
244245

245246
@Override
246-
protected void installNotification(final int notificationId, final Notification n) {
247+
protected void installNotification(final int notificationId, final Notification n, UserHandle user) {
247248
}
248249

249250
@Override
250-
protected void cancelNotification(final int id) {
251+
protected void cancelNotification(final int id, UserHandle user) {
251252
}
252253
}
253254
}

packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,8 @@ public boolean notificationIsForCurrentUser(StatusBarNotification n) {
293293
Slog.v(TAG, String.format("%s: current userid: %d, notification userid: %d",
294294
n, thisUserId, notificationUserId));
295295
}
296-
return thisUserId == notificationUserId;
296+
return notificationUserId == UserHandle.USER_ALL
297+
|| thisUserId == notificationUserId;
297298
}
298299

299300
protected View updateNotificationVetoButton(View row, StatusBarNotification n) {

packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import android.os.Environment;
2626
import android.os.Handler;
2727
import android.os.HandlerThread;
28+
import android.os.UserHandle;
2829
import android.os.storage.StorageEventListener;
2930
import android.os.storage.StorageManager;
3031
import android.provider.Settings;
@@ -311,7 +312,8 @@ private synchronized void setUsbStorageNotification(int titleId, int messageId,
311312
mUsbStorageNotification.tickerText = title;
312313
if (pi == null) {
313314
Intent intent = new Intent();
314-
pi = PendingIntent.getBroadcast(mContext, 0, intent, 0);
315+
pi = PendingIntent.getBroadcastAsUser(mContext, 0, intent, 0,
316+
UserHandle.CURRENT);
315317
}
316318

317319
mUsbStorageNotification.setLatestEventInfo(mContext, title, message, pi);
@@ -336,9 +338,10 @@ private synchronized void setUsbStorageNotification(int titleId, int messageId,
336338

337339
final int notificationId = mUsbStorageNotification.icon;
338340
if (visible) {
339-
notificationManager.notify(notificationId, mUsbStorageNotification);
341+
notificationManager.notifyAsUser(null, notificationId, mUsbStorageNotification,
342+
UserHandle.ALL);
340343
} else {
341-
notificationManager.cancel(notificationId);
344+
notificationManager.cancelAsUser(null, notificationId, UserHandle.ALL);
342345
}
343346
}
344347

@@ -398,7 +401,8 @@ private synchronized void setMediaStorageNotification(int titleId, int messageId
398401
mMediaStorageNotification.tickerText = title;
399402
if (pi == null) {
400403
Intent intent = new Intent();
401-
pi = PendingIntent.getBroadcast(mContext, 0, intent, 0);
404+
pi = PendingIntent.getBroadcastAsUser(mContext, 0, intent, 0,
405+
UserHandle.CURRENT);
402406
}
403407

404408
mMediaStorageNotification.icon = icon;
@@ -407,9 +411,10 @@ private synchronized void setMediaStorageNotification(int titleId, int messageId
407411

408412
final int notificationId = mMediaStorageNotification.icon;
409413
if (visible) {
410-
notificationManager.notify(notificationId, mMediaStorageNotification);
414+
notificationManager.notifyAsUser(null, notificationId,
415+
mMediaStorageNotification, UserHandle.ALL);
411416
} else {
412-
notificationManager.cancel(notificationId);
417+
notificationManager.cancelAsUser(null, notificationId, UserHandle.ALL);
413418
}
414419
}
415420
}

services/java/com/android/server/DeviceStorageMonitorService.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -396,13 +396,15 @@ private final void sendNotification() {
396396
com.android.internal.R.string.low_internal_storage_view_title);
397397
CharSequence details = mContext.getText(
398398
com.android.internal.R.string.low_internal_storage_view_text);
399-
PendingIntent intent = PendingIntent.getActivity(mContext, 0, lowMemIntent, 0);
399+
PendingIntent intent = PendingIntent.getActivityAsUser(mContext, 0, lowMemIntent, 0,
400+
null, UserHandle.CURRENT);
400401
Notification notification = new Notification();
401402
notification.icon = com.android.internal.R.drawable.stat_notify_disk_full;
402403
notification.tickerText = title;
403404
notification.flags |= Notification.FLAG_NO_CLEAR;
404405
notification.setLatestEventInfo(mContext, title, details, intent);
405-
mNotificationMgr.notify(LOW_MEMORY_NOTIFICATION_ID, notification);
406+
mNotificationMgr.notifyAsUser(null, LOW_MEMORY_NOTIFICATION_ID, notification,
407+
UserHandle.ALL);
406408
mContext.sendStickyBroadcast(mStorageLowIntent);
407409
}
408410

@@ -415,7 +417,7 @@ private final void cancelNotification() {
415417
(NotificationManager)mContext.getSystemService(
416418
Context.NOTIFICATION_SERVICE);
417419
//cancel notification since memory has been freed
418-
mNotificationMgr.cancel(LOW_MEMORY_NOTIFICATION_ID);
420+
mNotificationMgr.cancelAsUser(null, LOW_MEMORY_NOTIFICATION_ID, UserHandle.ALL);
419421

420422
mContext.removeStickyBroadcastAsUser(mStorageLowIntent, UserHandle.ALL);
421423
mContext.sendBroadcastAsUser(mStorageOkIntent, UserHandle.ALL);

services/java/com/android/server/NotificationManagerService.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@
5353
import android.os.UserHandle;
5454
import android.os.Vibrator;
5555
import android.provider.Settings;
56-
import android.service.dreams.IDreamManager;
5756
import android.telephony.TelephonyManager;
5857
import android.text.TextUtils;
5958
import android.util.AtomicFile;
@@ -890,7 +889,7 @@ public void enqueueNotificationInternal(String pkg, int callingUid, int callingP
890889
final boolean isSystemNotification = ("android".equals(pkg));
891890

892891
userId = ActivityManager.handleIncomingUser(callingPid,
893-
callingUid, userId, false, true, "enqueueNotification", pkg);
892+
callingUid, userId, true, true, "enqueueNotification", pkg);
894893

895894
// Limit the number of notifications that any given package except the android
896895
// package can enqueue. Prevents DOS attacks and deals with leaks.
@@ -900,7 +899,7 @@ public void enqueueNotificationInternal(String pkg, int callingUid, int callingP
900899
final int N = mNotificationList.size();
901900
for (int i=0; i<N; i++) {
902901
final NotificationRecord r = mNotificationList.get(i);
903-
if (r.pkg.equals(pkg)) {
902+
if (r.pkg.equals(pkg) && r.userId == userId) {
904903
count++;
905904
if (count >= MAX_PACKAGE_NOTIFICATIONS) {
906905
Slog.e(TAG, "Package has already posted " + count
@@ -1261,7 +1260,7 @@ boolean cancelAllNotificationsInt(String pkg, int mustHaveFlags,
12611260
public void cancelNotificationWithTag(String pkg, String tag, int id, int userId) {
12621261
checkCallerIsSystemOrSameApp(pkg);
12631262
userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
1264-
Binder.getCallingUid(), userId, false, true, "cancelNotificationWithTag", pkg);
1263+
Binder.getCallingUid(), userId, true, true, "cancelNotificationWithTag", pkg);
12651264
// Don't allow client applications to cancel foreground service notis.
12661265
cancelNotification(pkg, tag, id, 0,
12671266
Binder.getCallingUid() == Process.SYSTEM_UID

services/java/com/android/server/ThrottleService.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,8 @@ private void postNotification(int titleInt, int messageInt, int icon, int flags)
670670
intent.setClassName("com.android.phone", "com.android.phone.DataUsage");
671671
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
672672

673-
PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
673+
PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0, intent, 0,
674+
null, UserHandle.CURRENT);
674675

675676
Resources r = Resources.getSystem();
676677
CharSequence title = r.getText(titleInt);
@@ -686,7 +687,8 @@ private void postNotification(int titleInt, int messageInt, int icon, int flags)
686687
mThrottlingNotification.tickerText = title;
687688
mThrottlingNotification.setLatestEventInfo(mContext, title, message, pi);
688689

689-
mNotificationManager.notify(mThrottlingNotification.icon, mThrottlingNotification);
690+
mNotificationManager.notifyAsUser(null, mThrottlingNotification.icon,
691+
mThrottlingNotification, UserHandle.ALL);
690692
}
691693

692694

@@ -701,7 +703,8 @@ private void clearThrottleAndNotification() {
701703
Intent broadcast = new Intent(ThrottleManager.THROTTLE_ACTION);
702704
broadcast.putExtra(ThrottleManager.EXTRA_THROTTLE_LEVEL, -1);
703705
mContext.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL);
704-
mNotificationManager.cancel(R.drawable.stat_sys_throttled);
706+
mNotificationManager.cancelAsUser(null, R.drawable.stat_sys_throttled,
707+
UserHandle.ALL);
705708
mWarningNotificationSent = false;
706709
}
707710
}

services/java/com/android/server/UiModeManagerService.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -521,10 +521,13 @@ private void adjustStatusBarCarModeLocked() {
521521
mContext,
522522
mContext.getString(R.string.car_mode_disable_notification_title),
523523
mContext.getString(R.string.car_mode_disable_notification_message),
524-
PendingIntent.getActivity(mContext, 0, carModeOffIntent, 0));
525-
mNotificationManager.notify(0, n);
524+
PendingIntent.getActivityAsUser(mContext, 0, carModeOffIntent, 0,
525+
null, UserHandle.CURRENT));
526+
mNotificationManager.notifyAsUser(null,
527+
R.string.car_mode_disable_notification_title, n, UserHandle.ALL);
526528
} else {
527-
mNotificationManager.cancel(0);
529+
mNotificationManager.cancelAsUser(null,
530+
R.string.car_mode_disable_notification_title, UserHandle.ALL);
528531
}
529532
}
530533
}

0 commit comments

Comments
 (0)