Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 66f64bbc authored by Jing Ji's avatar Jing Ji
Browse files

Allow preventing unrestricted Apps from being Stopped

This CL adds a flag to allow toggling the behavior on whether or not
the foreground service task manager should show a stop button for
unrestricted apps.

Bug: 230449539
Test: Manual - device_config put systemui \
      show_stop_button_for_user_allowlisted_apps true|false
Test: atest FgsManagerControllerTest
Change-Id: I4cfe54933d7c6807a7ffbac9ee709c7d8d6b83d3
Merged-In: I4cfe54933d7c6807a7ffbac9ee709c7d8d6b83d3
parent c6d82a8c
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -548,6 +548,12 @@ public final class SystemUiDeviceConfigFlags {
     */
    public static final String TASK_MANAGER_SHOW_FOOTER_DOT = "task_manager_show_footer_dot";

    /**
     * (boolean) Whether the task manager should show a stop button if the app is allowlisted
     * by the user.
     */
    public static final String TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS =
            "show_stop_button_for_user_allowlisted_apps";

    /**
     * (boolean) Whether the clipboard overlay is enabled.
+33 −0
Original line number Diff line number Diff line
@@ -40,11 +40,13 @@ import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import androidx.annotation.GuardedBy
import androidx.annotation.VisibleForTesting
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.TASK_MANAGER_ENABLED
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_FOOTER_DOT
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS
import com.android.internal.jank.InteractionJankMonitor
import com.android.systemui.Dumpable
import com.android.systemui.R
@@ -87,6 +89,7 @@ class FgsManagerController @Inject constructor(
        private val LOG_TAG = FgsManagerController::class.java.simpleName
        private const val DEFAULT_TASK_MANAGER_ENABLED = true
        private const val DEFAULT_TASK_MANAGER_SHOW_FOOTER_DOT = false
        private const val DEFAULT_TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS = true
    }

    var changesSinceDialog = false
@@ -96,6 +99,8 @@ class FgsManagerController @Inject constructor(
        private set
    var showFooterDot = false
        private set
    var showStopBtnForUserAllowlistedApps = false
        private set

    private val lock = Any()

@@ -163,6 +168,9 @@ class FgsManagerController @Inject constructor(
                isAvailable = it.getBoolean(TASK_MANAGER_ENABLED, isAvailable)
                showFooterDot =
                    it.getBoolean(TASK_MANAGER_SHOW_FOOTER_DOT, showFooterDot)
                showStopBtnForUserAllowlistedApps = it.getBoolean(
                    TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS,
                    showStopBtnForUserAllowlistedApps)
            }

            isAvailable = deviceConfigProxy.getBoolean(
@@ -173,6 +181,10 @@ class FgsManagerController @Inject constructor(
                NAMESPACE_SYSTEMUI,
                TASK_MANAGER_SHOW_FOOTER_DOT, DEFAULT_TASK_MANAGER_SHOW_FOOTER_DOT
            )
            showStopBtnForUserAllowlistedApps = deviceConfigProxy.getBoolean(
                NAMESPACE_SYSTEMUI,
                TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS,
                DEFAULT_TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS)

            dumpManager.registerDumpable(this)

@@ -275,6 +287,20 @@ class FgsManagerController @Inject constructor(
        }
    }

    @VisibleForTesting
    @JvmName("getNumVisibleButtons")
    internal fun getNumVisibleButtons(): Int {
        synchronized(lock) {
            return getNumVisibleButtonsLocked()
        }
    }

    private fun getNumVisibleButtonsLocked(): Int {
        return runningServiceTokens.keys.count {
            it.uiControl != UIControl.HIDE_BUTTON && currentProfileIds.contains(it.userId)
        }
    }

    fun shouldUpdateFooterVisibility() = dialog == null

    fun showDialog(viewLaunchedFrom: View?) {
@@ -505,6 +531,13 @@ class FgsManagerController @Inject constructor(
                PowerExemptionManager.REASON_PROC_STATE_PERSISTENT_UI,
                PowerExemptionManager.REASON_ROLE_DIALER,
                PowerExemptionManager.REASON_SYSTEM_MODULE -> UIControl.HIDE_BUTTON

                PowerExemptionManager.REASON_ALLOWLISTED_PACKAGE ->
                    if (showStopBtnForUserAllowlistedApps) {
                        UIControl.NORMAL
                    } else {
                        UIControl.HIDE_BUTTON
                    }
                else -> UIControl.NORMAL
            }
            uiControlInitialized = true
+37 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.systemui.qs;

import static android.os.PowerExemptionManager.REASON_ALLOWLISTED_PACKAGE;

import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
@@ -34,6 +36,7 @@ import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.os.Binder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -222,7 +225,41 @@ public class FgsManagerControllerTest extends SysuiTestCase {
        Assert.assertEquals(2, mFmc.getNumRunningPackages());
    }

    @Test
    public void testButtonVisibilityOnShowAllowlistButtonFlagChange() throws Exception {
        setUserProfiles(0);
        setBackgroundRestrictionExemptionReason("pkg", 12345, REASON_ALLOWLISTED_PACKAGE);

        final Binder binder = new Binder();
        setShowStopButtonForUserAllowlistedApps(true);
        mIForegroundServiceObserver.onForegroundStateChanged(binder, "pkg", 0, true);
        Assert.assertEquals(1, mFmc.getNumVisibleButtons());

        mIForegroundServiceObserver.onForegroundStateChanged(binder, "pkg", 0, false);
        Assert.assertEquals(0, mFmc.getNumVisibleButtons());

        setShowStopButtonForUserAllowlistedApps(false);
        mIForegroundServiceObserver.onForegroundStateChanged(binder, "pkg", 0, true);
        Assert.assertEquals(0, mFmc.getNumVisibleButtons());
    }

    private void setShowStopButtonForUserAllowlistedApps(boolean enable) {
        mDeviceConfigProxyFake.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
                SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS,
                enable ? "true" : "false", false);
        mBackgroundExecutor.advanceClockToLast();
        mBackgroundExecutor.runAllReady();
    }

    private void setBackgroundRestrictionExemptionReason(String pkgName, int uid, int reason)
            throws Exception {
        Mockito.doReturn(uid)
                .when(mPackageManager)
                .getPackageUidAsUser(pkgName, UserHandle.getUserId(uid));
        Mockito.doReturn(reason)
                .when(mIActivityManager)
                .getBackgroundRestrictionExemptionReason(uid);
    }

    FgsManagerController createFgsManagerController() throws RemoteException {
        ArgumentCaptor<IForegroundServiceObserver> iForegroundServiceObserverArgumentCaptor =