diff options
| author | 2025-01-13 08:08:39 -0800 | |
|---|---|---|
| committer | 2025-01-13 08:08:39 -0800 | |
| commit | 878ba9230e7afe1d7286f47d57a5fecb227ac16b (patch) | |
| tree | 176715aa1ad1f1a2bc2ccf418279f5694286e14f | |
| parent | 17586613e8e9fa7af5fb4eae8f2cc3d96194bfe1 (diff) | |
| parent | 5e1e59acb5f855eaa69172e1350ac049077c7634 (diff) | |
Merge "Fix Notification inflation on secondary displays" into main
3 files changed, 93 insertions, 13 deletions
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java index 146c2b6fa46e..105fa3ffd4cd 100644 --- a/core/java/android/service/notification/StatusBarNotification.java +++ b/core/java/android/service/notification/StatusBarNotification.java @@ -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 @@ -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, @@ -453,7 +465,11 @@ public class StatusBarNotification implements Parcelable { * @hide */ public void clearPackageContext() { - mContext = null; + if (enablePerDisplayPackageContextCacheInStatusbarNotif()) { + mContextForDisplayId.clear(); + } else { + mContext = null; + } } /** @@ -475,21 +491,42 @@ public class StatusBarNotification implements Parcelable { */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public Context getPackageContext(Context context) { - if (mContext == null) { - try { - ApplicationInfo ai = context.getPackageManager() - .getApplicationInfoAsUser(pkg, PackageManager.MATCH_UNINSTALLED_PACKAGES, - getNormalizedUserId()); - mContext = context.createApplicationContext(ai, - Context.CONTEXT_RESTRICTED); - } catch (PackageManager.NameNotFoundException e) { - mContext = null; + 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, + getNormalizedUserId()); + mContext = context.createApplicationContext(ai, + Context.CONTEXT_RESTRICTED); + } catch (PackageManager.NameNotFoundException e) { + mContext = null; + } + } + if (mContext == null) { + mContext = context; } + return mContext; } - if (mContext == null) { - mContext = context; + } + + 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(); } - return mContext; } /** diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig index be0b4fea459c..91d9a16faf4d 100644 --- a/core/java/android/window/flags/lse_desktop_experience.aconfig +++ b/core/java/android/window/flags/lse_desktop_experience.aconfig @@ -531,6 +531,16 @@ flag { } 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" description: "Enables starting DesktopWallpaperActivity on system user." diff --git a/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java b/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java index 504240812559..7a4cc7f98a1a 100644 --- a/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java +++ b/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java @@ -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; @@ -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; @@ -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; @@ -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(); @@ -221,6 +236,24 @@ public class StatusBarNotificationTest { } @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"); |