diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 17c4d25d82d78..03d4d5e10e648 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -3512,6 +3512,17 @@ public abstract class PackageManager { @SdkConstant(SdkConstantType.FEATURE) public static final String FEATURE_TUNER = "android.hardware.tv.tuner"; + /** + * Feature for {@link #getSystemAvailableFeatures} and + * {@link #hasSystemFeature}: The device supports a enabling/disabling sensor privacy for + * camera. When sensory privacy for the camera is enabled no camera data is send to clients, + * e.g. the view finder in a camera app would appear blank. + * + * @hide + */ + @SdkConstant(SdkConstantType.FEATURE) + public static final String FEATURE_CAMERA_TOGGLE = "android.hardware.camera.toggle"; + /** * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device has * the necessary changes to support app enumeration. diff --git a/packages/SystemUI/res/drawable/ic_camera_blocked.xml b/packages/SystemUI/res/drawable/ic_camera_blocked.xml new file mode 100644 index 0000000000000..0161bcbd19370 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_camera_blocked.xml @@ -0,0 +1,29 @@ + + + + + diff --git a/packages/SystemUI/res/drawable/ic_mic_blocked.xml b/packages/SystemUI/res/drawable/ic_mic_blocked.xml new file mode 100644 index 0000000000000..0ce7a581a7e5d --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_mic_blocked.xml @@ -0,0 +1,29 @@ + + + + + diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 101124ec2a2e6..93d2f751e7542 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -107,7 +107,7 @@ - wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,dark,work,cast,night,screenrecord,reverse,reduce_brightness + wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,dark,work,cast,night,screenrecord,reverse,reduce_brightness,cameratoggle,mictoggle diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 7cdd8b1b80cab..ac2e342b3c34a 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -821,6 +821,10 @@ Location Location Off + + Block Camera + + Mute Microphone Media device diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml index 6eec5dc9e1c18..902de23a9e2a4 100644 --- a/packages/SystemUI/res/xml/tuner_prefs.xml +++ b/packages/SystemUI/res/xml/tuner_prefs.xml @@ -50,6 +50,10 @@ android:key="bluetooth" android:title="@string/quick_settings_bluetooth_label" /> + + diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java index 7ca8e63bfae15..239a77eb2f45f 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java @@ -20,6 +20,7 @@ import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME import static com.android.systemui.Dependency.LEAK_REPORT_EMAIL_NAME; import android.content.Context; +import android.hardware.SensorPrivacyManager; import android.os.Handler; import android.os.PowerManager; @@ -62,6 +63,10 @@ import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl; import com.android.systemui.statusbar.policy.HeadsUpManager; +import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController; +import com.android.systemui.statusbar.policy.IndividualSensorPrivacyControllerImpl; +import com.android.systemui.statusbar.policy.SensorPrivacyController; +import com.android.systemui.statusbar.policy.SensorPrivacyControllerImpl; import javax.inject.Named; @@ -116,6 +121,25 @@ public abstract class SystemUIDefaultModule { return bC; } + @Provides + @SysUISingleton + static SensorPrivacyController provideSensorPrivacyController( + SensorPrivacyManager sensorPrivacyManager) { + SensorPrivacyController spC = new SensorPrivacyControllerImpl(sensorPrivacyManager); + spC.init(); + return spC; + } + + @Provides + @SysUISingleton + static IndividualSensorPrivacyController provideIndividualSensorPrivacyController( + SensorPrivacyManager sensorPrivacyManager) { + IndividualSensorPrivacyController spC = new IndividualSensorPrivacyControllerImpl( + sensorPrivacyManager); + spC.init(); + return spC; + } + @Binds @SysUISingleton public abstract QSFactory bindQSFactory(QSFactoryImpl qsFactoryImpl); 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 ba71fa6a8fb39..9b3775e72f9a5 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java @@ -30,6 +30,7 @@ import com.android.systemui.qs.external.CustomTile; import com.android.systemui.qs.tiles.AirplaneModeTile; import com.android.systemui.qs.tiles.BatterySaverTile; import com.android.systemui.qs.tiles.BluetoothTile; +import com.android.systemui.qs.tiles.CameraToggleTile; import com.android.systemui.qs.tiles.CastTile; import com.android.systemui.qs.tiles.CellularTile; import com.android.systemui.qs.tiles.ColorInversionTile; @@ -39,6 +40,7 @@ import com.android.systemui.qs.tiles.FlashlightTile; import com.android.systemui.qs.tiles.HotspotTile; import com.android.systemui.qs.tiles.InternetTile; import com.android.systemui.qs.tiles.LocationTile; +import com.android.systemui.qs.tiles.MicrophoneToggleTile; import com.android.systemui.qs.tiles.NfcTile; import com.android.systemui.qs.tiles.NightDisplayTile; import com.android.systemui.qs.tiles.ReduceBrightColorsTile; @@ -83,6 +85,8 @@ public class QSFactoryImpl implements QSFactory { private final Provider mUiModeNightTileProvider; private final Provider mScreenRecordTileProvider; private final Provider mReduceBrightColorsTileProvider; + private final Provider mCameraToggleTileProvider; + private final Provider mMicrophoneToggleTileProvider; private final Lazy mQsHostLazy; private final Provider mCustomTileBuilderProvider; @@ -115,7 +119,9 @@ public class QSFactoryImpl implements QSFactory { Provider memoryTileProvider, Provider uiModeNightTileProvider, Provider screenRecordTileProvider, - Provider reduceBrightColorsTileProvider) { + Provider reduceBrightColorsTileProvider, + Provider cameraToggleTileProvider, + Provider microphoneToggleTileProvider) { mQsHostLazy = qsHostLazy; mCustomTileBuilderProvider = customTileBuilderProvider; @@ -143,6 +149,8 @@ public class QSFactoryImpl implements QSFactory { mUiModeNightTileProvider = uiModeNightTileProvider; mScreenRecordTileProvider = screenRecordTileProvider; mReduceBrightColorsTileProvider = reduceBrightColorsTileProvider; + mCameraToggleTileProvider = cameraToggleTileProvider; + mMicrophoneToggleTileProvider = microphoneToggleTileProvider; } public QSTile createTile(String tileSpec) { @@ -198,6 +206,10 @@ public class QSFactoryImpl implements QSFactory { return mScreenRecordTileProvider.get(); case "reduce_brightness": return mReduceBrightColorsTileProvider.get(); + case "cameratoggle": + return mCameraToggleTileProvider.get(); + case "mictoggle": + return mMicrophoneToggleTileProvider.get(); } // Custom tiles diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java new file mode 100644 index 0000000000000..98740a20a7c0c --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2020 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 android.service.SensorPrivacyIndividualEnabledSensorProto.CAMERA; + +import static com.android.systemui.DejankUtils.whitelistIpcs; + +import android.annotation.StringRes; +import android.os.Handler; +import android.os.Looper; +import android.provider.DeviceConfig; + +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; + +import com.android.internal.logging.MetricsLogger; +import com.android.systemui.R; +import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.plugins.ActivityStarter; +import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.logging.QSLogger; +import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController; + +import javax.inject.Inject; + +public class CameraToggleTile extends SensorPrivacyToggleTile { + + @Inject + protected CameraToggleTile(QSHost host, + @Background Looper backgroundLooper, + @Main Handler mainHandler, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger, + IndividualSensorPrivacyController sensorPrivacyController) { + super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController, + activityStarter, qsLogger, sensorPrivacyController); + } + + @Override + public boolean isAvailable() { + return /*getHost().getContext().getPackageManager().hasSystemFeature(FEATURE_CAMERA_TOGGLE) + && */whitelistIpcs(() -> DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, + "camera_toggle_enabled", + false)); + } + + @Override + public @DrawableRes int getIconRes() { + return R.drawable.ic_camera_blocked; + } + + @Override + public @NonNull CharSequence getTileLabel() { + return mContext.getString(R.string.quick_settings_camera_label); + } + + @Override + public int getSensorId() { + return CAMERA; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java new file mode 100644 index 0000000000000..8cc0d7b4e8b8b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2020 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 android.service.SensorPrivacyIndividualEnabledSensorProto.MICROPHONE; + +import static com.android.systemui.DejankUtils.whitelistIpcs; + +import android.os.Handler; +import android.os.Looper; +import android.provider.DeviceConfig; + +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; + +import com.android.internal.logging.MetricsLogger; +import com.android.systemui.R; +import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.plugins.ActivityStarter; +import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.logging.QSLogger; +import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController; + +import javax.inject.Inject; + +public class MicrophoneToggleTile extends SensorPrivacyToggleTile { + + @Inject + protected MicrophoneToggleTile(QSHost host, + @Background Looper backgroundLooper, + @Main Handler mainHandler, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger, + IndividualSensorPrivacyController sensorPrivacyController) { + super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController, + activityStarter, qsLogger, sensorPrivacyController); + } + + @Override + public boolean isAvailable() { + return whitelistIpcs(() -> DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, + "mic_toggle_enabled", + false)); + } + + @Override + public @DrawableRes int getIconRes() { + return R.drawable.ic_mic_blocked; + } + + @Override + public @NonNull CharSequence getTileLabel() { + return mContext.getString(R.string.quick_settings_mic_label); + } + + @Override + public int getSensorId() { + return MICROPHONE; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java new file mode 100644 index 0000000000000..12205d6483a8a --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2020 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.IndividualSensor; +import android.os.Handler; +import android.os.Looper; +import android.service.quicksettings.Tile; +import android.widget.Switch; + +import androidx.annotation.DrawableRes; + +import com.android.internal.logging.MetricsLogger; +import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.plugins.ActivityStarter; +import com.android.systemui.plugins.qs.QSTile; +import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.logging.QSLogger; +import com.android.systemui.qs.tileimpl.QSTileImpl; +import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController; + +/** + * Superclass to toggle individual sensor privacy via quick settings tiles + */ +public abstract class SensorPrivacyToggleTile extends QSTileImpl implements + IndividualSensorPrivacyController.Callback { + + private IndividualSensorPrivacyController mSensorPrivacyController; + + /** + * @return Id of the sensor that will be toggled + */ + public abstract @IndividualSensor int getSensorId(); + + /** + * @return icon for the QS tile + */ + public abstract @DrawableRes int getIconRes(); + + protected SensorPrivacyToggleTile(QSHost host, + @Background Looper backgroundLooper, + @Main Handler mainHandler, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger, + IndividualSensorPrivacyController sensorPrivacyController) { + super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController, + activityStarter, qsLogger); + mSensorPrivacyController = sensorPrivacyController; + mSensorPrivacyController.observe(getLifecycle(), this); + } + + @Override + public BooleanState newTileState() { + return new BooleanState(); + } + + @Override + protected void handleClick() { + mSensorPrivacyController.setSensorBlocked(getSensorId(), + !mSensorPrivacyController.isSensorBlocked(getSensorId())); + } + + @Override + protected void handleUpdateState(BooleanState state, Object arg) { + boolean isBlocked = arg == null ? mSensorPrivacyController.isSensorBlocked(getSensorId()) + : (boolean) arg; + + state.icon = ResourceIcon.get(getIconRes()); + state.state = isBlocked ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; + state.value = isBlocked; + state.label = getTileLabel(); + state.handlesLongClick = false; + state.contentDescription = state.label; + state.expandedAccessibilityClassName = Switch.class.getName(); + } + + @Override + public int getMetricsCategory() { + return 0; + } + + @Override + public Intent getLongClickIntent() { + return null; + } + + @Override + public void onSensorBlockedChanged(int sensor, boolean blocked) { + if (sensor == getSensorId()) { + refreshState(blocked); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java new file mode 100644 index 0000000000000..a76d08a438f25 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2020 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.hardware.SensorPrivacyManager.IndividualSensor; + +public interface IndividualSensorPrivacyController extends + CallbackController { + void init(); + + boolean isSensorBlocked(@IndividualSensor int sensor); + + void setSensorBlocked(@IndividualSensor int sensor, boolean blocked); + + interface Callback { + void onSensorBlockedChanged(@IndividualSensor int sensor, boolean blocked); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java new file mode 100644 index 0000000000000..231fe08e6a998 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2020 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 static android.service.SensorPrivacyIndividualEnabledSensorProto.CAMERA; +import static android.service.SensorPrivacyIndividualEnabledSensorProto.MICROPHONE; + +import android.hardware.SensorPrivacyManager; +import android.hardware.SensorPrivacyManager.IndividualSensor; +import android.util.ArraySet; +import android.util.SparseBooleanArray; + +import androidx.annotation.NonNull; + +import java.util.Set; + +public class IndividualSensorPrivacyControllerImpl implements IndividualSensorPrivacyController { + + private static final int[] SENSORS = new int[] {CAMERA, MICROPHONE}; + + private final @NonNull SensorPrivacyManager mSensorPrivacyManager; + private final SparseBooleanArray mState = new SparseBooleanArray(); + private final Set mCallbacks = new ArraySet<>(); + + public IndividualSensorPrivacyControllerImpl( + @NonNull SensorPrivacyManager sensorPrivacyManager) { + mSensorPrivacyManager = sensorPrivacyManager; + } + + @Override + public void init() { + for (int sensor : SENSORS) { + mSensorPrivacyManager.addSensorPrivacyListener(sensor, + (enabled) -> onSensorPrivacyChanged(sensor, enabled)); + + mState.put(sensor, mSensorPrivacyManager.isIndividualSensorPrivacyEnabled(sensor)); + } + } + + @Override + public boolean isSensorBlocked(@IndividualSensor int sensor) { + return mState.get(sensor, false); + } + + @Override + public void setSensorBlocked(@IndividualSensor int sensor, boolean blocked) { + mSensorPrivacyManager.setIndividualSensorPrivacyForProfileGroup(sensor, blocked); + } + + @Override + public void addCallback(@NonNull Callback listener) { + mCallbacks.add(listener); + } + + @Override + public void removeCallback(@NonNull Callback listener) { + mCallbacks.remove(listener); + } + + private void onSensorPrivacyChanged(@IndividualSensor int sensor, boolean blocked) { + mState.put(sensor, blocked); + + for (Callback callback : mCallbacks) { + callback.onSensorBlockedChanged(sensor, blocked); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyController.java index 6d5ce60ef621d..4a09234325caf 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyController.java @@ -22,6 +22,11 @@ package com.android.systemui.statusbar.policy; public interface SensorPrivacyController extends CallbackController { + /** + * Initialize the controller. Needs to be called after constructing the object + */ + void init(); + /** * Returns whether sensor privacy is 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 index 20cc46ff6bbdd..a2334f3a23d6e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java @@ -35,20 +35,21 @@ import javax.inject.Inject; public class SensorPrivacyControllerImpl implements SensorPrivacyController, SensorPrivacyManager.OnSensorPrivacyChangedListener { private SensorPrivacyManager mSensorPrivacyManager; - private final List mListeners; + private final List mListeners = new ArrayList<>(1); private Object mLock = new Object(); private boolean mSensorPrivacyEnabled; /** * Public constructor. */ - @Inject - public SensorPrivacyControllerImpl(Context context) { - mSensorPrivacyManager = (SensorPrivacyManager) context.getSystemService( - Context.SENSOR_PRIVACY_SERVICE); + public SensorPrivacyControllerImpl(@NonNull SensorPrivacyManager sensorPrivacyManager) { + mSensorPrivacyManager = sensorPrivacyManager; + } + + @Override + public void init() { mSensorPrivacyEnabled = mSensorPrivacyManager.isSensorPrivacyEnabled(); mSensorPrivacyManager.addSensorPrivacyListener(this); - mListeners = new ArrayList<>(1); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java index 069b4051af502..7a4b912d40713 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java @@ -105,11 +105,6 @@ public interface StatusBarPolicyModule { @Binds SecurityController provideSecurityController(SecurityControllerImpl controllerImpl); - /** */ - @Binds - SensorPrivacyController provideSensorPrivacyControllerImpl( - SensorPrivacyControllerImpl controllerImpl); - /** */ @Binds UserInfoController provideUserInfoContrller(UserInfoControllerImpl controllerImpl); diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java index 56a4c203e8402..df889f2c2ca61 100644 --- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java @@ -20,6 +20,7 @@ import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME import static com.android.systemui.Dependency.LEAK_REPORT_EMAIL_NAME; import android.content.Context; +import android.hardware.SensorPrivacyManager; import android.os.Handler; import android.os.PowerManager; @@ -63,6 +64,10 @@ import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl; import com.android.systemui.statusbar.policy.HeadsUpManager; +import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController; +import com.android.systemui.statusbar.policy.IndividualSensorPrivacyControllerImpl; +import com.android.systemui.statusbar.policy.SensorPrivacyController; +import com.android.systemui.statusbar.policy.SensorPrivacyControllerImpl; import com.android.systemui.statusbar.tv.notifications.TvNotificationHandler; import javax.inject.Named; @@ -109,6 +114,25 @@ public abstract class TvSystemUIModule { return bC; } + @Provides + @SysUISingleton + static SensorPrivacyController provideSensorPrivacyController( + SensorPrivacyManager sensorPrivacyManager) { + SensorPrivacyController spC = new SensorPrivacyControllerImpl(sensorPrivacyManager); + spC.init(); + return spC; + } + + @Provides + @SysUISingleton + static IndividualSensorPrivacyController provideIndividualSensorPrivacyController( + SensorPrivacyManager sensorPrivacyManager) { + IndividualSensorPrivacyController spC = new IndividualSensorPrivacyControllerImpl( + sensorPrivacyManager); + spC.init(); + return spC; + } + @Binds @SysUISingleton abstract QSFactory bindQSFactory(QSFactoryImpl qsFactoryImpl); diff --git a/services/core/java/com/android/server/SensorPrivacyService.java b/services/core/java/com/android/server/SensorPrivacyService.java index 9ba71dc5f4f7b..e99bb245a2e03 100644 --- a/services/core/java/com/android/server/SensorPrivacyService.java +++ b/services/core/java/com/android/server/SensorPrivacyService.java @@ -283,11 +283,16 @@ public final class SensorPrivacyService extends SystemService { mIndividualEnabled.put(userId, userIndividualEnabled); if (!enable) { - // Remove any notifications prompting the user to disable sensory privacy - NotificationManager notificationManager = - mContext.getSystemService(NotificationManager.class); + long token = Binder.clearCallingIdentity(); + try { + // Remove any notifications prompting the user to disable sensory privacy + NotificationManager notificationManager = + mContext.getSystemService(NotificationManager.class); - notificationManager.cancel(sensor); + notificationManager.cancel(sensor); + } finally { + Binder.restoreCallingIdentity(token); + } } persistSensorPrivacyState(); }