summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Nicolò Mazzucato <nicomazz@google.com> 2025-01-13 08:08:39 -0800
committer Android (Google) Code Review <android-gerrit@google.com> 2025-01-13 08:08:39 -0800
commit878ba9230e7afe1d7286f47d57a5fecb227ac16b (patch)
tree176715aa1ad1f1a2bc2ccf418279f5694286e14f
parent17586613e8e9fa7af5fb4eae8f2cc3d96194bfe1 (diff)
parent5e1e59acb5f855eaa69172e1350ac049077c7634 (diff)
Merge "Fix Notification inflation on secondary displays" into main
-rw-r--r--core/java/android/service/notification/StatusBarNotification.java63
-rw-r--r--core/java/android/window/flags/lse_desktop_experience.aconfig10
-rw-r--r--core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java33
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");