Loading core/java/android/service/notification/StatusBarNotification.java +50 −13 Original line number Diff line number Diff line Loading @@ -30,13 +30,17 @@ import android.metrics.LogMaker; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.os.Trace; import android.os.UserHandle; import android.util.ArrayMap; import com.android.internal.logging.InstanceId; import com.android.internal.logging.nano.MetricsProto; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import static com.android.window.flags.Flags.enablePerDisplayPackageContextCacheInStatusbarNotif; import java.util.ArrayList; import java.util.Map; /** * Class encapsulating a Notification. Sent by the NotificationManagerService to clients including Loading Loading @@ -69,7 +73,15 @@ public class StatusBarNotification implements Parcelable { // A small per-notification ID, used for statsd logging. private InstanceId mInstanceId; // Not final, see setInstanceId() /** * @deprecated This field is only used when * {@link enablePerDisplayPackageContextCacheInStatusbarNotif} * is disabled. */ @Deprecated private Context mContext; // used for inflation & icon expansion // Maps display id to context used for remote view content inflation and status bar icon. private final Map<Integer, Context> mContextForDisplayId = new ArrayMap<>(); /** @hide */ public StatusBarNotification(String pkg, String opPkg, int id, Loading Loading @@ -453,8 +465,12 @@ public class StatusBarNotification implements Parcelable { * @hide */ public void clearPackageContext() { if (enablePerDisplayPackageContextCacheInStatusbarNotif()) { mContextForDisplayId.clear(); } else { mContext = null; } } /** * @hide Loading @@ -475,10 +491,16 @@ public class StatusBarNotification implements Parcelable { */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public Context getPackageContext(Context context) { if (enablePerDisplayPackageContextCacheInStatusbarNotif()) { if (context == null) return null; return mContextForDisplayId.computeIfAbsent(context.getDisplayId(), (displayId) -> createPackageContext(context)); } else { if (mContext == null) { try { ApplicationInfo ai = context.getPackageManager() .getApplicationInfoAsUser(pkg, PackageManager.MATCH_UNINSTALLED_PACKAGES, .getApplicationInfoAsUser(pkg, PackageManager.MATCH_UNINSTALLED_PACKAGES, getNormalizedUserId()); mContext = context.createApplicationContext(ai, Context.CONTEXT_RESTRICTED); Loading @@ -491,6 +513,21 @@ public class StatusBarNotification implements Parcelable { } return mContext; } } private Context createPackageContext(Context context) { try { Trace.beginSection("StatusBarNotification#createPackageContext"); ApplicationInfo ai = context.getPackageManager() .getApplicationInfoAsUser(pkg, PackageManager.MATCH_UNINSTALLED_PACKAGES, getNormalizedUserId()); return context.createApplicationContext(ai, Context.CONTEXT_RESTRICTED); } catch (PackageManager.NameNotFoundException e) { return context; } finally { Trace.endSection(); } } /** * Returns a LogMaker that contains all basic information of the notification. Loading core/java/android/window/flags/lse_desktop_experience.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -530,6 +530,16 @@ flag { bug: "381935663" } flag { name: "enable_per_display_package_context_cache_in_statusbar_notif" namespace: "lse_desktop_experience" description: "Enables per-display package context caching in StatusBarNotification" bug: "388886443" metadata { purpose: PURPOSE_BUGFIX } } flag { name: "enable_desktop_wallpaper_activity_for_system_user" namespace: "lse_desktop_experience" Loading core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java +33 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static junit.framework.Assert.assertNotSame; import static junit.framework.Assert.assertNull; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; Loading @@ -35,14 +36,19 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.metrics.LogMaker; import android.os.UserHandle; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.view.Display; import androidx.test.InstrumentationRegistry; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.window.flags.Flags; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; Loading @@ -52,11 +58,16 @@ import org.mockito.MockitoAnnotations; @SmallTest public class StatusBarNotificationTest { @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); private final Context mMockContext = mock(Context.class); @Mock private Context mRealContext; @Mock private PackageManager mPm; @Mock private Context mSecondaryDisplayContext; private static final String PKG = "com.example.o"; private static final int UID = 9583; Loading @@ -80,6 +91,10 @@ public class StatusBarNotificationTest { InstrumentationRegistry.getContext().getResources()); when(mMockContext.getPackageManager()).thenReturn(mPm); when(mMockContext.getApplicationInfo()).thenReturn(new ApplicationInfo()); when(mMockContext.getDisplayId()).thenReturn(Display.DEFAULT_DISPLAY); when(mSecondaryDisplayContext.getPackageManager()).thenReturn(mPm); when(mSecondaryDisplayContext.getApplicationInfo()).thenReturn(new ApplicationInfo()); when(mSecondaryDisplayContext.getDisplayId()).thenReturn(2); when(mPm.getApplicationLabel(any())).thenReturn(""); mRealContext = InstrumentationRegistry.getContext(); Loading Loading @@ -220,6 +235,24 @@ public class StatusBarNotificationTest { assertEquals(pkg, resultContext.getPackageName()); } @Test @EnableFlags(Flags.FLAG_ENABLE_PER_DISPLAY_PACKAGE_CONTEXT_CACHE_IN_STATUSBAR_NOTIF) public void testGetPackageContext_multipleDisplaysCase() { String pkg = "com.android.systemui"; int uid = 1000; Notification notification = getNotificationBuilder(GROUP_ID_1, CHANNEL_ID).build(); StatusBarNotification sbn = new StatusBarNotification( pkg, pkg, ID, TAG, uid, uid, notification, UserHandle.ALL, null, UID); Context defaultContext = sbn.getPackageContext(mRealContext); Context secondaryContext = sbn.getPackageContext(mSecondaryDisplayContext); assertNotSame(mRealContext, defaultContext); assertNotSame(defaultContext, secondaryContext); // Let's make sure it caches it: assertSame(defaultContext, sbn.getPackageContext(mRealContext)); assertSame(secondaryContext, sbn.getPackageContext(mSecondaryDisplayContext)); } @Test public void testGetUidFromKey() { StatusBarNotification sbn = getNotification("pkg", null, "channel"); Loading Loading
core/java/android/service/notification/StatusBarNotification.java +50 −13 Original line number Diff line number Diff line Loading @@ -30,13 +30,17 @@ import android.metrics.LogMaker; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.os.Trace; import android.os.UserHandle; import android.util.ArrayMap; import com.android.internal.logging.InstanceId; import com.android.internal.logging.nano.MetricsProto; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import static com.android.window.flags.Flags.enablePerDisplayPackageContextCacheInStatusbarNotif; import java.util.ArrayList; import java.util.Map; /** * Class encapsulating a Notification. Sent by the NotificationManagerService to clients including Loading Loading @@ -69,7 +73,15 @@ public class StatusBarNotification implements Parcelable { // A small per-notification ID, used for statsd logging. private InstanceId mInstanceId; // Not final, see setInstanceId() /** * @deprecated This field is only used when * {@link enablePerDisplayPackageContextCacheInStatusbarNotif} * is disabled. */ @Deprecated private Context mContext; // used for inflation & icon expansion // Maps display id to context used for remote view content inflation and status bar icon. private final Map<Integer, Context> mContextForDisplayId = new ArrayMap<>(); /** @hide */ public StatusBarNotification(String pkg, String opPkg, int id, Loading Loading @@ -453,8 +465,12 @@ public class StatusBarNotification implements Parcelable { * @hide */ public void clearPackageContext() { if (enablePerDisplayPackageContextCacheInStatusbarNotif()) { mContextForDisplayId.clear(); } else { mContext = null; } } /** * @hide Loading @@ -475,10 +491,16 @@ public class StatusBarNotification implements Parcelable { */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public Context getPackageContext(Context context) { if (enablePerDisplayPackageContextCacheInStatusbarNotif()) { if (context == null) return null; return mContextForDisplayId.computeIfAbsent(context.getDisplayId(), (displayId) -> createPackageContext(context)); } else { if (mContext == null) { try { ApplicationInfo ai = context.getPackageManager() .getApplicationInfoAsUser(pkg, PackageManager.MATCH_UNINSTALLED_PACKAGES, .getApplicationInfoAsUser(pkg, PackageManager.MATCH_UNINSTALLED_PACKAGES, getNormalizedUserId()); mContext = context.createApplicationContext(ai, Context.CONTEXT_RESTRICTED); Loading @@ -491,6 +513,21 @@ public class StatusBarNotification implements Parcelable { } return mContext; } } private Context createPackageContext(Context context) { try { Trace.beginSection("StatusBarNotification#createPackageContext"); ApplicationInfo ai = context.getPackageManager() .getApplicationInfoAsUser(pkg, PackageManager.MATCH_UNINSTALLED_PACKAGES, getNormalizedUserId()); return context.createApplicationContext(ai, Context.CONTEXT_RESTRICTED); } catch (PackageManager.NameNotFoundException e) { return context; } finally { Trace.endSection(); } } /** * Returns a LogMaker that contains all basic information of the notification. Loading
core/java/android/window/flags/lse_desktop_experience.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -530,6 +530,16 @@ flag { bug: "381935663" } flag { name: "enable_per_display_package_context_cache_in_statusbar_notif" namespace: "lse_desktop_experience" description: "Enables per-display package context caching in StatusBarNotification" bug: "388886443" metadata { purpose: PURPOSE_BUGFIX } } flag { name: "enable_desktop_wallpaper_activity_for_system_user" namespace: "lse_desktop_experience" Loading
core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java +33 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static junit.framework.Assert.assertNotSame; import static junit.framework.Assert.assertNull; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; Loading @@ -35,14 +36,19 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.metrics.LogMaker; import android.os.UserHandle; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.view.Display; import androidx.test.InstrumentationRegistry; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.window.flags.Flags; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; Loading @@ -52,11 +58,16 @@ import org.mockito.MockitoAnnotations; @SmallTest public class StatusBarNotificationTest { @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); private final Context mMockContext = mock(Context.class); @Mock private Context mRealContext; @Mock private PackageManager mPm; @Mock private Context mSecondaryDisplayContext; private static final String PKG = "com.example.o"; private static final int UID = 9583; Loading @@ -80,6 +91,10 @@ public class StatusBarNotificationTest { InstrumentationRegistry.getContext().getResources()); when(mMockContext.getPackageManager()).thenReturn(mPm); when(mMockContext.getApplicationInfo()).thenReturn(new ApplicationInfo()); when(mMockContext.getDisplayId()).thenReturn(Display.DEFAULT_DISPLAY); when(mSecondaryDisplayContext.getPackageManager()).thenReturn(mPm); when(mSecondaryDisplayContext.getApplicationInfo()).thenReturn(new ApplicationInfo()); when(mSecondaryDisplayContext.getDisplayId()).thenReturn(2); when(mPm.getApplicationLabel(any())).thenReturn(""); mRealContext = InstrumentationRegistry.getContext(); Loading Loading @@ -220,6 +235,24 @@ public class StatusBarNotificationTest { assertEquals(pkg, resultContext.getPackageName()); } @Test @EnableFlags(Flags.FLAG_ENABLE_PER_DISPLAY_PACKAGE_CONTEXT_CACHE_IN_STATUSBAR_NOTIF) public void testGetPackageContext_multipleDisplaysCase() { String pkg = "com.android.systemui"; int uid = 1000; Notification notification = getNotificationBuilder(GROUP_ID_1, CHANNEL_ID).build(); StatusBarNotification sbn = new StatusBarNotification( pkg, pkg, ID, TAG, uid, uid, notification, UserHandle.ALL, null, UID); Context defaultContext = sbn.getPackageContext(mRealContext); Context secondaryContext = sbn.getPackageContext(mSecondaryDisplayContext); assertNotSame(mRealContext, defaultContext); assertNotSame(defaultContext, secondaryContext); // Let's make sure it caches it: assertSame(defaultContext, sbn.getPackageContext(mRealContext)); assertSame(secondaryContext, sbn.getPackageContext(mSecondaryDisplayContext)); } @Test public void testGetUidFromKey() { StatusBarNotification sbn = getNotification("pkg", null, "channel"); Loading