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

Commit cc548928 authored by Nate Myren's avatar Nate Myren
Browse files

Make AutoTileManager lisen for component enable/disable

This will allow the Safety Tile to be shown/hidden.

Test: atest AutoTileManagerTest,SafetyControllerTest
Bug: 222127376
Change-Id: Iad666a9aafe74092871ca18fc8b1973a68e1312b
parent c435e6ca
Loading
Loading
Loading
Loading
+0 −1
Original line number Original line Diff line number Diff line
@@ -490,5 +490,4 @@ public class FrameworkServicesModule {
    static SafetyCenterManager provideSafetyCenterManager(Context context) {
    static SafetyCenterManager provideSafetyCenterManager(Context context) {
        return context.getSystemService(SafetyCenterManager.class);
        return context.getSystemService(SafetyCenterManager.class);
    }
    }

}
}
+3 −0
Original line number Original line Diff line number Diff line
@@ -35,6 +35,7 @@ import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.DataSaverController;
import com.android.systemui.statusbar.policy.DataSaverController;
import com.android.systemui.statusbar.policy.DeviceControlsController;
import com.android.systemui.statusbar.policy.DeviceControlsController;
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.SafetyController;
import com.android.systemui.statusbar.policy.WalletController;
import com.android.systemui.statusbar.policy.WalletController;
import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.util.settings.SecureSettings;


@@ -66,6 +67,7 @@ public interface QSModule {
            ReduceBrightColorsController reduceBrightColorsController,
            ReduceBrightColorsController reduceBrightColorsController,
            DeviceControlsController deviceControlsController,
            DeviceControlsController deviceControlsController,
            WalletController walletController,
            WalletController walletController,
            SafetyController safetyController,
            @Named(RBC_AVAILABLE) boolean isReduceBrightColorsAvailable) {
            @Named(RBC_AVAILABLE) boolean isReduceBrightColorsAvailable) {
        AutoTileManager manager = new AutoTileManager(
        AutoTileManager manager = new AutoTileManager(
                context,
                context,
@@ -81,6 +83,7 @@ public interface QSModule {
                reduceBrightColorsController,
                reduceBrightColorsController,
                deviceControlsController,
                deviceControlsController,
                walletController,
                walletController,
                safetyController,
                isReduceBrightColorsAvailable
                isReduceBrightColorsAvailable
        );
        );
        manager.init();
        manager.init();
+30 −4
Original line number Original line Diff line number Diff line
@@ -40,6 +40,7 @@ import com.android.systemui.statusbar.policy.DataSaverController.Listener;
import com.android.systemui.statusbar.policy.DeviceControlsController;
import com.android.systemui.statusbar.policy.DeviceControlsController;
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.HotspotController.Callback;
import com.android.systemui.statusbar.policy.HotspotController.Callback;
import com.android.systemui.statusbar.policy.SafetyController;
import com.android.systemui.statusbar.policy.WalletController;
import com.android.systemui.statusbar.policy.WalletController;
import com.android.systemui.util.UserAwareController;
import com.android.systemui.util.UserAwareController;
import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.util.settings.SecureSettings;
@@ -83,6 +84,7 @@ public class AutoTileManager implements UserAwareController {
    private final DeviceControlsController mDeviceControlsController;
    private final DeviceControlsController mDeviceControlsController;
    private final WalletController mWalletController;
    private final WalletController mWalletController;
    private final ReduceBrightColorsController mReduceBrightColorsController;
    private final ReduceBrightColorsController mReduceBrightColorsController;
    private final SafetyController mSafetyController;
    private final boolean mIsReduceBrightColorsAvailable;
    private final boolean mIsReduceBrightColorsAvailable;
    private final ArrayList<AutoAddSetting> mAutoAddSettingList = new ArrayList<>();
    private final ArrayList<AutoAddSetting> mAutoAddSettingList = new ArrayList<>();


@@ -98,6 +100,7 @@ public class AutoTileManager implements UserAwareController {
            ReduceBrightColorsController reduceBrightColorsController,
            ReduceBrightColorsController reduceBrightColorsController,
            DeviceControlsController deviceControlsController,
            DeviceControlsController deviceControlsController,
            WalletController walletController,
            WalletController walletController,
            SafetyController safetyController,
            @Named(RBC_AVAILABLE) boolean isReduceBrightColorsAvailable) {
            @Named(RBC_AVAILABLE) boolean isReduceBrightColorsAvailable) {
        mContext = context;
        mContext = context;
        mHost = host;
        mHost = host;
@@ -114,6 +117,7 @@ public class AutoTileManager implements UserAwareController {
        mIsReduceBrightColorsAvailable = isReduceBrightColorsAvailable;
        mIsReduceBrightColorsAvailable = isReduceBrightColorsAvailable;
        mDeviceControlsController = deviceControlsController;
        mDeviceControlsController = deviceControlsController;
        mWalletController = walletController;
        mWalletController = walletController;
        mSafetyController = safetyController;
        String safetySpecRes;
        String safetySpecRes;
        try {
        try {
            safetySpecRes = context.getResources().getString(R.string.safety_quick_settings_tile);
            safetySpecRes = context.getResources().getString(R.string.safety_quick_settings_tile);
@@ -163,9 +167,12 @@ public class AutoTileManager implements UserAwareController {
        if (!mAutoTracker.isAdded(WALLET)) {
        if (!mAutoTracker.isAdded(WALLET)) {
            initWalletController();
            initWalletController();
        }
        }
        if (mSafetySpec != null && !mAutoTracker.isAdded(mSafetySpec)) {
        if (mSafetySpec != null) {
            if (!mAutoTracker.isAdded(mSafetySpec)) {
                initSafetyTile();
                initSafetyTile();
            }
            }
            mSafetyController.addCallback(mSafetyCallback);
        }


        int settingsN = mAutoAddSettingList.size();
        int settingsN = mAutoAddSettingList.size();
        for (int i = 0; i < settingsN; i++) {
        for (int i = 0; i < settingsN; i++) {
@@ -187,6 +194,9 @@ public class AutoTileManager implements UserAwareController {
        }
        }
        mCastController.removeCallback(mCastCallback);
        mCastController.removeCallback(mCastCallback);
        mDeviceControlsController.removeCallback();
        mDeviceControlsController.removeCallback();
        if (mSafetySpec != null) {
            mSafetyController.removeCallback(mSafetyCallback);
        }
        int settingsN = mAutoAddSettingList.size();
        int settingsN = mAutoAddSettingList.size();
        for (int i = 0; i < settingsN; i++) {
        for (int i = 0; i < settingsN; i++) {
            mAutoAddSettingList.get(i).setListening(false);
            mAutoAddSettingList.get(i).setListening(false);
@@ -327,10 +337,9 @@ public class AutoTileManager implements UserAwareController {
    }
    }


    private void initSafetyTile() {
    private void initSafetyTile() {
        if (mSafetySpec == null) {
        if (mSafetySpec == null || mAutoTracker.isAdded(mSafetySpec)) {
            return;
            return;
        }
        }
        if (mAutoTracker.isAdded(mSafetySpec)) return;
        mHost.addTile(CustomTile.getComponentFromSpec(mSafetySpec), true);
        mHost.addTile(CustomTile.getComponentFromSpec(mSafetySpec), true);
        mAutoTracker.setTileAdded(mSafetySpec);
        mAutoTracker.setTileAdded(mSafetySpec);
    }
    }
@@ -402,6 +411,23 @@ public class AutoTileManager implements UserAwareController {
        }
        }
    };
    };


    @VisibleForTesting
    final SafetyController.Listener mSafetyCallback = new SafetyController.Listener() {
        @Override
        public void onSafetyCenterEnableChanged(boolean isSafetyCenterEnabled) {
            if (mSafetySpec == null) {
                return;
            }

            if (isSafetyCenterEnabled && !mAutoTracker.isAdded(mSafetySpec)) {
                initSafetyTile();
            } else if (!isSafetyCenterEnabled && mAutoTracker.isAdded(mSafetySpec)) {
                mHost.removeTile(CustomTile.getComponentFromSpec(mSafetySpec));
                mHost.unmarkTileAsAutoAdded(mSafetySpec);
            }
        }
    };

    @VisibleForTesting
    @VisibleForTesting
    protected SettingObserver getSecureSettingForKey(String key) {
    protected SettingObserver getSecureSettingForKey(String key) {
        for (SettingObserver s : mAutoAddSettingList) {
        for (SettingObserver s : mAutoAddSettingList) {
+146 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2022 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.
 */

package com.android.systemui.statusbar.policy;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Handler;
import android.safetycenter.SafetyCenterManager;

import androidx.annotation.NonNull;

import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.dagger.qualifiers.Background;

import java.util.ArrayList;
import java.util.Objects;

import javax.inject.Inject;

/**
 * Controller which calls listeners when a PACKAGE_CHANGED broadcast is sent for the
 * PermissionController. These broadcasts may be because the PermissionController enabled or
 * disabled its TileService, and the tile should be added if the component was enabled, or removed
 * if disabled.
 */
public class SafetyController implements
        CallbackController<SafetyController.Listener> {
    private boolean mSafetyCenterEnabled;
    private final Handler mBgHandler;
    private final ArrayList<Listener> mListeners = new ArrayList<>();
    private static final IntentFilter PKG_CHANGE_INTENT_FILTER;
    private final Context mContext;
    private final SafetyCenterManager mSafetyCenterManager;
    private final PackageManager mPackageManager;

    static {
        PKG_CHANGE_INTENT_FILTER = new IntentFilter(Intent.ACTION_PACKAGE_CHANGED);
        PKG_CHANGE_INTENT_FILTER.addDataScheme("package");
    }

    @Inject
    public SafetyController(Context context, PackageManager pm, SafetyCenterManager scm,
            @Background Handler bgHandler) {
        mContext = context;
        mSafetyCenterManager = scm;
        mPackageManager = pm;
        mBgHandler = bgHandler;
        mSafetyCenterEnabled = mSafetyCenterManager.isSafetyCenterEnabled();
    }

    public boolean isSafetyCenterEnabled() {
        return mSafetyCenterEnabled;
    }

    /**
     * Adds a listener, registering the broadcast receiver if need be. Immediately calls the
     * provided listener on the calling thread.
     */
    @Override
    public void addCallback(@NonNull Listener listener) {
        synchronized (mListeners) {
            mListeners.add(listener);
            if (mListeners.size() == 1) {
                mContext.registerReceiver(mPermControllerChangeReceiver, PKG_CHANGE_INTENT_FILTER);
                mBgHandler.post(() -> {
                    mSafetyCenterEnabled = mSafetyCenterManager.isSafetyCenterEnabled();
                    listener.onSafetyCenterEnableChanged(isSafetyCenterEnabled());
                });
            } else {
                listener.onSafetyCenterEnableChanged(isSafetyCenterEnabled());
            }
        }
    }

    @Override
    public void removeCallback(@NonNull Listener listener) {
        synchronized (mListeners) {
            mListeners.remove(listener);
            if (mListeners.isEmpty()) {
                mContext.unregisterReceiver(mPermControllerChangeReceiver);
            }
        }
    }

    private void handleSafetyCenterEnableChange() {
        synchronized (mListeners) {
            for (int i = 0; i < mListeners.size(); i++) {
                mListeners.get(i).onSafetyCenterEnableChanged(mSafetyCenterEnabled);
            }
        }
    }

    /**
     * Upon receiving a package changed broadcast for the PermissionController, checks if the
     * safety center is enabled or disabled, and sends an update on the main thread if the state
     * changed.
     */
    @VisibleForTesting
    final BroadcastReceiver mPermControllerChangeReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String packageName = intent.getData() != null ? intent.getData().getSchemeSpecificPart()
                    : null;
            if (!Objects.equals(packageName,
                    mPackageManager.getPermissionControllerPackageName())) {
                return;
            }

            boolean wasSafetyCenterEnabled = mSafetyCenterEnabled;
            mSafetyCenterEnabled = mSafetyCenterManager.isSafetyCenterEnabled();
            if (wasSafetyCenterEnabled == mSafetyCenterEnabled) {
                return;
            }

            mBgHandler.post(() -> handleSafetyCenterEnableChange());
        }
    };

    /**
     * Listener for safety center enabled changes
     */
    public interface Listener {
        /**
         * Callback to be notified when the safety center is enabled or disabled
         * @param isSafetyCenterEnabled If the safety center is enabled
         */
        void onSafetyCenterEnableChanged(boolean isSafetyCenterEnabled);
    }
}
+36 −2
Original line number Original line Diff line number Diff line
@@ -58,6 +58,7 @@ import com.android.systemui.statusbar.policy.CastController.CastDevice;
import com.android.systemui.statusbar.policy.DataSaverController;
import com.android.systemui.statusbar.policy.DataSaverController;
import com.android.systemui.statusbar.policy.DeviceControlsController;
import com.android.systemui.statusbar.policy.DeviceControlsController;
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.SafetyController;
import com.android.systemui.statusbar.policy.WalletController;
import com.android.systemui.statusbar.policy.WalletController;
import com.android.systemui.util.settings.FakeSettings;
import com.android.systemui.util.settings.FakeSettings;
import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.util.settings.SecureSettings;
@@ -101,6 +102,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
    @Mock private ReduceBrightColorsController mReduceBrightColorsController;
    @Mock private ReduceBrightColorsController mReduceBrightColorsController;
    @Mock private DeviceControlsController mDeviceControlsController;
    @Mock private DeviceControlsController mDeviceControlsController;
    @Mock private WalletController mWalletController;
    @Mock private WalletController mWalletController;
    @Mock private SafetyController mSafetyController;
    @Mock(answer = Answers.RETURNS_SELF)
    @Mock(answer = Answers.RETURNS_SELF)
    private AutoAddTracker.Builder mAutoAddTrackerBuilder;
    private AutoAddTracker.Builder mAutoAddTrackerBuilder;
    @Mock private Context mUserContext;
    @Mock private Context mUserContext;
@@ -150,6 +152,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
            ReduceBrightColorsController reduceBrightColorsController,
            ReduceBrightColorsController reduceBrightColorsController,
            DeviceControlsController deviceControlsController,
            DeviceControlsController deviceControlsController,
            WalletController walletController,
            WalletController walletController,
            SafetyController safetyController,
            @Named(RBC_AVAILABLE) boolean isReduceBrightColorsAvailable) {
            @Named(RBC_AVAILABLE) boolean isReduceBrightColorsAvailable) {
        return new AutoTileManager(context, autoAddTrackerBuilder, mQsTileHost,
        return new AutoTileManager(context, autoAddTrackerBuilder, mQsTileHost,
                Handler.createAsync(TestableLooper.get(this).getLooper()),
                Handler.createAsync(TestableLooper.get(this).getLooper()),
@@ -162,6 +165,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
                reduceBrightColorsController,
                reduceBrightColorsController,
                deviceControlsController,
                deviceControlsController,
                walletController,
                walletController,
                safetyController,
                isReduceBrightColorsAvailable);
                isReduceBrightColorsAvailable);
    }
    }


@@ -169,7 +173,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
        return createAutoTileManager(context, mAutoAddTrackerBuilder, mHotspotController,
        return createAutoTileManager(context, mAutoAddTrackerBuilder, mHotspotController,
                mDataSaverController, mManagedProfileController, mNightDisplayListener,
                mDataSaverController, mManagedProfileController, mNightDisplayListener,
                mCastController, mReduceBrightColorsController, mDeviceControlsController,
                mCastController, mReduceBrightColorsController, mDeviceControlsController,
                mWalletController, mIsReduceBrightColorsAvailable);
                mWalletController, mSafetyController, mIsReduceBrightColorsAvailable);
    }
    }


    @Test
    @Test
@@ -185,10 +189,11 @@ public class AutoTileManagerTest extends SysuiTestCase {
        ReduceBrightColorsController rBC = mock(ReduceBrightColorsController.class);
        ReduceBrightColorsController rBC = mock(ReduceBrightColorsController.class);
        DeviceControlsController dCC = mock(DeviceControlsController.class);
        DeviceControlsController dCC = mock(DeviceControlsController.class);
        WalletController wC = mock(WalletController.class);
        WalletController wC = mock(WalletController.class);
        SafetyController sC = mock(SafetyController.class);


        AutoTileManager manager =
        AutoTileManager manager =
                createAutoTileManager(mock(Context.class), builder, hC, dSC, mPC, nDS, cC, rBC,
                createAutoTileManager(mock(Context.class), builder, hC, dSC, mPC, nDS, cC, rBC,
                        dCC, wC, true);
                        dCC, wC, sC, true);


        verify(tracker, never()).initialize();
        verify(tracker, never()).initialize();
        verify(hC, never()).addCallback(any());
        verify(hC, never()).addCallback(any());
@@ -199,6 +204,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
        verify(rBC, never()).addCallback(any());
        verify(rBC, never()).addCallback(any());
        verify(dCC, never()).setCallback(any());
        verify(dCC, never()).setCallback(any());
        verify(wC, never()).getWalletPosition();
        verify(wC, never()).getWalletPosition();
        verify(sC, never()).addCallback(any());
        assertNull(manager.getSecureSettingForKey(TEST_SETTING));
        assertNull(manager.getSecureSettingForKey(TEST_SETTING));
        assertNull(manager.getSecureSettingForKey(TEST_SETTING_COMPONENT));
        assertNull(manager.getSecureSettingForKey(TEST_SETTING_COMPONENT));
    }
    }
@@ -253,6 +259,10 @@ public class AutoTileManagerTest extends SysuiTestCase {


        verify(mWalletController, times(2)).getWalletPosition();
        verify(mWalletController, times(2)).getWalletPosition();


        InOrder inOrderSafety = inOrder(mSafetyController);
        inOrderSafety.verify(mSafetyController).removeCallback(any());
        inOrderSafety.verify(mSafetyController).addCallback(any());

        SettingObserver setting = mAutoTileManager.getSecureSettingForKey(TEST_SETTING);
        SettingObserver setting = mAutoTileManager.getSecureSettingForKey(TEST_SETTING);
        assertEquals(USER + 1, setting.getCurrentUser());
        assertEquals(USER + 1, setting.getCurrentUser());
        assertTrue(setting.isListening());
        assertTrue(setting.isListening());
@@ -303,6 +313,10 @@ public class AutoTileManagerTest extends SysuiTestCase {


        verify(mWalletController, times(2)).getWalletPosition();
        verify(mWalletController, times(2)).getWalletPosition();


        InOrder inOrderSafety = inOrder(mSafetyController);
        inOrderSafety.verify(mSafetyController).removeCallback(any());
        inOrderSafety.verify(mSafetyController).addCallback(any());

        SettingObserver setting = mAutoTileManager.getSecureSettingForKey(TEST_SETTING);
        SettingObserver setting = mAutoTileManager.getSecureSettingForKey(TEST_SETTING);
        assertEquals(USER + 1, setting.getCurrentUser());
        assertEquals(USER + 1, setting.getCurrentUser());
        assertFalse(setting.isListening());
        assertFalse(setting.isListening());
@@ -457,6 +471,26 @@ public class AutoTileManagerTest extends SysuiTestCase {
        mAutoTileManager.changeUser(UserHandle.of(USER + 1));
        mAutoTileManager.changeUser(UserHandle.of(USER + 1));
        verify(mQsTileHost, times(2)).addTile(safetyComponent, true);
        verify(mQsTileHost, times(2)).addTile(safetyComponent, true);
    }
    }

    @Test
    public void testSafetyTileRemoved_onSafetyCenterDisable() {
        ComponentName safetyComponent = CustomTile.getComponentFromSpec(TEST_CUSTOM_SAFETY_SPEC);
        mAutoTileManager.init();
        when(mAutoAddTracker.isAdded(TEST_CUSTOM_SAFETY_SPEC)).thenReturn(true);
        mAutoTileManager.mSafetyCallback.onSafetyCenterEnableChanged(false);
        verify(mQsTileHost, times(1)).removeTile(safetyComponent);
    }

    @Test
    public void testSafetyTileAdded_onSafetyCenterEnable() {
        ComponentName safetyComponent = CustomTile.getComponentFromSpec(TEST_CUSTOM_SAFETY_SPEC);
        mAutoTileManager.init();
        verify(mQsTileHost, times(1)).addTile(safetyComponent, true);
        mAutoTileManager.mSafetyCallback.onSafetyCenterEnableChanged(false);
        mAutoTileManager.mSafetyCallback.onSafetyCenterEnableChanged(true);
        verify(mQsTileHost, times(2)).addTile(safetyComponent, true);
    }

    @Test
    @Test
    public void testEmptyArray_doesNotCrash() {
    public void testEmptyArray_doesNotCrash() {
        mContext.getOrCreateTestableResources().addOverride(
        mContext.getOrCreateTestableResources().addOverride(
Loading