Merge "Add support for HW privacy toggles in sensor unblock dialog" into tm-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
9d0392bc04
10
packages/SystemUI/res/drawable/ic_mic_off.xml
Normal file
10
packages/SystemUI/res/drawable/ic_mic_off.xml
Normal file
@@ -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>
|
||||
13
packages/SystemUI/res/drawable/ic_videocam_off.xml
Normal file
13
packages/SystemUI/res/drawable/ic_videocam_off.xml
Normal file
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
26
packages/SystemUI/res/values/drawables.xml
Normal file
26
packages/SystemUI/res/values/drawables.xml
Normal file
@@ -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>
|
||||
@@ -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 & 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>
|
||||
|
||||
|
||||
@@ -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 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);
|
||||
// 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);
|
||||
|
||||
switch (mSensor) {
|
||||
private void showToastAndFinish() {
|
||||
final int toastMsgResId;
|
||||
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);
|
||||
toastMsgResId = R.string.sensor_privacy_mic_unblocked_toast_content;
|
||||
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);
|
||||
toastMsgResId = R.string.sensor_privacy_camera_unblocked_toast_content;
|
||||
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);
|
||||
toastMsgResId = R.string.sensor_privacy_mic_camera_unblocked_toast_content;
|
||||
break;
|
||||
}
|
||||
unblockButton.setText(
|
||||
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() {
|
||||
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
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
cancelButton.setText(android.R.string.cancel);
|
||||
cancelButton.setOnClickListener(v -> finish());
|
||||
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();
|
||||
|
||||
mSecondIcon.getLayoutParams().width = iconWidth;
|
||||
mSecondIcon.getLayoutParams().height = iconHeight;
|
||||
mSecondIcon.invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
updateUI();
|
||||
mSensorPrivacyController.addCallback(mSensorPrivacyCallback);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
mState.put(sensor, mSensorPrivacyManager.isSensorPrivacyEnabled(sensor));
|
||||
@Override
|
||||
public void onSensorPrivacyChanged(int sensor, boolean enabled) {
|
||||
// handled in onSensorPrivacyChanged(SensorPrivacyChangedParams)
|
||||
}
|
||||
});
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user