Show privacy icons in status bar

Adds PrivacyItemController to PhoneStatusBarPolicy so that we can show
microphone and camera privacy icons in the status bar.

Test: open camera to show the camera icon
Test: open a recording app to show microphone
Bug: 112331475
Change-Id: Ia14f838d715a2808db595c9da3be236d36cc6589
This commit is contained in:
Evan Laird
2018-11-14 13:46:08 -05:00
parent b513876655
commit cf1a103d70
6 changed files with 115 additions and 3 deletions

View File

@@ -55,6 +55,8 @@
<item><xliff:g id="id">@string/status_bar_hotspot</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_mobile</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_airplane</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_microphone</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_camera</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_battery</xliff:g></item>
</string-array>
@@ -87,6 +89,8 @@
<string translatable="false" name="status_bar_mobile">mobile</string>
<string translatable="false" name="status_bar_vpn">vpn</string>
<string translatable="false" name="status_bar_ethernet">ethernet</string>
<string translatable="false" name="status_bar_microphone">microphone</string>
<string translatable="false" name="status_bar_camera">camera</string>
<string translatable="false" name="status_bar_airplane">airplane</string>
<!-- Flag indicating whether the surface flinger has limited

View File

@@ -2808,6 +2808,8 @@
<java-symbol type="string" name="status_bar_mobile" />
<java-symbol type="string" name="status_bar_ethernet" />
<java-symbol type="string" name="status_bar_vpn" />
<java-symbol type="string" name="status_bar_microphone" />
<java-symbol type="string" name="status_bar_camera" />
<!-- Locale picker -->
<java-symbol type="id" name="locale_search_menu" />

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
**
** Copyright 2018, 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.
*/
-->
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:insetLeft="3dp"
android:insetRight="3dp">
<vector
android:width="17dp"
android:height="17dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFF"
android:pathData="M20,5h-3.17L15,3H9L7.17,5H4C2.9,5 2,5.9 2,7v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V7C22,5.9 21.1,5 20,5zM20,19H4V7h16V19zM12,9c-2.21,0 -4,1.79 -4,4c0,2.21 1.79,4 4,4s4,-1.79 4,-4C16,10.79 14.21,9 12,9z"/>
</vector>
</inset>

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
**
** Copyright 2018, 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="18dp"
android:height="18dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFF"
android:pathData="M12,14c1.66,0 3,-1.34 3,-3V5c0,-1.66 -1.34,-3 -3,-3S9,3.34 9,5v6C9,12.66 10.34,14 12,14zM11,5c0,-0.55 0.45,-1 1,-1s1,0.45 1,1v6c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1V5z"/>
<path
android:fillColor="#FFF"
android:pathData="M17,11c0,2.76 -2.24,5 -5,5s-5,-2.24 -5,-5H5c0,3.53 2.61,6.43 6,6.92V21h2v-3.08c3.39,-0.49 6,-3.39 6,-6.92H17z"/>
</vector>

View File

@@ -23,9 +23,9 @@ import com.android.systemui.R
typealias Privacy = PrivacyType
enum class PrivacyType(val nameId: Int, val iconId: Int) {
TYPE_CAMERA(R.string.privacy_type_camera, com.android.internal.R.drawable.ic_camera),
TYPE_CAMERA(R.string.privacy_type_camera, R.drawable.stat_sys_camera),
TYPE_LOCATION(R.string.privacy_type_location, R.drawable.stat_sys_location),
TYPE_MICROPHONE(R.string.privacy_type_microphone, R.drawable.ic_mic_26dp);
TYPE_MICROPHONE(R.string.privacy_type_microphone, R.drawable.stat_sys_mic_none);
fun getName(context: Context) = context.resources.getString(nameId)

View File

@@ -66,6 +66,8 @@ import com.android.systemui.DockedStackExistsListener;
import com.android.systemui.R;
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.UiOffloadThread;
import com.android.systemui.privacy.PrivacyItem;
import com.android.systemui.privacy.PrivacyItemController;
import com.android.systemui.qs.tiles.DndTile;
import com.android.systemui.qs.tiles.RotationLockTile;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -101,7 +103,8 @@ import java.util.Locale;
*/
public class PhoneStatusBarPolicy implements Callback, Callbacks,
RotationLockControllerCallback, Listener, LocationChangeCallback,
ZenModeController.Callback, DeviceProvisionedListener, KeyguardMonitor.Callback {
ZenModeController.Callback, DeviceProvisionedListener, KeyguardMonitor.Callback,
PrivacyItemController.Callback {
private static final String TAG = "PhoneStatusBarPolicy";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -120,6 +123,8 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
private final String mSlotHeadset;
private final String mSlotDataSaver;
private final String mSlotLocation;
private final String mSlotMicrophone;
private final String mSlotCamera;
private final Context mContext;
private final Handler mHandler = new Handler();
@@ -136,6 +141,7 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
private final DeviceProvisionedController mProvisionedController;
private final KeyguardMonitor mKeyguardMonitor;
private final LocationController mLocationController;
private final PrivacyItemController mPrivacyItemController;
private final ArraySet<Pair<String, Integer>> mCurrentNotifs = new ArraySet<>();
private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
@@ -169,6 +175,7 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
mProvisionedController = Dependency.get(DeviceProvisionedController.class);
mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
mLocationController = Dependency.get(LocationController.class);
mPrivacyItemController = new PrivacyItemController(mContext, this);
mSlotCast = context.getString(com.android.internal.R.string.status_bar_cast);
mSlotHotspot = context.getString(com.android.internal.R.string.status_bar_hotspot);
@@ -183,6 +190,8 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
mSlotHeadset = context.getString(com.android.internal.R.string.status_bar_headset);
mSlotDataSaver = context.getString(com.android.internal.R.string.status_bar_data_saver);
mSlotLocation = context.getString(com.android.internal.R.string.status_bar_location);
mSlotMicrophone = context.getString(com.android.internal.R.string.status_bar_microphone);
mSlotCamera = context.getString(com.android.internal.R.string.status_bar_camera);
// listen for broadcasts
IntentFilter filter = new IntentFilter();
@@ -241,6 +250,12 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
context.getString(R.string.accessibility_data_saver_on));
mIconController.setIconVisibility(mSlotDataSaver, false);
// privacy items
mIconController.setIcon(mSlotMicrophone, R.drawable.stat_sys_mic_none, null);
mIconController.setIconVisibility(mSlotMicrophone, false);
mIconController.setIcon(mSlotCamera, R.drawable.stat_sys_camera, null);
mIconController.setIconVisibility(mSlotCamera, false);
mRotationLockController.addCallback(this);
mBluetooth.addCallback(this);
mProvisionedController.addCallback(this);
@@ -251,6 +266,7 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
mDataSaver.addCallback(this);
mKeyguardMonitor.addCallback(this);
mLocationController.addCallback(this);
mPrivacyItemController.setListening(true);
SysUiServiceProvider.getComponent(mContext, CommandQueue.class).addCallbacks(this);
ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskListener);
@@ -279,6 +295,7 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
mDataSaver.removeCallback(this);
mKeyguardMonitor.removeCallback(this);
mLocationController.removeCallback(this);
mPrivacyItemController.setListening(false);
SysUiServiceProvider.getComponent(mContext, CommandQueue.class).removeCallbacks(this);
mContext.unregisterReceiver(mIntentReceiver);
@@ -798,6 +815,34 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
mIconController.setIconVisibility(mSlotDataSaver, isDataSaving);
}
@Override // PrivacyItemController.Callback
public void privacyChanged(List<PrivacyItem> privacyItems) {
updatePrivacyItems(privacyItems);
}
private void updatePrivacyItems(List<PrivacyItem> items) {
boolean showCamera = false;
boolean showMicrophone = false;
boolean showLocation = false;
for (PrivacyItem item : items) {
switch (item.getPrivacyType()) {
case TYPE_CAMERA:
showCamera = true;
break;
case TYPE_LOCATION:
showLocation = true;
break;
case TYPE_MICROPHONE:
showMicrophone = true;
break;
}
}
mIconController.setIconVisibility(mSlotCamera, showCamera);
mIconController.setIconVisibility(mSlotMicrophone, showMicrophone);
mIconController.setIconVisibility(mSlotLocation, showLocation);
}
private final TaskStackChangeListener mTaskListener = new TaskStackChangeListener() {
@Override
public void onTaskStackChanged() {