Loading core/res/res/values/stoppable_fgs_system_apps.xml 0 → 100644 +26 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- /** * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ --> <resources> <!-- A list of system apps whose FGS can be stopped in the task manager. --> <string-array translatable="false" name="stoppable_fgs_system_apps"> </string-array> <!-- stoppable_fgs_system_apps which is supposed to be overridden by vendor --> <string-array translatable="false" name="vendor_stoppable_fgs_system_apps"> </string-array> </resources> core/res/res/values/symbols.xml +2 −0 Original line number Diff line number Diff line Loading @@ -1306,6 +1306,8 @@ <java-symbol type="array" name="vendor_policy_exempt_apps" /> <java-symbol type="array" name="cloneable_apps" /> <java-symbol type="array" name="config_securityStatePackages" /> <java-symbol type="array" name="stoppable_fgs_system_apps" /> <java-symbol type="array" name="vendor_stoppable_fgs_system_apps" /> <java-symbol type="drawable" name="default_wallpaper" /> <java-symbol type="drawable" name="default_lock_wallpaper" /> Loading packages/SystemUI/aconfig/systemui.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -1743,3 +1743,13 @@ flag { description: "An implementation of shortcut customizations through shortcut helper." bug: "365064144" } flag { name: "stoppable_fgs_system_app" namespace: "systemui" description: "System app with foreground service can opt in to be stoppable." bug: "376564917" metadata { purpose: PURPOSE_BUGFIX } } packages/SystemUI/multivalentTests/src/com/android/systemui/qs/FgsManagerControllerTest.java +33 −3 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import android.content.pm.UserInfo; import android.os.Binder; import android.os.RemoteException; import android.os.UserHandle; import android.platform.test.annotations.EnableFlags; import android.provider.DeviceConfig; import android.testing.TestableLooper; Loading @@ -49,6 +50,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.systemui.Flags; import com.android.systemui.SysuiTestCase; import com.android.systemui.animation.DialogTransitionAnimator; import com.android.systemui.broadcast.BroadcastDispatcher; Loading Loading @@ -314,6 +316,29 @@ public class FgsManagerControllerTest extends SysuiTestCase { Assert.assertEquals(0, mFmc.visibleButtonsCount()); } @Test @EnableFlags(Flags.FLAG_STOPPABLE_FGS_SYSTEM_APP) public void testButtonVisibilityOfStoppableApps() throws Exception { setUserProfiles(0); setBackgroundRestrictionExemptionReason("pkg", 12345, REASON_ALLOWLISTED_PACKAGE); setBackgroundRestrictionExemptionReason("vendor_pkg", 67890, REASON_ALLOWLISTED_PACKAGE); // Same as above, but apps are opt-in to be stoppable setStoppableApps(new String[] {"pkg"}, /* vendor */ false); setStoppableApps(new String[] {"vendor_pkg"}, /* vendor */ true); final Binder binder = new Binder(); setShowStopButtonForUserAllowlistedApps(true); // Both are foreground. mIForegroundServiceObserver.onForegroundStateChanged(binder, "pkg", 0, true); mIForegroundServiceObserver.onForegroundStateChanged(binder, "vendor_pkg", 0, true); Assert.assertEquals(2, mFmc.visibleButtonsCount()); // The vendor package is no longer foreground. Only `pkg` remains. mIForegroundServiceObserver.onForegroundStateChanged(binder, "vendor_pkg", 0, false); Assert.assertEquals(1, mFmc.visibleButtonsCount()); } @Test public void testShowUserVisibleJobsOnCreation() { // Test when the default is on. Loading @@ -321,7 +346,7 @@ public class FgsManagerControllerTest extends SysuiTestCase { SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_USER_VISIBLE_JOBS, "true", false); FgsManagerController fmc = new FgsManagerControllerImpl( mContext, mContext.getResources(), mMainExecutor, mBackgroundExecutor, mSystemClock, Loading @@ -348,7 +373,7 @@ public class FgsManagerControllerTest extends SysuiTestCase { SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_USER_VISIBLE_JOBS, "false", false); fmc = new FgsManagerControllerImpl( mContext, mContext.getResources(), mMainExecutor, mBackgroundExecutor, mSystemClock, Loading Loading @@ -446,6 +471,11 @@ public class FgsManagerControllerTest extends SysuiTestCase { .getBackgroundRestrictionExemptionReason(uid); } private void setStoppableApps(String[] packageNames, boolean vendor) throws Exception { overrideResource(vendor ? com.android.internal.R.array.vendor_stoppable_fgs_system_apps : com.android.internal.R.array.stoppable_fgs_system_apps, packageNames); } FgsManagerController createFgsManagerController() throws RemoteException { ArgumentCaptor<IForegroundServiceObserver> iForegroundServiceObserverArgumentCaptor = ArgumentCaptor.forClass(IForegroundServiceObserver.class); Loading @@ -455,7 +485,7 @@ public class FgsManagerControllerTest extends SysuiTestCase { ArgumentCaptor.forClass(BroadcastReceiver.class); FgsManagerController result = new FgsManagerControllerImpl( mContext, mContext.getResources(), mMainExecutor, mBackgroundExecutor, mSystemClock, Loading packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt +24 −1 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.content.Intent import android.content.IntentFilter import android.content.pm.PackageManager import android.content.pm.UserInfo import android.content.res.Resources import android.graphics.drawable.Drawable import android.os.IBinder import android.os.PowerExemptionManager Loading Loading @@ -54,6 +55,7 @@ import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.TASK_MANAGER_ import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_USER_VISIBLE_JOBS import com.android.internal.jank.InteractionJankMonitor import com.android.systemui.Dumpable import com.android.systemui.Flags; import com.android.systemui.res.R import com.android.systemui.animation.DialogCuj import com.android.systemui.animation.DialogTransitionAnimator Loading Loading @@ -137,7 +139,7 @@ interface FgsManagerController { @SysUISingleton class FgsManagerControllerImpl @Inject constructor( private val context: Context, @Main private val resources: Resources, @Main private val mainExecutor: Executor, @Background private val backgroundExecutor: Executor, private val systemClock: SystemClock, Loading Loading @@ -223,6 +225,14 @@ class FgsManagerControllerImpl @Inject constructor( private val userVisibleJobObserver = UserVisibleJobObserver() private val stoppableApps by lazy { resources .getStringArray(com.android.internal.R.array.stoppable_fgs_system_apps) } private val vendorStoppableApps by lazy { resources .getStringArray(com.android.internal.R.array.vendor_stoppable_fgs_system_apps) } override fun init() { synchronized(lock) { if (initialized) { Loading Loading @@ -725,9 +735,22 @@ class FgsManagerControllerImpl @Inject constructor( } else -> UIControl.NORMAL } // If the app wants to be a good citizen by being stoppable, even if the category it // belongs to is exempted for background restriction, let it be stoppable by user. if (Flags.stoppableFgsSystemApp()) { if (isStoppableApp(packageName)) { uiControl = UIControl.NORMAL } } uiControlInitialized = true } fun isStoppableApp(packageName: String): Boolean { return stoppableApps.contains(packageName) || vendorStoppableApps.contains(packageName) } override fun equals(other: Any?): Boolean { if (other !is UserPackage) { return false Loading Loading
core/res/res/values/stoppable_fgs_system_apps.xml 0 → 100644 +26 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- /** * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ --> <resources> <!-- A list of system apps whose FGS can be stopped in the task manager. --> <string-array translatable="false" name="stoppable_fgs_system_apps"> </string-array> <!-- stoppable_fgs_system_apps which is supposed to be overridden by vendor --> <string-array translatable="false" name="vendor_stoppable_fgs_system_apps"> </string-array> </resources>
core/res/res/values/symbols.xml +2 −0 Original line number Diff line number Diff line Loading @@ -1306,6 +1306,8 @@ <java-symbol type="array" name="vendor_policy_exempt_apps" /> <java-symbol type="array" name="cloneable_apps" /> <java-symbol type="array" name="config_securityStatePackages" /> <java-symbol type="array" name="stoppable_fgs_system_apps" /> <java-symbol type="array" name="vendor_stoppable_fgs_system_apps" /> <java-symbol type="drawable" name="default_wallpaper" /> <java-symbol type="drawable" name="default_lock_wallpaper" /> Loading
packages/SystemUI/aconfig/systemui.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -1743,3 +1743,13 @@ flag { description: "An implementation of shortcut customizations through shortcut helper." bug: "365064144" } flag { name: "stoppable_fgs_system_app" namespace: "systemui" description: "System app with foreground service can opt in to be stoppable." bug: "376564917" metadata { purpose: PURPOSE_BUGFIX } }
packages/SystemUI/multivalentTests/src/com/android/systemui/qs/FgsManagerControllerTest.java +33 −3 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import android.content.pm.UserInfo; import android.os.Binder; import android.os.RemoteException; import android.os.UserHandle; import android.platform.test.annotations.EnableFlags; import android.provider.DeviceConfig; import android.testing.TestableLooper; Loading @@ -49,6 +50,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.systemui.Flags; import com.android.systemui.SysuiTestCase; import com.android.systemui.animation.DialogTransitionAnimator; import com.android.systemui.broadcast.BroadcastDispatcher; Loading Loading @@ -314,6 +316,29 @@ public class FgsManagerControllerTest extends SysuiTestCase { Assert.assertEquals(0, mFmc.visibleButtonsCount()); } @Test @EnableFlags(Flags.FLAG_STOPPABLE_FGS_SYSTEM_APP) public void testButtonVisibilityOfStoppableApps() throws Exception { setUserProfiles(0); setBackgroundRestrictionExemptionReason("pkg", 12345, REASON_ALLOWLISTED_PACKAGE); setBackgroundRestrictionExemptionReason("vendor_pkg", 67890, REASON_ALLOWLISTED_PACKAGE); // Same as above, but apps are opt-in to be stoppable setStoppableApps(new String[] {"pkg"}, /* vendor */ false); setStoppableApps(new String[] {"vendor_pkg"}, /* vendor */ true); final Binder binder = new Binder(); setShowStopButtonForUserAllowlistedApps(true); // Both are foreground. mIForegroundServiceObserver.onForegroundStateChanged(binder, "pkg", 0, true); mIForegroundServiceObserver.onForegroundStateChanged(binder, "vendor_pkg", 0, true); Assert.assertEquals(2, mFmc.visibleButtonsCount()); // The vendor package is no longer foreground. Only `pkg` remains. mIForegroundServiceObserver.onForegroundStateChanged(binder, "vendor_pkg", 0, false); Assert.assertEquals(1, mFmc.visibleButtonsCount()); } @Test public void testShowUserVisibleJobsOnCreation() { // Test when the default is on. Loading @@ -321,7 +346,7 @@ public class FgsManagerControllerTest extends SysuiTestCase { SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_USER_VISIBLE_JOBS, "true", false); FgsManagerController fmc = new FgsManagerControllerImpl( mContext, mContext.getResources(), mMainExecutor, mBackgroundExecutor, mSystemClock, Loading @@ -348,7 +373,7 @@ public class FgsManagerControllerTest extends SysuiTestCase { SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_USER_VISIBLE_JOBS, "false", false); fmc = new FgsManagerControllerImpl( mContext, mContext.getResources(), mMainExecutor, mBackgroundExecutor, mSystemClock, Loading Loading @@ -446,6 +471,11 @@ public class FgsManagerControllerTest extends SysuiTestCase { .getBackgroundRestrictionExemptionReason(uid); } private void setStoppableApps(String[] packageNames, boolean vendor) throws Exception { overrideResource(vendor ? com.android.internal.R.array.vendor_stoppable_fgs_system_apps : com.android.internal.R.array.stoppable_fgs_system_apps, packageNames); } FgsManagerController createFgsManagerController() throws RemoteException { ArgumentCaptor<IForegroundServiceObserver> iForegroundServiceObserverArgumentCaptor = ArgumentCaptor.forClass(IForegroundServiceObserver.class); Loading @@ -455,7 +485,7 @@ public class FgsManagerControllerTest extends SysuiTestCase { ArgumentCaptor.forClass(BroadcastReceiver.class); FgsManagerController result = new FgsManagerControllerImpl( mContext, mContext.getResources(), mMainExecutor, mBackgroundExecutor, mSystemClock, Loading
packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt +24 −1 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.content.Intent import android.content.IntentFilter import android.content.pm.PackageManager import android.content.pm.UserInfo import android.content.res.Resources import android.graphics.drawable.Drawable import android.os.IBinder import android.os.PowerExemptionManager Loading Loading @@ -54,6 +55,7 @@ import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.TASK_MANAGER_ import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_USER_VISIBLE_JOBS import com.android.internal.jank.InteractionJankMonitor import com.android.systemui.Dumpable import com.android.systemui.Flags; import com.android.systemui.res.R import com.android.systemui.animation.DialogCuj import com.android.systemui.animation.DialogTransitionAnimator Loading Loading @@ -137,7 +139,7 @@ interface FgsManagerController { @SysUISingleton class FgsManagerControllerImpl @Inject constructor( private val context: Context, @Main private val resources: Resources, @Main private val mainExecutor: Executor, @Background private val backgroundExecutor: Executor, private val systemClock: SystemClock, Loading Loading @@ -223,6 +225,14 @@ class FgsManagerControllerImpl @Inject constructor( private val userVisibleJobObserver = UserVisibleJobObserver() private val stoppableApps by lazy { resources .getStringArray(com.android.internal.R.array.stoppable_fgs_system_apps) } private val vendorStoppableApps by lazy { resources .getStringArray(com.android.internal.R.array.vendor_stoppable_fgs_system_apps) } override fun init() { synchronized(lock) { if (initialized) { Loading Loading @@ -725,9 +735,22 @@ class FgsManagerControllerImpl @Inject constructor( } else -> UIControl.NORMAL } // If the app wants to be a good citizen by being stoppable, even if the category it // belongs to is exempted for background restriction, let it be stoppable by user. if (Flags.stoppableFgsSystemApp()) { if (isStoppableApp(packageName)) { uiControl = UIControl.NORMAL } } uiControlInitialized = true } fun isStoppableApp(packageName: String): Boolean { return stoppableApps.contains(packageName) || vendorStoppableApps.contains(packageName) } override fun equals(other: Any?): Boolean { if (other !is UserPackage) { return false Loading