summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/content/pm/PackageManager.java11
-rw-r--r--packages/SystemUI/res/drawable/ic_camera_blocked.xml29
-rw-r--r--packages/SystemUI/res/values/strings.xml2
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java48
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/CameraToggleController.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/CameraToggleControllerImpl.java76
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyController.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java12
-rw-r--r--services/core/java/com/android/server/SensorPrivacyService.java15
12 files changed, 135 insertions, 107 deletions
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 17c4d25d82d7..03d4d5e10e64 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3513,6 +3513,17 @@ public abstract class PackageManager {
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 000000000000..0161bcbd1937
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_camera_blocked.xml
@@ -0,0 +1,29 @@
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="m18,12c-2.75,0 -5,2.25 -5,5 0,2.75 2.25,5 5,5 2.75,0 5,-2.25 5,-5 0,-2.75 -2.1667,-5 -5,-5zM15.5,17.8333h5v-1.6666h-5z"
+ android:fillColor="#30302a"
+ android:fillType="evenOdd"/>
+ <path
+ android:pathData="m16.4,5.5004h-2.536l-1.464,-1.6H7.6l-1.464,1.6H3.6c-0.88,0 -1.6,0.72 -1.6,1.6v9.6c0,0.88 0.72,1.6 1.6,1.6h8.5413C12.0488,17.8817 12,17.4465 12,17c0,-0.1005 0.0025,-0.2004 0.0073,-0.2996H3.6V7.1004H16.4V11.2157C16.9094,11.0751 17.4459,11 18,11V7.1004c0,-0.88 -0.72,-1.6 -1.6,-1.6zM6.8,11.9004c0,-1.768 1.432,-3.2 3.2,-3.2 1.768,0 3.2,1.432 3.2,3.2 0,1.768 -1.432,3.2 -3.2,3.2 -1.768,0 -3.2,-1.432 -3.2,-3.2z"
+ android:fillColor="#30302a"
+ android:fillType="evenOdd"/>
+</vector>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 7cdd8b1b80ca..e12342c9d42b 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -821,6 +821,8 @@
<string name="quick_settings_location_label">Location</string>
<!-- QuickSettings: Location (Off) [CHAR LIMIT=NONE] -->
<string name="quick_settings_location_off_label">Location Off</string>
+ <!-- QuickSettings: Camera [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_camera_label">Block Camera</string>
<!-- QuickSettings: Media device [CHAR LIMIT=NONE] -->
<string name="quick_settings_media_device_label">Media device</string>
<!-- QuickSettings: RSSI [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
index 7ca8e63bfae1..754879e59dd9 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,8 @@ 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.SensorPrivacyController;
+import com.android.systemui.statusbar.policy.SensorPrivacyControllerImpl;
import javax.inject.Named;
@@ -116,6 +119,15 @@ public abstract class SystemUIDefaultModule {
return bC;
}
+ @Provides
+ @SysUISingleton
+ static SensorPrivacyController provideSensorPrivacyController(
+ SensorPrivacyManager sensorPrivacyManager) {
+ SensorPrivacyController spC = new SensorPrivacyControllerImpl(sensorPrivacyManager);
+ spC.init();
+ return spC;
+ }
+
@Binds
@SysUISingleton
public abstract QSFactory bindQSFactory(QSFactoryImpl qsFactoryImpl);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java
index d719fc3f0d7b..093163070dd5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java
@@ -16,11 +16,12 @@
package com.android.systemui.qs.tiles;
-import android.content.Context;
+import static com.android.systemui.DejankUtils.whitelistIpcs;
+
import android.content.Intent;
-import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
+import android.provider.DeviceConfig;
import android.service.quicksettings.Tile;
import android.widget.Switch;
@@ -38,7 +39,8 @@ import com.android.systemui.statusbar.policy.CameraToggleController;
import javax.inject.Inject;
-public class CameraToggleTile extends QSTileImpl<QSTile.BooleanState> {
+public class CameraToggleTile extends QSTileImpl<QSTile.BooleanState> implements
+ CameraToggleController.Callback {
private CameraToggleController mCameraToggleController;
@@ -54,7 +56,15 @@ public class CameraToggleTile extends QSTileImpl<QSTile.BooleanState> {
super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController,
activityStarter, qsLogger);
mCameraToggleController = cameraToggleController;
- mCameraToggleController.addCallback((b) -> refreshState());
+ mCameraToggleController.observe(getLifecycle(), this);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return /*getHost().getContext().getPackageManager().hasSystemFeature(FEATURE_CAMERA_TOGGLE)
+ && */whitelistIpcs(() -> DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
+ "camera_toggle_enabled",
+ false));
}
@Override
@@ -64,21 +74,18 @@ public class CameraToggleTile extends QSTileImpl<QSTile.BooleanState> {
@Override
protected void handleClick() {
- mCameraToggleController.setCameraEnabled(!mCameraToggleController.isCameraEnabled());
+ mCameraToggleController.setCameraBlocked(!mCameraToggleController.isCameraBlocked());
}
@Override
protected void handleUpdateState(BooleanState state, Object arg) {
- state.icon = new CameraToggleTileIcon();
- state.state = mCameraToggleController.isCameraEnabled()
- ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
- state.value = mCameraToggleController.isCameraEnabled();
- state.label = "Camera";
- if (!mCameraToggleController.isCameraAvailable()) {
- state.secondaryLabel = "Currently in use";
- } else {
- state.secondaryLabel = null;
- }
+ boolean isBlocked = arg == null ? mCameraToggleController.setCameraBlocked()
+ : (boolean) arg;
+
+ state.icon = ResourceIcon.get(R.drawable.ic_camera_blocked);
+ 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();
@@ -96,14 +103,11 @@ public class CameraToggleTile extends QSTileImpl<QSTile.BooleanState> {
@Override
public CharSequence getTileLabel() {
- return "Camera";
+ return mContext.getString(R.string.quick_settings_camera_label);
}
- class CameraToggleTileIcon extends Icon {
-
- @Override
- public Drawable getDrawable(Context context) {
- return context.getDrawable(R.drawable.ic_camera);
- }
+ @Override
+ public void onCameraBlockedChanged(boolean enable) {
+ refreshState(enable);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CameraToggleController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CameraToggleController.java
index 544f0050d352..b9de21c1fb82 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CameraToggleController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CameraToggleController.java
@@ -16,18 +16,14 @@
package com.android.systemui.statusbar.policy;
-import com.android.systemui.Dumpable;
+public interface CameraToggleController extends
+ CallbackController<CameraToggleController.Callback> {
-public interface CameraToggleController extends CallbackController<CameraToggleController.Callback>,
- Dumpable {
+ boolean isCameraBlocked();
- boolean isCameraEnabled();
- void setCameraEnabled(boolean enabled);
-
- boolean isCameraAvailable();
+ void setCameraBlocked(boolean blocked);
interface Callback {
- void onCameraEnabledChanged(boolean enable);
+ void onCameraBlockedChanged(boolean blocked);
}
-
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CameraToggleControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CameraToggleControllerImpl.java
index 7496813247c9..3fb1ac56226e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CameraToggleControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CameraToggleControllerImpl.java
@@ -16,86 +16,42 @@
package com.android.systemui.statusbar.policy;
+import static android.service.SensorPrivacyIndividualEnabledSensorProto.CAMERA;
+
import android.content.Context;
-import android.hardware.camera2.CameraManager;
-import android.hardware.camera2.CameraToggleManager;
-import android.os.Looper;
+import android.hardware.SensorPrivacyManager;
import android.util.ArraySet;
-import android.widget.Toast;
import androidx.annotation.NonNull;
-import com.android.systemui.dagger.qualifiers.Background;
-import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.dump.DumpManager;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
import java.util.Set;
import javax.inject.Inject;
public class CameraToggleControllerImpl implements CameraToggleController {
- private final Context mContext;
- private final DumpManager mDumpManager;
- private final CameraToggleManager mCameraToggleManager;
-
- private boolean mState = true;
-
- Set<Callback> mCallbacks = new ArraySet<>();
+ private final @NonNull Context mContext;
+ private final @NonNull SensorPrivacyManager mSensorPrivacyManager;
+ private boolean mState;
+ private Set<Callback> mCallbacks = new ArraySet<>();
- Set<String> mUsedCameras = new ArraySet<>();
-
- /**
- */
@Inject
- public CameraToggleControllerImpl(
- Context context,
- DumpManager dumpManager,
- @Background Looper bgLooper,
- @Main Looper mainLooper) {
+ public CameraToggleControllerImpl(@NonNull Context context) {
mContext = context;
- mDumpManager = dumpManager;
- mCameraToggleManager = context.getSystemService(CameraToggleManager.class);
- mCameraToggleManager.addCameraToggleChangeListener(this::onCameraChanged);
- mState = mCameraToggleManager.isCameraEnabled();
- mContext.getSystemService(CameraManager.class).registerAvailabilityCallback(
- context.getMainExecutor(), new CameraManager.AvailabilityCallback() {
- @Override
- public void onCameraAvailable(@NonNull String cameraId) {
- mUsedCameras.remove(cameraId);
- onCameraChanged(mState);
- }
+ mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class);
+ mSensorPrivacyManager.addSensorPrivacyListener(CAMERA, this::onCameraPrivacyChanged);
- @Override
- public void onCameraUnavailable(@NonNull String cameraId) {
- mUsedCameras.add(cameraId);
- onCameraChanged(mState);
- }
- });
+ mState = mSensorPrivacyManager.isIndividualSensorPrivacyEnabled(CAMERA);
}
@Override
- public boolean isCameraEnabled() {
+ public boolean isCameraBlocked() {
return mState;
}
@Override
- public void setCameraEnabled(boolean enabled) {
- if (!/*mCameraToggleManager.setCameraEnabled(enabled)*/true) {
- Toast.makeText(mContext, "Can't disable camera while in use", Toast.LENGTH_LONG);
- }
- }
-
- @Override
- public boolean isCameraAvailable() {
- return false;/*mUsedCameras.isEmpty();*/
- }
-
- @Override
- public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
-
+ public void setCameraBlocked(boolean blocked) {
+ mSensorPrivacyManager.setIndividualSensorPrivacyForProfileGroup(CAMERA, blocked);
}
@Override
@@ -108,10 +64,10 @@ public class CameraToggleControllerImpl implements CameraToggleController {
mCallbacks.remove(listener);
}
- private void onCameraChanged(boolean state) {
+ private void onCameraPrivacyChanged(boolean state) {
mState = state;
for (Callback callback : mCallbacks) {
- callback.onCameraEnabledChanged(state);
+ callback.onCameraBlockedChanged(mState);
}
}
}
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 6d5ce60ef621..4a09234325ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyController.java
@@ -23,6 +23,11 @@ public interface SensorPrivacyController extends
CallbackController<SensorPrivacyController.OnSensorPrivacyChangedListener> {
/**
+ * Initialize the controller. Needs to be called after constructing the object
+ */
+ void init();
+
+ /**
* Returns whether sensor privacy is enabled.
*/
boolean isSensorPrivacyEnabled();
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 20cc46ff6bbd..a2334f3a23d6 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<OnSensorPrivacyChangedListener> mListeners;
+ private final List<OnSensorPrivacyChangedListener> 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 916a1a8e3582..a6278d689e0f 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
@@ -109,11 +109,6 @@ public interface StatusBarPolicyModule {
/** */
@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 56a4c203e840..a24f7dd64481 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,8 @@ 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.SensorPrivacyController;
+import com.android.systemui.statusbar.policy.SensorPrivacyControllerImpl;
import com.android.systemui.statusbar.tv.notifications.TvNotificationHandler;
import javax.inject.Named;
@@ -109,6 +112,15 @@ public abstract class TvSystemUIModule {
return bC;
}
+ @Provides
+ @SysUISingleton
+ static SensorPrivacyController provideSensorPrivacyController(
+ SensorPrivacyManager sensorPrivacyManager) {
+ SensorPrivacyController spC = new SensorPrivacyControllerImpl(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 9ba71dc5f4f7..e99bb245a2e0 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);
-
- notificationManager.cancel(sensor);
+ long token = Binder.clearCallingIdentity();
+ try {
+ // Remove any notifications prompting the user to disable sensory privacy
+ NotificationManager notificationManager =
+ mContext.getSystemService(NotificationManager.class);
+
+ notificationManager.cancel(sensor);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
persistSensorPrivacyState();
}