Loading core/java/android/window/flags/responsible_apis.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -49,3 +49,10 @@ flag { description: "Prevent BAL based on it is bound by foreground Uid but the app switch is stopped." bug: "283801068" } flag { name: "bal_improved_metrics" namespace: "responsible_apis" description: "Improved metrics." bug: "339245692" } services/core/java/com/android/server/wm/BackgroundActivityStartController.java +53 −17 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_FG_ONL import static com.android.server.wm.ActivityTaskSupervisor.getApplicationLabel; import static com.android.server.wm.PendingRemoteAnimationRegistry.TIMEOUT_MS; import static com.android.window.flags.Flags.balDontBringExistingBackgroundTaskStackToFg; import static com.android.window.flags.Flags.balImprovedMetrics; import static com.android.window.flags.Flags.balImproveRealCallerVisibilityCheck; import static com.android.window.flags.Flags.balRequireOptInByPendingIntentCreator; import static com.android.window.flags.Flags.balRequireOptInSameUid; Loading Loading @@ -1660,6 +1661,19 @@ public class BackgroundActivityStartController { (state.mOriginatingPendingIntent != null)); } if (balImprovedMetrics()) { if (shouldLogStats(finalVerdict, state)) { String activityName; if (shouldLogIntentActivity(finalVerdict, state)) { Intent intent = state.mIntent; activityName = intent == null ? "noIntent" // should never happen : requireNonNull(intent.getComponent()).flattenToShortString(); } else { activityName = ""; } writeBalAllowedLog(activityName, finalVerdict.getCode(), state); } } else { @BalCode int code = finalVerdict.getCode(); int callingUid = state.mCallingUid; int realCallingUid = state.mRealCallingUid; Loading @@ -1677,11 +1691,33 @@ public class BackgroundActivityStartController { || code == BAL_ALLOW_SAW_PERMISSION) { // We don't need to know which activity in this case. writeBalAllowedLog("", code, state); } } return finalVerdict; } @VisibleForTesting boolean shouldLogStats(BalVerdict finalVerdict, BalState state) { if (finalVerdict.blocks()) { return false; } if (!state.isPendingIntent() && finalVerdict.getRawCode() == BAL_ALLOW_VISIBLE_WINDOW) { return false; } if (state.mBalAllowedByPiSender.allowsBackgroundActivityStarts() && state.mResultForRealCaller.getRawCode() == BAL_ALLOW_VISIBLE_WINDOW) { return false; } return true; } @VisibleForTesting boolean shouldLogIntentActivity(BalVerdict finalVerdict, BalState state) { return finalVerdict.mBasedOnRealCaller ? state.mRealCallingUid < Process.FIRST_APPLICATION_UID : state.mCallingUid < Process.FIRST_APPLICATION_UID; } @VisibleForTesting void writeBalAllowedLog(String activityName, int code, BalState state) { FrameworkStatsLog.write(FrameworkStatsLog.BAL_ALLOWED, activityName, Loading services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerTests.java +49 −6 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ package com.android.server.wm; import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_PENDING_INTENT; import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_PERMISSION; import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_VISIBLE_WINDOW; import static com.android.server.wm.BackgroundActivityStartController.BAL_BLOCK; import static com.android.window.flags.Flags.balImprovedMetrics; import static com.google.common.truth.Truth.assertThat; Loading Loading @@ -144,6 +146,16 @@ public class BackgroundActivityStartControllerTests { mBalAllowedLogs.add(new BalAllowedLog(activityName, code)); } @Override boolean shouldLogStats(BalVerdict finalVerdict, BalState state) { return true; } @Override boolean shouldLogIntentActivity(BalVerdict finalVerdict, BalState state) { return true; } @Override BalVerdict checkBackgroundActivityStartAllowedByCaller(BalState state) { return mCallerVerdict.orElseGet( Loading Loading @@ -238,8 +250,13 @@ public class BackgroundActivityStartControllerTests { // assertions assertThat(verdict.getCode()).isEqualTo(BackgroundActivityStartController.BAL_BLOCK); if (balImprovedMetrics()) { assertThat(mBalAllowedLogs).containsExactly( new BalAllowedLog("package.app3/someClass", BAL_BLOCK)); } else { assertThat(mBalAllowedLogs).isEmpty(); // not allowed } } // Tests for BackgroundActivityStartController.checkBackgroundActivityStart Loading Loading @@ -268,8 +285,13 @@ public class BackgroundActivityStartControllerTests { // assertions assertThat(verdict).isEqualTo(BalVerdict.BLOCK); if (balImprovedMetrics()) { assertThat(mBalAllowedLogs).containsExactly( new BalAllowedLog("package.app3/someClass", BAL_BLOCK)); } else { assertThat(mBalAllowedLogs).isEmpty(); // not allowed } } @Test public void testRegularActivityStart_allowedByCaller_isAllowed() { Loading Loading @@ -298,8 +320,13 @@ public class BackgroundActivityStartControllerTests { // assertions assertThat(verdict).isEqualTo(callerVerdict); if (balImprovedMetrics()) { assertThat(mBalAllowedLogs).containsExactly( new BalAllowedLog("package.app3/someClass", callerVerdict.getCode())); } else { assertThat(mBalAllowedLogs).isEmpty(); // non-critical exception } } @Test public void testRegularActivityStart_allowedByRealCaller_isAllowed() { Loading Loading @@ -362,7 +389,13 @@ public class BackgroundActivityStartControllerTests { // assertions assertThat(verdict).isEqualTo(callerVerdict); assertThat(mBalAllowedLogs).containsExactly(new BalAllowedLog("", callerVerdict.getCode())); if (balImprovedMetrics()) { assertThat(mBalAllowedLogs).containsExactly( new BalAllowedLog("package.app3/someClass", callerVerdict.getCode())); } else { assertThat(mBalAllowedLogs).containsExactly( new BalAllowedLog("", callerVerdict.getCode())); } } @Test Loading Loading @@ -398,8 +431,13 @@ public class BackgroundActivityStartControllerTests { // assertions assertThat(verdict).isEqualTo(BalVerdict.BLOCK); if (balImprovedMetrics()) { assertThat(mBalAllowedLogs).containsExactly( new BalAllowedLog("package.app3/someClass", BAL_BLOCK)); } else { assertThat(mBalAllowedLogs).isEmpty(); } } @Test public void testPendingIntent_allowedByCallerAndOptIn_isAllowed() { Loading Loading @@ -430,8 +468,13 @@ public class BackgroundActivityStartControllerTests { // assertions assertThat(verdict).isEqualTo(callerVerdict); if (balImprovedMetrics()) { assertThat(mBalAllowedLogs).containsExactly( new BalAllowedLog("package.app3/someClass", callerVerdict.getCode())); } else { assertThat(mBalAllowedLogs).isEmpty(); } } @Test public void testPendingIntent_allowedByRealCallerAndOptIn_isAllowed() { Loading Loading
core/java/android/window/flags/responsible_apis.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -49,3 +49,10 @@ flag { description: "Prevent BAL based on it is bound by foreground Uid but the app switch is stopped." bug: "283801068" } flag { name: "bal_improved_metrics" namespace: "responsible_apis" description: "Improved metrics." bug: "339245692" }
services/core/java/com/android/server/wm/BackgroundActivityStartController.java +53 −17 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_FG_ONL import static com.android.server.wm.ActivityTaskSupervisor.getApplicationLabel; import static com.android.server.wm.PendingRemoteAnimationRegistry.TIMEOUT_MS; import static com.android.window.flags.Flags.balDontBringExistingBackgroundTaskStackToFg; import static com.android.window.flags.Flags.balImprovedMetrics; import static com.android.window.flags.Flags.balImproveRealCallerVisibilityCheck; import static com.android.window.flags.Flags.balRequireOptInByPendingIntentCreator; import static com.android.window.flags.Flags.balRequireOptInSameUid; Loading Loading @@ -1660,6 +1661,19 @@ public class BackgroundActivityStartController { (state.mOriginatingPendingIntent != null)); } if (balImprovedMetrics()) { if (shouldLogStats(finalVerdict, state)) { String activityName; if (shouldLogIntentActivity(finalVerdict, state)) { Intent intent = state.mIntent; activityName = intent == null ? "noIntent" // should never happen : requireNonNull(intent.getComponent()).flattenToShortString(); } else { activityName = ""; } writeBalAllowedLog(activityName, finalVerdict.getCode(), state); } } else { @BalCode int code = finalVerdict.getCode(); int callingUid = state.mCallingUid; int realCallingUid = state.mRealCallingUid; Loading @@ -1677,11 +1691,33 @@ public class BackgroundActivityStartController { || code == BAL_ALLOW_SAW_PERMISSION) { // We don't need to know which activity in this case. writeBalAllowedLog("", code, state); } } return finalVerdict; } @VisibleForTesting boolean shouldLogStats(BalVerdict finalVerdict, BalState state) { if (finalVerdict.blocks()) { return false; } if (!state.isPendingIntent() && finalVerdict.getRawCode() == BAL_ALLOW_VISIBLE_WINDOW) { return false; } if (state.mBalAllowedByPiSender.allowsBackgroundActivityStarts() && state.mResultForRealCaller.getRawCode() == BAL_ALLOW_VISIBLE_WINDOW) { return false; } return true; } @VisibleForTesting boolean shouldLogIntentActivity(BalVerdict finalVerdict, BalState state) { return finalVerdict.mBasedOnRealCaller ? state.mRealCallingUid < Process.FIRST_APPLICATION_UID : state.mCallingUid < Process.FIRST_APPLICATION_UID; } @VisibleForTesting void writeBalAllowedLog(String activityName, int code, BalState state) { FrameworkStatsLog.write(FrameworkStatsLog.BAL_ALLOWED, activityName, Loading
services/tests/wmtests/src/com/android/server/wm/BackgroundActivityStartControllerTests.java +49 −6 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ package com.android.server.wm; import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_PENDING_INTENT; import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_PERMISSION; import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_VISIBLE_WINDOW; import static com.android.server.wm.BackgroundActivityStartController.BAL_BLOCK; import static com.android.window.flags.Flags.balImprovedMetrics; import static com.google.common.truth.Truth.assertThat; Loading Loading @@ -144,6 +146,16 @@ public class BackgroundActivityStartControllerTests { mBalAllowedLogs.add(new BalAllowedLog(activityName, code)); } @Override boolean shouldLogStats(BalVerdict finalVerdict, BalState state) { return true; } @Override boolean shouldLogIntentActivity(BalVerdict finalVerdict, BalState state) { return true; } @Override BalVerdict checkBackgroundActivityStartAllowedByCaller(BalState state) { return mCallerVerdict.orElseGet( Loading Loading @@ -238,8 +250,13 @@ public class BackgroundActivityStartControllerTests { // assertions assertThat(verdict.getCode()).isEqualTo(BackgroundActivityStartController.BAL_BLOCK); if (balImprovedMetrics()) { assertThat(mBalAllowedLogs).containsExactly( new BalAllowedLog("package.app3/someClass", BAL_BLOCK)); } else { assertThat(mBalAllowedLogs).isEmpty(); // not allowed } } // Tests for BackgroundActivityStartController.checkBackgroundActivityStart Loading Loading @@ -268,8 +285,13 @@ public class BackgroundActivityStartControllerTests { // assertions assertThat(verdict).isEqualTo(BalVerdict.BLOCK); if (balImprovedMetrics()) { assertThat(mBalAllowedLogs).containsExactly( new BalAllowedLog("package.app3/someClass", BAL_BLOCK)); } else { assertThat(mBalAllowedLogs).isEmpty(); // not allowed } } @Test public void testRegularActivityStart_allowedByCaller_isAllowed() { Loading Loading @@ -298,8 +320,13 @@ public class BackgroundActivityStartControllerTests { // assertions assertThat(verdict).isEqualTo(callerVerdict); if (balImprovedMetrics()) { assertThat(mBalAllowedLogs).containsExactly( new BalAllowedLog("package.app3/someClass", callerVerdict.getCode())); } else { assertThat(mBalAllowedLogs).isEmpty(); // non-critical exception } } @Test public void testRegularActivityStart_allowedByRealCaller_isAllowed() { Loading Loading @@ -362,7 +389,13 @@ public class BackgroundActivityStartControllerTests { // assertions assertThat(verdict).isEqualTo(callerVerdict); assertThat(mBalAllowedLogs).containsExactly(new BalAllowedLog("", callerVerdict.getCode())); if (balImprovedMetrics()) { assertThat(mBalAllowedLogs).containsExactly( new BalAllowedLog("package.app3/someClass", callerVerdict.getCode())); } else { assertThat(mBalAllowedLogs).containsExactly( new BalAllowedLog("", callerVerdict.getCode())); } } @Test Loading Loading @@ -398,8 +431,13 @@ public class BackgroundActivityStartControllerTests { // assertions assertThat(verdict).isEqualTo(BalVerdict.BLOCK); if (balImprovedMetrics()) { assertThat(mBalAllowedLogs).containsExactly( new BalAllowedLog("package.app3/someClass", BAL_BLOCK)); } else { assertThat(mBalAllowedLogs).isEmpty(); } } @Test public void testPendingIntent_allowedByCallerAndOptIn_isAllowed() { Loading Loading @@ -430,8 +468,13 @@ public class BackgroundActivityStartControllerTests { // assertions assertThat(verdict).isEqualTo(callerVerdict); if (balImprovedMetrics()) { assertThat(mBalAllowedLogs).containsExactly( new BalAllowedLog("package.app3/someClass", callerVerdict.getCode())); } else { assertThat(mBalAllowedLogs).isEmpty(); } } @Test public void testPendingIntent_allowedByRealCallerAndOptIn_isAllowed() { Loading