diff options
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 & 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)); } } } |