Snap for 7814173 from 4471035b62809f3e9d61f1216c86cd5c94aa379b to mainline-resolv-release
Change-Id: Iac681de54fbb3d98bbcd966140e097d176af3ec6
diff --git a/PermissionController/AndroidManifest.xml b/PermissionController/AndroidManifest.xml
index a6fee58..6c9cf20 100644
--- a/PermissionController/AndroidManifest.xml
+++ b/PermissionController/AndroidManifest.xml
@@ -46,6 +46,7 @@
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_ROUTING" />
+ <uses-permission android:name="android.permission.OBSERVE_SENSOR_PRIVACY" />
<!-- TODO(b/170896938): make this privileged(signature may only work on pixel) -->
<uses-permission android:name="android.permission.MANAGE_NOTIFICATION_LISTENERS" />
<uses-permission android:name="android.permission.START_VIEW_PERMISSION_USAGE" />
diff --git a/PermissionController/res/drawable/ic_camera_blocked.xml b/PermissionController/res/drawable/ic_camera_blocked.xml
new file mode 100644
index 0000000..775974e
--- /dev/null
+++ b/PermissionController/res/drawable/ic_camera_blocked.xml
@@ -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.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>
diff --git a/PermissionController/res/drawable/ic_location_blocked.xml b/PermissionController/res/drawable/ic_location_blocked.xml
new file mode 100644
index 0000000..cdfc853
--- /dev/null
+++ b/PermissionController/res/drawable/ic_location_blocked.xml
@@ -0,0 +1,26 @@
+<!--
+ ~ 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.0"
+ android:viewportHeight="24.0"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M21.19,21.19l-4.92,-4.92 -1.45,-1.45 -7.51,-7.51 -1.53,-1.53 -2.97,-2.97 -1.42,1.41 3.7,3.7C5.04,8.27 5,8.63 5,9c0,5.25 7,13 7,13s1.52,-1.69 3.15,-4.02l4.63,4.63 1.41,-1.42zM12,18.88c-1.87,-2.39 -4.41,-6.15 -4.91,-8.95l6.62,6.62c-0.58,0.84 -1.17,1.64 -1.71,2.33zM12,4c2.76,0 5,2.24 5,5 0,1.16 -0.48,2.56 -1.18,3.99l1.48,1.48C18.28,12.62 19,10.68 19,9c0,-3.87 -3.13,-7 -7,-7 -1.98,0 -3.76,0.82 -5.03,2.14l1.42,1.42C9.3,4.6 10.58,4 12,4zM10.15,7.33l3.52,3.52c0.5,-0.46 0.83,-1.11 0.83,-1.85 0,-1.38 -1.12,-2.5 -2.5,-2.5 -0.73,0 -1.39,0.32 -1.85,0.83z"/>
+</vector>
\ No newline at end of file
diff --git a/PermissionController/res/drawable/ic_mic_blocked.xml b/PermissionController/res/drawable/ic_mic_blocked.xml
new file mode 100644
index 0000000..21fc7aa
--- /dev/null
+++ b/PermissionController/res/drawable/ic_mic_blocked.xml
@@ -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="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/PermissionController/res/layout/warning_banner_preference_card.xml b/PermissionController/res/layout/warning_banner_preference_card.xml
new file mode 100644
index 0000000..af533ba
--- /dev/null
+++ b/PermissionController/res/layout/warning_banner_preference_card.xml
@@ -0,0 +1,52 @@
+<?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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@style/WarningBannerMainContainer" >
+
+ <androidx.cardview.widget.CardView
+ style="@style/WarningBannerCardView" >
+
+ <RelativeLayout
+ style="@style/WarningBannerDimensions" >
+
+ <androidx.preference.internal.PreferenceImageView
+ android:id="@android:id/icon"
+ style="@style/WarningBannerIcon" />
+
+ <TextView android:id="@android:id/title"
+ android:layout_below="@android:id/icon"
+ style="@style/WarningBannerTitle" />
+
+ <TextView android:id="@android:id/summary"
+ android:layout_below="@android:id/title"
+ android:layout_alignStart="@android:id/title"
+ style="@style/WarningBannerSummary" />
+
+ <Button
+ android:id="@+id/button_id"
+ android:layout_below="@android:id/summary"
+ style="@style/WarningBannerButton" />
+
+ </RelativeLayout>
+
+ </androidx.cardview.widget.CardView>
+
+ <!-- Preference should place its actual preference widget here. -->
+ <LinearLayout android:id="@android:id/widget_frame"
+ style="@style/WarningBannerWidgetFrame" />
+
+</LinearLayout>
diff --git a/PermissionController/res/values-es-rUS/strings.xml b/PermissionController/res/values-es-rUS/strings.xml
index 0525dcc..e895158 100644
--- a/PermissionController/res/values-es-rUS/strings.xml
+++ b/PermissionController/res/values-es-rUS/strings.xml
@@ -345,7 +345,7 @@
<string name="no_apps_allowed" msgid="7718822655254468631">"No se le otorgó permiso a ninguna app"</string>
<string name="no_apps_allowed_full" msgid="8011716991498934104">"Ninguna app tiene el permiso para todos los archivos"</string>
<string name="no_apps_allowed_scoped" msgid="4908850477787659501">"Ninguna app tiene el permiso solo para contenido multimedia"</string>
- <string name="no_apps_denied" msgid="7663435886986784743">"No se le rechazó el permiso a ninguna app"</string>
+ <string name="no_apps_denied" msgid="7663435886986784743">"No hay permisos rechazados"</string>
<string name="car_permission_selected" msgid="180837028920791596">"Seleccionado"</string>
<string name="settings" msgid="5409109923158713323">"Configuración"</string>
<string name="accessibility_service_dialog_title_single" msgid="7956432823014102366">"<xliff:g id="SERVICE_NAME">%s</xliff:g> tiene acceso completo a tu dispositivo"</string>
diff --git a/PermissionController/res/values-es/strings.xml b/PermissionController/res/values-es/strings.xml
index 838be63..8fb0991 100644
--- a/PermissionController/res/values-es/strings.xml
+++ b/PermissionController/res/values-es/strings.xml
@@ -218,7 +218,7 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Ver todos los permisos de <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Ver todas las aplicaciones con este permiso"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Mostrar el uso del micrófono del Asistente"</string>
- <string name="auto_revoke_label" msgid="5068393642936571656">"Quitar permisos si la aplicación no se utiliza"</string>
+ <string name="auto_revoke_label" msgid="5068393642936571656">"Quitar permisos si la aplicación no se usa"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Quitar permisos y liberar espacio"</string>
<string name="auto_revoke_summary" msgid="5867548789805911683">"Para proteger tus datos, se quitarán los permisos de esta aplicación si no la usas durante unos meses."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Para proteger tus datos, si la aplicación no se ha utilizado durante unos meses, se quitarán los siguientes permisos: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-ja/strings.xml b/PermissionController/res/values-ja/strings.xml
index c6372d0..e1ec61a 100644
--- a/PermissionController/res/values-ja/strings.xml
+++ b/PermissionController/res/values-ja/strings.xml
@@ -54,7 +54,7 @@
<string name="no_unused_apps" msgid="12809387670415295">"使用されていないアプリなし"</string>
<string name="app_disable_dlg_positive" msgid="7418444149981904940">"アプリを無効にする"</string>
<string name="app_disable_dlg_text" msgid="3126943217146120240">"このアプリを無効にすると、Android などの他のアプリが正しく動作しなくなるおそれがあります。このアプリはデバイスにプリインストールされているため、削除できません。無効にするには、このアプリをオフにし、デバイスにアプリが表示されないようにします。"</string>
- <string name="app_permission_manager" msgid="3903811137630909550">"権限マネージャ"</string>
+ <string name="app_permission_manager" msgid="3903811137630909550">"権限マネージャー"</string>
<string name="never_ask_again" msgid="4728762438198560329">"今後表示しない"</string>
<string name="no_permissions" msgid="3881676756371148563">"権限がありません"</string>
<string name="additional_permissions" msgid="5801285469338873430">"その他の権限"</string>
diff --git a/PermissionController/res/values-night-v31/colors.xml b/PermissionController/res/values-night-v31/colors.xml
new file mode 100644
index 0000000..e5e4518
--- /dev/null
+++ b/PermissionController/res/values-night-v31/colors.xml
@@ -0,0 +1,20 @@
+<?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.
+ -->
+<resources>
+ <color name="warning_surface">#333124</color>
+ <color name="warning_onsurface">#FDD663</color>
+</resources>
\ No newline at end of file
diff --git a/PermissionController/res/values-v31/colors.xml b/PermissionController/res/values-v31/colors.xml
new file mode 100644
index 0000000..1e4d8c1
--- /dev/null
+++ b/PermissionController/res/values-v31/colors.xml
@@ -0,0 +1,20 @@
+<?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.
+ -->
+<resources>
+ <color name="warning_surface">#F0E3A8</color>
+ <color name="warning_onsurface">#895900</color>
+</resources>
\ No newline at end of file
diff --git a/PermissionController/res/values-zh-rTW/strings.xml b/PermissionController/res/values-zh-rTW/strings.xml
index 8b0fea6..6a3a9ec 100644
--- a/PermissionController/res/values-zh-rTW/strings.xml
+++ b/PermissionController/res/values-zh-rTW/strings.xml
@@ -342,10 +342,10 @@
<string name="app_perms_content_provider_all_files" msgid="3315281519230304799">"上次存取時間:過去 24 小時內 • 所有檔案"</string>
<string name="no_permissions_allowed" msgid="6081976856354669209">"未授予任何權限"</string>
<string name="no_permissions_denied" msgid="8159923922804043282">"未拒絕授予任何權限"</string>
- <string name="no_apps_allowed" msgid="7718822655254468631">"未授權給任何應用程式"</string>
+ <string name="no_apps_allowed" msgid="7718822655254468631">"未允許任何應用程式"</string>
<string name="no_apps_allowed_full" msgid="8011716991498934104">"未授予任何應用程式「允許存取所有檔案」的權限"</string>
<string name="no_apps_allowed_scoped" msgid="4908850477787659501">"未授予任何應用程式「僅允許存取媒體檔案」的權限"</string>
- <string name="no_apps_denied" msgid="7663435886986784743">"未拒絕授權給任何應用程式"</string>
+ <string name="no_apps_denied" msgid="7663435886986784743">"未拒絕任何應用程式"</string>
<string name="car_permission_selected" msgid="180837028920791596">"已選取"</string>
<string name="settings" msgid="5409109923158713323">"設定"</string>
<string name="accessibility_service_dialog_title_single" msgid="7956432823014102366">"「<xliff:g id="SERVICE_NAME">%s</xliff:g>」可完整存取你的裝置"</string>
diff --git a/PermissionController/res/values/overlayable.xml b/PermissionController/res/values/overlayable.xml
index 47e9cd6..10561a9 100644
--- a/PermissionController/res/values/overlayable.xml
+++ b/PermissionController/res/values/overlayable.xml
@@ -279,6 +279,18 @@
<item type="bool" name="config_useMaterial3PermissionGrantDialog" />
<!-- END GENERAL CONFIGS -->
+ <!-- START WARNING BANNER PREFERENCE STYLE -->
+ <item type="style" name="WarningBannerMainContainer" />
+ <item type="style" name="WarningBannerCardView" />
+ <item type="style" name="WarningBannerIcon" />
+ <item type="style" name="WarningBannerDimensions" />
+ <item type="style" name="WarningBannerText" />
+ <item type="style" name="WarningBannerTitle" />
+ <item type="style" name="WarningBannerSummary" />
+ <item type="style" name="WarningBannerButton" />
+ <item type="style" name="WarningBannerWidgetFrame" />
+ <!-- END WARNING BANNER PREFERENCE STYLE -->
+
</policy>
</overlayable>
diff --git a/PermissionController/res/values/strings.xml b/PermissionController/res/values/strings.xml
index a365070..4fd9c64 100644
--- a/PermissionController/res/values/strings.xml
+++ b/PermissionController/res/values/strings.xml
@@ -1342,4 +1342,15 @@
<!-- Info label for permissions for apps holding special exempted roles. [CHAR LIMIT=none] -->
<string name="exempt_info_label"><xliff:g id="app_name" example="Gmail">%1$s</xliff:g> is protected by Android. Because your data is processed on this device, this app’s permission usage isn’t shown on your privacy dashboard. </string>
+ <!-- Info label for the warning banner title if sensor is blocked [CHAR LIMIT=none] -->
+ <string name="blocked_sensor_title">Device <xliff:g id="sensor_name" example="camera">%1$s</xliff:g> is blocked</string>
+ <!-- Info label for the warning banner title if location is off [CHAR LIMIT=none] -->
+ <string name="blocked_location_title">Device <xliff:g id="sensor_name" example="location">%1$s</xliff:g> is off</string>
+ <!-- Info label to display that the sensor is blocked for apps and services [CHAR LIMIT=none] -->
+ <string name="blocked_sensor_summary">For apps and services</string>
+ <!-- Info label to display that the mic is blocked for apps and services [CHAR LIMIT=none] -->
+ <string name="blocked_mic_summary">Microphone data may still be shared when you call an emergency number.</string>
+ <!-- Label for the button to change the sensor status [CHAR LIMIT=none] -->
+ <string name="blocked_sensor_button_label">Change</string>
+
</resources>
diff --git a/PermissionController/res/values/styles.xml b/PermissionController/res/values/styles.xml
index 4478b01..e21557d 100644
--- a/PermissionController/res/values/styles.xml
+++ b/PermissionController/res/values/styles.xml
@@ -1094,4 +1094,83 @@
<!-- END PRIVACY DASHBOARD -->
+ <!-- START WARNING BANNER -->
+
+ <style name="WarningBannerMainContainer">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:background">?android:attr/selectableItemBackground</item>
+ <item name="android:clipToPadding">false</item>
+ <item name="android:focusable">true</item>
+ <item name="android:gravity">center_vertical</item>
+ <item name="android:minHeight">?android:attr/listPreferredItemHeightSmall</item>
+ <item name="android:paddingEnd">?android:attr/listPreferredItemPaddingEnd</item>
+ <item name="android:paddingStart">?android:attr/listPreferredItemPaddingStart</item>
+ </style>
+
+ <style name="WarningBannerCardView"
+ xmlns:card_view="http://schemas.android.com/apk/res-auto"
+ xmlns:app="http://schemas.android.com/apk/res-auto" >
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="app:cardCornerRadius">20dp</item>
+ <item name="app:cardBackgroundColor">@color/warning_surface</item>
+ <item name="app:cardElevation">0dp</item>
+ <item name="card_view:contentPaddingBottom">8dp</item>
+ <item name="card_view:contentPaddingTop">20dp</item>
+ <item name="card_view:contentPaddingLeft">20dp</item>
+ <item name="card_view:contentPaddingRight">20dp</item>
+ </style>
+
+ <style name="WarningBannerIcon" parent="@style/ImageViewIcon">
+ <item name="android:layout_marginBottom">8dp</item>
+ <item name="android:tint">@color/warning_onsurface</item>
+ </style>
+
+ <style name="WarningBannerDimensions">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ </style>
+
+ <style name="WarningBannerText">
+ <item name="android:layout_marginBottom">8dp</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
+ </style>
+
+ <style name="WarningBannerTitle" parent="@style/WarningBannerText">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textSize">20sp</item>
+ <item name="android:lineHeight">24sp</item>
+ </style>
+
+ <style name="WarningBannerSummary" parent="@style/WarningBannerText">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textSize">14sp</item>
+ <item name="android:lineHeight">20sp</item>
+ </style>
+
+ <style name="WarningBannerButton">
+ <item name="android:layout_height">36dp</item>
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_alignParentBottom">true</item>
+ <item name="android:layout_alignParentEnd">true</item>
+ <item name="android:textSize">14sp</item>
+ <item name="android:lineHeight">20sp</item>
+ <item name="android:layout_marginBottom">8dp</item>
+ <item name="android:textColor">@color/warning_onsurface</item>
+ <item name="android:background">?android:attr/selectableItemBackground</item>
+ </style>
+
+ <style name="WarningBannerWidgetFrame">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">match_parent</item>
+ <item name="android:gravity">end|center_vertical</item>
+ <item name="android:paddingStart">16dp</item>
+ <item name="android:orientation">vertical</item>
+ </style>
+
+ <!-- END WARNING BANNER -->
+
</resources>
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
index b96efef..8eff99b 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
@@ -351,6 +351,11 @@
// We are animating the top view, need to compensate for that in motion events.
ev.setLocation(ev.getX(), ev.getY() - rootView.getTop());
}
+ final int x = (int) ev.getX();
+ final int y = (int) ev.getY();
+ if ((x < 0) || (y < 0) || (x > (rootView.getWidth())) || (y > (rootView.getHeight()))) {
+ finishAfterTransition();
+ }
return super.dispatchTouchEvent(ev);
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/CardViewPreference.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/CardViewPreference.java
new file mode 100644
index 0000000..bb63cdd
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/CardViewPreference.java
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+package com.android.permissioncontroller.permission.ui.handheld;
+
+import android.content.Context;
+import android.content.Intent;
+import android.view.View;
+import android.widget.Button;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.permissioncontroller.R;
+
+
+/**
+ * A Preference representing a banner message represented as a CardView
+ */
+public class CardViewPreference extends Preference {
+
+ private String mAction;
+
+ public CardViewPreference(Context context, String action) {
+ super(context);
+ this.setLayoutResource(R.layout.warning_banner_preference_card);
+ mAction = action;
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+ Button button = (Button) holder.findViewById(R.id.button_id);
+ button.setText(R.string.blocked_sensor_button_label);
+ button.setVisibility(View.VISIBLE);
+ button.setOnClickListener(v -> {
+ getContext().startActivity(new Intent(mAction));
+ });
+ }
+
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionAppsFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionAppsFragment.java
index 4491557..78fe098 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionAppsFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionAppsFragment.java
@@ -45,6 +45,7 @@
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
+import android.provider.Settings;
import android.util.ArrayMap;
import android.util.Log;
import android.view.Menu;
@@ -77,6 +78,7 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Random;
@@ -97,6 +99,7 @@
private static final String LOG_TAG = "PermissionAppsFragment";
private static final String STORAGE_ALLOWED_FULL = "allowed_storage_full";
private static final String STORAGE_ALLOWED_SCOPED = "allowed_storage_scoped";
+ private static final String BLOCKED_SENSOR_PREF_KEY = "sensor_card";
private static final int SHOW_LOAD_DELAY_MS = 200;
private static final int AGGREGATE_DATA_FILTER_BEGIN_DAYS = 1;
@@ -123,6 +126,7 @@
private PermissionAppsViewModel mViewModel;
private PermissionUsages mPermissionUsages;
private List<AppPermissionUsage> mAppPermissionUsages = new ArrayList<>();
+ private Boolean mSensorStatus;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -173,6 +177,10 @@
mPermissionUsages.load(null, null, filterTimeBeginMillis, Long.MAX_VALUE,
PermissionUsages.USAGE_FLAG_LAST, getActivity().getLoaderManager(),
false, false, this, false);
+
+ if (Utils.shouldDisplayCardIfBlocked(mPermGroupName)) {
+ mViewModel.getSensorStatusLiveData().observe(this, this::setSensorStatus);
+ }
}
}
@@ -243,6 +251,62 @@
}
}
+
+ private void setSensorStatus(Boolean sensorStatus) {
+ mSensorStatus = sensorStatus;
+ displaySensorCard();
+ }
+
+ private void displaySensorCard() {
+ if (Utils.shouldDisplayCardIfBlocked(mPermGroupName)) {
+ if (mSensorStatus) {
+ setSensorCard();
+ } else {
+ removeSensorCard();
+ }
+ }
+ }
+
+
+ private void setSensorCard() {
+ CardViewPreference sensorCard = findPreference(BLOCKED_SENSOR_PREF_KEY);
+ if (sensorCard == null) {
+ sensorCard = createSensorCard();
+ getPreferenceScreen().addPreference(sensorCard);
+ }
+ sensorCard.setVisible(true);
+ }
+
+ private CardViewPreference createSensorCard() {
+ String label = KotlinUtils.INSTANCE.getPermGroupLabel(getPreferenceManager().getContext(),
+ mPermGroupName).toString().toLowerCase(
+ Locale.ROOT);
+ boolean isLocation = Manifest.permission_group.LOCATION.equals(mPermGroupName);
+ Context context = getPreferenceManager().getContext();
+ String action = isLocation ? Settings.ACTION_LOCATION_SOURCE_SETTINGS
+ : Settings.ACTION_PRIVACY_SETTINGS;
+ CardViewPreference sensorCard = new CardViewPreference(context, action);
+ sensorCard.setKey(BLOCKED_SENSOR_PREF_KEY);
+ sensorCard.setIcon(Utils.getBlockedIcon(mPermGroupName));
+ int cardTitle =
+ isLocation ? R.string.blocked_location_title : R.string.blocked_sensor_title;
+ sensorCard.setTitle(context.getString(cardTitle, label));
+ boolean isMicrophone = Manifest.permission_group.MICROPHONE.equals(mPermGroupName);
+ int cardSummary =
+ isMicrophone ? R.string.blocked_mic_summary : R.string.blocked_sensor_summary;
+ sensorCard.setSummary(context.getString(cardSummary));
+ sensorCard.setVisible(true);
+ sensorCard.setOrder(-1);
+ return sensorCard;
+ }
+
+ private void removeSensorCard() {
+ CardViewPreference sensorCard = findPreference(BLOCKED_SENSOR_PREF_KEY);
+ if (sensorCard != null) {
+ sensorCard.setVisible(false);
+ }
+ }
+
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
@@ -285,8 +349,11 @@
Map<String, Preference> existingPrefs = new ArrayMap<>();
for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); i++) {
- PreferenceCategory category = (PreferenceCategory)
- getPreferenceScreen().getPreference(i);
+ Preference pref = getPreferenceScreen().getPreference(i);
+ if (BLOCKED_SENSOR_PREF_KEY.equals(pref.getKey())) {
+ continue;
+ }
+ PreferenceCategory category = (PreferenceCategory) pref;
category.setOrderingAsAdded(true);
int numPreferences = category.getPreferenceCount();
for (int j = 0; j < numPreferences; j++) {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/PermissionAppsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/PermissionAppsViewModel.kt
index c7a13db..ed97375 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/PermissionAppsViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/PermissionAppsViewModel.kt
@@ -17,10 +17,14 @@
package com.android.permissioncontroller.permission.ui.model
import android.Manifest
+import android.Manifest.permission_group.LOCATION
import android.app.Application
import android.content.Intent
+import android.hardware.SensorPrivacyManager
+import android.os.Build
import android.os.Bundle
import android.os.UserHandle
+import androidx.annotation.RequiresApi
import androidx.fragment.app.Fragment
import androidx.lifecycle.AbstractSavedStateViewModelFactory
import androidx.lifecycle.MediatorLiveData
@@ -33,6 +37,7 @@
import com.android.permissioncontroller.permission.data.FullStoragePermissionAppsLiveData
import com.android.permissioncontroller.permission.data.FullStoragePermissionAppsLiveData.FullStoragePackageState
import com.android.permissioncontroller.permission.data.SinglePermGroupPackagesUiInfoLiveData
+import com.android.permissioncontroller.permission.data.SmartUpdateMediatorLiveData
import com.android.permissioncontroller.permission.model.livedatatypes.AppPermGroupUiInfo.PermGrantState
import com.android.permissioncontroller.permission.ui.Category
import com.android.permissioncontroller.permission.ui.LocationProviderInterceptDialog
@@ -41,6 +46,7 @@
import com.android.permissioncontroller.permission.ui.model.PermissionAppsViewModel.Companion.SHOULD_SHOW_SYSTEM_KEY
import com.android.permissioncontroller.permission.ui.model.PermissionAppsViewModel.Companion.SHOW_ALWAYS_ALLOWED
import com.android.permissioncontroller.permission.utils.LocationUtils
+import com.android.permissioncontroller.permission.utils.Utils
import com.android.permissioncontroller.permission.utils.navigateSafe
/**
@@ -70,6 +76,11 @@
val showAllowAlwaysStringLiveData = state.getLiveData(SHOW_ALWAYS_ALLOWED, false)
val categorizedAppsLiveData = CategorizedAppsLiveData(groupName)
+ @RequiresApi(Build.VERSION_CODES.S)
+ fun getSensorStatusLiveData(): SensorStatusLiveData {
+ return SensorStatusLiveData()
+ }
+
fun updateShowSystem(showSystem: Boolean) {
if (showSystem != state.get(SHOULD_SHOW_SYSTEM_KEY)) {
state.set(SHOULD_SHOW_SYSTEM_KEY, showSystem)
@@ -80,6 +91,68 @@
get() = state.get(CREATION_LOGGED_KEY) ?: false
set(value) = state.set(CREATION_LOGGED_KEY, value)
+ /**
+ * A LiveData that tracks the status (blocked or available) of a sensor
+ *
+ * @param permGroupName Permission group name for the sensor
+ */
+ @RequiresApi(Build.VERSION_CODES.S)
+ inner class SensorStatusLiveData() : SmartUpdateMediatorLiveData<Boolean>() {
+ val sensorPrivacyManager = app.getSystemService(SensorPrivacyManager::class.java)!!
+ val sensor = Utils.getSensorCode(groupName)
+ val isLocation = LOCATION.equals(groupName)
+
+ init {
+ checkAndUpdateStatus()
+ }
+
+ fun checkAndUpdateStatus() {
+ var blocked: Boolean
+
+ if (isLocation) {
+ val userContext = Utils.getUserContext(app, android.os.Process.myUserHandle())
+ blocked = !LocationUtils.isLocationEnabled(userContext)
+ } else {
+ blocked = sensorPrivacyManager.isSensorPrivacyEnabled(sensor)
+ }
+
+ if (blocked) {
+ value = blocked
+ }
+ }
+
+ override fun onActive() {
+ super.onActive()
+ checkAndUpdateStatus()
+ if (isLocation) {
+ LocationUtils.addLocationListener(locListener)
+ } else {
+ sensorPrivacyManager.addSensorPrivacyListener(sensor, listener)
+ }
+ }
+
+ override fun onInactive() {
+ super.onInactive()
+ if (isLocation) {
+ LocationUtils.removeLocationListener(locListener)
+ } else {
+ sensorPrivacyManager.removeSensorPrivacyListener(sensor, listener)
+ }
+ }
+
+ private val listener = { sensor: Int, status: Boolean ->
+ value = status
+ }
+
+ private val locListener = { status: Boolean ->
+ value = !status
+ }
+
+ override fun onUpdate() {
+ // Do nothing
+ }
+ }
+
inner class CategorizedAppsLiveData(groupName: String)
: MediatorLiveData<@kotlin.jvm.JvmSuppressWildcards
Map<Category, List<Pair<String, UserHandle>>>>() {
@@ -265,4 +338,4 @@
@Suppress("UNCHECKED_CAST")
return PermissionAppsViewModel(state, app, groupName) as T
}
-}
\ No newline at end of file
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java b/PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java
index e87407f..c7f7182 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java
@@ -64,6 +64,7 @@
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
+import android.hardware.SensorPrivacyManager;
import android.os.Build;
import android.os.Parcelable;
import android.os.Process;
@@ -84,6 +85,7 @@
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
import androidx.annotation.StringRes;
import androidx.core.text.BidiFormatter;
import androidx.core.util.Preconditions;
@@ -192,6 +194,11 @@
private static final ArrayMap<String, Integer> PERM_GROUP_UPGRADE_REQUEST_RES;
private static final ArrayMap<String, Integer> PERM_GROUP_UPGRADE_REQUEST_DETAIL_RES;
+ /** Permission -> Sensor codes */
+ private static final ArrayMap<String, Integer> PERM_SENSOR_CODES;
+ /** Permission -> Icon res id */
+ private static final ArrayMap<String, Integer> PERM_BLOCKED_ICON;
+
public static final int FLAGS_ALWAYS_USER_SENSITIVE =
FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED
| FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED;
@@ -350,6 +357,17 @@
.put(MICROPHONE, R.string.permgroupupgraderequestdetail_microphone);
PERM_GROUP_UPGRADE_REQUEST_DETAIL_RES
.put(CAMERA, R.string.permgroupupgraderequestdetail_camera);
+
+ PERM_SENSOR_CODES = new ArrayMap<>();
+ if (SdkLevel.isAtLeastS()) {
+ PERM_SENSOR_CODES.put(CAMERA, SensorPrivacyManager.Sensors.CAMERA);
+ PERM_SENSOR_CODES.put(MICROPHONE, SensorPrivacyManager.Sensors.MICROPHONE);
+ }
+
+ PERM_BLOCKED_ICON = new ArrayMap<>();
+ PERM_BLOCKED_ICON.put(CAMERA, R.drawable.ic_camera_blocked);
+ PERM_BLOCKED_ICON.put(MICROPHONE, R.drawable.ic_mic_blocked);
+ PERM_BLOCKED_ICON.put(LOCATION, R.drawable.ic_location_blocked);
}
private Utils() {
@@ -1235,4 +1253,27 @@
public static boolean isStatusBarIndicatorPermission(@NonNull String permissionGroupName) {
return CAMERA.equals(permissionGroupName) || MICROPHONE.equals(permissionGroupName);
}
+
+ /**
+ * Returns if a card should be shown if the sensor is blocked
+ **/
+ public static boolean shouldDisplayCardIfBlocked(@NonNull String permissionGroupName) {
+ return CAMERA.equals(permissionGroupName) || MICROPHONE.equals(permissionGroupName)
+ || LOCATION.equals(permissionGroupName);
+ }
+
+ /**
+ * Returns the sensor code for a permission
+ **/
+ @RequiresApi(Build.VERSION_CODES.S)
+ public static int getSensorCode(@NonNull String permissionGroupName) {
+ return PERM_SENSOR_CODES.getOrDefault(permissionGroupName, -1);
+ }
+
+ /**
+ * Returns the blocked icon code for a permission
+ **/
+ public static int getBlockedIcon(@NonNull String permissionGroupName) {
+ return PERM_BLOCKED_ICON.getOrDefault(permissionGroupName, -1);
+ }
}