Loading services/core/java/com/android/server/wm/BackgroundActivityStartController.java +30 −16 Original line number Diff line number Diff line Loading @@ -1016,7 +1016,8 @@ public class BackgroundActivityStartController { } if (state.mCallingUidHasNonAppVisibleWindow) { return new BalVerdict(BAL_ALLOW_NON_APP_VISIBLE_WINDOW, /*background*/ false, "callingUid has non-app visible window"); /*background*/ false, "callingUid has non-app visible window " + mService.mActiveUids.getNonAppVisibleWindowDetails(state.mCallingUid)); } // Don't abort if the callerApp or other processes of that uid are considered to be in the // foreground. Loading Loading @@ -1142,7 +1143,8 @@ public class BackgroundActivityStartController { } if (state.mRealCallingUidHasNonAppVisibleWindow) { return new BalVerdict(BAL_ALLOW_NON_APP_VISIBLE_WINDOW, /*background*/ false, "realCallingUid has non-app visible window"); /*background*/ false, "realCallingUid has non-app visible window " + mService.mActiveUids.getNonAppVisibleWindowDetails(state.mRealCallingUid)); } // Don't abort if the realCallerApp or other processes of that uid are considered to be in Loading Loading @@ -1894,20 +1896,8 @@ public class BackgroundActivityStartController { (state.mOriginatingPendingIntent != null)); } if (finalVerdict.getRawCode() == BAL_ALLOW_GRACE_PERIOD) { if (state.realCallerExplicitOptInOrAutoOptIn() && state.mResultForRealCaller.allows() && state.mResultForRealCaller.getRawCode() != BAL_ALLOW_GRACE_PERIOD) { // real caller could allow with a different exemption } else if (state.callerExplicitOptInOrAutoOptIn() && state.mResultForCaller.allows() && state.mResultForCaller.getRawCode() != BAL_ALLOW_GRACE_PERIOD) { // caller could allow with a different exemption } else { // log to determine grace period length distribution Slog.wtf(TAG, "Activity start ONLY allowed by BAL_ALLOW_GRACE_PERIOD " + finalVerdict.mMessage + ": " + state); } } logIfOnlyAllowedBy(finalVerdict, state, BAL_ALLOW_GRACE_PERIOD); logIfOnlyAllowedBy(finalVerdict, state, BAL_ALLOW_NON_APP_VISIBLE_WINDOW); if (balImprovedMetrics()) { if (shouldLogStats(finalVerdict, state)) { Loading Loading @@ -1946,6 +1936,30 @@ public class BackgroundActivityStartController { return finalVerdict; } /** * Logs details about the activity starts if the only reason it is allowed is the provided * {@code balCode}. */ private static void logIfOnlyAllowedBy(BalVerdict finalVerdict, BalState state, int balCode) { if (finalVerdict.getRawCode() == balCode) { if (state.realCallerExplicitOptInOrAutoOptIn() && state.mResultForRealCaller != null && state.mResultForRealCaller.allows() && state.mResultForRealCaller.getRawCode() != balCode) { // real caller could allow with a different exemption } else if (state.callerExplicitOptInOrAutoOptIn() && state.mResultForCaller != null && state.mResultForCaller.allows() && state.mResultForCaller.getRawCode() != balCode) { // caller could allow with a different exemption } else { // log to determine grace period length distribution Slog.wtf(TAG, "Activity start ONLY allowed by " + balCodeToString(balCode) + " " + finalVerdict.mMessage + ": " + state); } } } @VisibleForTesting boolean shouldLogStats(BalVerdict finalVerdict, BalState state) { if (finalVerdict.getRawCode() == BAL_ALLOW_VISIBLE_WINDOW) { Loading services/core/java/com/android/server/wm/MirrorActiveUids.java +41 −6 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.wm; import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; import android.app.ActivityManager.ProcessState; import android.util.SparseArray; import android.util.SparseIntArray; import java.io.PrintWriter; Loading @@ -34,6 +35,8 @@ class MirrorActiveUids { /** Uid -> number of non-app visible windows belong to the uid. */ private final SparseIntArray mNumNonAppVisibleWindowMap = new SparseIntArray(); /** Type -> Uid -> number of non-app visible windows for type/uid. */ private final SparseArray<SparseIntArray> mNumNonAppVisibleWindowMapByType = new SparseArray(); synchronized void onUidActive(int uid, int procState) { mUidStates.put(uid, procState); Loading @@ -55,17 +58,31 @@ class MirrorActiveUids { } /** Called when the surface of non-application (exclude toast) window is shown or hidden. */ synchronized void onNonAppSurfaceVisibilityChanged(int uid, boolean visible) { final int index = mNumNonAppVisibleWindowMap.indexOfKey(uid); synchronized void onNonAppSurfaceVisibilityChanged(int uid, int type, boolean visible) { updateCount(uid, visible, mNumNonAppVisibleWindowMap); updateCount(uid, visible, getNumNonAppVisibleWindowMapByType(type)); } private SparseIntArray getNumNonAppVisibleWindowMapByType(int type) { SparseIntArray result = mNumNonAppVisibleWindowMapByType.get(type); if (result == null) { result = new SparseIntArray(); mNumNonAppVisibleWindowMapByType.append(type, result); } return result; } private void updateCount(int uid, boolean visible, SparseIntArray numNonAppVisibleWindowMap) { final int index = numNonAppVisibleWindowMap.indexOfKey(uid); if (index >= 0) { final int num = mNumNonAppVisibleWindowMap.valueAt(index) + (visible ? 1 : -1); final int num = numNonAppVisibleWindowMap.valueAt(index) + (visible ? 1 : -1); if (num > 0) { mNumNonAppVisibleWindowMap.setValueAt(index, num); numNonAppVisibleWindowMap.setValueAt(index, num); } else { mNumNonAppVisibleWindowMap.removeAt(index); numNonAppVisibleWindowMap.removeAt(index); } } else if (visible) { mNumNonAppVisibleWindowMap.append(uid, 1); numNonAppVisibleWindowMap.append(uid, 1); } } Loading @@ -78,6 +95,24 @@ class MirrorActiveUids { return mNumNonAppVisibleWindowMap.get(uid) > 0; } /** * Returns details about the windows that contribute to the result of * {@link #hasNonAppVisibleWindow(int)}. * * @return a map of window type to count */ synchronized SparseIntArray getNonAppVisibleWindowDetails(int uid) { SparseIntArray result = new SparseIntArray(); for (int i = 0; i < mNumNonAppVisibleWindowMapByType.size(); i++) { SparseIntArray numNonAppVisibleWindowMap = mNumNonAppVisibleWindowMapByType.valueAt(i); int count = numNonAppVisibleWindowMap.get(uid); if (count > 0) { result.append(mNumNonAppVisibleWindowMapByType.keyAt(i), count); } } return result; } synchronized void dump(PrintWriter pw, String prefix) { pw.print(prefix + "NumNonAppVisibleWindowUidMap:["); for (int i = mNumNonAppVisibleWindowMap.size() - 1; i >= 0; i--) { Loading services/core/java/com/android/server/wm/WindowState.java +2 −1 Original line number Diff line number Diff line Loading @@ -3436,7 +3436,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP && mAttrs.type != TYPE_PRIVATE_PRESENTATION && !(mAttrs.type == TYPE_PRESENTATION && isOnVirtualDisplay()) ) { mWmService.mAtmService.mActiveUids.onNonAppSurfaceVisibilityChanged(mOwnerUid, shown); mWmService.mAtmService.mActiveUids.onNonAppSurfaceVisibilityChanged(mOwnerUid, mAttrs.type, shown); } } Loading services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerExemptionTests.java +4 −2 Original line number Diff line number Diff line Loading @@ -333,7 +333,8 @@ public class BackgroundActivityStartControllerExemptionTests { int realCallingPid = REGULAR_PID_2; // setup state mActiveUids.onNonAppSurfaceVisibilityChanged(callingUid, true); mActiveUids.onNonAppSurfaceVisibilityChanged(callingUid, WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY, true); when(mService.getBalAppSwitchesState()).thenReturn(APP_SWITCH_ALLOW); // prepare call Loading Loading @@ -367,7 +368,8 @@ public class BackgroundActivityStartControllerExemptionTests { int realCallingPid = REGULAR_PID_2; // setup state mActiveUids.onNonAppSurfaceVisibilityChanged(realCallingUid, true); mActiveUids.onNonAppSurfaceVisibilityChanged(realCallingUid, WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY, true); when(mService.getBalAppSwitchesState()).thenReturn(APP_SWITCH_ALLOW); // prepare call Loading Loading
services/core/java/com/android/server/wm/BackgroundActivityStartController.java +30 −16 Original line number Diff line number Diff line Loading @@ -1016,7 +1016,8 @@ public class BackgroundActivityStartController { } if (state.mCallingUidHasNonAppVisibleWindow) { return new BalVerdict(BAL_ALLOW_NON_APP_VISIBLE_WINDOW, /*background*/ false, "callingUid has non-app visible window"); /*background*/ false, "callingUid has non-app visible window " + mService.mActiveUids.getNonAppVisibleWindowDetails(state.mCallingUid)); } // Don't abort if the callerApp or other processes of that uid are considered to be in the // foreground. Loading Loading @@ -1142,7 +1143,8 @@ public class BackgroundActivityStartController { } if (state.mRealCallingUidHasNonAppVisibleWindow) { return new BalVerdict(BAL_ALLOW_NON_APP_VISIBLE_WINDOW, /*background*/ false, "realCallingUid has non-app visible window"); /*background*/ false, "realCallingUid has non-app visible window " + mService.mActiveUids.getNonAppVisibleWindowDetails(state.mRealCallingUid)); } // Don't abort if the realCallerApp or other processes of that uid are considered to be in Loading Loading @@ -1894,20 +1896,8 @@ public class BackgroundActivityStartController { (state.mOriginatingPendingIntent != null)); } if (finalVerdict.getRawCode() == BAL_ALLOW_GRACE_PERIOD) { if (state.realCallerExplicitOptInOrAutoOptIn() && state.mResultForRealCaller.allows() && state.mResultForRealCaller.getRawCode() != BAL_ALLOW_GRACE_PERIOD) { // real caller could allow with a different exemption } else if (state.callerExplicitOptInOrAutoOptIn() && state.mResultForCaller.allows() && state.mResultForCaller.getRawCode() != BAL_ALLOW_GRACE_PERIOD) { // caller could allow with a different exemption } else { // log to determine grace period length distribution Slog.wtf(TAG, "Activity start ONLY allowed by BAL_ALLOW_GRACE_PERIOD " + finalVerdict.mMessage + ": " + state); } } logIfOnlyAllowedBy(finalVerdict, state, BAL_ALLOW_GRACE_PERIOD); logIfOnlyAllowedBy(finalVerdict, state, BAL_ALLOW_NON_APP_VISIBLE_WINDOW); if (balImprovedMetrics()) { if (shouldLogStats(finalVerdict, state)) { Loading Loading @@ -1946,6 +1936,30 @@ public class BackgroundActivityStartController { return finalVerdict; } /** * Logs details about the activity starts if the only reason it is allowed is the provided * {@code balCode}. */ private static void logIfOnlyAllowedBy(BalVerdict finalVerdict, BalState state, int balCode) { if (finalVerdict.getRawCode() == balCode) { if (state.realCallerExplicitOptInOrAutoOptIn() && state.mResultForRealCaller != null && state.mResultForRealCaller.allows() && state.mResultForRealCaller.getRawCode() != balCode) { // real caller could allow with a different exemption } else if (state.callerExplicitOptInOrAutoOptIn() && state.mResultForCaller != null && state.mResultForCaller.allows() && state.mResultForCaller.getRawCode() != balCode) { // caller could allow with a different exemption } else { // log to determine grace period length distribution Slog.wtf(TAG, "Activity start ONLY allowed by " + balCodeToString(balCode) + " " + finalVerdict.mMessage + ": " + state); } } } @VisibleForTesting boolean shouldLogStats(BalVerdict finalVerdict, BalState state) { if (finalVerdict.getRawCode() == BAL_ALLOW_VISIBLE_WINDOW) { Loading
services/core/java/com/android/server/wm/MirrorActiveUids.java +41 −6 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.wm; import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; import android.app.ActivityManager.ProcessState; import android.util.SparseArray; import android.util.SparseIntArray; import java.io.PrintWriter; Loading @@ -34,6 +35,8 @@ class MirrorActiveUids { /** Uid -> number of non-app visible windows belong to the uid. */ private final SparseIntArray mNumNonAppVisibleWindowMap = new SparseIntArray(); /** Type -> Uid -> number of non-app visible windows for type/uid. */ private final SparseArray<SparseIntArray> mNumNonAppVisibleWindowMapByType = new SparseArray(); synchronized void onUidActive(int uid, int procState) { mUidStates.put(uid, procState); Loading @@ -55,17 +58,31 @@ class MirrorActiveUids { } /** Called when the surface of non-application (exclude toast) window is shown or hidden. */ synchronized void onNonAppSurfaceVisibilityChanged(int uid, boolean visible) { final int index = mNumNonAppVisibleWindowMap.indexOfKey(uid); synchronized void onNonAppSurfaceVisibilityChanged(int uid, int type, boolean visible) { updateCount(uid, visible, mNumNonAppVisibleWindowMap); updateCount(uid, visible, getNumNonAppVisibleWindowMapByType(type)); } private SparseIntArray getNumNonAppVisibleWindowMapByType(int type) { SparseIntArray result = mNumNonAppVisibleWindowMapByType.get(type); if (result == null) { result = new SparseIntArray(); mNumNonAppVisibleWindowMapByType.append(type, result); } return result; } private void updateCount(int uid, boolean visible, SparseIntArray numNonAppVisibleWindowMap) { final int index = numNonAppVisibleWindowMap.indexOfKey(uid); if (index >= 0) { final int num = mNumNonAppVisibleWindowMap.valueAt(index) + (visible ? 1 : -1); final int num = numNonAppVisibleWindowMap.valueAt(index) + (visible ? 1 : -1); if (num > 0) { mNumNonAppVisibleWindowMap.setValueAt(index, num); numNonAppVisibleWindowMap.setValueAt(index, num); } else { mNumNonAppVisibleWindowMap.removeAt(index); numNonAppVisibleWindowMap.removeAt(index); } } else if (visible) { mNumNonAppVisibleWindowMap.append(uid, 1); numNonAppVisibleWindowMap.append(uid, 1); } } Loading @@ -78,6 +95,24 @@ class MirrorActiveUids { return mNumNonAppVisibleWindowMap.get(uid) > 0; } /** * Returns details about the windows that contribute to the result of * {@link #hasNonAppVisibleWindow(int)}. * * @return a map of window type to count */ synchronized SparseIntArray getNonAppVisibleWindowDetails(int uid) { SparseIntArray result = new SparseIntArray(); for (int i = 0; i < mNumNonAppVisibleWindowMapByType.size(); i++) { SparseIntArray numNonAppVisibleWindowMap = mNumNonAppVisibleWindowMapByType.valueAt(i); int count = numNonAppVisibleWindowMap.get(uid); if (count > 0) { result.append(mNumNonAppVisibleWindowMapByType.keyAt(i), count); } } return result; } synchronized void dump(PrintWriter pw, String prefix) { pw.print(prefix + "NumNonAppVisibleWindowUidMap:["); for (int i = mNumNonAppVisibleWindowMap.size() - 1; i >= 0; i--) { Loading
services/core/java/com/android/server/wm/WindowState.java +2 −1 Original line number Diff line number Diff line Loading @@ -3436,7 +3436,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP && mAttrs.type != TYPE_PRIVATE_PRESENTATION && !(mAttrs.type == TYPE_PRESENTATION && isOnVirtualDisplay()) ) { mWmService.mAtmService.mActiveUids.onNonAppSurfaceVisibilityChanged(mOwnerUid, shown); mWmService.mAtmService.mActiveUids.onNonAppSurfaceVisibilityChanged(mOwnerUid, mAttrs.type, shown); } } Loading
services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerExemptionTests.java +4 −2 Original line number Diff line number Diff line Loading @@ -333,7 +333,8 @@ public class BackgroundActivityStartControllerExemptionTests { int realCallingPid = REGULAR_PID_2; // setup state mActiveUids.onNonAppSurfaceVisibilityChanged(callingUid, true); mActiveUids.onNonAppSurfaceVisibilityChanged(callingUid, WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY, true); when(mService.getBalAppSwitchesState()).thenReturn(APP_SWITCH_ALLOW); // prepare call Loading Loading @@ -367,7 +368,8 @@ public class BackgroundActivityStartControllerExemptionTests { int realCallingPid = REGULAR_PID_2; // setup state mActiveUids.onNonAppSurfaceVisibilityChanged(realCallingUid, true); mActiveUids.onNonAppSurfaceVisibilityChanged(realCallingUid, WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY, true); when(mService.getBalAppSwitchesState()).thenReturn(APP_SWITCH_ALLOW); // prepare call Loading