diff options
7 files changed, 84 insertions, 89 deletions
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index 35a4f475c878..5b87eeac938d 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -758,7 +758,8 @@ public final class DisplayManagerService extends SystemService { mContext.registerReceiver(mIdleModeReceiver, filter); - mSmallAreaDetectionController = SmallAreaDetectionController.create(mContext); + mSmallAreaDetectionController = (mFlags.isSmallAreaDetectionEnabled()) + ? SmallAreaDetectionController.create(mContext) : null; } @VisibleForTesting diff --git a/services/core/java/com/android/server/display/SmallAreaDetectionController.java b/services/core/java/com/android/server/display/SmallAreaDetectionController.java index adaa5390cb9b..bf384b02d95e 100644 --- a/services/core/java/com/android/server/display/SmallAreaDetectionController.java +++ b/services/core/java/com/android/server/display/SmallAreaDetectionController.java @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.content.pm.PackageManagerInternal; +import android.os.UserHandle; import android.provider.DeviceConfig; import android.provider.DeviceConfigInterface; import android.util.ArrayMap; @@ -30,15 +31,14 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.BackgroundThread; import com.android.server.LocalServices; -import com.android.server.pm.UserManagerInternal; +import com.android.server.pm.pkg.PackageStateInternal; import java.io.PrintWriter; -import java.util.Arrays; import java.util.Map; final class SmallAreaDetectionController { - private static native void nativeUpdateSmallAreaDetection(int[] uids, float[] thresholds); - private static native void nativeSetSmallAreaDetectionThreshold(int uid, float threshold); + private static native void nativeUpdateSmallAreaDetection(int[] appIds, float[] thresholds); + private static native void nativeSetSmallAreaDetectionThreshold(int appId, float threshold); // TODO(b/281720315): Move this to DeviceConfig once server side ready. private static final String KEY_SMALL_AREA_DETECTION_ALLOWLIST = @@ -47,12 +47,8 @@ final class SmallAreaDetectionController { private final Object mLock = new Object(); private final Context mContext; private final PackageManagerInternal mPackageManager; - private final UserManagerInternal mUserManager; @GuardedBy("mLock") private final Map<String, Float> mAllowPkgMap = new ArrayMap<>(); - // TODO(b/298722189): Update allowlist when user changes - @GuardedBy("mLock") - private int[] mUserIds; static SmallAreaDetectionController create(@NonNull Context context) { final SmallAreaDetectionController controller = @@ -67,7 +63,6 @@ final class SmallAreaDetectionController { SmallAreaDetectionController(Context context, DeviceConfigInterface deviceConfig) { mContext = context; mPackageManager = LocalServices.getService(PackageManagerInternal.class); - mUserManager = LocalServices.getService(UserManagerInternal.class); deviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER, BackgroundThread.getExecutor(), new SmallAreaDetectionController.OnPropertiesChangedListener()); @@ -76,6 +71,7 @@ final class SmallAreaDetectionController { @VisibleForTesting void updateAllowlist(@Nullable String property) { + final Map<String, Float> allowPkgMap = new ArrayMap<>(); synchronized (mLock) { mAllowPkgMap.clear(); if (property != null) { @@ -86,8 +82,11 @@ final class SmallAreaDetectionController { .getStringArray(R.array.config_smallAreaDetectionAllowlist); for (String defaultMapString : defaultMapStrings) putToAllowlist(defaultMapString); } - updateSmallAreaDetection(); + + if (mAllowPkgMap.isEmpty()) return; + allowPkgMap.putAll(mAllowPkgMap); } + updateSmallAreaDetection(allowPkgMap); } @GuardedBy("mLock") @@ -105,43 +104,32 @@ final class SmallAreaDetectionController { } } - @GuardedBy("mLock") - private void updateUidListForAllUsers(SparseArray<Float> list, String pkg, float threshold) { - for (int i = 0; i < mUserIds.length; i++) { - final int userId = mUserIds[i]; - final int uid = mPackageManager.getPackageUid(pkg, 0, userId); - if (uid > 0) list.put(uid, threshold); - } - } - - @GuardedBy("mLock") - private void updateSmallAreaDetection() { - if (mAllowPkgMap.isEmpty()) return; - - mUserIds = mUserManager.getUserIds(); - - final SparseArray<Float> uidThresholdList = new SparseArray<>(); - for (String pkg : mAllowPkgMap.keySet()) { - final float threshold = mAllowPkgMap.get(pkg); - updateUidListForAllUsers(uidThresholdList, pkg, threshold); + private void updateSmallAreaDetection(Map<String, Float> allowPkgMap) { + final SparseArray<Float> appIdThresholdList = new SparseArray(allowPkgMap.size()); + for (String pkg : allowPkgMap.keySet()) { + final float threshold = allowPkgMap.get(pkg); + final PackageStateInternal stage = mPackageManager.getPackageStateInternal(pkg); + if (stage != null) { + appIdThresholdList.put(stage.getAppId(), threshold); + } } - final int[] uids = new int[uidThresholdList.size()]; - final float[] thresholds = new float[uidThresholdList.size()]; - for (int i = 0; i < uidThresholdList.size(); i++) { - uids[i] = uidThresholdList.keyAt(i); - thresholds[i] = uidThresholdList.valueAt(i); + final int[] appIds = new int[appIdThresholdList.size()]; + final float[] thresholds = new float[appIdThresholdList.size()]; + for (int i = 0; i < appIdThresholdList.size(); i++) { + appIds[i] = appIdThresholdList.keyAt(i); + thresholds[i] = appIdThresholdList.valueAt(i); } - updateSmallAreaDetection(uids, thresholds); + updateSmallAreaDetection(appIds, thresholds); } @VisibleForTesting - void updateSmallAreaDetection(int[] uids, float[] thresholds) { - nativeUpdateSmallAreaDetection(uids, thresholds); + void updateSmallAreaDetection(int[] appIds, float[] thresholds) { + nativeUpdateSmallAreaDetection(appIds, thresholds); } - void setSmallAreaDetectionThreshold(int uid, float threshold) { - nativeSetSmallAreaDetectionThreshold(uid, threshold); + void setSmallAreaDetectionThreshold(int appId, float threshold) { + nativeSetSmallAreaDetectionThreshold(appId, threshold); } void dump(PrintWriter pw) { @@ -151,7 +139,6 @@ final class SmallAreaDetectionController { for (String pkg : mAllowPkgMap.keySet()) { pw.println(" " + pkg + " threshold = " + mAllowPkgMap.get(pkg)); } - pw.println(" mUserIds=" + Arrays.toString(mUserIds)); } } @@ -167,11 +154,15 @@ final class SmallAreaDetectionController { private final class PackageReceiver implements PackageManagerInternal.PackageListObserver { @Override public void onPackageAdded(@NonNull String packageName, int uid) { + float threshold = 0.0f; synchronized (mLock) { if (mAllowPkgMap.containsKey(packageName)) { - setSmallAreaDetectionThreshold(uid, mAllowPkgMap.get(packageName)); + threshold = mAllowPkgMap.get(packageName); } } + if (threshold > 0.0f) { + setSmallAreaDetectionThreshold(UserHandle.getAppId(uid), threshold); + } } } } diff --git a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java index fae8383bb62e..d953e8e52365 100644 --- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java +++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java @@ -71,6 +71,10 @@ public class DisplayManagerFlags { Flags.FLAG_ENABLE_POWER_THROTTLING_CLAMPER, Flags::enablePowerThrottlingClamper); + private final FlagState mSmallAreaDetectionFlagState = new FlagState( + Flags.FLAG_ENABLE_SMALL_AREA_DETECTION, + Flags::enableSmallAreaDetection); + /** Returns whether connected display management is enabled or not. */ public boolean isConnectedDisplayManagementEnabled() { return mConnectedDisplayManagementFlagState.isEnabled(); @@ -147,6 +151,10 @@ public class DisplayManagerFlags { return mBackUpSmoothDisplayAndForcePeakRefreshRateFlagState.isEnabled(); } + public boolean isSmallAreaDetectionEnabled() { + return mSmallAreaDetectionFlagState.isEnabled(); + } + private static class FlagState { private final String mName; diff --git a/services/core/java/com/android/server/display/feature/display_flags.aconfig b/services/core/java/com/android/server/display/feature/display_flags.aconfig index 9ab9c9def61b..9141814da6fc 100644 --- a/services/core/java/com/android/server/display/feature/display_flags.aconfig +++ b/services/core/java/com/android/server/display/feature/display_flags.aconfig @@ -104,3 +104,12 @@ flag { bug: "211737588" is_fixed_read_only: true } + +flag { + name: "enable_small_area_detection" + namespace: "display_manager" + description: "Feature flag for SmallAreaDetection" + bug: "298722189" + is_fixed_read_only: true +} + diff --git a/services/core/jni/com_android_server_display_SmallAreaDetectionController.cpp b/services/core/jni/com_android_server_display_SmallAreaDetectionController.cpp index b256f168f2af..1844d3063cd8 100644 --- a/services/core/jni/com_android_server_display_SmallAreaDetectionController.cpp +++ b/services/core/jni/com_android_server_display_SmallAreaDetectionController.cpp @@ -24,33 +24,33 @@ #include "utils/Log.h" namespace android { -static void nativeUpdateSmallAreaDetection(JNIEnv* env, jclass clazz, jintArray juids, +static void nativeUpdateSmallAreaDetection(JNIEnv* env, jclass clazz, jintArray jappIds, jfloatArray jthresholds) { - if (juids == nullptr || jthresholds == nullptr) return; + if (jappIds == nullptr || jthresholds == nullptr) return; - ScopedIntArrayRO uids(env, juids); + ScopedIntArrayRO appIds(env, jappIds); ScopedFloatArrayRO thresholds(env, jthresholds); - if (uids.size() != thresholds.size()) { - ALOGE("uids size exceeds thresholds size!"); + if (appIds.size() != thresholds.size()) { + ALOGE("appIds size exceeds thresholds size!"); return; } - std::vector<int32_t> uidVector; + std::vector<int32_t> appIdVector; std::vector<float> thresholdVector; - size_t size = uids.size(); - uidVector.reserve(size); + size_t size = appIds.size(); + appIdVector.reserve(size); thresholdVector.reserve(size); for (int i = 0; i < size; i++) { - uidVector.push_back(static_cast<int32_t>(uids[i])); + appIdVector.push_back(static_cast<int32_t>(appIds[i])); thresholdVector.push_back(static_cast<float>(thresholds[i])); } - SurfaceComposerClient::updateSmallAreaDetection(uidVector, thresholdVector); + SurfaceComposerClient::updateSmallAreaDetection(appIdVector, thresholdVector); } -static void nativeSetSmallAreaDetectionThreshold(JNIEnv* env, jclass clazz, jint uid, +static void nativeSetSmallAreaDetectionThreshold(JNIEnv* env, jclass clazz, jint appId, jfloat threshold) { - SurfaceComposerClient::setSmallAreaDetectionThreshold(uid, threshold); + SurfaceComposerClient::setSmallAreaDetectionThreshold(appId, threshold); } static const JNINativeMethod gMethods[] = { diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java index d021f1d5aaea..16d72e40fbb5 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java @@ -117,7 +117,6 @@ import com.android.server.display.feature.DisplayManagerFlags; import com.android.server.display.notifications.DisplayNotificationManager; import com.android.server.input.InputManagerInternal; import com.android.server.lights.LightsManager; -import com.android.server.pm.UserManagerInternal; import com.android.server.sensors.SensorManagerInternal; import com.android.server.wm.WindowManagerInternal; @@ -312,7 +311,6 @@ public class DisplayManagerServiceTest { @Mock SensorManager mSensorManager; @Mock DisplayDeviceConfig mMockDisplayDeviceConfig; @Mock PackageManagerInternal mMockPackageManagerInternal; - @Mock UserManagerInternal mMockUserManagerInternal; @Captor ArgumentCaptor<ContentRecordingSession> mContentRecordingSessionCaptor; @@ -336,8 +334,6 @@ public class DisplayManagerServiceTest { VirtualDeviceManagerInternal.class, mMockVirtualDeviceManagerInternal); LocalServices.removeServiceForTest(PackageManagerInternal.class); LocalServices.addService(PackageManagerInternal.class, mMockPackageManagerInternal); - LocalServices.removeServiceForTest(UserManagerInternal.class); - LocalServices.addService(UserManagerInternal.class, mMockUserManagerInternal); // TODO: b/287945043 mContext = spy(new ContextWrapper(ApplicationProvider.getApplicationContext())); mResources = Mockito.spy(mContext.getResources()); diff --git a/services/tests/mockingservicestests/src/com/android/server/display/SmallAreaDetectionControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/display/SmallAreaDetectionControllerTest.java index 1ce79a5b596b..05ac5b5720e6 100644 --- a/services/tests/mockingservicestests/src/com/android/server/display/SmallAreaDetectionControllerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/display/SmallAreaDetectionControllerTest.java @@ -16,8 +16,6 @@ package com.android.server.display; -import static android.os.Process.INVALID_UID; - import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; @@ -35,7 +33,7 @@ import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.server.LocalServices; -import com.android.server.pm.UserManagerInternal; +import com.android.server.pm.pkg.PackageStateInternal; import org.junit.Before; import org.junit.Rule; @@ -55,7 +53,10 @@ public class SmallAreaDetectionControllerTest { @Mock private PackageManagerInternal mMockPackageManagerInternal; @Mock - private UserManagerInternal mMockUserManagerInternal; + private PackageStateInternal mMockPkgStateA; + @Mock + private PackageStateInternal mMockPkgStateB; + private SmallAreaDetectionController mSmallAreaDetectionController; @@ -64,29 +65,18 @@ public class SmallAreaDetectionControllerTest { private static final String PKG_NOT_INSTALLED = "com.not.installed"; private static final float THRESHOLD_A = 0.05f; private static final float THRESHOLD_B = 0.07f; - private static final int USER_1 = 110; - private static final int USER_2 = 111; - private static final int UID_A_1 = 11011111; - private static final int UID_A_2 = 11111111; - private static final int UID_B_1 = 11022222; - private static final int UID_B_2 = 11122222; + private static final int APP_ID_A = 11111; + private static final int APP_ID_B = 22222; @Before public void setup() { LocalServices.removeServiceForTest(PackageManagerInternal.class); LocalServices.addService(PackageManagerInternal.class, mMockPackageManagerInternal); - LocalServices.removeServiceForTest(UserManagerInternal.class); - LocalServices.addService(UserManagerInternal.class, mMockUserManagerInternal); - - when(mMockUserManagerInternal.getUserIds()).thenReturn(new int[]{USER_1, USER_2}); - when(mMockPackageManagerInternal.getPackageUid(PKG_A, 0, USER_1)).thenReturn(UID_A_1); - when(mMockPackageManagerInternal.getPackageUid(PKG_A, 0, USER_2)).thenReturn(UID_A_2); - when(mMockPackageManagerInternal.getPackageUid(PKG_B, 0, USER_1)).thenReturn(UID_B_1); - when(mMockPackageManagerInternal.getPackageUid(PKG_B, 0, USER_2)).thenReturn(UID_B_2); - when(mMockPackageManagerInternal.getPackageUid(PKG_NOT_INSTALLED, 0, USER_1)).thenReturn( - INVALID_UID); - when(mMockPackageManagerInternal.getPackageUid(PKG_NOT_INSTALLED, 0, USER_2)).thenReturn( - INVALID_UID); + + when(mMockPackageManagerInternal.getPackageStateInternal(PKG_A)).thenReturn(mMockPkgStateA); + when(mMockPackageManagerInternal.getPackageStateInternal(PKG_B)).thenReturn(mMockPkgStateB); + when(mMockPkgStateA.getAppId()).thenReturn(APP_ID_A); + when(mMockPkgStateB.getAppId()).thenReturn(APP_ID_B); mSmallAreaDetectionController = spy(new SmallAreaDetectionController( new ContextWrapper(ApplicationProvider.getApplicationContext()), @@ -99,9 +89,9 @@ public class SmallAreaDetectionControllerTest { final String property = PKG_A + ":" + THRESHOLD_A + "," + PKG_B + ":" + THRESHOLD_B; mSmallAreaDetectionController.updateAllowlist(property); - final int[] resultUidArray = {UID_A_1, UID_B_1, UID_A_2, UID_B_2}; - final float[] resultThresholdArray = {THRESHOLD_A, THRESHOLD_B, THRESHOLD_A, THRESHOLD_B}; - verify(mSmallAreaDetectionController).updateSmallAreaDetection(eq(resultUidArray), + final int[] resultAppIdArray = {APP_ID_A, APP_ID_B}; + final float[] resultThresholdArray = {THRESHOLD_A, THRESHOLD_B}; + verify(mSmallAreaDetectionController).updateSmallAreaDetection(eq(resultAppIdArray), eq(resultThresholdArray)); } @@ -110,9 +100,9 @@ public class SmallAreaDetectionControllerTest { final String property = PKG_A + "," + PKG_B + ":" + THRESHOLD_B; mSmallAreaDetectionController.updateAllowlist(property); - final int[] resultUidArray = {UID_B_1, UID_B_2}; - final float[] resultThresholdArray = {THRESHOLD_B, THRESHOLD_B}; - verify(mSmallAreaDetectionController).updateSmallAreaDetection(eq(resultUidArray), + final int[] resultAppIdArray = {APP_ID_B}; + final float[] resultThresholdArray = {THRESHOLD_B}; + verify(mSmallAreaDetectionController).updateSmallAreaDetection(eq(resultAppIdArray), eq(resultThresholdArray)); } @@ -122,9 +112,9 @@ public class SmallAreaDetectionControllerTest { PKG_A + ":" + THRESHOLD_A + "," + PKG_NOT_INSTALLED + ":" + THRESHOLD_B; mSmallAreaDetectionController.updateAllowlist(property); - final int[] resultUidArray = {UID_A_1, UID_A_2}; - final float[] resultThresholdArray = {THRESHOLD_A, THRESHOLD_A}; - verify(mSmallAreaDetectionController).updateSmallAreaDetection(eq(resultUidArray), + final int[] resultAppIdArray = {APP_ID_A}; + final float[] resultThresholdArray = {THRESHOLD_A}; + verify(mSmallAreaDetectionController).updateSmallAreaDetection(eq(resultAppIdArray), eq(resultThresholdArray)); } |