Add Sensors Off QS tile and display status bar icon when active
This CL will replace the SensorPrivacyTile with a new tile that can be
enabled from the developer settings. When this new tile is enabled only
the camera, mic, and sensors controlled by the SensorManager will be
disabled; the location and airplane mode tiles will not be modified.
The user will be notified when this tile is enabled with the sensors
off icon in the status bar.
Fixes: 126618519
Test: Manually verified airplane and location are not modified when sensors
off is enabled; also verified icon is displayed when mode is active.
Change-Id: Iabf099d0d76c015015ce9859edc0b225ec554020
diff --git a/packages/SystemUI/res/drawable/ic_signal_sensors.xml b/packages/SystemUI/res/drawable/ic_signal_sensors.xml
deleted file mode 100644
index faaddf6..0000000
--- a/packages/SystemUI/res/drawable/ic_signal_sensors.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
- Copyright (C) 2018 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.
--->
-
-<vector android:height="48dp" android:viewportHeight="5"
- android:viewportWidth="5" android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="#00000000"
- android:pathData="m4.762,0.661 l-4.233,4.233"
- android:strokeAlpha="1" android:strokeColor="#000000"
- android:strokeLineCap="round" android:strokeLineJoin="miter" android:strokeWidth=".5"/>
- <path android:fillColor="#00000000"
- android:pathData="M0.265,2.778L1.058,2.778l0.529,-1.323 0.529,2.646 0.529,-3.175 0.529,2.646 0.529,-1.587 0.265,0.794h1.058"
- android:strokeAlpha="1" android:strokeColor="#000000"
- android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth=".33"/>
-</vector>
-
diff --git a/packages/SystemUI/res/drawable/stat_sys_sensors_off.xml b/packages/SystemUI/res/drawable/stat_sys_sensors_off.xml
new file mode 100644
index 0000000..ca8f993
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_sensors_off.xml
@@ -0,0 +1,41 @@
+<!--
+ Copyright (C) 2019 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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:insetLeft="3dp"
+ android:insetRight="3dp"
+ android:width="17dp"
+ android:height="17dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M21.966,2 L2,22"
+ android:strokeLineCap="round"
+ android:strokeColor="#000000"
+ android:fillColor="#00000000"
+ android:strokeWidth="1.6521436"
+ android:strokeLineJoin="miter"
+ android:strokeAlpha="1"/>
+ <path
+ android:pathData="M0.752,12L4.496,12l2.496,-6.25 2.496,12.5 2.496,-15 2.496,12.5 2.496,-7.5 1.248,3.75h4.992"
+ android:strokeLineCap="round"
+ android:strokeColor="#000000"
+ android:fillColor="#00000000"
+ android:strokeWidth="1.25090861"
+ android:strokeLineJoin="round"
+ android:strokeAlpha="1"/>
+</vector>
+
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index b7d1900..70f2cce 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -97,6 +97,7 @@
import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
import com.android.systemui.statusbar.policy.RotationLockController;
import com.android.systemui.statusbar.policy.SecurityController;
+import com.android.systemui.statusbar.policy.SensorPrivacyController;
import com.android.systemui.statusbar.policy.SmartReplyConstants;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
@@ -291,6 +292,7 @@
@Inject Lazy<ActivityManagerWrapper> mActivityManagerWrapper;
@Inject Lazy<DevicePolicyManagerWrapper> mDevicePolicyManagerWrapper;
@Inject Lazy<PackageManagerWrapper> mPackageManagerWrapper;
+ @Inject Lazy<SensorPrivacyController> mSensorPrivacyController;
@Inject
public Dependency() {
@@ -461,6 +463,7 @@
mProviders.put(ActivityManagerWrapper.class, mActivityManagerWrapper::get);
mProviders.put(DevicePolicyManagerWrapper.class, mDevicePolicyManagerWrapper::get);
mProviders.put(PackageManagerWrapper.class, mPackageManagerWrapper::get);
+ mProviders.put(SensorPrivacyController.class, mSensorPrivacyController::get);
// TODO(b/118592525): to support multi-display , we start to add something which is
diff --git a/packages/SystemUI/src/com/android/systemui/DependencyBinder.java b/packages/SystemUI/src/com/android/systemui/DependencyBinder.java
index 3c6f081..53050bf 100644
--- a/packages/SystemUI/src/com/android/systemui/DependencyBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/DependencyBinder.java
@@ -60,6 +60,8 @@
import com.android.systemui.statusbar.policy.RotationLockControllerImpl;
import com.android.systemui.statusbar.policy.SecurityController;
import com.android.systemui.statusbar.policy.SecurityControllerImpl;
+import com.android.systemui.statusbar.policy.SensorPrivacyController;
+import com.android.systemui.statusbar.policy.SensorPrivacyControllerImpl;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.ZenModeController;
@@ -225,5 +227,11 @@
/**
*/
@Binds
+ public abstract SensorPrivacyController provideSensorPrivacyControllerImpl(
+ SensorPrivacyControllerImpl controllerImpl);
+
+ /**
+ */
+ @Binds
public abstract QSHost provideQsHost(QSTileHost controllerImpl);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index d26cee9..2956ad0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -41,7 +41,6 @@
import com.android.systemui.qs.tiles.NfcTile;
import com.android.systemui.qs.tiles.NightDisplayTile;
import com.android.systemui.qs.tiles.RotationLockTile;
-import com.android.systemui.qs.tiles.SensorPrivacyTile;
import com.android.systemui.qs.tiles.UserTile;
import com.android.systemui.qs.tiles.WifiTile;
import com.android.systemui.qs.tiles.WorkModeTile;
@@ -73,7 +72,6 @@
private final Provider<DataSaverTile> mDataSaverTileProvider;
private final Provider<NightDisplayTile> mNightDisplayTileProvider;
private final Provider<NfcTile> mNfcTileProvider;
- private final Provider<SensorPrivacyTile> mSensorPrivacyTileProvider;
private final Provider<GarbageMonitor.MemoryTile> mMemoryTileProvider;
private QSTileHost mHost;
@@ -96,7 +94,6 @@
Provider<DataSaverTile> dataSaverTileProvider,
Provider<NightDisplayTile> nightDisplayTileProvider,
Provider<NfcTile> nfcTileProvider,
- Provider<SensorPrivacyTile> sensorPrivacyTileProvider,
Provider<GarbageMonitor.MemoryTile> memoryTileProvider) {
mWifiTileProvider = wifiTileProvider;
mBluetoothTileProvider = bluetoothTileProvider;
@@ -115,7 +112,6 @@
mDataSaverTileProvider = dataSaverTileProvider;
mNightDisplayTileProvider = nightDisplayTileProvider;
mNfcTileProvider = nfcTileProvider;
- mSensorPrivacyTileProvider = sensorPrivacyTileProvider;
mMemoryTileProvider = memoryTileProvider;
}
@@ -168,8 +164,6 @@
return mNightDisplayTileProvider.get();
case "nfc":
return mNfcTileProvider.get();
- case "sensorprivacy":
- return mSensorPrivacyTileProvider.get();
}
// Intent tiles.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyTile.java
deleted file mode 100644
index 7ee37d5..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyTile.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2018 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.qs.tiles;
-
-import android.content.Intent;
-import android.hardware.SensorPrivacyManager;
-import android.service.quicksettings.Tile;
-import android.widget.Switch;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.R;
-import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.qs.QSTile.BooleanState;
-import com.android.systemui.qs.QSHost;
-import com.android.systemui.qs.tileimpl.QSTileImpl;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
-
-import javax.inject.Inject;
-
-/** Quick settings tile: SensorPrivacy mode **/
-public class SensorPrivacyTile extends QSTileImpl<BooleanState> implements
- SensorPrivacyManager.OnSensorPrivacyChangedListener {
- private static final String TAG = "SensorPrivacy";
- private final Icon mIcon =
- ResourceIcon.get(R.drawable.ic_signal_sensors);
- private final KeyguardMonitor mKeyguard;
- private final SensorPrivacyManager mSensorPrivacyManager;
- private final ActivityStarter mActivityStarter;
-
- @Inject
- public SensorPrivacyTile(QSHost host, SensorPrivacyManager sensorPrivacyManager,
- KeyguardMonitor keyguardMonitor, ActivityStarter activityStarter) {
- super(host);
-
- mSensorPrivacyManager = sensorPrivacyManager;
- mKeyguard = keyguardMonitor;
- mActivityStarter = activityStarter;
- }
-
- @Override
- public BooleanState newTileState() {
- return new BooleanState();
- }
-
- @Override
- public void handleClick() {
- final boolean wasEnabled = mState.value;
- // Don't allow disabling from the lockscreen.
- if (wasEnabled && mKeyguard.isSecure() && mKeyguard.isShowing()) {
- mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
- MetricsLogger.action(mContext, getMetricsCategory(), !wasEnabled);
- setEnabled(!wasEnabled);
- });
- return;
- }
-
- MetricsLogger.action(mContext, getMetricsCategory(), !wasEnabled);
- setEnabled(!wasEnabled);
- }
-
- private void setEnabled(boolean enabled) {
- mSensorPrivacyManager.setSensorPrivacy(enabled);
- }
-
- @Override
- public CharSequence getTileLabel() {
- return mContext.getString(R.string.sensor_privacy_mode);
- }
-
- @Override
- public Intent getLongClickIntent() {
- return new Intent();
- }
-
- @Override
- protected void handleUpdateState(BooleanState state, Object arg) {
- final boolean enabled = arg instanceof Boolean ? (Boolean) arg
- : mSensorPrivacyManager.isSensorPrivacyEnabled();
- state.value = enabled;
- state.label = mContext.getString(R.string.sensor_privacy_mode);
- state.icon = mIcon;
- state.state = enabled ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
- state.contentDescription = state.label;
- state.expandedAccessibilityClassName = Switch.class.getName();
- }
-
- @Override
- public int getMetricsCategory() {
- return MetricsEvent.QS_SENSOR_PRIVACY;
- }
-
- @Override
- protected String composeChangeAnnouncement() {
- if (mState.value) {
- return mContext
- .getString(R.string.accessibility_quick_settings_sensor_privacy_changed_on);
- } else {
- return mContext
- .getString(R.string.accessibility_quick_settings_sensor_privacy_changed_off);
- }
- }
-
- @Override
- protected void handleSetListening(boolean listening) {
- if (listening) {
- mSensorPrivacyManager.addSensorPrivacyListener(this);
- } else {
- mSensorPrivacyManager.removeSensorPrivacyListener(this);
- }
- }
-
- @Override
- public void onSensorPrivacyChanged(boolean enabled) {
- refreshState(enabled);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 4a86484..b7a7873 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -60,6 +60,7 @@
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.RotationLockController;
import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback;
+import com.android.systemui.statusbar.policy.SensorPrivacyController;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.ZenModeController;
@@ -100,6 +101,7 @@
private final String mSlotLocation;
private final String mSlotMicrophone;
private final String mSlotCamera;
+ private final String mSlotSensorsOff;
private final Context mContext;
private final Handler mHandler = new Handler();
@@ -118,6 +120,7 @@
private final LocationController mLocationController;
private final PrivacyItemController mPrivacyItemController;
private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
+ private final SensorPrivacyController mSensorPrivacyController;
// Assume it's all good unless we hear otherwise. We don't always seem
// to get broadcasts that it *is* there.
@@ -149,6 +152,7 @@
mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
mLocationController = Dependency.get(LocationController.class);
mPrivacyItemController = Dependency.get(PrivacyItemController.class);
+ mSensorPrivacyController = Dependency.get(SensorPrivacyController.class);
mSlotCast = context.getString(com.android.internal.R.string.status_bar_cast);
mSlotHotspot = context.getString(com.android.internal.R.string.status_bar_hotspot);
@@ -165,6 +169,7 @@
mSlotLocation = context.getString(com.android.internal.R.string.status_bar_location);
mSlotMicrophone = context.getString(com.android.internal.R.string.status_bar_microphone);
mSlotCamera = context.getString(com.android.internal.R.string.status_bar_camera);
+ mSlotSensorsOff = context.getString(com.android.internal.R.string.status_bar_sensors_off);
// listen for broadcasts
IntentFilter filter = new IntentFilter();
@@ -232,6 +237,11 @@
mContext.getString(R.string.accessibility_location_active));
mIconController.setIconVisibility(mSlotLocation, false);
+ // sensors off
+ mIconController.setIcon(mSlotSensorsOff, R.drawable.stat_sys_sensors_off, null);
+ mIconController.setIconVisibility(mSlotSensorsOff,
+ mSensorPrivacyController.isSensorPrivacyEnabled());
+
mRotationLockController.addCallback(this);
mBluetooth.addCallback(this);
mProvisionedController.addCallback(this);
@@ -242,6 +252,7 @@
mDataSaver.addCallback(this);
mKeyguardMonitor.addCallback(this);
mPrivacyItemController.addCallback(this);
+ mSensorPrivacyController.addCallback(mSensorPrivacyListener);
SysUiServiceProvider.getComponent(mContext, CommandQueue.class).addCallback(this);
}
@@ -514,6 +525,16 @@
}
};
+ private final SensorPrivacyController.OnSensorPrivacyChangedListener mSensorPrivacyListener =
+ new SensorPrivacyController.OnSensorPrivacyChangedListener() {
+ @Override
+ public void onSensorPrivacyChanged(boolean enabled) {
+ mHandler.post(() -> {
+ mIconController.setIconVisibility(mSlotSensorsOff, enabled);
+ });
+ }
+ };
+
@Override
public void appTransitionStarting(int displayId, long startTime, long duration,
boolean forced) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyController.java
new file mode 100644
index 0000000..6d5ce60
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyController.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2019 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;
+
+/**
+ * Interface for classes to control sensor privacy state and notification.
+ */
+public interface SensorPrivacyController extends
+ CallbackController<SensorPrivacyController.OnSensorPrivacyChangedListener> {
+
+ /**
+ * Returns whether sensor privacy is enabled.
+ */
+ boolean isSensorPrivacyEnabled();
+
+ /**
+ * Interface for classes to receive callbacks when sensor privacy state changes.
+ */
+ interface OnSensorPrivacyChangedListener {
+ void onSensorPrivacyChanged(boolean enabled);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java
new file mode 100644
index 0000000..5db6693
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2019 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.Context;
+import android.hardware.SensorPrivacyManager;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Controls sensor privacy state and notification.
+ */
+@Singleton
+public class SensorPrivacyControllerImpl implements SensorPrivacyController,
+ SensorPrivacyManager.OnSensorPrivacyChangedListener {
+ private SensorPrivacyManager mSensorPrivacyManager;
+ private final List<OnSensorPrivacyChangedListener> mListeners;
+ private Object mLock = new Object();
+ private boolean mSensorPrivacyEnabled;
+
+ /**
+ * Public constructor.
+ */
+ @Inject
+ public SensorPrivacyControllerImpl(Context context) {
+ mSensorPrivacyManager = (SensorPrivacyManager) context.getSystemService(
+ Context.SENSOR_PRIVACY_SERVICE);
+ mSensorPrivacyEnabled = mSensorPrivacyManager.isSensorPrivacyEnabled();
+ mSensorPrivacyManager.addSensorPrivacyListener(this);
+ mListeners = new ArrayList<>(1);
+ }
+
+ /**
+ * Returns whether sensor privacy is enabled.
+ */
+ public boolean isSensorPrivacyEnabled() {
+ synchronized (mLock) {
+ return mSensorPrivacyEnabled;
+ }
+ }
+
+ /**
+ * Adds the provided listener for callbacks when sensor privacy state changes.
+ */
+ public void addCallback(OnSensorPrivacyChangedListener listener) {
+ synchronized (mLock) {
+ mListeners.add(listener);
+ notifyListenerLocked(listener);
+ }
+ }
+
+ /**
+ * Removes the provided listener from callbacks when sensor privacy state changes.
+ */
+ public void removeCallback(OnSensorPrivacyChangedListener listener) {
+ synchronized (mLock) {
+ mListeners.remove(listener);
+ }
+ }
+
+ /**
+ * Callback invoked by the SensorPrivacyService when sensor privacy state changes.
+ */
+ public void onSensorPrivacyChanged(boolean enabled) {
+ synchronized (mLock) {
+ mSensorPrivacyEnabled = enabled;
+ for (OnSensorPrivacyChangedListener listener : mListeners) {
+ notifyListenerLocked(listener);
+ }
+ }
+ }
+
+ private void notifyListenerLocked(OnSensorPrivacyChangedListener listener) {
+ listener.onSensorPrivacyChanged(mSensorPrivacyEnabled);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/SensorPrivacyTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/SensorPrivacyTileTest.java
deleted file mode 100644
index 6386c4c..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/SensorPrivacyTileTest.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2018 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.qs.tiles;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.hardware.SensorPrivacyManager;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.Dependency;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.qs.QSTileHost;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
-@SmallTest
-public class SensorPrivacyTileTest extends SysuiTestCase {
-
- @Mock
- private KeyguardMonitor mKeyguard;
- @Mock
- private QSTileHost mHost;
- @Mock
- SensorPrivacyManager mSensorPrivacyManager;
-
- private TestableLooper mTestableLooper;
-
- private SensorPrivacyTile mSensorPrivacyTile;
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
-
- mTestableLooper = TestableLooper.get(this);
- mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper());
- mKeyguard = mDependency.injectMockDependency(KeyguardMonitor.class);
-
- mSensorPrivacyManager = mDependency.injectMockDependency(SensorPrivacyManager.class);
-
- when(mHost.getContext()).thenReturn(mContext);
-
- mSensorPrivacyTile = new SensorPrivacyTile(mHost, mSensorPrivacyManager, mKeyguard,
- mock(ActivityStarter.class));
- }
-
- @Test
- public void testSensorPrivacyListenerAdded_handleListeningTrue() {
- // To prevent access to privacy related features from apps with WRITE_SECURE_SETTINGS the
- // sensor privacy state is not stored in Settings; to receive notification apps must add
- // themselves as a listener with the SensorPrivacyManager. This test verifies when
- // setListening is called with a value of true the tile adds itself as a listener.
- mSensorPrivacyTile.handleSetListening(true);
- mTestableLooper.processAllMessages();
- verify(mSensorPrivacyManager).addSensorPrivacyListener(mSensorPrivacyTile);
- }
-
- @Test
- public void testSensorPrivacyListenerRemoved_handleListeningFalse() {
- // Similar to the test above verifies that the tile removes itself as a listener when
- // setListening is called with a value of false.
- mSensorPrivacyTile.handleSetListening(false);
- mTestableLooper.processAllMessages();
- verify(mSensorPrivacyManager).removeSensorPrivacyListener((mSensorPrivacyTile));
- }
-
- @Test
- public void testSensorPrivacyEnabled_handleClick() {
- // Verifies when the SensorPrivacy tile is clicked it invokes the SensorPrivacyManager to
- // set sensor privacy.
- mSensorPrivacyTile.getState().value = false;
- mSensorPrivacyTile.handleClick();
- mTestableLooper.processAllMessages();
- verify(mSensorPrivacyManager).setSensorPrivacy(true);
-
- mSensorPrivacyTile.getState().value = true;
- mSensorPrivacyTile.handleClick();
- mTestableLooper.processAllMessages();
- verify(mSensorPrivacyManager).setSensorPrivacy(false);
- }
-
- @Test
- public void testSensorPrivacyNotDisabled_keyguard() {
- // Verifies when the device is locked that sensor privacy cannot be disabled
- when(mKeyguard.isSecure()).thenReturn(true);
- when(mKeyguard.isShowing()).thenReturn(true);
- mSensorPrivacyTile.getState().value = true;
- mSensorPrivacyTile.handleClick();
- mTestableLooper.processAllMessages();
- verify(mSensorPrivacyManager, never()).setSensorPrivacy(false);
- }
-}