summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/res/drawable/ic_mic_off.xml10
-rw-r--r--packages/SystemUI/res/drawable/ic_videocam_off.xml13
-rw-r--r--packages/SystemUI/res/values-television/config.xml4
-rw-r--r--packages/SystemUI/res/values-television/dimens.xml3
-rw-r--r--packages/SystemUI/res/values/drawables.xml26
-rw-r--r--packages/SystemUI/res/values/strings.xml40
-rw-r--r--packages/SystemUI/src/com/android/systemui/sensorprivacy/television/TvUnblockSensorActivity.java199
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java46
9 files changed, 306 insertions, 41 deletions
diff --git a/packages/SystemUI/res/drawable/ic_mic_off.xml b/packages/SystemUI/res/drawable/ic_mic_off.xml
new file mode 100644
index 000000000000..fe23754f7467
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_mic_off.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M11,5c0,-0.55 0.45,-1 1,-1s1,0.45 1,1v5.17l1.82,1.82c0.11,-0.31 0.18,-0.64 0.18,-0.99V5c0,-1.66 -1.34,-3 -3,-3S9,3.34 9,5v1.17l2,2V5zM2.81,2.81L1.39,4.22l11.65,11.65c-0.33,0.08 -0.68,0.13 -1.04,0.13 -2.76,0 -5,-2.24 -5,-5H5c0,3.53 2.61,6.43 6,6.92V21h2v-3.08c0.57,-0.08 1.12,-0.24 1.64,-0.46l5.14,5.14 1.41,-1.41L2.81,2.81zM19,11h-2c0,0.91 -0.26,1.75 -0.69,2.48l1.46,1.46C18.54,13.82 19,12.47 19,11z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_videocam_off.xml b/packages/SystemUI/res/drawable/ic_videocam_off.xml
new file mode 100644
index 000000000000..b609f36d912d
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_videocam_off.xml
@@ -0,0 +1,13 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M15,8v2.67l5.85,5.85C20.94,16.37 21,16.2 21,16V8c0,-0.82 -0.94,-1.29 -1.6,-0.8L17,9V8c0,-1.1 -0.9,-2 -2,-2h-4.67l2,2H15z"/>
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M2,3.32l2.71,2.71C3.74,6.17 3,7 3,8v8c0,1.1 0.9,2 2,2h11.68l3,3l1.41,-1.41L3.41,1.91L2,3.32zM5,8h1.68l8,8H5V8z"/>
+</vector>
diff --git a/packages/SystemUI/res/values-television/config.xml b/packages/SystemUI/res/values-television/config.xml
index a9e6d22461b6..94f6c3952e06 100644
--- a/packages/SystemUI/res/values-television/config.xml
+++ b/packages/SystemUI/res/values-television/config.xml
@@ -42,4 +42,8 @@
<!-- Whether to use window background blur for the volume dialog. -->
<bool name="config_volumeDialogUseBackgroundBlur">true</bool>
+
+ <!-- Whether to tint the icon of the sensor hardware privacy toggle unblock dialog.
+ Set to false if using a custom icon. -->
+ <bool name="config_unblockHwSensorIconEnableTint">true</bool>
</resources>
diff --git a/packages/SystemUI/res/values-television/dimens.xml b/packages/SystemUI/res/values-television/dimens.xml
index d4bfc4d11b89..7845ac49c06d 100644
--- a/packages/SystemUI/res/values-television/dimens.xml
+++ b/packages/SystemUI/res/values-television/dimens.xml
@@ -57,4 +57,7 @@
<dimen name="privacy_chip_dot_bg_height">18dp</dimen>
<dimen name="privacy_chip_dot_bg_radius">9dp</dimen>
+ <dimen name="unblock_hw_sensor_icon_width">@dimen/bottom_sheet_icon_size</dimen>
+ <dimen name="unblock_hw_sensor_icon_height">@dimen/bottom_sheet_icon_size</dimen>
+
</resources>
diff --git a/packages/SystemUI/res/values/drawables.xml b/packages/SystemUI/res/values/drawables.xml
new file mode 100644
index 000000000000..a1d6baa4808e
--- /dev/null
+++ b/packages/SystemUI/res/values/drawables.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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.
+ -->
+<resources>
+ <!-- Drawable shown for the sensor unblock dialog when blocked by the hardware camera toggle -->
+ <drawable name="unblock_hw_sensor_camera">@drawable/ic_videocam_off</drawable>
+ <!-- Drawable shown for the sensor unblock dialog when blocked by the hardware microphone toggle -->
+ <drawable name="unblock_hw_sensor_microphone">@drawable/ic_mic_off</drawable>
+ <!-- Drawable shown for the sensor unblock dialog when blocked by the hardware privacy toggle -->
+ <drawable name="unblock_hw_sensor_all">@drawable/ic_videocam_off</drawable>
+ <!-- Second drawable shown for the sensor unblock dialog when blocked by the hardware privacy toggle -->
+ <drawable name="unblock_hw_sensor_all_second">@drawable/ic_mic_off</drawable>
+</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index bdc0a7fc56b6..8df614d3c522 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -720,16 +720,52 @@
<string name="sensor_privacy_start_use_mic_dialog_title">Unblock device microphone?</string>
<!--- Title of dialog triggered if the camera is disabled but an app tried to access it. [CHAR LIMIT=150] -->
<string name="sensor_privacy_start_use_camera_dialog_title">Unblock device camera?</string>
- <!--- Title of dialog triggered if the camera is disabled but an app tried to access it. [CHAR LIMIT=150] -->
+ <!--- Title of dialog triggered if both microphone and camera are disabled but an app tried to access them. [CHAR LIMIT=150] -->
<string name="sensor_privacy_start_use_mic_camera_dialog_title">Unblock device camera and microphone?</string>
<!--- Content of dialog triggered if the microphone is disabled but an app tried to access it. [CHAR LIMIT=NONE] -->
<string name="sensor_privacy_start_use_mic_dialog_content">This unblocks access for all apps and services allowed to use your microphone.</string>
<!--- Content of dialog triggered if the camera is disabled but an app tried to access it. [CHAR LIMIT=NONE] -->
<string name="sensor_privacy_start_use_camera_dialog_content">This unblocks access for all apps and services allowed to use your camera.</string>
- <!--- Content of dialog triggered if the camera is disabled but an app tried to access it. [CHAR LIMIT=NONE] -->
+ <!--- Title of dialog triggered if both microphone and camera are disabled but an app tried to access them. [CHAR LIMIT=150] -->
<string name="sensor_privacy_start_use_mic_camera_dialog_content">This unblocks access for all apps and services allowed to use your camera or microphone.</string>
+ <!--- Title of dialog triggered if the microphone is blocked by a hardware privacy switch but an app tried to access it. [CHAR LIMIT=150] -->
+ <string name="sensor_privacy_start_use_mic_blocked_dialog_title">Microphone is blocked</string>
+ <!--- Title of dialog triggered if the camera is blocked by a hardware privacy switch but an app tried to access it. [CHAR LIMIT=150] -->
+ <string name="sensor_privacy_start_use_camera_blocked_dialog_title">Camera is blocked</string>
+ <!--- Title of dialog triggered if both microphone and camera are blocked by a hardware privacy switch but an app tried to access them. [CHAR LIMIT=150] -->
+ <string name="sensor_privacy_start_use_mic_camera_blocked_dialog_title">The mic &amp; camera are blocked</string>
+
+ <!--- Content of dialog triggered if the microphone is disabled by HW toggle but an app tried to access it. [CHAR LIMIT=NONE] -->
+ <string name="sensor_privacy_start_use_mic_blocked_dialog_content">
+ To unblock, move the privacy switch on your device to the microphone on position to allow
+ microphone access. Refer to the device manual to locate the privacy switch on your device.
+ </string>
+ <!--- Content of dialog triggered if the camera is disabled by HW toggle but an app tried to access it. [CHAR LIMIT=NONE] -->
+ <string name="sensor_privacy_start_use_camera_blocked_dialog_content">
+ To unblock, move the privacy switch on your device to the camera on position to allow camera
+ access. Refer to the device manual to locate the privacy switch on your device.
+ </string>
+ <!--- Content of dialog triggered if the camera is disabled by HW toggle but an app tried to access it. [CHAR LIMIT=NONE] -->
+ <string name="sensor_privacy_start_use_mic_camera_blocked_dialog_content">
+ To unblock them, move the privacy switch on your device to the unblocked position to allow
+ access. Refer to the device manual to locate the privacy switch on your device.
+ </string>
+
+ <!--- Content of toast triggered if the microphone privacy is unblocked while the HW toggle privacy dialog was shown. [CHAR LIMIT=NONE] -->
+ <string name="sensor_privacy_mic_unblocked_toast_content">
+ Microphone available
+ </string>
+ <!--- Content of toast triggered if the camera privacy is unblocked while the HW toggle privacy dialog was shown. [CHAR LIMIT=NONE] -->
+ <string name="sensor_privacy_camera_unblocked_toast_content">
+ Camera available
+ </string>
+ <!--- Content of toast triggered if both mic and camera privacy is unblocked while the HW toggle privacy dialog was shown. [CHAR LIMIT=NONE] -->
+ <string name="sensor_privacy_mic_camera_unblocked_toast_content">
+ Microphone and camera available
+ </string>
+
<!-- Default name for the media device shown in the output switcher when the name is not available [CHAR LIMIT=30] -->
<string name="media_seamless_other_device">Other device</string>
diff --git a/packages/SystemUI/src/com/android/systemui/sensorprivacy/television/TvUnblockSensorActivity.java b/packages/SystemUI/src/com/android/systemui/sensorprivacy/television/TvUnblockSensorActivity.java
index cc5cf4b63f99..d543eb2d647a 100644
--- a/packages/SystemUI/src/com/android/systemui/sensorprivacy/television/TvUnblockSensorActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/sensorprivacy/television/TvUnblockSensorActivity.java
@@ -20,6 +20,11 @@ import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE;
import static android.hardware.SensorPrivacyManager.Sources.OTHER;
+import android.annotation.DimenRes;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.graphics.drawable.Animatable;
+import android.graphics.drawable.Drawable;
import android.hardware.SensorPrivacyManager;
import android.os.Bundle;
import android.util.Log;
@@ -28,6 +33,7 @@ import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
+import android.widget.Toast;
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
@@ -36,18 +42,29 @@ import com.android.systemui.tv.TvBottomSheetActivity;
import javax.inject.Inject;
/**
- * Bottom sheet that is shown when the camera/mic sensors are blocked by the global toggle and
- * allows the user to re-enable them.
+ * Bottom sheet that is shown when the camera/mic sensors are blocked by the global software toggle
+ * or physical privacy switch.
*/
public class TvUnblockSensorActivity extends TvBottomSheetActivity {
private static final String TAG = TvUnblockSensorActivity.class.getSimpleName();
+ private static final String ACTION_MANAGE_CAMERA_PRIVACY =
+ "android.settings.MANAGE_CAMERA_PRIVACY";
+ private static final String ACTION_MANAGE_MICROPHONE_PRIVACY =
+ "android.settings.MANAGE_MICROPHONE_PRIVACY";
private static final int ALL_SENSORS = Integer.MAX_VALUE;
+
private int mSensor = -1;
private final IndividualSensorPrivacyController mSensorPrivacyController;
private IndividualSensorPrivacyController.Callback mSensorPrivacyCallback;
+ private TextView mTitle;
+ private TextView mContent;
+ private ImageView mIcon;
+ private ImageView mSecondIcon;
+ private Button mPositiveButton;
+ private Button mCancelButton;
@Inject
public TvUnblockSensorActivity(
@@ -76,52 +93,145 @@ public class TvUnblockSensorActivity extends TvBottomSheetActivity {
}
mSensorPrivacyCallback = (sensor, blocked) -> {
- if (mSensor == ALL_SENSORS) {
- if (!mSensorPrivacyController.isSensorBlocked(CAMERA)
- && !mSensorPrivacyController.isSensorBlocked(MICROPHONE)) {
- finish();
- }
+ if (mSensor == ALL_SENSORS && !mSensorPrivacyController.isSensorBlocked(CAMERA)
+ && !mSensorPrivacyController.isSensorBlocked(MICROPHONE)) {
+ showToastAndFinish();
} else if (this.mSensor == sensor && !blocked) {
- finish();
+ showToastAndFinish();
+ } else {
+ updateUI();
}
};
initUI();
}
+ private void showToastAndFinish() {
+ final int toastMsgResId;
+ switch(mSensor) {
+ case MICROPHONE:
+ toastMsgResId = R.string.sensor_privacy_mic_unblocked_toast_content;
+ break;
+ case CAMERA:
+ toastMsgResId = R.string.sensor_privacy_camera_unblocked_toast_content;
+ break;
+ case ALL_SENSORS:
+ default:
+ toastMsgResId = R.string.sensor_privacy_mic_camera_unblocked_toast_content;
+ break;
+ }
+ Toast.makeText(this, toastMsgResId, Toast.LENGTH_SHORT).show();
+ finish();
+ }
+
+ private boolean isBlockedByHardwareToggle() {
+ if (mSensor == ALL_SENSORS) {
+ return mSensorPrivacyController.isSensorBlockedByHardwareToggle(CAMERA)
+ || mSensorPrivacyController.isSensorBlockedByHardwareToggle(MICROPHONE);
+ } else {
+ return mSensorPrivacyController.isSensorBlockedByHardwareToggle(mSensor);
+ }
+ }
+
private void initUI() {
- TextView title = findViewById(R.id.bottom_sheet_title);
- TextView content = findViewById(R.id.bottom_sheet_body);
- ImageView icon = findViewById(R.id.bottom_sheet_icon);
+ mTitle = findViewById(R.id.bottom_sheet_title);
+ mContent = findViewById(R.id.bottom_sheet_body);
+ mIcon = findViewById(R.id.bottom_sheet_icon);
// mic icon if both icons are shown
- ImageView secondIcon = findViewById(R.id.bottom_sheet_second_icon);
- Button unblockButton = findViewById(R.id.bottom_sheet_positive_button);
- Button cancelButton = findViewById(R.id.bottom_sheet_negative_button);
+ mSecondIcon = findViewById(R.id.bottom_sheet_second_icon);
+ mPositiveButton = findViewById(R.id.bottom_sheet_positive_button);
+ mCancelButton = findViewById(R.id.bottom_sheet_negative_button);
+
+ mCancelButton.setText(android.R.string.cancel);
+ mCancelButton.setOnClickListener(v -> finish());
+
+ updateUI();
+ }
+
+ private void updateUI() {
+ if (isBlockedByHardwareToggle()) {
+ updateUiForHardwareToggle();
+ } else {
+ updateUiForSoftwareToggle();
+ }
+ }
+
+ private void updateUiForHardwareToggle() {
+ final Resources resources = getResources();
+
+ boolean micBlocked = (mSensor == MICROPHONE || mSensor == ALL_SENSORS)
+ && mSensorPrivacyController.isSensorBlockedByHardwareToggle(MICROPHONE);
+ boolean cameraBlocked = (mSensor == CAMERA || mSensor == ALL_SENSORS)
+ && mSensorPrivacyController.isSensorBlockedByHardwareToggle(CAMERA);
+
+ setIconTint(resources.getBoolean(R.bool.config_unblockHwSensorIconEnableTint));
+ setIconSize(R.dimen.unblock_hw_sensor_icon_width, R.dimen.unblock_hw_sensor_icon_height);
+
+ if (micBlocked && cameraBlocked) {
+ mTitle.setText(R.string.sensor_privacy_start_use_mic_camera_blocked_dialog_title);
+ mContent.setText(
+ R.string.sensor_privacy_start_use_mic_camera_blocked_dialog_content);
+ mIcon.setImageResource(R.drawable.unblock_hw_sensor_all);
+
+ Drawable secondIconDrawable = resources.getDrawable(
+ R.drawable.unblock_hw_sensor_all_second, getTheme());
+ if (secondIconDrawable == null) {
+ mSecondIcon.setVisibility(View.GONE);
+ } else {
+ mSecondIcon.setImageDrawable(secondIconDrawable);
+ }
+ } else if (cameraBlocked) {
+ mTitle.setText(R.string.sensor_privacy_start_use_camera_blocked_dialog_title);
+ mContent.setText(R.string.sensor_privacy_start_use_camera_blocked_dialog_content);
+ mIcon.setImageResource(R.drawable.unblock_hw_sensor_camera);
+ mSecondIcon.setVisibility(View.GONE);
+ } else if (micBlocked) {
+ mTitle.setText(R.string.sensor_privacy_start_use_mic_blocked_dialog_title);
+ mContent.setText(R.string.sensor_privacy_start_use_mic_blocked_dialog_content);
+ mIcon.setImageResource(R.drawable.unblock_hw_sensor_microphone);
+ mSecondIcon.setVisibility(View.GONE);
+ }
+
+ // Start animation if drawable is animated
+ Drawable iconDrawable = mIcon.getDrawable();
+ if (iconDrawable instanceof Animatable) {
+ ((Animatable) iconDrawable).start();
+ }
+
+ mPositiveButton.setVisibility(View.GONE);
+ mCancelButton.setText(android.R.string.ok);
+ }
+
+ private void updateUiForSoftwareToggle() {
+ setIconTint(true);
+ setIconSize(R.dimen.bottom_sheet_icon_size, R.dimen.bottom_sheet_icon_size);
switch (mSensor) {
case MICROPHONE:
- title.setText(R.string.sensor_privacy_start_use_mic_dialog_title);
- content.setText(R.string.sensor_privacy_start_use_mic_dialog_content);
- icon.setImageResource(com.android.internal.R.drawable.perm_group_microphone);
- secondIcon.setVisibility(View.GONE);
+ mTitle.setText(R.string.sensor_privacy_start_use_mic_dialog_title);
+ mContent.setText(R.string.sensor_privacy_start_use_mic_dialog_content);
+ mIcon.setImageResource(com.android.internal.R.drawable.perm_group_microphone);
+ mSecondIcon.setVisibility(View.GONE);
break;
case CAMERA:
- title.setText(R.string.sensor_privacy_start_use_camera_dialog_title);
- content.setText(R.string.sensor_privacy_start_use_camera_dialog_content);
- icon.setImageResource(com.android.internal.R.drawable.perm_group_camera);
- secondIcon.setVisibility(View.GONE);
+ mTitle.setText(R.string.sensor_privacy_start_use_camera_dialog_title);
+ mContent.setText(R.string.sensor_privacy_start_use_camera_dialog_content);
+ mIcon.setImageResource(com.android.internal.R.drawable.perm_group_camera);
+ mSecondIcon.setVisibility(View.GONE);
break;
case ALL_SENSORS:
default:
- title.setText(R.string.sensor_privacy_start_use_mic_camera_dialog_title);
- content.setText(R.string.sensor_privacy_start_use_mic_camera_dialog_content);
- icon.setImageResource(com.android.internal.R.drawable.perm_group_camera);
- secondIcon.setImageResource(com.android.internal.R.drawable.perm_group_microphone);
+ mTitle.setText(R.string.sensor_privacy_start_use_mic_camera_dialog_title);
+ mContent.setText(R.string.sensor_privacy_start_use_mic_camera_dialog_content);
+ mIcon.setImageResource(com.android.internal.R.drawable.perm_group_camera);
+ mSecondIcon.setImageResource(
+ com.android.internal.R.drawable.perm_group_microphone);
break;
}
- unblockButton.setText(
+
+ mPositiveButton.setText(
com.android.internal.R.string.sensor_privacy_start_use_dialog_turn_on_button);
- unblockButton.setOnClickListener(v -> {
+ mPositiveButton.setOnClickListener(v -> {
if (mSensor == ALL_SENSORS) {
mSensorPrivacyController.setSensorBlocked(OTHER, CAMERA, false);
mSensorPrivacyController.setSensorBlocked(OTHER, MICROPHONE, false);
@@ -129,14 +239,43 @@ public class TvUnblockSensorActivity extends TvBottomSheetActivity {
mSensorPrivacyController.setSensorBlocked(OTHER, mSensor, false);
}
});
+ }
+
+ private void setIconTint(boolean enableTint) {
+ final Resources resources = getResources();
+
+ if (enableTint) {
+ final ColorStateList iconTint = resources.getColorStateList(
+ R.color.bottom_sheet_icon_color, getTheme());
+ mIcon.setImageTintList(iconTint);
+ mSecondIcon.setImageTintList(iconTint);
+ } else {
+ mIcon.setImageTintList(null);
+ mSecondIcon.setImageTintList(null);
+ }
+
+ mIcon.invalidate();
+ mSecondIcon.invalidate();
+ }
+
+ private void setIconSize(@DimenRes int widthRes, @DimenRes int heightRes) {
+ final Resources resources = getResources();
+ final int iconWidth = resources.getDimensionPixelSize(widthRes);
+ final int iconHeight = resources.getDimensionPixelSize(heightRes);
+
+ mIcon.getLayoutParams().width = iconWidth;
+ mIcon.getLayoutParams().height = iconHeight;
+ mIcon.invalidate();
- cancelButton.setText(android.R.string.cancel);
- cancelButton.setOnClickListener(v -> finish());
+ mSecondIcon.getLayoutParams().width = iconWidth;
+ mSecondIcon.getLayoutParams().height = iconHeight;
+ mSecondIcon.invalidate();
}
@Override
public void onResume() {
super.onResume();
+ updateUI();
mSensorPrivacyController.addCallback(mSensorPrivacyCallback);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java
index e01b95e81da8..1e73d593c8de 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java
@@ -27,6 +27,12 @@ public interface IndividualSensorPrivacyController extends
boolean isSensorBlocked(@Sensor int sensor);
+ /**
+ * Returns {@code true} if the given sensor is blocked by a hardware toggle, {@code false}
+ * if the sensor is not blocked or blocked by a software toggle.
+ */
+ boolean isSensorBlockedByHardwareToggle(@Sensor int sensor);
+
void setSensorBlocked(@Source int source, @Sensor int sensor, boolean blocked);
void suppressSensorPrivacyReminders(int sensor, boolean suppress);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java
index 1d71301c7454..e4c444da5da9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java
@@ -22,6 +22,7 @@ import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE;
import android.hardware.SensorPrivacyManager;
import android.hardware.SensorPrivacyManager.Sensors.Sensor;
import android.hardware.SensorPrivacyManager.Sources.Source;
+import android.hardware.SensorPrivacyManager.ToggleType;
import android.util.ArraySet;
import android.util.SparseBooleanArray;
@@ -34,7 +35,8 @@ public class IndividualSensorPrivacyControllerImpl implements IndividualSensorPr
private static final int[] SENSORS = new int[] {CAMERA, MICROPHONE};
private final @NonNull SensorPrivacyManager mSensorPrivacyManager;
- private final SparseBooleanArray mState = new SparseBooleanArray();
+ private final SparseBooleanArray mSoftwareToggleState = new SparseBooleanArray();
+ private final SparseBooleanArray mHardwareToggleState = new SparseBooleanArray();
private final Set<Callback> mCallbacks = new ArraySet<>();
public IndividualSensorPrivacyControllerImpl(
@@ -44,11 +46,27 @@ public class IndividualSensorPrivacyControllerImpl implements IndividualSensorPr
@Override
public void init() {
- for (int sensor : SENSORS) {
- mSensorPrivacyManager.addSensorPrivacyListener(sensor,
- (s, enabled) -> onSensorPrivacyChanged(sensor, enabled));
+ mSensorPrivacyManager.addSensorPrivacyListener(
+ new SensorPrivacyManager.OnSensorPrivacyChangedListener() {
+ @Override
+ public void onSensorPrivacyChanged(SensorPrivacyChangedParams params) {
+ IndividualSensorPrivacyControllerImpl.this.onSensorPrivacyChanged(
+ params.getSensor(), params.getToggleType(), params.isEnabled());
+ }
+
+ @Override
+ public void onSensorPrivacyChanged(int sensor, boolean enabled) {
+ // handled in onSensorPrivacyChanged(SensorPrivacyChangedParams)
+ }
+ });
- mState.put(sensor, mSensorPrivacyManager.isSensorPrivacyEnabled(sensor));
+ for (int sensor : SENSORS) {
+ boolean softwarePrivacyEnabled = mSensorPrivacyManager.isSensorPrivacyEnabled(
+ SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE, sensor);
+ boolean hardwarePrivacyEnabled = mSensorPrivacyManager.isSensorPrivacyEnabled(
+ SensorPrivacyManager.TOGGLE_TYPE_HARDWARE, sensor);
+ mSoftwareToggleState.put(sensor, softwarePrivacyEnabled);
+ mHardwareToggleState.put(sensor, hardwarePrivacyEnabled);
}
}
@@ -59,7 +77,12 @@ public class IndividualSensorPrivacyControllerImpl implements IndividualSensorPr
@Override
public boolean isSensorBlocked(@Sensor int sensor) {
- return mState.get(sensor, false);
+ return mSoftwareToggleState.get(sensor, false) || mHardwareToggleState.get(sensor, false);
+ }
+
+ @Override
+ public boolean isSensorBlockedByHardwareToggle(@Sensor int sensor) {
+ return mHardwareToggleState.get(sensor, false);
}
@Override
@@ -82,11 +105,16 @@ public class IndividualSensorPrivacyControllerImpl implements IndividualSensorPr
mCallbacks.remove(listener);
}
- private void onSensorPrivacyChanged(@Sensor int sensor, boolean blocked) {
- mState.put(sensor, blocked);
+ private void onSensorPrivacyChanged(@Sensor int sensor, @ToggleType int toggleType,
+ boolean enabled) {
+ if (toggleType == SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE) {
+ mSoftwareToggleState.put(sensor, enabled);
+ } else if (toggleType == SensorPrivacyManager.TOGGLE_TYPE_HARDWARE) {
+ mHardwareToggleState.put(sensor, enabled);
+ }
for (Callback callback : mCallbacks) {
- callback.onSensorBlockedChanged(sensor, blocked);
+ callback.onSensorBlockedChanged(sensor, isSensorBlocked(sensor));
}
}
}