Merge "Update mic/cam toggles to the latest UI mocks" into sc-dev

This commit is contained in:
Evan Severson
2021-04-09 03:09:07 +00:00
committed by Android (Google) Code Review
17 changed files with 319 additions and 103 deletions

View File

@@ -73,6 +73,13 @@ public final class SensorPrivacyManager {
public static final String EXTRA_SENSOR = SensorPrivacyManager.class.getName()
+ ".extra.sensor";
/**
* An extra indicating if all sensors are affected
* @hide
*/
public static final String EXTRA_ALL_SENSORS = SensorPrivacyManager.class.getName()
+ ".extra.all_sensors";
/**
* Individual sensors not listed in {@link Sensors}
* @hide

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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"
android:tint="?attr/colorControlNormal">
<path android:fillColor="@android:color/white"
android:pathData="M18,10.48L18,6c0,-1.1 -0.9,-2 -2,-2L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2v-4.48l4,3.98v-11l-4,3.98zM16,9.69L16,18L4,18L4,6h12v3.69z"/>
</vector>

View File

@@ -1,29 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ 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.
-->
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"/>
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path android:fillColor="@android:color/white"
android:pathData="M18,10.48V6c0,-1.1 -0.9,-2 -2,-2H6.83l2,2H16v7.17l2,2v-1.65l4,3.98v-11l-4,3.98zM16,16L6,6 4,4 2.81,2.81 1.39,4.22l0.85,0.85C2.09,5.35 2,5.66 2,6v12c0,1.1 0.9,2 2,2h12c0.34,0 0.65,-0.09 0.93,-0.24l2.85,2.85 1.41,-1.41L18,18l-2,-2zM4,18V6.83L15.17,18H4z"/>
</vector>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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"
android:tint="?attr/colorControlNormal">
<path android:fillColor="@android:color/white"
android:pathData="M12,14c1.66,0 3,-1.34 3,-3L15,5c0,-1.66 -1.34,-3 -3,-3S9,3.34 9,5v6c0,1.66 1.34,3 3,3zM11,5c0,-0.55 0.45,-1 1,-1s1,0.45 1,1v6c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1L11,5zM17,11c0,2.76 -2.24,5 -5,5s-5,-2.24 -5,-5L5,11c0,3.53 2.61,6.43 6,6.92L11,21h2v-3.08c3.39,-0.49 6,-3.39 6,-6.92h-2z"/>
</vector>

View File

@@ -1,29 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ 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.
-->
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="m17,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,-5zM14.5,17.8333h5v-1.6666h-5z"
android:fillColor="#30302a"
android:fillType="evenOdd"/>
<path
android:pathData="m12,12c0,1.66 -1.34,3 -3,3C7.34,15 6,13.66 6,12L6,6C6,4.34 7.34,3 9,3c1.66,0 3,1.34 3,3zM9,5C8.45,5 8,5.45 8,6v6c0,0.55 0.45,1 1,1 0.55,0 1,-0.45 1,-1L10,6C10,5.45 9.55,5 9,5ZM11.0147,16.577C10.3983,16.849 9.7167,17 9,17 6.24,17 4,14.76 4,12L2,12c0,3.53 2.61,6.43 6,6.92L8,22h2v-3.08c0.4212,-0.0609 0.8303,-0.1589 1.2238,-0.2908C11.078,18.1111 11,17.5647 11,17c0,-0.1422 0.0049,-0.2832 0.0147,-0.423z"
android:fillColor="#30302a"
android:fillType="evenOdd"/>
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>

View File

@@ -5941,12 +5941,14 @@ ul.</string>
<!-- Notification action to dismiss. [CHAR LIMIT=50] -->
<string name="dismiss_action">Dismiss</string>
<!--- Content of notification triggered if the microphone is disabled but an app tried to access it. [CHAR LIMIT=NONE] -->
<string name="sensor_privacy_start_use_mic_notification_content">To continue, &lt;b&gt;<xliff:g id="app" example="Gmail">%s</xliff:g>&lt;/b&gt; needs access to your device microphone.</string>
<!--- Title of notification triggered if the microphone is disabled but an app tried to access it. [CHAR LIMIT=NONE] -->
<string name="sensor_privacy_start_use_mic_notification_content_title">Unblock device microphone</string>
<!--- Title of notification triggered if the camera is disabled but an app tried to access it. [CHAR LIMIT=NONE] -->
<string name="sensor_privacy_start_use_camera_notification_content_title">Unblock device camera</string>
<!--- Content of notification triggered if the camera is disabled but an app tried to access it. [CHAR LIMIT=NONE] -->
<string name="sensor_privacy_start_use_camera_notification_content">To continue, &lt;b&gt;<xliff:g id="app" example="Gmail">%s</xliff:g>&lt;/b&gt; needs access to your devices camera.</string>
<string name="sensor_privacy_start_use_notification_content_text">For &lt;b&gt;<xliff:g id="app" example="Gmail">%s</xliff:g>&lt;/b&gt; and all apps and services</string>
<!--- Action button in the dialog triggered if a sensor (e.g. microphone or camera) is disabled but an app tried to access it. [CHAR LIMIT=60] -->
<string name="sensor_privacy_start_use_dialog_turn_on_button">Turn on</string>
<string name="sensor_privacy_start_use_dialog_turn_on_button">Unblock</string>
<!--- Label for notification channel for all sensor privacy related notifications. [CHAR LIMIT=NONE] -->
<string name="sensor_privacy_notification_channel_label">Sensor Privacy</string>

View File

@@ -4202,8 +4202,11 @@
<java-symbol type="drawable" name="ic_camera_blocked" />
<java-symbol type="drawable" name="ic_mic_blocked" />
<java-symbol type="string" name="sensor_privacy_start_use_mic_notification_content" />
<java-symbol type="string" name="sensor_privacy_start_use_camera_notification_content" />
<java-symbol type="drawable" name="ic_camera_allowed" />
<java-symbol type="drawable" name="ic_mic_allowed" />
<java-symbol type="string" name="sensor_privacy_start_use_mic_notification_content_title" />
<java-symbol type="string" name="sensor_privacy_start_use_camera_notification_content_title" />
<java-symbol type="string" name="sensor_privacy_start_use_notification_content_text" />
<java-symbol type="string" name="sensor_privacy_start_use_dialog_turn_on_button" />
<java-symbol type="string" name="sensor_privacy_notification_channel_label" />

View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright 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.
*/
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:gravity="center_vertical"
android:paddingTop="?android:attr/listPreferredItemPaddingStart"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:orientation="horizontal"
android:gravity="center">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:id="@+id/sensor_use_camera_icon"
android:src="@*android:drawable/perm_group_camera"
android:tint="?android:attr/colorAccent"
android:visibility="gone" />
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:id="@+id/sensor_use_microphone_icon"
android:src="@*android:drawable/perm_group_microphone"
android:tint="?android:attr/colorAccent"
android:visibility="gone" />
</LinearLayout>
<com.android.internal.widget.DialogTitle
android:id="@+id/sensor_use_started_title_message"
style="@android:style/TextAppearance.DeviceDefault.WindowTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center" />
</LinearLayout>

View File

@@ -832,9 +832,13 @@
<!-- 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>
<string name="quick_settings_camera_label">Camera access</string>
<!-- QuickSettings: Microphone [CHAR LIMIT=NONE] -->
<string name="quick_settings_mic_label">Mute Microphone</string>
<string name="quick_settings_mic_label">Mic access</string>
<!-- QuickSettings: Camera or microphone access is allowed [CHAR LIMIT=NONE] -->
<string name="quick_settings_camera_mic_available">Available</string>
<!-- QuickSettings: Camera or microphone access is blocked [CHAR LIMIT=NONE] -->
<string name="quick_settings_camera_mic_blocked">Blocked</string>
<!-- QuickSettings: Media device [CHAR LIMIT=NONE] -->
<string name="quick_settings_media_device_label">Media device</string>
<!-- QuickSettings: RSSI [CHAR LIMIT=NONE] -->
@@ -981,10 +985,19 @@
<!-- QuickSettings: Text to prompt the user to stop an ongoing recording [CHAR LIMIT=20] -->
<string name="quick_settings_screen_record_stop">Stop</string>
<!--- Title of dialog triggered if the microphone is disabled but an app tried to access it. [CHAR LIMIT=150] -->
<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] -->
<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">To continue, &lt;b&gt;<xliff:g id="app" example="Gmail">%s</xliff:g>&lt;/b&gt; needs access to your device microphone.</string>
<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">To continue, &lt;b&gt;<xliff:g id="app" example="Gmail">%s</xliff:g>&lt;/b&gt; needs access to your devices camera.</string>
<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] -->
<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>
<!-- Default name for the media device shown in the output switcher when the name is not available [CHAR LIMIT=30] -->
<string name="media_seamless_remote_device">Device</string>

View File

@@ -24,6 +24,7 @@ import com.android.systemui.people.PeopleSpaceActivity;
import com.android.systemui.people.widget.LaunchConversationActivity;
import com.android.systemui.screenrecord.ScreenRecordDialog;
import com.android.systemui.screenshot.LongScreenshotActivity;
import com.android.systemui.sensorprivacy.SensorUseStartedActivity;
import com.android.systemui.settings.brightness.BrightnessDialog;
import com.android.systemui.statusbar.tv.notifications.TvNotificationPanelActivity;
import com.android.systemui.tuner.TunerActivity;
@@ -113,4 +114,10 @@ public abstract class DefaultActivityBinder {
@IntoMap
@ClassKey(LaunchConversationActivity.class)
public abstract Activity bindLaunchConversationActivity(LaunchConversationActivity activity);
/** Inject into SensorUseStartedActivity. */
@Binds
@IntoMap
@ClassKey(SensorUseStartedActivity.class)
public abstract Activity bindSensorUseStartedActivity(SensorUseStartedActivity activity);
}

View File

@@ -70,8 +70,12 @@ public class CameraToggleTile extends SensorPrivacyToggleTile {
}
@Override
public @DrawableRes int getIconRes() {
return com.android.internal.R.drawable.ic_camera_blocked;
public @DrawableRes int getIconRes(boolean isBlocked) {
if (isBlocked) {
return com.android.internal.R.drawable.ic_camera_blocked;
} else {
return com.android.internal.R.drawable.ic_camera_allowed;
}
}
@Override

View File

@@ -71,8 +71,12 @@ public class MicrophoneToggleTile extends SensorPrivacyToggleTile {
}
@Override
public @DrawableRes int getIconRes() {
return com.android.internal.R.drawable.ic_mic_blocked;
public @DrawableRes int getIconRes(boolean isBlocked) {
if (isBlocked) {
return com.android.internal.R.drawable.ic_mic_blocked;
} else {
return com.android.internal.R.drawable.ic_mic_allowed;
}
}
@Override

View File

@@ -26,10 +26,12 @@ import android.widget.Switch;
import androidx.annotation.DrawableRes;
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.FalsingManager;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.QSHost;
@@ -55,7 +57,7 @@ public abstract class SensorPrivacyToggleTile extends QSTileImpl<QSTile.BooleanS
/**
* @return icon for the QS tile
*/
public abstract @DrawableRes int getIconRes();
public abstract @DrawableRes int getIconRes(boolean isBlocked);
protected SensorPrivacyToggleTile(QSHost host,
@Background Looper backgroundLooper,
@@ -97,10 +99,15 @@ public abstract class SensorPrivacyToggleTile extends QSTileImpl<QSTile.BooleanS
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.icon = ResourceIcon.get(getIconRes(isBlocked));
state.state = isBlocked ? Tile.STATE_INACTIVE : Tile.STATE_ACTIVE;
state.value = !isBlocked;
state.label = getTileLabel();
if (isBlocked) {
state.secondaryLabel = mContext.getString(R.string.quick_settings_camera_mic_blocked);
} else {
state.secondaryLabel = mContext.getString(R.string.quick_settings_camera_mic_available);
}
state.handlesLongClick = false;
state.contentDescription = state.label;
state.expandedAccessibilityClassName = Switch.class.getName();
@@ -116,6 +123,11 @@ public abstract class SensorPrivacyToggleTile extends QSTileImpl<QSTile.BooleanS
return null;
}
@Override
public DetailAdapter getDetailAdapter() {
return super.getDetailAdapter();
}
@Override
public void onSensorBlockedChanged(int sensor, boolean blocked) {
if (sensor == getSensorId()) {

View File

@@ -16,7 +16,6 @@
package com.android.systemui.sensorprivacy
import android.app.AppOpsManager
import android.app.KeyguardManager
import android.app.KeyguardManager.KeyguardDismissCallback
import android.content.DialogInterface
@@ -24,15 +23,22 @@ import android.content.Intent.EXTRA_PACKAGE_NAME
import android.content.pm.PackageManager
import android.content.res.Resources
import android.hardware.SensorPrivacyManager
import android.hardware.SensorPrivacyManager.EXTRA_ALL_SENSORS
import android.hardware.SensorPrivacyManager.EXTRA_SENSOR
import android.hardware.SensorPrivacyManager.Sensors.CAMERA
import android.hardware.SensorPrivacyManager.Sensors.MICROPHONE
import android.os.Bundle
import android.os.Handler
import android.text.Html
import android.util.Log
import android.view.View.GONE
import android.view.View.VISIBLE
import android.widget.ImageView
import com.android.internal.app.AlertActivity
import com.android.internal.widget.DialogTitle
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.R
import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController
import javax.inject.Inject
/**
* Dialog to be shown on top of apps that are attempting to use a sensor (e.g. microphone) which is
@@ -40,21 +46,27 @@ import com.android.systemui.R
*
* <p>The dialog is started for the user the app is running for which might be a secondary users.
*/
class SensorUseStartedActivity : AlertActivity(), DialogInterface.OnClickListener {
class SensorUseStartedActivity @Inject constructor(
private val sensorPrivacyController: IndividualSensorPrivacyController,
private val keyguardManager: KeyguardManager,
private val keyguardUpdateMonitor: KeyguardUpdateMonitor
) : AlertActivity(), DialogInterface.OnClickListener {
companion object {
private val LOG_TAG = SensorUseStartedActivity::class.java.simpleName
private const val SUPPRESS_REMINDERS_REMOVAL_DELAY_MILLIS = 2000L
private const val CAMERA = SensorPrivacyManager.Sensors.CAMERA
private const val MICROPHONE = SensorPrivacyManager.Sensors.MICROPHONE
private const val ALL_SENSORS = Integer.MAX_VALUE
}
private var sensor = -1
private lateinit var sensorUsePackageName: String
private var unsuppressImmediately = false
private lateinit var sensorPrivacyManager: SensorPrivacyManager
private lateinit var appOpsManager: AppOpsManager
private lateinit var keyguardManager: KeyguardManager
private lateinit var sensorPrivacyListener: IndividualSensorPrivacyController.Callback
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -64,35 +76,81 @@ class SensorUseStartedActivity : AlertActivity(), DialogInterface.OnClickListene
setFinishOnTouchOutside(false)
setResult(RESULT_CANCELED)
sensorPrivacyManager = getSystemService(SensorPrivacyManager::class.java)!!
appOpsManager = getSystemService(AppOpsManager::class.java)!!
keyguardManager = getSystemService(KeyguardManager::class.java)!!
sensorUsePackageName = intent.getStringExtra(EXTRA_PACKAGE_NAME) ?: return
sensor = intent.getIntExtra(EXTRA_SENSOR, -1).also {
if (it == -1) {
if (intent.getBooleanExtra(EXTRA_ALL_SENSORS, false)) {
sensor = ALL_SENSORS
sensorPrivacyListener =
IndividualSensorPrivacyController.Callback { _, _ ->
if (!sensorPrivacyController.isSensorBlocked(MICROPHONE) &&
!sensorPrivacyController.isSensorBlocked(CAMERA)) {
dismiss()
}
}
sensorPrivacyController.addCallback(sensorPrivacyListener)
if (!sensorPrivacyController.isSensorBlocked(MICROPHONE) &&
!sensorPrivacyController.isSensorBlocked(CAMERA)) {
finish()
return
}
} else {
sensor = intent.getIntExtra(EXTRA_SENSOR, -1).also {
if (it == -1) {
finish()
return
}
}
sensorPrivacyListener =
IndividualSensorPrivacyController.Callback {
whichSensor: Int, isBlocked: Boolean ->
if (whichSensor == sensor && !isBlocked) {
dismiss()
}
}
sensorPrivacyController.addCallback(sensorPrivacyListener)
if (!sensorPrivacyController.isSensorBlocked(sensor)) {
finish()
return
}
}
sensorPrivacyManager.addSensorPrivacyListener(sensor) { isBlocked ->
if (!isBlocked) {
dismiss()
}
}
if (!sensorPrivacyManager.isSensorPrivacyEnabled(sensor)) {
finish()
return
}
mAlertParams.apply {
try {
mCustomTitleView = mInflater.inflate(R.layout.sensor_use_started_title, null)
mCustomTitleView.findViewById<DialogTitle>(R.id.sensor_use_started_title_message)!!
.setText(when (sensor) {
MICROPHONE ->
R.string.sensor_privacy_start_use_mic_dialog_title
CAMERA ->
R.string.sensor_privacy_start_use_camera_dialog_title
ALL_SENSORS ->
R.string.sensor_privacy_start_use_mic_camera_dialog_title
else -> Resources.ID_NULL
})
mCustomTitleView.findViewById<ImageView>(R.id.sensor_use_microphone_icon)!!
.visibility = if (sensor == MICROPHONE || sensor == ALL_SENSORS) {
VISIBLE
} else {
GONE
}
mCustomTitleView.findViewById<ImageView>(R.id.sensor_use_camera_icon)!!
.visibility = if (sensor == CAMERA || sensor == ALL_SENSORS) {
VISIBLE
} else {
GONE
}
mMessage = Html.fromHtml(getString(when (sensor) {
MICROPHONE ->
R.string.sensor_privacy_start_use_mic_dialog_content
CAMERA ->
R.string.sensor_privacy_start_use_camera_dialog_content
ALL_SENSORS ->
R.string.sensor_privacy_start_use_mic_camera_dialog_content
else -> Resources.ID_NULL
}, packageManager.getApplicationInfo(sensorUsePackageName, 0)
.loadLabel(packageManager)), 0)
@@ -101,13 +159,6 @@ class SensorUseStartedActivity : AlertActivity(), DialogInterface.OnClickListene
return
}
mIconId = when (sensor) {
MICROPHONE ->
com.android.internal.R.drawable.perm_group_microphone
CAMERA -> com.android.internal.R.drawable.perm_group_camera
else -> Resources.ID_NULL
}
mPositiveButtonText = getString(
com.android.internal.R.string.sensor_privacy_start_use_dialog_turn_on_button)
mNegativeButtonText = getString(android.R.string.cancel)
@@ -121,14 +172,14 @@ class SensorUseStartedActivity : AlertActivity(), DialogInterface.OnClickListene
override fun onStart() {
super.onStart()
sensorPrivacyManager.suppressSensorPrivacyReminders(sensorUsePackageName, true)
sensorPrivacyController.suppressSensorPrivacyReminders(sensorUsePackageName, true)
unsuppressImmediately = false
}
override fun onClick(dialog: DialogInterface?, which: Int) {
when (which) {
BUTTON_POSITIVE -> {
if (keyguardManager.isDeviceLocked) {
if (keyguardUpdateMonitor.getUserHasTrust(userId)) {
keyguardManager
.requestDismissKeyguard(this, object : KeyguardDismissCallback() {
override fun onDismissError() {
@@ -152,25 +203,30 @@ class SensorUseStartedActivity : AlertActivity(), DialogInterface.OnClickListene
}
override fun onStop() {
super.onDestroy()
super.onStop()
if (unsuppressImmediately) {
sensorPrivacyManager
sensorPrivacyController
.suppressSensorPrivacyReminders(sensorUsePackageName, false)
} else {
Handler(mainLooper).postDelayed({
sensorPrivacyManager
sensorPrivacyController
.suppressSensorPrivacyReminders(sensorUsePackageName, false)
}, SUPPRESS_REMINDERS_REMOVAL_DELAY_MILLIS)
}
}
override fun onDestroy() {
super.onDestroy()
sensorPrivacyController.removeCallback(sensorPrivacyListener)
}
override fun onBackPressed() {
// do not allow backing out
}
private fun disableSensorPrivacy() {
sensorPrivacyManager.setSensorPrivacyForProfileGroup(sensor, false)
sensorPrivacyController.setSensorBlocked(sensor, false)
unsuppressImmediately = true
setResult(RESULT_OK)
}

View File

@@ -26,6 +26,8 @@ public interface IndividualSensorPrivacyController extends
void setSensorBlocked(@Sensor int sensor, boolean blocked);
void suppressSensorPrivacyReminders(String packageName, boolean suppress);
interface Callback {
void onSensorBlockedChanged(@Sensor int sensor, boolean blocked);
}

View File

@@ -61,6 +61,11 @@ public class IndividualSensorPrivacyControllerImpl implements IndividualSensorPr
mSensorPrivacyManager.setSensorPrivacyForProfileGroup(sensor, blocked);
}
@Override
public void suppressSensorPrivacyReminders(String packageName, boolean suppress) {
mSensorPrivacyManager.suppressSensorPrivacyReminders(packageName, suppress);
}
@Override
public void addCallback(@NonNull Callback listener) {
mCallbacks.add(listener);

View File

@@ -63,6 +63,7 @@ import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.ShellCommand;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.SensorPrivacyIndividualEnabledSensorProto;
import android.service.SensorPrivacyServiceDumpProto;
import android.service.SensorPrivacyUserProto;
@@ -368,10 +369,10 @@ public final class SensorPrivacyService extends SystemService {
if (sensor == MICROPHONE) {
iconRes = R.drawable.ic_mic_blocked;
messageRes = R.string.sensor_privacy_start_use_mic_notification_content;
messageRes = R.string.sensor_privacy_start_use_mic_notification_content_title;
} else {
iconRes = R.drawable.ic_camera_blocked;
messageRes = R.string.sensor_privacy_start_use_camera_notification_content;
messageRes = R.string.sensor_privacy_start_use_camera_notification_content_title;
}
NotificationManager notificationManager =
@@ -390,10 +391,11 @@ public final class SensorPrivacyService extends SystemService {
Icon icon = Icon.createWithResource(getUiContext().getResources(), iconRes);
notificationManager.notify(sensor,
new Notification.Builder(mContext, SENSOR_PRIVACY_CHANNEL_ID)
.setContentTitle(Html.fromHtml(getUiContext().getString(messageRes,
.setContentTitle(getUiContext().getString(messageRes))
.setContentText(Html.fromHtml(getUiContext().getString(
R.string.sensor_privacy_start_use_notification_content_text,
packageLabel),0))
.setSmallIcon(icon)
.setLargeIcon(icon)
.addAction(new Notification.Action.Builder(icon,
getUiContext().getString(
R.string.sensor_privacy_start_use_dialog_turn_on_button),
@@ -405,6 +407,10 @@ public final class SensorPrivacyService extends SystemService {
PendingIntent.FLAG_IMMUTABLE
| PendingIntent.FLAG_UPDATE_CURRENT))
.build())
.setContentIntent(PendingIntent.getActivity(mContext, sensor,
new Intent(Settings.ACTION_PRIVACY_SETTINGS),
PendingIntent.FLAG_IMMUTABLE
| PendingIntent.FLAG_UPDATE_CURRENT))
.build());
}