From 8943ad6325c890c279b8d600784680ef8d0eb3c2 Mon Sep 17 00:00:00 2001 From: "Philip P. Moltmann" <moltmann@google.com> Date: Wed, 25 Jul 2018 12:12:30 -0700 Subject: [PATCH] Split PackageInstaller app into installation and permissions management The two components were mostly independant for a long time. Since I1e80a3f5e63d02b3859ecf74af21ca4c61f96874 the installation flow does not grant any permissions anymore and the last connection between these parts was broken. The new app "com.android.packageinstaller" in frameworks/base/packages/PackageInstaller will only handle (side load) package installtion and uninstallation. The exisiting app will be renamed to "com.android.permissioncontroller" and only handle permission granting and permission management. This change does only minimal cleanup cleanup. In particularly it does not move any files in the old permissions controller. This is to not disturb other features currently in development. This change set also updates the make files to install the two apps on the appropriate devices. Further the permisson policy xmls need to be updated to point to the right packages. Test: Installed + uninstalled packages Granted permissions + managed permissions GtsPackageInstallTestCases GtsNoPermissionTestCases GtsNoPermissionTestCases25 GtsPackageInstallerTapjackingTestCases GtsPackageUninstallTestCases Change-Id: I2d3796b837fc0049e712c82a990907f305c8febf --- PREUPLOAD.cfg | 1 + .../content/pm/PackageManagerInternal.java | 2 + data/etc/hiddenapi-package-whitelist.xml | 2 +- data/etc/privapp-permissions-platform.xml | 9 +- packages/PackageInstaller/Android.mk | 30 +- packages/PackageInstaller/AndroidManifest.xml | 70 +- packages/PackageInstaller/PREUPLOAD.cfg | 7 - packages/PackageInstaller/proguard.flags | 8 - .../color/btn_colored_background_material.xml | 21 - .../res/drawable-hdpi/ic_fail.png | Bin 707 -> 0 bytes .../res/drawable-hdpi/ic_success.png | Bin 651 -> 0 bytes .../drawable-hdpi/tab_unselected_holo.9.png | Bin 153 -> 0 bytes .../res/drawable-mdpi/ic_fail.png | Bin 594 -> 0 bytes .../res/drawable-mdpi/ic_success.png | Bin 505 -> 0 bytes .../drawable-mdpi/tab_unselected_holo.9.png | Bin 157 -> 0 bytes .../grant_permissions_action_item.xml | 20 - ...ant_permissions_action_item_background.xml | 21 - .../grant_permissions_action_item_shape.xml | 28 - .../accept_deny_dialog_negative_bg.xml | 32 - .../accept_deny_dialog_positive_bg.xml | 32 - .../res/drawable-watch/action_negative_bg.xml | 24 - .../res/drawable-watch/action_positive_bg.xml | 24 - .../res/drawable-watch/cancel_button.xml | 19 - .../res/drawable-watch/confirm_button.xml | 19 - .../res/drawable-watch/deny_button.xml | 19 - .../res/drawable-watch/ic_cc_checkmark.xml | 24 - .../res/drawable-watch/ic_cc_clear.xml | 24 - .../res/drawable-watch/ic_cc_deny.xml | 24 - .../res/drawable-xhdpi/ic_fail.png | Bin 947 -> 0 bytes .../res/drawable-xhdpi/ic_success.png | Bin 820 -> 0 bytes .../drawable-xhdpi/tab_unselected_holo.9.png | Bin 166 -> 0 bytes .../drawable-xxhdpi/tab_unselected_holo.9.png | Bin 1054 -> 0 bytes .../res/drawable/button_ripple_bg.xml | 23 - .../res/drawable/ic_arrow_back.xml | 30 - .../res/drawable/ic_dialog_alert_material.xml | 25 - .../res/drawable/ic_fail_material.xml | 18 - .../res/drawable/ic_info_outline.xml | 24 - .../res/drawable/ic_more_items.xml | 29 - .../res/drawable/ic_perm_device_info.xml | 24 - .../res/drawable/ic_success_material.xml | 18 - .../PackageInstaller/res/drawable/ic_toc.xml | 24 - .../res/drawable/rectangle_ripple_mask.xml | 22 - .../layout-television/grant_permissions.xml | 91 -- .../res/layout-television/header.xml | 47 - .../layout-television/permissions_frame.xml | 47 - .../res/layout-watch/accept_deny_dialog.xml | 111 -- .../wear_review_permission_action_pref.xml | 25 - .../wear_review_permission_title_pref.xml | 38 - .../res/layout/car_app_permissions.xml | 68 - .../res/layout/grant_permissions.xml | 141 -- .../res/layout/grant_permissions_content.xml | 105 -- .../PackageInstaller/res/layout/header.xml | 54 - .../PackageInstaller/res/layout/label.xml | 22 - .../res/layout/loading_container.xml | 36 - .../res/layout/permissions_frame.xml | 40 - .../res/layout/permissions_list.xml | 31 - .../layout/preference_category_material.xml | 35 - .../res/layout/preference_permissions.xml | 80 - .../layout/preference_permissions_switch.xml | 80 - .../res/layout/review_permissions.xml | 112 -- .../res/values-television/colors.xml | 11 - .../res/values-television/dimens.xml | 7 - .../res/values-television/strings.xml | 38 - .../res/values-television/styles.xml | 37 - .../res/values-television/themes.xml | 71 - .../res/values-watch/strings.xml | 15 - .../res/values-watch/themes.xml | 6 - .../PackageInstaller/res/values/strings.xml | 193 --- .../PackageInstaller/res/values/themes.xml | 22 - .../res/xml-watch/watch_permissions.xml | 22 - .../res/xml/all_permissions.xml | 24 - .../wearable/view/AcceptDenyDialog.java | 182 --- .../wearable/view/CircledImageView.java | 603 ------- .../support/wearable/view/Gusterpolator.java | 84 - .../wearable/view/ProgressDrawable.java | 176 --- .../wearable/view/SimpleAnimatorListener.java | 67 - .../wearable/view/WearableDialogHelper.java | 217 --- .../wearable/view/WearableListView.java | 1387 ----------------- .../permission/model/AppPermissionGroup.java | 1001 ------------ .../permission/model/AppPermissions.java | 175 --- .../permission/model/Permission.java | 233 --- .../permission/model/PermissionApps.java | 441 ------ .../permission/model/PermissionGroup.java | 120 -- .../permission/model/PermissionGroups.java | 262 ---- ...RuntimePermissionPresenterServiceImpl.java | 84 - .../permission/ui/ButtonBarLayout.java | 111 -- .../ui/ConfirmActionDialogFragment.java | 61 - .../ui/GrantPermissionsActivity.java | 834 ---------- .../ui/GrantPermissionsViewHandler.java | 106 -- .../ui/GrantPermissionsWatchViewHandler.java | 216 --- .../ui/ManagePermissionsActivity.java | 128 -- .../permission/ui/ManualLayoutFrame.java | 78 - .../permission/ui/OverlayWarningDialog.java | 63 - .../permission/ui/PreferenceImageView.java | 69 - .../ui/ReviewPermissionsActivity.java | 81 - .../ui/auto/AppPermissionsFragment.java | 204 --- .../auto/GrantPermissionsAutoViewHandler.java | 46 - .../handheld/AllAppPermissionsFragment.java | 378 ----- .../ui/handheld/AppPermissionsFragment.java | 331 ---- .../GrantPermissionsViewHandlerImpl.java | 446 ------ .../ManageCustomPermissionsFragment.java | 46 - .../handheld/ManagePermissionsFragment.java | 154 -- .../ManageStandardPermissionsFragment.java | 107 -- .../handheld/MultiTargetSwitchPreference.java | 60 - .../ui/handheld/PermissionAppsFragment.java | 390 ----- .../ui/handheld/PermissionPreference.java | 581 ------- .../ui/handheld/PermissionsFrameFragment.java | 121 -- .../handheld/RestrictedSwitchPreference.java | 84 - .../handheld/ReviewPermissionsFragment.java | 404 ----- .../ui/handheld/SettingsWithHeader.java | 84 - .../television/AllAppPermissionsFragment.java | 319 ---- .../ui/television/AppPermissionsFragment.java | 411 ----- .../GrantPermissionsViewHandlerImpl.java | 137 -- .../television/ManagePermissionsFragment.java | 238 --- .../ui/television/PermissionAppsFragment.java | 438 ------ .../television/PermissionsFrameFragment.java | 206 --- .../ui/television/SettingsWithHeader.java | 74 - .../ui/wear/AppPermissionsFragmentWear.java | 403 ----- .../wear/ReviewPermissionsWearFragment.java | 357 ----- .../permission/utils/ArrayUtils.java | 63 - .../permission/utils/EventLogger.java | 43 - .../permission/utils/IoUtils.java | 36 - .../permission/utils/LocationUtils.java | 72 - .../permission/utils/SafetyNetLogger.java | 128 -- .../permission/utils/Utils.java | 211 --- .../server/pm/PackageManagerService.java | 6 +- .../permission/PermissionManagerService.java | 10 +- 127 files changed, 30 insertions(+), 15643 deletions(-) delete mode 100644 packages/PackageInstaller/PREUPLOAD.cfg delete mode 100644 packages/PackageInstaller/proguard.flags delete mode 100644 packages/PackageInstaller/res/color/btn_colored_background_material.xml delete mode 100644 packages/PackageInstaller/res/drawable-hdpi/ic_fail.png delete mode 100644 packages/PackageInstaller/res/drawable-hdpi/ic_success.png delete mode 100644 packages/PackageInstaller/res/drawable-hdpi/tab_unselected_holo.9.png delete mode 100644 packages/PackageInstaller/res/drawable-mdpi/ic_fail.png delete mode 100644 packages/PackageInstaller/res/drawable-mdpi/ic_success.png delete mode 100644 packages/PackageInstaller/res/drawable-mdpi/tab_unselected_holo.9.png delete mode 100644 packages/PackageInstaller/res/drawable-television/grant_permissions_action_item.xml delete mode 100644 packages/PackageInstaller/res/drawable-television/grant_permissions_action_item_background.xml delete mode 100644 packages/PackageInstaller/res/drawable-television/grant_permissions_action_item_shape.xml delete mode 100644 packages/PackageInstaller/res/drawable-watch/accept_deny_dialog_negative_bg.xml delete mode 100644 packages/PackageInstaller/res/drawable-watch/accept_deny_dialog_positive_bg.xml delete mode 100644 packages/PackageInstaller/res/drawable-watch/action_negative_bg.xml delete mode 100644 packages/PackageInstaller/res/drawable-watch/action_positive_bg.xml delete mode 100644 packages/PackageInstaller/res/drawable-watch/cancel_button.xml delete mode 100644 packages/PackageInstaller/res/drawable-watch/confirm_button.xml delete mode 100644 packages/PackageInstaller/res/drawable-watch/deny_button.xml delete mode 100644 packages/PackageInstaller/res/drawable-watch/ic_cc_checkmark.xml delete mode 100644 packages/PackageInstaller/res/drawable-watch/ic_cc_clear.xml delete mode 100644 packages/PackageInstaller/res/drawable-watch/ic_cc_deny.xml delete mode 100644 packages/PackageInstaller/res/drawable-xhdpi/ic_fail.png delete mode 100644 packages/PackageInstaller/res/drawable-xhdpi/ic_success.png delete mode 100644 packages/PackageInstaller/res/drawable-xhdpi/tab_unselected_holo.9.png delete mode 100644 packages/PackageInstaller/res/drawable-xxhdpi/tab_unselected_holo.9.png delete mode 100644 packages/PackageInstaller/res/drawable/button_ripple_bg.xml delete mode 100644 packages/PackageInstaller/res/drawable/ic_arrow_back.xml delete mode 100644 packages/PackageInstaller/res/drawable/ic_dialog_alert_material.xml delete mode 100644 packages/PackageInstaller/res/drawable/ic_fail_material.xml delete mode 100644 packages/PackageInstaller/res/drawable/ic_info_outline.xml delete mode 100644 packages/PackageInstaller/res/drawable/ic_more_items.xml delete mode 100644 packages/PackageInstaller/res/drawable/ic_perm_device_info.xml delete mode 100644 packages/PackageInstaller/res/drawable/ic_success_material.xml delete mode 100644 packages/PackageInstaller/res/drawable/ic_toc.xml delete mode 100644 packages/PackageInstaller/res/drawable/rectangle_ripple_mask.xml delete mode 100644 packages/PackageInstaller/res/layout-television/grant_permissions.xml delete mode 100644 packages/PackageInstaller/res/layout-television/header.xml delete mode 100644 packages/PackageInstaller/res/layout-television/permissions_frame.xml delete mode 100644 packages/PackageInstaller/res/layout-watch/accept_deny_dialog.xml delete mode 100644 packages/PackageInstaller/res/layout-watch/wear_review_permission_action_pref.xml delete mode 100644 packages/PackageInstaller/res/layout-watch/wear_review_permission_title_pref.xml delete mode 100644 packages/PackageInstaller/res/layout/car_app_permissions.xml delete mode 100644 packages/PackageInstaller/res/layout/grant_permissions.xml delete mode 100644 packages/PackageInstaller/res/layout/grant_permissions_content.xml delete mode 100644 packages/PackageInstaller/res/layout/header.xml delete mode 100644 packages/PackageInstaller/res/layout/label.xml delete mode 100644 packages/PackageInstaller/res/layout/loading_container.xml delete mode 100644 packages/PackageInstaller/res/layout/permissions_frame.xml delete mode 100644 packages/PackageInstaller/res/layout/permissions_list.xml delete mode 100644 packages/PackageInstaller/res/layout/preference_category_material.xml delete mode 100644 packages/PackageInstaller/res/layout/preference_permissions.xml delete mode 100644 packages/PackageInstaller/res/layout/preference_permissions_switch.xml delete mode 100644 packages/PackageInstaller/res/layout/review_permissions.xml delete mode 100644 packages/PackageInstaller/res/values-television/strings.xml delete mode 100644 packages/PackageInstaller/res/values-television/styles.xml delete mode 100644 packages/PackageInstaller/res/values-television/themes.xml delete mode 100644 packages/PackageInstaller/res/xml-watch/watch_permissions.xml delete mode 100644 packages/PackageInstaller/res/xml/all_permissions.xml delete mode 100644 packages/PackageInstaller/src/android/support/wearable/view/AcceptDenyDialog.java delete mode 100644 packages/PackageInstaller/src/android/support/wearable/view/CircledImageView.java delete mode 100644 packages/PackageInstaller/src/android/support/wearable/view/Gusterpolator.java delete mode 100644 packages/PackageInstaller/src/android/support/wearable/view/ProgressDrawable.java delete mode 100644 packages/PackageInstaller/src/android/support/wearable/view/SimpleAnimatorListener.java delete mode 100644 packages/PackageInstaller/src/android/support/wearable/view/WearableDialogHelper.java delete mode 100644 packages/PackageInstaller/src/android/support/wearable/view/WearableListView.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/model/AppPermissionGroup.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/model/AppPermissions.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/model/Permission.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/model/PermissionApps.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/model/PermissionGroup.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/model/PermissionGroups.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/service/RuntimePermissionPresenterServiceImpl.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/ButtonBarLayout.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/ConfirmActionDialogFragment.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/GrantPermissionsViewHandler.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/GrantPermissionsWatchViewHandler.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/ManagePermissionsActivity.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/ManualLayoutFrame.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/OverlayWarningDialog.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/PreferenceImageView.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/ReviewPermissionsActivity.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/auto/AppPermissionsFragment.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/auto/GrantPermissionsAutoViewHandler.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/AllAppPermissionsFragment.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/AppPermissionsFragment.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/GrantPermissionsViewHandlerImpl.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/ManageCustomPermissionsFragment.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/ManagePermissionsFragment.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/ManageStandardPermissionsFragment.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/MultiTargetSwitchPreference.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/PermissionAppsFragment.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/PermissionPreference.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/PermissionsFrameFragment.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/RestrictedSwitchPreference.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/ReviewPermissionsFragment.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/SettingsWithHeader.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/television/AllAppPermissionsFragment.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/television/AppPermissionsFragment.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/television/GrantPermissionsViewHandlerImpl.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/television/ManagePermissionsFragment.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/television/PermissionAppsFragment.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/television/PermissionsFrameFragment.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/television/SettingsWithHeader.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/wear/AppPermissionsFragmentWear.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/wear/ReviewPermissionsWearFragment.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/utils/ArrayUtils.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/utils/EventLogger.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/utils/IoUtils.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/utils/LocationUtils.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/utils/SafetyNetLogger.java delete mode 100644 packages/PackageInstaller/src/com/android/packageinstaller/permission/utils/Utils.java diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg index c74516d410b5..2df7042a53d9 100644 --- a/PREUPLOAD.cfg +++ b/PREUPLOAD.cfg @@ -5,6 +5,7 @@ checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPL core/tests/coretests/src/android/ packages/PrintRecommendationService/ packages/PrintSpooler/ + packages/PackageInstaller/ services/print/ services/usb/ telephony/ diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java index ee752f8b8186..edddb7939ead 100644 --- a/core/java/android/content/pm/PackageManagerInternal.java +++ b/core/java/android/content/pm/PackageManagerInternal.java @@ -48,6 +48,7 @@ public abstract class PackageManagerInternal { public static final int PACKAGE_VERIFIER = 3; public static final int PACKAGE_BROWSER = 4; public static final int PACKAGE_SYSTEM_TEXT_CLASSIFIER = 5; + public static final int PACKAGE_PERMISSION_CONTROLLER = 6; @IntDef(value = { PACKAGE_SYSTEM, PACKAGE_SETUP_WIZARD, @@ -55,6 +56,7 @@ public abstract class PackageManagerInternal { PACKAGE_VERIFIER, PACKAGE_BROWSER, PACKAGE_SYSTEM_TEXT_CLASSIFIER, + PACKAGE_PERMISSION_CONTROLLER, }) @Retention(RetentionPolicy.SOURCE) public @interface KnownPackage {} diff --git a/data/etc/hiddenapi-package-whitelist.xml b/data/etc/hiddenapi-package-whitelist.xml index 4e09c69b6779..5cfae1170097 100644 --- a/data/etc/hiddenapi-package-whitelist.xml +++ b/data/etc/hiddenapi-package-whitelist.xml @@ -38,7 +38,7 @@ platform cert need to be included, as apps signed with the platform cert are exe <hidden-api-whitelisted-app package="com.android.launcher3" /> <hidden-api-whitelisted-app package="com.android.mtp" /> <hidden-api-whitelisted-app package="com.android.musicfx" /> - <hidden-api-whitelisted-app package="com.android.packageinstaller" /> + <hidden-api-whitelisted-app package="com.android.permissioncontroller" /> <hidden-api-whitelisted-app package="com.android.printservice.recommendation" /> <hidden-api-whitelisted-app package="com.android.printspooler" /> <hidden-api-whitelisted-app package="com.android.providers.blockednumber" /> diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index 434af14ff44f..f6587d38d857 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -133,13 +133,18 @@ applications that come with the platform </privapp-permissions> <privapp-permissions package="com.android.packageinstaller"> - <permission name="android.permission.CLEAR_APP_CACHE"/> <permission name="android.permission.DELETE_PACKAGES"/> <permission name="android.permission.INSTALL_PACKAGES"/> + <permission name="android.permission.USE_RESERVED_DISK"/> + <permission name="android.permission.MANAGE_USERS"/> + <permission name="android.permission.UPDATE_APP_OPS_STATS"/> + </privapp-permissions> + + <privapp-permissions package="com.android.permissioncontroller"> + <permission name="android.permission.CLEAR_APP_CACHE"/> <permission name="android.permission.MANAGE_USERS"/> <permission name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS"/> <permission name="android.permission.UPDATE_APP_OPS_STATS"/> - <permission name="android.permission.USE_RESERVED_DISK"/> </privapp-permissions> <privapp-permissions package="com.android.phone"> diff --git a/packages/PackageInstaller/Android.mk b/packages/PackageInstaller/Android.mk index 65b82557bcb6..f556b48f27b1 100644 --- a/packages/PackageInstaller/Android.mk +++ b/packages/PackageInstaller/Android.mk @@ -9,42 +9,16 @@ LOCAL_SRC_FILES := \ $(call all-java-files-under, src) LOCAL_STATIC_ANDROID_LIBRARIES += \ - androidx.car_car \ - androidx.design_design \ - androidx.transition_transition \ - androidx.core_core \ - androidx.media_media \ - androidx.legacy_legacy-support-core-utils \ - androidx.legacy_legacy-support-core-ui \ - androidx.fragment_fragment \ - androidx.appcompat_appcompat \ - androidx.preference_preference \ - androidx.recyclerview_recyclerview \ - androidx.legacy_legacy-preference-v14 \ - androidx.leanback_leanback \ - androidx.leanback_leanback-preference \ - SettingsLib + androidx.leanback_leanback LOCAL_STATIC_JAVA_LIBRARIES := \ xz-java \ androidx.annotation_annotation LOCAL_PACKAGE_NAME := PackageInstaller -LOCAL_CERTIFICATE := platform +LOCAL_CERTIFICATE := platform LOCAL_PRIVILEGED_MODULE := true - -LOCAL_PROGUARD_FLAG_FILES := proguard.flags - -# Comment for now unitl all private API dependencies are removed -# LOCAL_SDK_VERSION := system_current LOCAL_PRIVATE_PLATFORM_APIS := true include $(BUILD_PACKAGE) - -ifeq (PackageInstaller,$(LOCAL_PACKAGE_NAME)) - # Use the following include to make our test apk. - ifeq (,$(ONE_SHOT_MAKEFILE)) - include $(call all-makefiles-under,$(LOCAL_PATH)) - endif -endif diff --git a/packages/PackageInstaller/AndroidManifest.xml b/packages/PackageInstaller/AndroidManifest.xml index 578207529880..f4b9cefc99ce 100644 --- a/packages/PackageInstaller/AndroidManifest.xml +++ b/packages/PackageInstaller/AndroidManifest.xml @@ -1,35 +1,20 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.packageinstaller" coreApp="true"> - - <original-package android:name="com.android.packageinstaller" /> + package="com.android.packageinstaller"> + <uses-permission android:name="android.permission.MANAGE_USERS" /> <uses-permission android:name="android.permission.INSTALL_PACKAGES" /> <uses-permission android:name="android.permission.DELETE_PACKAGES" /> - <uses-permission android:name="android.permission.CLEAR_APP_CACHE" /> - <uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" /> - <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> - <uses-permission android:name="android.permission.MANAGE_USERS" /> - <uses-permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS" /> - <uses-permission android:name="android.permission.REVOKE_RUNTIME_PERMISSIONS" /> - <uses-permission android:name="android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS" /> - <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> - <uses-permission android:name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS" /> <uses-permission android:name="android.permission.READ_INSTALL_SESSIONS" /> - <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" /> - <uses-permission android:name="android.permission.MANAGE_APP_OPS_MODES" /> - <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> - <uses-permission android:name="android.permission.WAKE_LOCK" /> - <uses-permission android:name="android.permission.KILL_UID" /> - <uses-permission android:name="android.permission.MANAGE_APP_OPS_RESTRICTIONS" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS" /> <uses-permission android:name="android.permission.USE_RESERVED_DISK" /> + <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" /> + <uses-permission android:name="android.permission.MANAGE_APP_OPS_MODES" /> + <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> <uses-permission android:name="com.google.android.permission.INSTALL_WEARABLE_PACKAGES" /> - <uses-permission android:name="android.permission.ACCESS_INSTANT_APPS" /> - <application android:name=".PackageInstallerApplication" android:label="@string/app_name" android:allowBackup="false" @@ -131,56 +116,11 @@ android:configChanges="mnc|mnc|touchscreen|navigation|screenLayout|screenSize|smallestScreenSize|orientation|locale|keyboard|keyboardHidden|fontScale|uiMode|layoutDirection|density" android:exported="false" /> - <activity android:name=".permission.ui.GrantPermissionsActivity" - android:configChanges="keyboardHidden|screenSize" - android:excludeFromRecents="true" - android:theme="@style/GrantPermissions" - android:visibleToInstantApps="true"> - <intent-filter android:priority="1"> - <action android:name="android.content.pm.action.REQUEST_PERMISSIONS" /> - <category android:name="android.intent.category.DEFAULT" /> - </intent-filter> - </activity> - - <activity android:name=".permission.ui.ManagePermissionsActivity" - android:configChanges="orientation|keyboardHidden|screenSize" - android:label="@string/app_permissions" - android:theme="@style/Settings" - android:permission="android.permission.GRANT_RUNTIME_PERMISSIONS"> - <intent-filter android:priority="1"> - <action android:name="android.intent.action.MANAGE_PERMISSIONS" /> - <action android:name="android.intent.action.MANAGE_APP_PERMISSIONS" /> - <action android:name="android.intent.action.MANAGE_PERMISSION_APPS" /> - <category android:name="android.intent.category.DEFAULT" /> - </intent-filter> - </activity> - - <activity android:name=".permission.ui.ReviewPermissionsActivity" - android:excludeFromRecents="true" - android:theme="@style/Settings.NoActionBar" - android:permission="android.permission.GRANT_RUNTIME_PERMISSIONS"> - <intent-filter android:priority="1"> - <action android:name="android.intent.action.REVIEW_PERMISSIONS" /> - <category android:name="android.intent.category.DEFAULT" /> - </intent-filter> - </activity> - - <activity android:name=".permission.ui.OverlayWarningDialog" - android:excludeFromRecents="true" - android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.NoActionBar" /> - <!-- Wearable Components --> <service android:name=".wear.WearPackageInstallerService" android:permission="com.google.android.permission.INSTALL_WEARABLE_PACKAGES" android:exported="true"/> - <service android:name=".permission.service.RuntimePermissionPresenterServiceImpl" - android:permission="android.permission.BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE"> - <intent-filter android:priority="1"> - <action android:name="android.permissionpresenterservice.RuntimePermissionPresenterService"/> - </intent-filter> - </service> - <provider android:name=".wear.WearPackageIconProvider" android:authorities="com.google.android.packageinstaller.wear.provider" android:grantUriPermissions="true" diff --git a/packages/PackageInstaller/PREUPLOAD.cfg b/packages/PackageInstaller/PREUPLOAD.cfg deleted file mode 100644 index 94e464042243..000000000000 --- a/packages/PackageInstaller/PREUPLOAD.cfg +++ /dev/null @@ -1,7 +0,0 @@ -[Builtin Hooks] -xmllint = true -commit_msg_changeid_field = true - -[Hook Scripts] -checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT} -strings_lint_hook = ${REPO_ROOT}/frameworks/base/tools/stringslint/stringslint_sha.sh ${PREUPLOAD_COMMIT} diff --git a/packages/PackageInstaller/proguard.flags b/packages/PackageInstaller/proguard.flags deleted file mode 100644 index 46a929e383e0..000000000000 --- a/packages/PackageInstaller/proguard.flags +++ /dev/null @@ -1,8 +0,0 @@ -# The support library contains references to newer platform versions. -# Don't warn about those in case this app is linking against an older -# platform version. We know about them, and they are safe. - --keep class androidx.preference.Preference* { - *; -} --dontwarn androidx.core.** diff --git a/packages/PackageInstaller/res/color/btn_colored_background_material.xml b/packages/PackageInstaller/res/color/btn_colored_background_material.xml deleted file mode 100644 index a6cd0890706a..000000000000 --- a/packages/PackageInstaller/res/color/btn_colored_background_material.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2016 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. ---> -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_enabled="false" - android:alpha="?android:disabledAlpha" - android:color="?android:colorButtonNormal" /> - <item android:color="?android:colorAccent" /> -</selector> diff --git a/packages/PackageInstaller/res/drawable-hdpi/ic_fail.png b/packages/PackageInstaller/res/drawable-hdpi/ic_fail.png deleted file mode 100644 index 30f75632cb92f495a943fc6f9f4e1427399cdf9a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 707 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k0wldT1B8JTQ<As43&a2R{xkc5JkA1-$YLPv z0mg18v+Wod7$11LIEHu}e|yzB@3sNMv5)<mn)*&&yQji`<isrVs0A-(HJ6-W&bTC} z9D6JK2iIHC9v07OM>>;({_`!$oV6^aRM+dkCXKp3GdFp7{feI^YHXca)w;wn)+kL; zXqDRe88NO}&t^Df_%5Bmc|C}2YLsxPzgRtYqQLtfXH^%qC+a;DwmqV{zvA`hnY+z9 zLfIJREDJd@hshv8bmH!6t|O)&ntWHbY}~_e|FvD^it_>+A|B+pu|Ct;!uK+Lp~KqZ z*$ac7P5YYW)*-ZUqk|~-nYQz*=H7auS7P;D*_J>2-Hn_?p)Bo1dII8to42-juE>4I z$n7Ix@bUTgobm*rRp*%>6g>RluwQv{fHe<e`%y;cvVTpTX&<}hFSu5}PEeco^rF_4 z*F{1?BDAzltUs97v-s2hz`uW&Do-`|%Dn%fvH8MlsUeZiCfXj6>z})lElvC*+s4}y zKlwE7;F6tp<2(Nzmp7k9qSgtx8mB&UGk%m{maiem-t){Yb(Z<W^#@qkdn|fpXqKMf zDDY{>&y~K-x!yu+o@G~hp^NNCpVr4yCx7dG%ba{nW_h>bqCQFEXSJthWCl#SGWoK* z<lg{IY18vUOV`+~yyXA&$s?CvO*$d1$)CD%{Ac(CSf)iDN@+S}d{^jy!cS&K4hiY( zdH(-_k*-?e8c~vxSdwa$T$Bo=7>o=I4RwLYz%azn#LB?b%FtZbz}(8fpku+72`CzJ z^HVa@DsgN0`Ikors6i5BLvVgtNqJ&XDuZK6ep0G}XKrG8YEWuoN@d~6R2!fo22WQ% Jmvv4FO#t%K9~b}t diff --git a/packages/PackageInstaller/res/drawable-hdpi/ic_success.png b/packages/PackageInstaller/res/drawable-hdpi/ic_success.png deleted file mode 100644 index f36d491a6be7e0e78fac93d5ecb1d4c53fca4fc3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 651 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k0wldT1B8JTQ<As43&a2R{xkc5JkA1-$YLPv z0mg18v+Wod7*}|@IEHu}e|y!|UnEe3;ez?***9)-bGWeB8yFfIUi1?d*453`)m^Kb zo16Pr^p`!)E^aO*g;_IJw6>no*?qie`{Cron=_X_^)udS{5|E_-QQ_W7QKNJdxMw6 z&u)#AKk0ws$=@>)0Vyq;ABK5dt&?+96W?>F*0Ij$nd*<1=OjW>q?*KUY;87gS|c{a z;QYqb&D+(ooWAw7J%~KH$5?ZPvD3s%u6c`AH&0vX5&kynkd0$_<F=R1J^y~oXR4oh zJSo!5xaVYYH2aE{$|b9pA2?N@cDW!eUnxi{QBF(g^T9V0vxQH;&)g~2{fL+I^8tC0 zA1@9Sp7FiE;pHp4sRreL`_8-)Q2QeO)AV0bc0(3d-fz*Frp3<Eatkd_-#9q!=p>-f z54rU<M)pa0PnsgNH$L!QBGu%2+i-W@!w5CWzmlhaga;km^YuhcS>_WF^($M-mh6iv zI2V;-7PD@Pq|mE9VLEYJMb4YWT3U#eu5jX?d(bZI{tVuOQ@(46oIDhM{~`MdPw#~4 zf@`mXg>TjMoa6}*k6r)y<|)45)VLGh|1a6PaMCH~73b!-P5r@d!BDtQCxD*=7<sBC zt`Q|Ei6yC4$wjF^iopmNSGquCU>IU(Vr5`zWoWKzU~Xk#(6M041QZRq`6-!cmAEzh z{L7;Q)F276Aviy+q&%@GmBBG3KPgqgGdD3kH7GSPrLyp3str&PgQu&X%Q~loCIF_b B2)zIR diff --git a/packages/PackageInstaller/res/drawable-hdpi/tab_unselected_holo.9.png b/packages/PackageInstaller/res/drawable-hdpi/tab_unselected_holo.9.png deleted file mode 100644 index 19532ab10d4fe414d597ed44ed50c91a3e3b9279..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 153 zcmeAS@N?(olHy`uVBq!ia0vp^tU%1c!3HD^Kbl$tDVAa<&kznEsNqQI0P;BtJR*x3 z7`Qt@n9=;?>9s&XYfl%)5RRG2KmPx>XJ%$TT(5HGK*O1ak257UFsy01aiHFf4G12u u^?&$m-q&fz7T&FR9W0_QnO}Q~fkExE@YIkG=lX%hFnGH9xvX<aXaWFP^)L7U diff --git a/packages/PackageInstaller/res/drawable-mdpi/ic_fail.png b/packages/PackageInstaller/res/drawable-mdpi/ic_fail.png deleted file mode 100644 index 12e269ea4fa664b4f8db5f48715368b67b250468..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 594 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM0wlfaz7_*1rX+877l!}s{b%+Ad7K3vkswhI zFm^kcZO6dCnD6Q07-DgH>*d{kqJa`^5A)A1xS<iXGN5zs#e3EU2X9nmWb%A}u<(G> zdYAVHyEqJ`_~+gbl+qTKzLEDW*^qhjx3b`f9bG5a*uUTXuk^(9Kkox4xqQFx@?~kr zS2K6@j9FasOF}PKOkQkqc#o%-SCG-kwK~T?3hi?BzIErFn7(sz?~aGdbD#f?blIpd zFKO{=KkoGhr*Z$?b9jEEe3*-|%({-#c41zt-+tW4T%KlKa!Pc5b*kr);vU&3>w9Us zF52sUG2OF#&Uwu3T~}-0Ntx7};TxVaD1U$U!1z?xcZtW-x9<PAtm;F`B;%Xs!zLY8 zsjjrP@px9E5%rO2|8F^Ky|1<YN6mkC-}%6pb3Sm@-~6N}Czv<Bie756*(><r_oIt; zq=~=Tp>ay*pOCUJ|L@tEM_0XnFnOuh%huyFDokRQgvD&{HWz#THDY_*!{euX*Uypt zU?jZY-E5<|hqSs&U2ZSod)yghB)KSh*`tW*erx|d{=s}pYSNK9tM|OXI8ZHdjVMV; zEJ?LWE=mPb3`PcqhPpsxU>IU(Vr5`zWoWKzU~Xk#(6M041QZRq`6-!cmAEzh{L7;Q x)F276Aviy+q&%@GmBBG3KPgqgGdD3kH7GSPrLyp3str&PgQu&X%Q~loCIFR}{00C3 diff --git a/packages/PackageInstaller/res/drawable-mdpi/ic_success.png b/packages/PackageInstaller/res/drawable-mdpi/ic_success.png deleted file mode 100644 index 51aab2e74242772a785f6ed6d87c3d6fe13c369f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 505 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM0wlfaz7_*1rX+877l!}s{b%+Ad7K3vkswhI zFm^kcZO6dCDCX(n7-DgH@8yktQyfLw9_Bwg-lEWvv%+)54n=P3ye5_@QPD~1*`BUW zo=R>!r-CZEV_0P0IUjuUYqyS0@0>KXncr<s{wz}ac|Y_S<Ga3DlkEM)y@Xaus($6H z5Wjh9cF(hI;ukwh_kRq#QduFoy6u6-l%GE~85bmNRIlKOFJamjCFEM&<!5-&MdT>= z@dsB<Ut4f}b<fnc@T-bHt{qnQd~++Kv*+UvrhU=x9`4*-cWCF<Wg>Hb@SI!or`h}= z^NtKJb-n}r)fLBt-<YQ=JW{s!{z~p%T7<y+gG-mH{oi86JU?ZV!o5cA>pz};^{Mf? zdDu69R^*Q<o0=CMTwLM5GU@iS<cgoGRXnq9SMmQ{Yn9q}>FkZ8>1(4CT^!H+724to z3@X(U*NBpo#FA92<f2p{#b9J$Xs8QB28JPqCRPTfR)*%f2If`<1|18wOhD0)o1c=I zR*74~&%Zo6Kn;>08-nxGO3D+9QW+dm@{>{(JaZG%Q-e|yQz{EjrrH1%F?hQAxvX<a GXaWGXe#?pg diff --git a/packages/PackageInstaller/res/drawable-mdpi/tab_unselected_holo.9.png b/packages/PackageInstaller/res/drawable-mdpi/tab_unselected_holo.9.png deleted file mode 100644 index a2dbf42b74f7fafb6d8a057306a9c021867d035c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 157 zcmeAS@N?(olHy`uVBq!ia0vp^EI`c0!3HFsSlX9@1d5$JLpXq-h9ji|$mcBZh%9Dc z;O+!rM)Q-W*8&CYJzX3_IA$jQ`2XLYnVI=;y+&GsLz;ns!JqUb2WA}}9-f|K(evAk wfFg6gPD@K@^jg!TZFujONZyK%*Ov1zxbO?iIdA+_5oi>Hr>mdKI;Vst04D7$hX4Qo diff --git a/packages/PackageInstaller/res/drawable-television/grant_permissions_action_item.xml b/packages/PackageInstaller/res/drawable-television/grant_permissions_action_item.xml deleted file mode 100644 index 96bf582c9bea..000000000000 --- a/packages/PackageInstaller/res/drawable-television/grant_permissions_action_item.xml +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2015 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. ---> - -<ripple xmlns:android="http://schemas.android.com/apk/res/android" - android:color="@color/grant_permissions_white_text_alpha_100"> - <item android:drawable="@drawable/grant_permissions_action_item_background" /> -</ripple> diff --git a/packages/PackageInstaller/res/drawable-television/grant_permissions_action_item_background.xml b/packages/PackageInstaller/res/drawable-television/grant_permissions_action_item_background.xml deleted file mode 100644 index 86d6b1f48a38..000000000000 --- a/packages/PackageInstaller/res/drawable-television/grant_permissions_action_item_background.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2015 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. ---> - -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_pressed="true" android:drawable="@drawable/grant_permissions_action_item_shape" /> - <item android:state_focused="true" android:drawable="@drawable/grant_permissions_action_item_shape" /> - <!-- no default background is specified, making the button transparent when not active --> -</selector> diff --git a/packages/PackageInstaller/res/drawable-television/grant_permissions_action_item_shape.xml b/packages/PackageInstaller/res/drawable-television/grant_permissions_action_item_shape.xml deleted file mode 100644 index 08cd3455949a..000000000000 --- a/packages/PackageInstaller/res/drawable-television/grant_permissions_action_item_shape.xml +++ /dev/null @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2015 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:insetRight="1dp" - android:insetBottom="1dp"> - <shape android:shape="rectangle"> - <corners android:radius="2dp" /> - <solid android:color="@color/grant_permissions_focus_highlight" /> - <padding android:left="8dp" - android:top="4dp" - android:right="8dp" - android:bottom="4dp" /> - </shape> -</inset> diff --git a/packages/PackageInstaller/res/drawable-watch/accept_deny_dialog_negative_bg.xml b/packages/PackageInstaller/res/drawable-watch/accept_deny_dialog_negative_bg.xml deleted file mode 100644 index 1ccc40abc804..000000000000 --- a/packages/PackageInstaller/res/drawable-watch/accept_deny_dialog_negative_bg.xml +++ /dev/null @@ -1,32 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2016 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. ---> -<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> - <item> - <ripple android:color="?android:colorControlHighlight" /> - </item> - <item> - <ripple android:color="?android:colorControlHighlight"> - <item> - <shape android:shape="oval" - android:tint="?android:colorButtonNormal"> - <solid android:color="@android:color/white" /> - <size android:width="@dimen/diag_button_size" - android:height="@dimen/diag_button_size" /> - </shape> - </item> - </ripple> - </item> -</layer-list> diff --git a/packages/PackageInstaller/res/drawable-watch/accept_deny_dialog_positive_bg.xml b/packages/PackageInstaller/res/drawable-watch/accept_deny_dialog_positive_bg.xml deleted file mode 100644 index 786a35ba21c6..000000000000 --- a/packages/PackageInstaller/res/drawable-watch/accept_deny_dialog_positive_bg.xml +++ /dev/null @@ -1,32 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2016 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. ---> -<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> - <item> - <ripple android:color="?android:colorAccent" /> - </item> - <item> - <ripple android:color="?android:colorControlHighlight"> - <item> - <shape android:shape="oval" - android:tint="@color/btn_colored_background_material"> - <solid android:color="@android:color/white" /> - <size android:width="@dimen/diag_button_size" - android:height="@dimen/diag_button_size" /> - </shape> - </item> - </ripple> - </item> -</layer-list> diff --git a/packages/PackageInstaller/res/drawable-watch/action_negative_bg.xml b/packages/PackageInstaller/res/drawable-watch/action_negative_bg.xml deleted file mode 100644 index 994ae8e2d4a8..000000000000 --- a/packages/PackageInstaller/res/drawable-watch/action_negative_bg.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2015 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. ---> -<ripple xmlns:android="http://schemas.android.com/apk/res/android" - android:color="?android:colorControlHighlight"> - <item> - <shape android:shape="oval" android:tint="?android:colorButtonNormal"> - <solid android:color="@android:color/white" /> - <size android:width="40dp" android:height="40dp" /> - </shape> - </item> -</ripple> diff --git a/packages/PackageInstaller/res/drawable-watch/action_positive_bg.xml b/packages/PackageInstaller/res/drawable-watch/action_positive_bg.xml deleted file mode 100644 index 3e8590f261ca..000000000000 --- a/packages/PackageInstaller/res/drawable-watch/action_positive_bg.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2015 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. ---> -<ripple xmlns:android="http://schemas.android.com/apk/res/android" - android:color="?android:colorControlHighlight"> - <item> - <shape android:shape="oval" android:tint="@color/btn_colored_background_material"> - <solid android:color="@android:color/white" /> - <size android:width="40dp" android:height="40dp" /> - </shape> - </item> -</ripple> diff --git a/packages/PackageInstaller/res/drawable-watch/cancel_button.xml b/packages/PackageInstaller/res/drawable-watch/cancel_button.xml deleted file mode 100644 index 8e4d2d48f8a5..000000000000 --- a/packages/PackageInstaller/res/drawable-watch/cancel_button.xml +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2015 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. ---> -<layer-list xmlns:android="http://schemas.android.com/apk/res/android" > - <item android:drawable="@drawable/action_negative_bg" /> - <item android:drawable="@drawable/ic_cc_clear" android:gravity="center" /> -</layer-list> diff --git a/packages/PackageInstaller/res/drawable-watch/confirm_button.xml b/packages/PackageInstaller/res/drawable-watch/confirm_button.xml deleted file mode 100644 index d1bfae331bf5..000000000000 --- a/packages/PackageInstaller/res/drawable-watch/confirm_button.xml +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2015 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. ---> -<layer-list xmlns:android="http://schemas.android.com/apk/res/android" > - <item android:drawable="@drawable/action_positive_bg" /> - <item android:drawable="@drawable/ic_cc_checkmark" android:gravity="center" /> -</layer-list> diff --git a/packages/PackageInstaller/res/drawable-watch/deny_button.xml b/packages/PackageInstaller/res/drawable-watch/deny_button.xml deleted file mode 100644 index 0a2e1ae16931..000000000000 --- a/packages/PackageInstaller/res/drawable-watch/deny_button.xml +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2015 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. ---> -<layer-list xmlns:android="http://schemas.android.com/apk/res/android" > - <item android:drawable="@drawable/action_negative_bg" /> - <item android:drawable="@drawable/ic_cc_deny" android:gravity="center" /> -</layer-list> diff --git a/packages/PackageInstaller/res/drawable-watch/ic_cc_checkmark.xml b/packages/PackageInstaller/res/drawable-watch/ic_cc_checkmark.xml deleted file mode 100644 index 832e090fc384..000000000000 --- a/packages/PackageInstaller/res/drawable-watch/ic_cc_checkmark.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2016 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"> - <path - android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z" - android:fillColor="#FFFFFF"/> -</vector> diff --git a/packages/PackageInstaller/res/drawable-watch/ic_cc_clear.xml b/packages/PackageInstaller/res/drawable-watch/ic_cc_clear.xml deleted file mode 100644 index 06bb30b3207e..000000000000 --- a/packages/PackageInstaller/res/drawable-watch/ic_cc_clear.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2016 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"> - <path - android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z" - android:fillColor="#FFFFFF"/> -</vector> diff --git a/packages/PackageInstaller/res/drawable-watch/ic_cc_deny.xml b/packages/PackageInstaller/res/drawable-watch/ic_cc_deny.xml deleted file mode 100644 index 971dfcc84f3f..000000000000 --- a/packages/PackageInstaller/res/drawable-watch/ic_cc_deny.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2016 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"> - <path - android:pathData="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zM4 12c0-4.42 3.58-8 8-8 1.85 0 3.55.63 4.9 1.69L5.69 16.9C4.63 15.55 4 13.85 4 12zm8 8c-1.85 0-3.55-.63-4.9-1.69L18.31 7.1C19.37 8.45 20 10.15 20 12c0 4.42-3.58 8-8 8z" - android:fillColor="#FFFFFF"/> -</vector> diff --git a/packages/PackageInstaller/res/drawable-xhdpi/ic_fail.png b/packages/PackageInstaller/res/drawable-xhdpi/ic_fail.png deleted file mode 100644 index 6deb808c81f9881494e34291f7c9588037a78db6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 947 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA0wn)(8}a}trX+877l!}s{b%+Ad7K3vk;OpT z1B~5HX4?T(T<~;p42d}WcKU9A5l5Nh^_$C&L|l$st++2~`A5;Ff(Qn?ENPA`lZ%(q zYgkw{Lwb7a8#+7dTY9&Bn<X$cBl$_8Mg~jS_vDR-@0_{!=5gN*iDf&_J~hAp{=2d9 zZe!(5H_dL_XLN9I{S8?awP|%|@y>tYo^LcKoT>VA)sA`TZ&p{a8;?%q3*LC@R=0Z3 z1jf##Sxe7Mo<AkKDdf|tt&Ci*?D~zCzXY__NdI1~&B4zg;l`n15TMcW{D4-#a`A<) zHZKUQmFM96dHCfKrSl376)T=9Cp6CLKjdZ4=W^u8ku^m!iW){1$E5_A6$6$}Tejg+ zKeOV-zR!(&UD-O1Muv5CmTb5BYt}lo&S|;-BA?5lHZF^nx^-;QFuMFcqCYTY!3rgw z&0bHIepved#JWAA&zDQEwl9)jxazXM#mnV4BZKT*4ZSh~b&8z$uPm8d*Jiu)>1+)> z3z6<CTWXa5s_%-L;vYCi{Ys|t1L^e*HzMj1<4=F`6`9WCnln#mw`AFN&H0OVWIRcB zQvN^nZ|-UHz?f&-<s`lc?7hEXk0Hkjr9Iac_x;=3bYY`n<@4E}BlNGc9kgkVjK3B3 zgjq{tUWBmBte+7{1<cJ)mK>k7HT<GK+pQ%VF8NFT6!>w*__LhL0VC(!fQrlN>u)l) zyzV<1bXsKQ%XG_@4Xh7WCEu0;`uWtvpXVHPgB^Ed+Ld!24e;dB{u`|RSH``^Wt04! zf;aVrt5{m!>G=XR-FcCxlb0U&L{fvP>B^1s#b<6BNQ-R`5>fB|p3?e(Bf|LZGs{_R z+jZVWi5O;onQFOhPNHB3M<eU5*~`x_+_6~G>4EI+z$db)rp~?c3|C&Bn`L!6i6?^b z-la~vZ_g!FDyt*YX3l$aG+l$KrTT!h75DjN=lCv6uK%)CL*x+0?M<uxicffw7EoZn zVBy4K`w!2A6cr{sGB5sX5a~E|Wtny7lottptCy}azg>UpACq~oysGenwX=bVT(!hC zq9i4;B-JXpC>2OC7#SEE>H?90VThrLm4T_1p}DSsxs`!I$AT>rP&DM`r(~v8;@0r< zFOLpTgCxj?;QX|b^2DN42FH~Aq*MjZ+{E<Mpwz^a%EFVWHb6xTp00i_>zopr0E!Nn AQvd(} diff --git a/packages/PackageInstaller/res/drawable-xhdpi/ic_success.png b/packages/PackageInstaller/res/drawable-xhdpi/ic_success.png deleted file mode 100644 index 25f8658f5c39e86a4bfe4438dacf7cb2b59a5d71..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 820 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA0wn)(8}a}trX+877l!}s{b%+Ad7K3vk;OpT z1B~5HX4?T(1bVtShD02GJKaBrH&Eo*`MKsBUmkOc;M%x3ptnukMYXpr%-bVpttyM+ zA*Y<&$gUeVZg#dFId<vLJ+C0w)vK1qd4D;3=6sT0`nlhiE7#}e9eFhOYW3vm`upGS z?ks-S<FWtOS9wvTCV>U}FBkoL5Xm~}$%_No9S$yKo|A$!IkP|XKj0A5GdyhAB5-iJ zOV^^Nf{7e6(lz#q$FYdWE5$tE=gdA}^1I;W+i%bR>FjTmh+vLW+Hr~L*k8`9uKtGa zJk<gQ@7yCyew^o7`Xh*mE&l23MamDDe}Ao#WNemyviRWn!UOVl4mVEs9IQ{evHthn zJ;p!uWpoZ?ub$-BzoT&fW=8wd3!Q9~nieaye(d=zyT|m$`Vi{}8}FG-Fi_t1(e0w4 z!SRQOww_;>yL{Kimcsp0uRFx5idh8RxVJ@|OY!{AqZPjoK6%Vmk$UHR@s`8q91B=j zY#0+-PhR7^`N)E;BJqxX*~K|muQM<3W4SUTW8RdV>pz^?5udQ6yLNr>dnQ57!fdWm z`3<ehkNp)ozS}CQq_f4^VUduj+UJuTeC;1j?1)d=a(el-oPE)1N43(88WuM_UU;xR zy+oKjnaxvmR`8Oa@1#G<_vCJRK0*IV?=%s`L$;-I%%^+47Oa^qVlExzqj<+`(djv_ zHYU#!x$e=?QMy%ra>JwgqD@D<J3R|ygH_gq&w5^RvMyg`T~?RMZOdG_1Dk|0+Mea! zw%+IY$jH#JG@(_qU%!P{h+*}d&rkOC9uZBmeE+lbnukS;?a}8kg`zbL8|;`0f6A}F z`fu@y_`kode--aCJ%7@y-$E6b%2Z2SBT7;dOH!?pi&B9UgOP!up)L>^7={>{SQ(gF z8Jg=Fm|GbbbS&610YyV@eoAIqC2kEr|MKVnHAsSN2+mI{DNig)WpGT%PfAtr%uP&B Z4N6T+sVqF1Y6Dcn;OXk;vd$@?2>?EHWjO!< diff --git a/packages/PackageInstaller/res/drawable-xhdpi/tab_unselected_holo.9.png b/packages/PackageInstaller/res/drawable-xhdpi/tab_unselected_holo.9.png deleted file mode 100644 index 9465173781eaa7fc9ab0e191904f928ad1c0b8f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 166 zcmeAS@N?(olHy`uVBq!ia0vp^Y(UJ#0V1dK=^FznmSQK*5Dp-y;YjHK@;M7UB8wRq zxI00Z(fs7;wLn1+PZ!4!j+x0n{{OdUW@bKIZ*t~9!x;yr|1&pm7#RS;1ieP?Kk11H z2?+-Ger=J9{IX`d2{ZSUyAFF~k44WnGFVV~q2hHg8$(d6=$w>Y|ILABGI+ZBxvX<a GXaWE(5Hf}U diff --git a/packages/PackageInstaller/res/drawable-xxhdpi/tab_unselected_holo.9.png b/packages/PackageInstaller/res/drawable-xxhdpi/tab_unselected_holo.9.png deleted file mode 100644 index 8fcecf76c1997917acacb7a5f4065614a9299512..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1054 zcmbVL&ui0A91oiv+h8i5oG=I}3>BNam!wS_R=YMyUBTAT6|Dz<q{-_Vw&ca+&1So7 zcu_$FJ&5=R=tXz%svsVB_U2WO4ljBTg!$4n)5F-oK=OX%`}usnKOZhOE=^6InPeDd zs<xmv={io|<KtuWd+O?qXLOk+Mw=|*F6o;AV#+q|Ahzb3%czM=d;QK1nq!#JuG4Ch zcKxzyVV5^!8$NP<ie{L(QskS~3L<O=EjwP3`~L0&$2xYAyOynky04+0v#=4MrHw|* z+E}p)HdngH&P6IEa1k-t$X)e9H7argUX||SYk^}2CS;|^?K{=3FR~gA5S!&e#sWFO z<{%FxSy7Y=tOy_wfG9vQ0~J*gRRGxG!%?-s?y60_I@F@4BG)6tR|TQp@AG|$$HB4y z3xz_=A&MDlkqOs5Vn!J+OeYLF3a!BLiGw{hW;8o^jTAZR>3#^VU#}k!d*LuqG-X0$ z`U2#E;JR^K1M849(O)+XwGLbBJ`$QJ#A|^?>(NaoV4Az5g<?bMjd~?;Xi>~n9b0QI z@<>fDa`X>xJGLroRVlBFRl^XaTpq%_0;}a*wrXUxavm63!f_Z@(&UPy=ve?OIS36{ zmc&Y>pj2c<5-CSE!PdNxn4X0aU5DxpvGS2vRSS?waL~edHR*uG9ws>KVV~8OvTWV7 z94|h{<=Kx`M}cz}+0_8M>>$6YbBI2W^8i9c28sxhxC=7Omlatt^18$gvG)JuOrXvP zadZ6BEXft^z<7Jm`t)!xJjkOH6VTB}PvmClST$;TxfOlx{My?qji%FIHpjkgJxQJ4 zd7ypVoE;n4N^Sorz0AyinjU{KKa+YC%{cFWo_lV--JQO9>-VcS>52PauVd%+)A<u% a<k)HEZ29C)>an~VPi)O-=-ZXs_x=DA97YZR diff --git a/packages/PackageInstaller/res/drawable/button_ripple_bg.xml b/packages/PackageInstaller/res/drawable/button_ripple_bg.xml deleted file mode 100644 index dabacb10c011..000000000000 --- a/packages/PackageInstaller/res/drawable/button_ripple_bg.xml +++ /dev/null @@ -1,23 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 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. ---> - -<ripple xmlns:android="http://schemas.android.com/apk/res/android" - android:color="@color/car_card_ripple_background" - android:radius="90dp"> - <item android:id="@android:id/mask" - android:drawable="@drawable/rectangle_ripple_mask" /> -</ripple> diff --git a/packages/PackageInstaller/res/drawable/ic_arrow_back.xml b/packages/PackageInstaller/res/drawable/ic_arrow_back.xml deleted file mode 100644 index 81da87fd1d5d..000000000000 --- a/packages/PackageInstaller/res/drawable/ic_arrow_back.xml +++ /dev/null @@ -1,30 +0,0 @@ -<!-- - ~ Copyright (C) 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 - --> - -<!-- This Icon is used in as the back icon on ActionBar. ActionBar hard code the icon layout and - ~ does not provide a way to customize it. Here to center the icon in action bar, we make up - ~ the margin by add the extra space in the icon itself --> -<vector - android:height="@dimen/car_primary_icon_size" - android:width="@dimen/car_primary_icon_size" - android:tint="@color/car_accent" - android:viewportHeight="24.0" - android:viewportWidth="24.0" - xmlns:android="http://schemas.android.com/apk/res/android"> - <path - android:fillColor="#FF000000" - android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/> -</vector> diff --git a/packages/PackageInstaller/res/drawable/ic_dialog_alert_material.xml b/packages/PackageInstaller/res/drawable/ic_dialog_alert_material.xml deleted file mode 100644 index b01a6d683c18..000000000000 --- a/packages/PackageInstaller/res/drawable/ic_dialog_alert_material.xml +++ /dev/null @@ -1,25 +0,0 @@ -<!-- -Copyright (C) 2014 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="?android:attr/colorControlNormal"> - <path - android:pathData="M1,21l22,0L12,2L1,21zM13,18l-2,0l0,-2l2,0L13,18zM13,14l-2,0l0,-4l2,0L13,14z" - android:fillColor="@android:color/white"/> -</vector> diff --git a/packages/PackageInstaller/res/drawable/ic_fail_material.xml b/packages/PackageInstaller/res/drawable/ic_fail_material.xml deleted file mode 100644 index 9d53fdc0180d..000000000000 --- a/packages/PackageInstaller/res/drawable/ic_fail_material.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2014 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. ---> -<bitmap xmlns:android="http://schemas.android.com/apk/res/android" - android:src="@drawable/ic_fail" - android:tint="?android:attr/colorControlNormal" /> diff --git a/packages/PackageInstaller/res/drawable/ic_info_outline.xml b/packages/PackageInstaller/res/drawable/ic_info_outline.xml deleted file mode 100644 index 86597586d9e6..000000000000 --- a/packages/PackageInstaller/res/drawable/ic_info_outline.xml +++ /dev/null @@ -1,24 +0,0 @@ -<!-- -Copyright (C) 2015 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="24.0dp" - android:height="24.0dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> - <path - android:fillColor="?android:attr/colorAccent" - android:pathData="M11.0,17.0l2.0,0.0l0.0,-6.0l-2.0,0.0l0.0,6.0zm1.0,-15.0C6.48,2.0 2.0,6.48 2.0,12.0s4.48,10.0 10.0,10.0 10.0,-4.48 10.0,-10.0S17.52,2.0 12.0,2.0zm0.0,18.0c-4.41,0.0 -8.0,-3.59 -8.0,-8.0s3.59,-8.0 8.0,-8.0 8.0,3.59 8.0,8.0 -3.59,8.0 -8.0,8.0zM11.0,9.0l2.0,0.0L13.0,7.0l-2.0,0.0l0.0,2.0z"/> -</vector> diff --git a/packages/PackageInstaller/res/drawable/ic_more_items.xml b/packages/PackageInstaller/res/drawable/ic_more_items.xml deleted file mode 100644 index 5fdcdcef7317..000000000000 --- a/packages/PackageInstaller/res/drawable/ic_more_items.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2015 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:fillColor="#000000" - android:pathData="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm0 4h14v-2H7v2zM7 -7v2h14V7H7z" /> - <path - android:pathData="M0 0h24v24H0z" /> -</vector> \ No newline at end of file diff --git a/packages/PackageInstaller/res/drawable/ic_perm_device_info.xml b/packages/PackageInstaller/res/drawable/ic_perm_device_info.xml deleted file mode 100644 index ef91c74620ac..000000000000 --- a/packages/PackageInstaller/res/drawable/ic_perm_device_info.xml +++ /dev/null @@ -1,24 +0,0 @@ -<!-- - Copyright (C) 2015 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="24.0dp" - android:height="24.0dp" - android:viewportWidth="48.0" - android:viewportHeight="48.0"> - <path - android:fillColor="#FF000000" - android:pathData="M26.0,14.0l-4.0,0.0l0.0,4.0l4.0,0.0l0.0,-4.0zm0.0,8.0l-4.0,0.0l0.0,12.0l4.0,0.0L26.0,22.0zm8.0,-19.98L14.0,2.0c-2.21,0.0 -4.0,1.79 -4.0,4.0l0.0,36.0c0.0,2.21 1.79,4.0 4.0,4.0l20.0,0.0c2.21,0.0 4.0,-1.79 4.0,-4.0L38.0,6.0c0.0,-2.21 -1.79,-3.98 -4.0,-3.98zM34.0,38.0L14.0,38.0L14.0,10.0l20.0,0.0l0.0,28.0z"/> -</vector> diff --git a/packages/PackageInstaller/res/drawable/ic_success_material.xml b/packages/PackageInstaller/res/drawable/ic_success_material.xml deleted file mode 100644 index ebcce3b5532c..000000000000 --- a/packages/PackageInstaller/res/drawable/ic_success_material.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2014 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. ---> -<bitmap xmlns:android="http://schemas.android.com/apk/res/android" - android:src="@drawable/ic_success" - android:tint="?android:attr/colorControlNormal" /> diff --git a/packages/PackageInstaller/res/drawable/ic_toc.xml b/packages/PackageInstaller/res/drawable/ic_toc.xml deleted file mode 100644 index 66c476bef832..000000000000 --- a/packages/PackageInstaller/res/drawable/ic_toc.xml +++ /dev/null @@ -1,24 +0,0 @@ -<!-- - Copyright (C) 2015 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="24.0dp" - android:height="24.0dp" - android:viewportWidth="48.0" - android:viewportHeight="48.0"> - <path - android:fillColor="#FF000000" - android:pathData="M6.0,18.0l28.0,0.0l0.0,-4.0L6.0,14.0l0.0,4.0zm0.0,8.0l28.0,0.0l0.0,-4.0L6.0,22.0l0.0,4.0zm0.0,8.0l28.0,0.0l0.0,-4.0L6.0,30.0l0.0,4.0zm32.0,0.0l4.0,0.0l0.0,-4.0l-4.0,0.0l0.0,4.0zm0.0,-20.0l0.0,4.0l4.0,0.0l0.0,-4.0l-4.0,0.0zm0.0,12.0l4.0,0.0l0.0,-4.0l-4.0,0.0l0.0,4.0z"/> -</vector> diff --git a/packages/PackageInstaller/res/drawable/rectangle_ripple_mask.xml b/packages/PackageInstaller/res/drawable/rectangle_ripple_mask.xml deleted file mode 100644 index 69eaf8bd4e4b..000000000000 --- a/packages/PackageInstaller/res/drawable/rectangle_ripple_mask.xml +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 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. ---> - -<shape xmlns:android="http://schemas.android.com/apk/res/android" - android:shape="rectangle"> - <corners android:radius="@dimen/car_radius_1" /> - <solid android:color="@android:color/white" /> -</shape> \ No newline at end of file diff --git a/packages/PackageInstaller/res/layout-television/grant_permissions.xml b/packages/PackageInstaller/res/layout-television/grant_permissions.xml deleted file mode 100644 index 44583bfbeb49..000000000000 --- a/packages/PackageInstaller/res/layout-television/grant_permissions.xml +++ /dev/null @@ -1,91 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2015 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="horizontal" - android:paddingLeft="@dimen/action_dialog_padding_left" - android:paddingRight="@dimen/action_dialog_padding_right" - android:paddingTop="@dimen/action_dialog_padding_top" - android:paddingBottom="@dimen/action_dialog_padding_bottom" - android:background="@color/grant_permissions_background_color"> - - <ImageView - android:id="@+id/permission_icon" - android:tint="@color/grant_permissions_app_color" - android:layout_width="@dimen/grant_permissions_app_icon_size" - android:layout_height="@dimen/grant_permissions_app_icon_size" - android:layout_marginTop="@dimen/grant_permissions_app_icon_margin_top"/> - - <LinearLayout - android:orientation="vertical" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_weight="1" - android:layout_marginLeft="@dimen/action_dialog_content_margin_left" - android:layout_marginRight="@dimen/action_dialog_content_margin_right"> - <TextView - android:id="@+id/current_page_text" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginBottom="@dimen/grant_permissions_app_breadcrumb_margin_bottom" - android:textAppearance="@style/GrantPermissions.BreadcrumbText" /> - - <TextView - android:id="@+id/permission_message" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginBottom="@dimen/grant_permissions_app_title_margin_bottom" - android:textAppearance="@style/GrantPermissions.TitleText"/> - - <TextView - android:layout_width="match_parent" - android:layout_height="0dp" - android:layout_marginBottom="@dimen/grant_permissions_app_details_margin_bottom" - android:layout_weight="1" - android:text="@string/grant_dialog_how_to_change" - android:textAppearance="@style/GrantPermissions.BodyText" /> - </LinearLayout> - - <LinearLayout - android:orientation="vertical" - android:layout_width="@dimen/action_dialog_actions_width" - android:layout_height="wrap_content" - android:layout_marginLeft="@dimen/action_dialog_actions_margin_left" - android:layout_marginTop="@dimen/action_dialog_actions_margin_top"> - <Button - android:id="@+id/permission_allow_button" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:text="@string/grant_dialog_button_allow" - style="@style/GrantPermissions.ActionItem" /> - - <Button - android:id="@+id/permission_deny_button" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:text="@string/grant_dialog_button_deny" - style="@style/GrantPermissions.ActionItem" /> - - <Button - android:id="@+id/permission_deny_dont_ask_again_button" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:text="@string/grant_dialog_button_deny_dont_ask_again" - style="@style/GrantPermissions.ActionItem" /> - </LinearLayout> - -</LinearLayout> diff --git a/packages/PackageInstaller/res/layout-television/header.xml b/packages/PackageInstaller/res/layout-television/header.xml deleted file mode 100644 index 56e35db7109c..000000000000 --- a/packages/PackageInstaller/res/layout-television/header.xml +++ /dev/null @@ -1,47 +0,0 @@ -<!-- - Copyright (C) 2016 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:layout_width="match_parent" - android:layout_height="wrap_content" - android:background="?attr/defaultBrandColor" - android:elevation="@dimen/lb_preference_decor_title_container_elevation" - android:orientation="vertical"> - - <FrameLayout - android:id="@+id/decor_title_container" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:background="?attr/defaultBrandColor" - android:elevation="@dimen/lb_preference_decor_title_container_elevation" - android:transitionGroup="false" - > - <TextView - android:id="@+id/decor_title" - android:layout_width="match_parent" - android:layout_height="@dimen/lb_preference_decor_title_text_height" - android:layout_marginTop="@dimen/lb_preference_decor_title_margin_top" - android:layout_marginStart="@dimen/lb_preference_decor_title_margin_start" - android:layout_marginEnd="@dimen/lb_preference_decor_title_margin_end" - android:fontFamily="sans-serif-condensed" - android:gravity="center_vertical" - android:singleLine="true" - android:textSize="@dimen/lb_preference_decor_title_text_size" - android:textColor="?android:attr/textColorPrimary" - /> - </FrameLayout> - -</LinearLayout> diff --git a/packages/PackageInstaller/res/layout-television/permissions_frame.xml b/packages/PackageInstaller/res/layout-television/permissions_frame.xml deleted file mode 100644 index 1dcda8d4abe6..000000000000 --- a/packages/PackageInstaller/res/layout-television/permissions_frame.xml +++ /dev/null @@ -1,47 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - ~ Copyright (C) 2015 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 - --> - -<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:filterTouchesWhenObscured="true"> - - <FrameLayout - android:layout_width="@dimen/lb_settings_pane_width" - android:layout_height="match_parent" - android:background="@color/lb_preference_decor_list_background" - android:layout_gravity="end"> - - <FrameLayout - android:id="@+id/prefs_container" - android:layout_width="match_parent" - android:layout_height="match_parent"> - - <TextView - android:id="@+id/no_permissions" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:text="@string/no_permissions" - android:gravity="center" - android:textAppearance="@android:style/TextAppearance.Large" - /> - - </FrameLayout> - - </FrameLayout> -</FrameLayout> diff --git a/packages/PackageInstaller/res/layout-watch/accept_deny_dialog.xml b/packages/PackageInstaller/res/layout-watch/accept_deny_dialog.xml deleted file mode 100644 index 1a0509eede2d..000000000000 --- a/packages/PackageInstaller/res/layout-watch/accept_deny_dialog.xml +++ /dev/null @@ -1,111 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2016 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. ---> -<ScrollView - xmlns:android="http://schemas.android.com/apk/res/android" - android:fillViewport="true" - android:layout_width="match_parent" - android:layout_height="match_parent"> - <LinearLayout - android:id="@android:id/content" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical"> - - <FrameLayout - android:adjustViewBounds="true" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:minHeight="@dimen/diag_preferred_padding"> - <ImageView android:id="@android:id/icon" - android:adjustViewBounds="true" - android:maxHeight="24dp" - android:maxWidth="24dp" - android:layout_marginTop="@dimen/diag_icon_margin_top" - android:layout_marginBottom="8dp" - android:layout_gravity="center_horizontal" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:scaleType="centerInside" - android:visibility="gone" - android:src="@null" /> - </FrameLayout> - - <TextView android:id="@android:id/title" - android:gravity="center" - android:layout_marginBottom="8dp" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:paddingLeft="@dimen/diag_preferred_padding" - android:paddingRight="@dimen/diag_preferred_padding" - android:textAppearance="@android:style/TextAppearance.Material.Title" /> - - <TextView - android:id="@android:id/message" - android:gravity="center" - android:layout_marginBottom="8dp" - android:layout_height="wrap_content" - android:layout_width="match_parent" - android:paddingLeft="@dimen/diag_preferred_padding" - android:paddingRight="@dimen/diag_preferred_padding" - android:textAppearance="@android:style/TextAppearance.Material.Subhead" - android:visibility="gone" /> - - <FrameLayout - android:id="@+id/buttonPanel" - android:layout_weight="1" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - <LinearLayout - android:id="@+id/buttonContainer" - android:orientation="horizontal" - android:gravity="center_horizontal|top" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_gravity="bottom" - android:paddingTop="8dp" - android:paddingBottom="@dimen/diag_button_padding_bottom" - android:paddingLeft="@dimen/diag_button_padding_horizontal" - android:paddingRight="@dimen/diag_button_padding_horizontal" - style="?android:attr/buttonBarStyle"> - - <ImageButton - android:id="@android:id/button2" - android:src="@drawable/ic_cc_clear" - android:background="@drawable/accept_deny_dialog_negative_bg" - android:contentDescription="@string/generic_cancel" - android:layout_width="@dimen/diag_button_size" - android:layout_height="@dimen/diag_button_size" - android:visibility="gone" /> - - <Space - android:id="@+id/spacer" - android:layout_width="0dp" - android:layout_height="0dp" - android:visibility="gone" - android:layout_weight="1" /> - - <ImageButton - android:id="@android:id/button1" - android:src="@drawable/ic_cc_checkmark" - android:background="@drawable/accept_deny_dialog_positive_bg" - android:contentDescription="@string/generic_yes" - android:layout_width="@dimen/diag_button_size" - android:layout_height="@dimen/diag_button_size" - android:visibility="gone" /> - </LinearLayout> - </FrameLayout> - </LinearLayout> -</ScrollView> diff --git a/packages/PackageInstaller/res/layout-watch/wear_review_permission_action_pref.xml b/packages/PackageInstaller/res/layout-watch/wear_review_permission_action_pref.xml deleted file mode 100644 index 2b10c4dbb0c6..000000000000 --- a/packages/PackageInstaller/res/layout-watch/wear_review_permission_action_pref.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2017 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. ---> - -<TextView - xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+android:id/title" - android:gravity="center" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:paddingTop="@dimen/wear_permission_review_pref_padding" - android:paddingBottom="@dimen/wear_permission_review_pref_padding" - android:textAppearance="@android:style/TextAppearance.Material.Title" /> diff --git a/packages/PackageInstaller/res/layout-watch/wear_review_permission_title_pref.xml b/packages/PackageInstaller/res/layout-watch/wear_review_permission_title_pref.xml deleted file mode 100644 index 67928356116f..000000000000 --- a/packages/PackageInstaller/res/layout-watch/wear_review_permission_title_pref.xml +++ /dev/null @@ -1,38 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2017 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:id="@android:id/content" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:paddingBottom="@dimen/wear_permission_review_pref_padding" - android:orientation="vertical"> - <ImageView android:id="@+android:id/icon" - android:adjustViewBounds="true" - android:maxHeight="@dimen/wear_permission_review_icon_size" - android:maxWidth="@dimen/wear_permission_review_icon_size" - android:layout_gravity="center_horizontal" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:scaleType="centerInside" /> - <TextView android:id="@+android:id/title" - android:gravity="center" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:paddingLeft="@dimen/diag_preferred_padding" - android:paddingRight="@dimen/diag_preferred_padding" - android:textAppearance="@android:style/TextAppearance.Material.Title" /> -</LinearLayout> diff --git a/packages/PackageInstaller/res/layout/car_app_permissions.xml b/packages/PackageInstaller/res/layout/car_app_permissions.xml deleted file mode 100644 index e052b67af81f..000000000000 --- a/packages/PackageInstaller/res/layout/car_app_permissions.xml +++ /dev/null @@ -1,68 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 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. ---> - -<LinearLayout - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="vertical"> - <RelativeLayout - android:layout_width="match_parent" - android:layout_height="@dimen/car_app_bar_height" - android:gravity="end|center_vertical" > - <FrameLayout - android:id="@+id/action_bar_icon_container" - android:layout_width="@dimen/car_margin" - android:layout_height="@dimen/car_app_bar_height" - android:foreground="@drawable/button_ripple_bg" - android:layout_alignParentStart="true"> - <ImageView - android:layout_width="@dimen/car_primary_icon_size" - android:layout_height="@dimen/car_primary_icon_size" - android:tint="@color/car_tint" - android:scaleType="fitCenter" - android:layout_gravity="center" - android:src="@drawable/ic_arrow_back"/> - </FrameLayout> - <TextView - android:id="@+id/title" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginStart="@dimen/car_margin" - android:textAppearance="@style/TextAppearance.Car.Title2" - android:text="@string/app_permissions" - android:layout_gravity="center_vertical" - android:layout_centerVertical="true" - android:layout_alignParentStart="true" - android:maxLines="1" - android:ellipsize="end"/> - </RelativeLayout> - - <View - android:layout_width="match_parent" - android:layout_height="@dimen/car_list_divider_height" - android:background="@color/car_list_divider"/> - - <androidx.car.widget.PagedListView - android:id="@+id/list" - android:layout_width="match_parent" - android:layout_height="match_parent" - app:showPagedListViewDivider="true" - app:alignDividerStartTo="@id/container" - app:gutter="both"/> - -</LinearLayout> diff --git a/packages/PackageInstaller/res/layout/grant_permissions.xml b/packages/PackageInstaller/res/layout/grant_permissions.xml deleted file mode 100644 index f2a041fd0f5f..000000000000 --- a/packages/PackageInstaller/res/layout/grant_permissions.xml +++ /dev/null @@ -1,141 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2015 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. ---> - -<!-- Position subsequent dialogs with the button bar at same height --> -<com.android.packageinstaller.permission.ui.ManualLayoutFrame - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:clipChildren="false"> - - <!-- In (hopefully very rare) case dialog is too high: allow scrolling --> - <ScrollView - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:clipChildren="false"> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" - android:clipChildren="false"> - - <!-- allow some space around dialog, esp. in landscape --> - <Space - android:layout_width="0dp" - android:layout_height="0dp" - android:layout_weight="10" - android:visibility="invisible" /> - - <!-- The dialog --> - <LinearLayout - android:layout_height="wrap_content" - android:orientation="vertical" - android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.PermissionGrant" - style="@*android:style/PermissionGrantDialog"> - - <FrameLayout - android:id="@+id/content_container" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - - <include layout="@layout/grant_permissions_content" /> - - </FrameLayout> - - <!-- Button row on bottom of dialog --> - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" - android:gravity="bottom" - style="?android:attr/buttonBarStyle"> - - <LinearLayout - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="horizontal"> - - <!-- dummy to enforce height --> - <Button - android:layout_width="0dp" - android:layout_height="wrap_content" - android:visibility="invisible" - style="?android:attr/buttonBarButtonStyle" /> - - <!-- If several dialogs are shown in a row, show e.g. "1/3" --> - <TextView - android:id="@+id/current_page_text" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - style="@*android:style/PermissionGrantIndex" /> - - </LinearLayout> - - <com.android.packageinstaller.permission.ui.ButtonBarLayout - android:id="@+id/button_group" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_weight="1" - android:orientation="horizontal" - android:gravity="end"> - - <Button - android:id="@+id/permission_more_info_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/grant_dialog_button_more_info" - android:visibility="gone" - style="?android:attr/buttonBarButtonStyle" /> - - <Space - android:layout_width="0dp" - android:layout_height="0dp" - android:layout_weight="1" - android:visibility="invisible" /> - - <Button - android:id="@+id/permission_deny_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/grant_dialog_button_deny" - style="?android:attr/buttonBarButtonStyle" /> - - <Button - android:id="@+id/permission_allow_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/grant_dialog_button_allow" - style="?android:attr/buttonBarButtonStyle" /> - - </com.android.packageinstaller.permission.ui.ButtonBarLayout> - - </LinearLayout> - - </LinearLayout> - - <!-- allow some space around dialog, esp. in landscape --> - <Space - android:layout_width="0dp" - android:layout_height="0dp" - android:layout_weight="10" - android:visibility="invisible" /> - - </LinearLayout> - - </ScrollView> - -</com.android.packageinstaller.permission.ui.ManualLayoutFrame> diff --git a/packages/PackageInstaller/res/layout/grant_permissions_content.xml b/packages/PackageInstaller/res/layout/grant_permissions_content.xml deleted file mode 100644 index caa1d7665ab5..000000000000 --- a/packages/PackageInstaller/res/layout/grant_permissions_content.xml +++ /dev/null @@ -1,105 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 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. - --> - -<!-- Title of dialog --> -<LinearLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.PermissionGrant"> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" - style="@*android:style/PermissionGrantDescription"> - - <ImageView - android:id="@+id/permission_icon" - style="@*android:style/PermissionGrantTitleIcon" /> - - <TextView - android:id="@+id/permission_message" - android:layout_width="match_parent" - android:layout_height="wrap_content" - style="?android:attr/titleTextStyle" /> - - </LinearLayout> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - style="@*android:style/PermissionGrantContent" > - - <!-- Option one: Show a radio group of foreground / always / deny --> - <RadioGroup - android:id="@+id/foreground_or_always_radiogroup" - android:animateLayoutChanges="true" - android:layout_width="match_parent" - android:layout_height="wrap_content" - style="@*android:style/PermissionGrantRadioGroup" > - - <RadioButton - android:id="@+id/foreground_only_radio_button" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:text="@string/allow_permission_foreground_only" - style="@android:attr/radioButtonStyle" /> - - <RadioButton - android:id="@+id/always_radio_button" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:text="@string/allow_permission_always" - style="@android:attr/radioButtonStyle" /> - - <RadioButton - android:id="@+id/deny_dont_ask_again_radio_button" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:text="@string/deny_permission_deny_and_dont_ask_again" - style="@android:attr/radioButtonStyle" /> - - </RadioGroup> - - <!-- Option two: Show a detailed message about the change --> - <TextView - android:id="@+id/detail_message" - android:layout_width="match_parent" - android:layout_height="wrap_content" - style="@*android:style/PermissionGrantDetailMessage" /> - - <!-- Shown when detail_message and do_not_ask_checkbox are shown --> - <Space - android:id="@+id/detail_message_do_not_ask_checkbox_space" - android:layout_width="match_parent" - style="@*android:style/PermissionGrantDetailMessageSpace" /> - - <!-- Either with option two or by itself: Show a checkbox allowing to deny with - prejudice --> - <CheckBox - android:id="@+id/do_not_ask_checkbox" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:text="@string/never_ask_again" - style="@android:attr/checkboxStyle" /> - - </LinearLayout> - -</LinearLayout> diff --git a/packages/PackageInstaller/res/layout/header.xml b/packages/PackageInstaller/res/layout/header.xml deleted file mode 100644 index 45e6972c4128..000000000000 --- a/packages/PackageInstaller/res/layout/header.xml +++ /dev/null @@ -1,54 +0,0 @@ -<!-- - Copyright (C) 2015 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. ---> - -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="?android:attr/actionBarSize" - android:background="?android:attr/colorSecondary" - android:gravity="center_vertical" > - - <ImageView android:id="@+id/icon" - android:layout_width="@dimen/header_subsettings_margin_start" - android:layout_height="40dp" - android:gravity="end" - android:layout_centerVertical="true" /> - - <TextView - android:id="@+id/name" - android:layout_height="wrap_content" - android:layout_width="match_parent" - android:layout_marginStart="@dimen/header_subsettings_margin_start" - android:layout_alignWithParentIfMissing="true" - android:layout_centerVertical="true" - android:textAppearance="?android:attr/textAppearanceMedium" - android:textColor="?android:attr/textColorPrimary" - android:textAlignment="viewStart" /> - - <ImageView - android:id="@+id/info" - android:layout_width="56dp" - android:layout_height="56dp" - android:layout_alignParentEnd="true" - android:layout_marginEnd="@dimen/header_subsettings_margin_end" - android:layout_centerVertical="true" - android:minHeight="0dp" - android:minWidth="0dp" - android:scaleType="center" - android:src="@drawable/ic_info_outline" - android:contentDescription="@string/app_permissions_info_button_label" - style="?android:attr/borderlessButtonStyle" /> - -</RelativeLayout> diff --git a/packages/PackageInstaller/res/layout/label.xml b/packages/PackageInstaller/res/layout/label.xml deleted file mode 100644 index e1a51434c1ed..000000000000 --- a/packages/PackageInstaller/res/layout/label.xml +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2012 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. ---> - -<TextView xmlns:android="http://schemas.android.com/apk/res/android" - android:textAppearance="?android:attr/textAppearanceMedium" - android:gravity="center" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:padding="16dp"/> diff --git a/packages/PackageInstaller/res/layout/loading_container.xml b/packages/PackageInstaller/res/layout/loading_container.xml deleted file mode 100644 index 5a165deee583..000000000000 --- a/packages/PackageInstaller/res/layout/loading_container.xml +++ /dev/null @@ -1,36 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2015 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:id="@+id/loading_container" - android:orientation="vertical" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:visibility="gone" - android:gravity="center"> - - <ProgressBar style="?android:attr/progressBarStyleLarge" - android:layout_width="wrap_content" - android:layout_height="wrap_content" /> - - <TextView android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textAppearance="?android:attr/textAppearanceSmall" - android:text="@string/loading" - android:paddingTop="4dip" - android:singleLine="true" /> - -</LinearLayout> diff --git a/packages/PackageInstaller/res/layout/permissions_frame.xml b/packages/PackageInstaller/res/layout/permissions_frame.xml deleted file mode 100644 index 156af57e897a..000000000000 --- a/packages/PackageInstaller/res/layout/permissions_frame.xml +++ /dev/null @@ -1,40 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2015 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. ---> - -<FrameLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="match_parent"> - - <FrameLayout - android:id="@+id/prefs_container" - android:layout_width="match_parent" - android:layout_height="match_parent"> - - <TextView - android:id="@+id/no_permissions" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:text="@string/no_permissions" - android:gravity="center" - style="?android:attr/textAppearanceLarge"> - </TextView> - - </FrameLayout> - - <include layout="@layout/loading_container" /> - -</FrameLayout> diff --git a/packages/PackageInstaller/res/layout/permissions_list.xml b/packages/PackageInstaller/res/layout/permissions_list.xml deleted file mode 100644 index 5e3ae0f5c23d..000000000000 --- a/packages/PackageInstaller/res/layout/permissions_list.xml +++ /dev/null @@ -1,31 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2012 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. ---> - -<!-- -This is the structure for the list of all permissions. ---> -<com.android.packageinstaller.CaffeinatedScrollView - xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/scrollview" - android:fillViewport="true"> - <LinearLayout - android:id="@+id/permission_list" - android:orientation="vertical" - android:layout_width="match_parent" - android:paddingEnd="4dp" - android:layout_height="wrap_content"> - </LinearLayout> -</com.android.packageinstaller.CaffeinatedScrollView> diff --git a/packages/PackageInstaller/res/layout/preference_category_material.xml b/packages/PackageInstaller/res/layout/preference_category_material.xml deleted file mode 100644 index f62260bc1900..000000000000 --- a/packages/PackageInstaller/res/layout/preference_category_material.xml +++ /dev/null @@ -1,35 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2015 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. ---> - -<!-- Based on frameworks/base/core/res/res/layout/preference_category_material.xml - but has a ViewGroup at the root to make the support lib happy.--> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical"> - - <TextView - android:id="@android:id/title" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginBottom="16dip" - android:textAppearance="@android:style/TextAppearance.Material.Body2" - android:paddingStart="?android:attr/listPreferredItemPaddingStart" - android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" - android:textColor="?android:attr/colorAccent" - android:paddingTop="16dip" /> - -</LinearLayout> diff --git a/packages/PackageInstaller/res/layout/preference_permissions.xml b/packages/PackageInstaller/res/layout/preference_permissions.xml deleted file mode 100644 index 2a03067c8a7a..000000000000 --- a/packages/PackageInstaller/res/layout/preference_permissions.xml +++ /dev/null @@ -1,80 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2015 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. ---> - -<!-- Based off frameworks/base/core/res/res/layout/preference_material.xml - except that this has the negative margin on the image removed - and has a set icon size (and some padding to realign). --> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:minHeight="?android:attr/listPreferredItemHeightSmall" - android:gravity="center_vertical" - android:paddingStart="?android:attr/listPreferredItemPaddingStart" - android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" - android:background="?android:attr/selectableItemBackground" - android:focusable="true" - android:clipToPadding="false"> - - <LinearLayout - android:id="@android:id/icon_frame" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:gravity="start|center_vertical" - android:orientation="horizontal" - android:paddingEnd="20dp" - android:paddingTop="4dp" - android:paddingBottom="4dp"> - <com.android.packageinstaller.permission.ui.PreferenceImageView - android:id="@android:id/icon" - android:layout_width="24dp" - android:layout_height="24dp" - android:scaleType="fitCenter" /> - </LinearLayout> - - <RelativeLayout - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_weight="1" - android:paddingTop="16dp" - android:paddingBottom="16dp"> - - <TextView android:id="@android:id/title" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:singleLine="true" - android:textAppearance="?android:attr/textAppearanceListItem" - android:ellipsize="marquee" /> - - <TextView android:id="@android:id/summary" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_below="@android:id/title" - android:layout_alignStart="@android:id/title" - android:textAppearance="?android:attr/textAppearanceListItemSecondary" - android:textColor="?android:attr/textColorSecondary" - android:maxLines="10" /> - - </RelativeLayout> - - <!-- Preference should place its actual preference widget here. --> - <LinearLayout android:id="@android:id/widget_frame" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:gravity="end|center_vertical" - android:paddingStart="16dp" - android:orientation="vertical" /> - -</LinearLayout> diff --git a/packages/PackageInstaller/res/layout/preference_permissions_switch.xml b/packages/PackageInstaller/res/layout/preference_permissions_switch.xml deleted file mode 100644 index 50e2c99f3a01..000000000000 --- a/packages/PackageInstaller/res/layout/preference_permissions_switch.xml +++ /dev/null @@ -1,80 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2015 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. ---> - -<!-- Based off frameworks/base/core/res/res/layout/preference_material.xml - except that this has the negative margin on the image removed - and has a set icon size (and some padding to align). --> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:minHeight="?android:attr/listPreferredItemHeightSmall" - android:gravity="center_vertical" - android:paddingStart="?android:attr/listPreferredItemPaddingStart" - android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" - android:background="?android:attr/selectableItemBackground" - android:focusable="true" - android:clipToPadding="false"> - - <LinearLayout - android:id="@android:id/icon_frame" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:gravity="start|center_vertical" - android:orientation="horizontal" - android:paddingEnd="20dp" - android:paddingTop="4dp" - android:paddingBottom="4dp"> - <com.android.packageinstaller.permission.ui.PreferenceImageView - android:id="@android:id/icon" - android:layout_width="36dp" - android:layout_height="36dp" - android:scaleType="fitCenter" /> - </LinearLayout> - - <RelativeLayout - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_weight="1" - android:paddingTop="16dp" - android:paddingBottom="16dp"> - - <TextView android:id="@android:id/title" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:singleLine="true" - android:textAppearance="?android:attr/textAppearanceListItem" - android:ellipsize="marquee" /> - - <TextView android:id="@android:id/summary" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_below="@android:id/title" - android:layout_alignStart="@android:id/title" - android:textAppearance="?android:attr/textAppearanceListItemSecondary" - android:textColor="?android:attr/textColorSecondary" - android:maxLines="10" /> - - </RelativeLayout> - - <!-- Preference should place its actual preference widget here. --> - <LinearLayout android:id="@android:id/widget_frame" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:gravity="end|center_vertical" - android:paddingStart="16dp" - android:orientation="vertical" /> - -</LinearLayout> diff --git a/packages/PackageInstaller/res/layout/review_permissions.xml b/packages/PackageInstaller/res/layout/review_permissions.xml deleted file mode 100644 index 6a1c6b3ea774..000000000000 --- a/packages/PackageInstaller/res/layout/review_permissions.xml +++ /dev/null @@ -1,112 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2015 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:layout_width="fill_parent" - android:layout_height="fill_parent" - android:layout_marginTop="32dip" - android:layout_marginBottom="8dip" - android:orientation="vertical"> - - <LinearLayout - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginStart="16dip" - android:layout_marginEnd="16dip" - android:layout_marginBottom="16dip" - android:orientation="horizontal"> - - <ImageView - android:id="@+id/app_icon" - android:layout_width="36dip" - android:layout_height="36dip" - android:scaleType="fitCenter"> - </ImageView> - - <TextView - android:id="@+id/permissions_message" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginStart="16dip" - style="?android:attr/textAppearanceMedium"> - </TextView> - - </LinearLayout> - - <FrameLayout - android:id="@+id/preferences_frame" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:layout_marginStart="2dip" - android:layout_marginEnd="2dip" - android:layout_weight="1"> - </FrameLayout> - - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" - android:paddingStart="2dip" - android:paddingTop="16dip"> - - <Button - android:id="@+id/permission_more_info_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="bottom" - android:visibility="gone" - style="?android:attr/buttonBarButtonStyle" - android:text="@string/grant_dialog_button_more_info"> - </Button> - - <Space - android:layout_width="0dp" - android:layout_height="0dp" - android:layout_weight="1" - android:visibility="invisible"> - </Space> - - <com.android.packageinstaller.permission.ui.ButtonBarLayout - android:id="@+id/button_group" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="bottom" - android:orientation="horizontal" - android:gravity="bottom"> - - <Button - android:id="@+id/cancel_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - style="?android:attr/buttonBarButtonStyle" - android:text="@string/review_button_cancel"> - </Button> - - <Button - android:id="@+id/continue_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - style="?android:attr/buttonBarButtonStyle" - android:layout_marginStart="8dip" - android:text="@string/review_button_continue"> - </Button> - - </com.android.packageinstaller.permission.ui.ButtonBarLayout> - - </LinearLayout> - -</LinearLayout> diff --git a/packages/PackageInstaller/res/values-television/colors.xml b/packages/PackageInstaller/res/values-television/colors.xml index 6afe24830790..1cacc002465b 100644 --- a/packages/PackageInstaller/res/values-television/colors.xml +++ b/packages/PackageInstaller/res/values-television/colors.xml @@ -24,16 +24,5 @@ <color name="lb_header_banner_color">#1f292d</color> - <color name="grant_permissions_background_color">#ff263238</color> - <color name="grant_permissions_app_color">@color/grant_permissions_white_text_alpha_100</color> - <color name="grant_permissions_progress_color">@color/grant_permissions_white_text_alpha_100</color> - <color name="grant_permissions_title_color">@color/grant_permissions_white_text_alpha_70</color> - <color name="grant_permissions_body_color">@color/grant_permissions_white_text_alpha_70</color> - <color name="grant_permissions_button_color">@color/grant_permissions_white_text_alpha_100</color> - <color name="grant_permissions_focus_highlight">#26eeeeee</color> - - <color name="grant_permissions_white_text_alpha_100">@color/off_white</color> - <color name="grant_permissions_white_text_alpha_70">#b2eeeeee</color> - <color name="off_white">#ffeeeeee</color> </resources> diff --git a/packages/PackageInstaller/res/values-television/dimens.xml b/packages/PackageInstaller/res/values-television/dimens.xml index 03038386e08d..d1c232e693b0 100644 --- a/packages/PackageInstaller/res/values-television/dimens.xml +++ b/packages/PackageInstaller/res/values-television/dimens.xml @@ -15,13 +15,6 @@ --> <resources> - <dimen name="grant_permissions_app_icon_size">64dp</dimen> - <dimen name="grant_permissions_app_icon_margin_top">19dp</dimen> - - <dimen name="grant_permissions_app_breadcrumb_margin_bottom">3dp</dimen> - <dimen name="grant_permissions_app_title_margin_bottom">18dp</dimen> - <dimen name="grant_permissions_app_details_margin_bottom">8dp</dimen> - <dimen name="action_dialog_z">16dp</dimen> <dimen name="action_dialog_padding_left">52dp</dimen> <dimen name="action_dialog_padding_right">40dp</dimen> diff --git a/packages/PackageInstaller/res/values-television/strings.xml b/packages/PackageInstaller/res/values-television/strings.xml deleted file mode 100644 index c11d865cedd8..000000000000 --- a/packages/PackageInstaller/res/values-television/strings.xml +++ /dev/null @@ -1,38 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2015 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- Title for the dialog button to deny a permission grant and never ask the user again. --> - <string name="grant_dialog_button_deny_dont_ask_again">Deny and don\'t ask again</string> - - <!-- Instructional text telling the user how to change permission grants later. --> - <string name="grant_dialog_how_to_change">You can change this later in Settings > Apps</string> - - <!-- Template for the current permission from the total number of permissions. --> - <string name="current_permission_template"> - <xliff:g id="current_permission_index" example="1">%1$s</xliff:g> / - <xliff:g id="permission_count" example="2">%2$s</xliff:g></string> - - <!-- Preference row title for showing system apps. --> - <string name="preference_show_system_apps">Show system apps</string> - - <!--decor title displayed as the page title for different TV permission screens--> - <string name="app_permissions_decor_title">App permissions</string> - <string name="manage_permissions_decor_title">App permissions</string> - <string name="permission_apps_decor_title"><xliff:g id="permission" example="Camera">%1$s</xliff:g> permissions</string> - <string name="additional_permissions_decor_title">Additional permissions</string> - <string name="system_apps_decor_title"><xliff:g id="permission" example="Camera">%1$s</xliff:g> permissions</string> -</resources> diff --git a/packages/PackageInstaller/res/values-television/styles.xml b/packages/PackageInstaller/res/values-television/styles.xml deleted file mode 100644 index 5f712f7d134b..000000000000 --- a/packages/PackageInstaller/res/values-television/styles.xml +++ /dev/null @@ -1,37 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2015 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> - - <style name="PreferenceThemeOverlay.v14.Permissions"> - <item name="preferenceStyle">@style/Preference.Permissions</item> - <item name="preferenceCategoryStyle">@style/Preference.Category.Permissions</item> - <item name="switchPreferenceStyle">@style/Preference.SwitchPreference.Permissions</item> - </style> - - <style name="Preference.Permissions"> - <item name="layout">@layout/preference_permissions</item> - </style> - - <style name="Preference.Category.Permissions"> - <item name="layout">@layout/preference_category_material</item> - </style> - - <style name="Preference.SwitchPreference.Permissions"> - <item name="layout">@layout/preference_permissions_switch</item> - </style> - -</resources> diff --git a/packages/PackageInstaller/res/values-television/themes.xml b/packages/PackageInstaller/res/values-television/themes.xml deleted file mode 100644 index f778fad25ccd..000000000000 --- a/packages/PackageInstaller/res/values-television/themes.xml +++ /dev/null @@ -1,71 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - ~ Copyright (C) 2015 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> - <style name="Settings" parent="Theme.Leanback"> - <item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Leanback</item> - <item name="android:windowBackground">@android:color/transparent</item> - <item name="android:windowIsTranslucent">true</item> - <item name="android:backgroundDimEnabled">true</item> - <item name="android:backgroundDimAmount">0.8</item> - </style> - - <style name="GrantPermissions" parent="Theme.Leanback"> - <item name="android:windowIsFloating">true</item> - <item name="android:windowAnimationStyle">@style/Animation.Snackbar</item> - <item name="android:windowElevation">@dimen/action_dialog_z</item> - </style> - - <style name="GrantPermissions.BreadcrumbText"> - <item name="android:fontFamily">sans-serif-condensed</item> - <item name="android:textSize">14sp</item> - <item name="android:textColor">@color/grant_permissions_progress_color</item> - </style> - - <style name="GrantPermissions.TitleText"> - <item name="android:fontFamily">sans-serif-light</item> - <item name="android:textSize">24sp</item> - <item name="android:textColor">@color/grant_permissions_title_color</item> - <item name="android:lineSpacingMultiplier">1.221</item> - </style> - - <style name="GrantPermissions.BodyText"> - <item name="android:fontFamily">sans-serif</item> - <item name="android:textSize">14sp</item> - <item name="android:textColor">@color/grant_permissions_body_color</item> - <item name="android:lineSpacingMultiplier">1.465</item> - </style> - - <style name="GrantPermissions.ActionItem"> - <item name="android:gravity">left|center_vertical</item> - <item name="android:fontFamily">sans-serif-condensed</item> - <item name="android:textSize">14sp</item> - <item name="android:textColor">@color/grant_permissions_button_color</item> - <item name="android:lineSpacingMultiplier">1</item> - <item name="android:background">@drawable/grant_permissions_action_item</item> - <item name="android:paddingLeft">@dimen/action_dialog_button_padding_left</item> - <item name="android:paddingRight">@dimen/action_dialog_button_padding_right</item> - <item name="android:paddingTop">@dimen/action_dialog_button_padding_top</item> - <item name="android:paddingBottom">@dimen/action_dialog_button_padding_bottom</item> - <item name="android:minHeight">@dimen/action_dialog_button_min_height</item> - </style> - - <style name="Animation.Snackbar" parent="@android:style/Animation"> - <item name="android:windowEnterAnimation">@anim/snackbar_enter</item> - <item name="android:windowExitAnimation">@anim/snackbar_exit</item> - </style> -</resources> diff --git a/packages/PackageInstaller/res/values-watch/strings.xml b/packages/PackageInstaller/res/values-watch/strings.xml index f940eae6552e..25e83893e2a3 100644 --- a/packages/PackageInstaller/res/values-watch/strings.xml +++ b/packages/PackageInstaller/res/values-watch/strings.xml @@ -15,21 +15,6 @@ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- Title for the dialog button to deny a permission grant and never ask the user again. [CHAR LIMIT=29]--> - <string name="grant_dialog_button_deny_dont_ask_again">Deny, don\'t ask again</string> - - <!-- Template for the current permission from the total number of permissions. --> - <string name="current_permission_template"> - <xliff:g id="current_permission_index" example="1">%1$s</xliff:g> / - <xliff:g id="permission_count" example="2">%2$s</xliff:g> - </string> - - <!-- Preference row title for showing system apps. --> - <string name="preference_show_system_apps">Show system apps</string> - - <!-- Summary of a permission switch when it's enforced by policy [CHAR LIMIT=17] --> - <string name="permission_summary_enforced_by_policy">Can\'t be changed</string> - <!-- Generic text to indicate a yes. [CHAR LIMIT=10] --> <string name="generic_yes">Yes</string> diff --git a/packages/PackageInstaller/res/values-watch/themes.xml b/packages/PackageInstaller/res/values-watch/themes.xml index 3adcfc546c00..5e52008c7fd6 100644 --- a/packages/PackageInstaller/res/values-watch/themes.xml +++ b/packages/PackageInstaller/res/values-watch/themes.xml @@ -17,10 +17,4 @@ <resources> <style name="DialogWhenLarge" parent="@android:style/Theme.DeviceDefault.NoActionBar"/> - - <style name="Settings" parent="@android:style/Theme.DeviceDefault.NoActionBar" /> - - <style name="GrantPermissions" parent="@android:style/Theme.DeviceDefault.NoActionBar"> - <item name="android:windowBackground">@android:color/transparent</item> - </style> </resources> diff --git a/packages/PackageInstaller/res/values/strings.xml b/packages/PackageInstaller/res/values/strings.xml index 23eb8657e299..6c7160fc2935 100644 --- a/packages/PackageInstaller/res/values/strings.xml +++ b/packages/PackageInstaller/res/values/strings.xml @@ -172,204 +172,11 @@ <!-- Dialog attributes to indicate parse errors --> <string name="Parse_error_dlg_text">There was a problem parsing the package.</string> - <!-- Tab label for new permissions being added to an existing app [CHAR LIMIT=20] --> - <string name="newPerms">New</string> - <!-- Tab label for all permissions of an app being installed [CHAR LIMIT=20] --> - <string name="allPerms">All</string> - <!-- Tab label for permissions related to user privacy [CHAR LIMIT=20] --> - <string name="privacyPerms">Privacy</string> - <!-- Tab label for permissions related to device behavior [CHAR LIMIT=20] --> - <string name="devicePerms">Device Access</string> - - <!-- Body text for new tab when there are no new permissions [CHAR LIMIT=NONE] --> - <string name="no_new_perms">This update requires no new permissions.</string> - - <!-- Title for the dialog button to deny a permission grant. [CHAR LIMIT=15] --> - <string name="grant_dialog_button_deny">Deny</string> - - <!-- Title for the dialog button to get more info about a permission. [CHAR LIMIT=15] --> - <string name="grant_dialog_button_more_info">More info</string> - - <!-- Title for the dialog button to deny a permission grant despite a warning of implications. [CHAR LIMIT=15] --> - <string name="grant_dialog_button_deny_anyway">Deny anyway</string> - - <!-- Template for the current permission from the total number of permissions. [CHAR LIMIT=100] --> - <string name="current_permission_template"> - <xliff:g id="current_permission_index" example="1">%1$s</xliff:g> of - <xliff:g id="permission_count" example="2">%2$s</xliff:g></string> - - <!-- Template for the warning message when an app requests a permission. [CHAR LIMIT=100] --> - <string name="permission_warning_template">Allow - <b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g></b> to - <xliff:g id="action" example="do something">%2$s</xliff:g>?</string> - - <!-- Template for the warning message when an app requests the permission to access a - resource even while in the background (i.e. always). [CHAR LIMIT=100] --> - <string name="permission_add_background_warning_template">Always allow - <b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g></b> to - <xliff:g id="action" example="do something">%2$s</xliff:g>?</string> - - <!-- Radio button shown for permissions that can be granted either only while the app is in - foreground or always. If this button is selected the app only gets the permission while in - foreground [CHAR LIMIT=50] --> - <string name="allow_permission_foreground_only">Only while using app</string> - - <!-- Radio button shown for permissions that can be granted either only while the app is in - foreground or always. If this button is selected the app always gets the permission (while in - foreground _and_ while in background) [CHAR LIMIT=50] --> - <string name="allow_permission_always">Always</string> - - <!-- Radio button shown for permissions that can be granted either only while the app is in - foreground or always. If this button is selected the app does not get the permission and the - permissions will always be denied from now on [CHAR LIMIT=50] --> - <string name="deny_permission_deny_and_dont_ask_again">Deny and don\u2019t ask again</string> - - <!-- Template for the message how many permissions are disabled. [CHAR LIMIT=30] --> - <string name="permission_revoked_count"><xliff:g id="count" example="2">%1$d</xliff:g> disabled</string> - - <!-- Message that all permissions are disabled. [CHAR LIMIT=30] --> - <string name="permission_revoked_all">all disabled</string> - - <!-- Message that no permissions are disabled. [CHAR LIMIT=30] --> - <string name="permission_revoked_none">none disabled</string> - - <!-- Permissions --> - - <!-- Title for the dialog button to allow a permission grant. [CHAR LIMIT=15] --> - <string name="grant_dialog_button_allow">Allow</string> - - <!-- Breadcrumb for page of managing application permissions [CHAR LIMIT=50] --> - <string name="app_permissions_breadcrumb">Apps</string> - - <!-- Title for page of managing application permissions [CHAR LIMIT=30] --> - <string name="app_permissions">App permissions</string> - <!-- Checkbox that allows user to not be questioned about this permission - request again [CHAR LIMIT=30] --> - <string name="never_ask_again">Don\'t ask again</string> - - <!-- Label when app requests no permissions [CHAR LIMIT=30] --> - <string name="no_permissions">No permissions</string> - - <!-- Label for button that leads to more permissions [CHAR LIMIT=40] --> - <string name="additional_permissions">Additional permissions</string> - - <!-- Accessibility label for button opening the app-info when clicked [CHAR LIMIT=none] --> - <string name="app_permissions_info_button_label">Open app info</string> - - <!-- Description of how many more permissions to view on next page [CHAR LIMIT=30] --> - <plurals name="additional_permissions_more"> - <item quantity="one"><xliff:g id="count" example="1">%1$d</xliff:g> more</item> - <item quantity="other"><xliff:g id="count" example="2">%1$d</xliff:g> more</item> - </plurals> - - <!-- Warning for turning off permissions on older apps [CHAR LIMIT=none] --> - <string name="old_sdk_deny_warning">This app was designed for an older version of Android. Denying permission may cause it to no longer function as intended.</string> - - <!-- The default description of a permission, i.e. what it does. [CHAR LIMIT=40] --> - <string name="default_permission_description">perform an unknown action</string> - - <!-- Summary of number of apps currently granted a single permission [CHAR LIMIT=45] --> - <string name="app_permissions_group_summary"><xliff:g id="count" example="10">%1$d</xliff:g> of <xliff:g id="count" example="10">%2$d</xliff:g> apps allowed</string> - - <!-- [CHAR LIMIT=NONE] Menu for manage permissions to control whether system apps are shown --> - <string name="menu_show_system">Show system</string> - <!-- [CHAR LIMIT=NONE] Menu for manage permissions to control whether system apps are hidden --> - <string name="menu_hide_system">Hide system</string> - - <!-- [CHAR LIMIT=NONE] Label when no apps requesting this permission --> - <string name="no_apps">No apps</string> - - <!-- [CHAR LIMIT=30] Title of button that leads to location settings --> - <string name="location_settings">Location Settings</string> - - <!-- [CHAR LIMIT=NONE] Warning about how this app cannot have location permission disabled --> - <string name="location_warning"><xliff:g id="app_name" example="Package Installer">%1$s</xliff:g> is a provider of location services for this device. Location access can be modified from location settings.</string> - - <!-- [CHAR LIMIT=NONE] Warning message when turning off permission for system apps --> - <string name="system_warning">If you deny this permission, basic features of your device may no longer function as intended.</string> - - <!-- [CHAR LIMIT=NONE] Summary of a permission switch when it's enforced by policy --> - <string name="permission_summary_enforced_by_policy">Enforced by policy</string> - - <!-- [CHAR LIMIT=60] Summary of a permission switch when the background access is denied by policy --> - <string name="permission_summary_disabled_by_policy_background_only">Background access disabled by policy</string> - - <!-- [CHAR LIMIT=60] Summary of a permission switch when the background access is enabled by policy --> - <string name="permission_summary_enabled_by_policy_background_only">Background access enabled by policy</string> - - <!-- [CHAR LIMIT=60] Summary of a permission switch when the background access is enabled by policy --> - <string name="permission_summary_enabled_by_policy_foreground_only">Foreground access enabled by policy</string> - - <!-- [CHAR LIMIT=60] Summary of a permission switch when it's enforced by an administrator --> - <string name="permission_summary_enforced_by_admin">Controlled by admin</string> - - <string-array name="background_access_chooser_dialog_choices"> - <item>@string/permission_access_always</item> - <item>@string/permission_access_only_foreground</item> - <item>@string/permission_access_never</item> - </string-array> - - <!-- [CHAR LIMIT=30] App can always (when app is in foreground or background) access the resource protected by the permission --> - <string name="permission_access_always">Always</string> - - <!-- [CHAR LIMIT=30] App can only access the resource protected by the permission while app is in foregroud --> - <string name="permission_access_only_foreground">Only while using app</string> - - <!-- [CHAR LIMIT=30] App can never access the resource protected by the permission (Not while app is in foregound and not while app is in background) --> - <string name="permission_access_never">Never</string> - - <!-- Text displayed until loading is done [CHAR LIMIT=50] --> - <string name="loading">Loading\u2026</string> - - <!-- [CHAR LIMIT=45] Title of all permissions settings --> - <string name="all_permissions">All permissions</string> - <!-- [CHAR LIMIT=45] Group of permissions granted to app automatically when installed. --> - <string name="other_permissions">Other app capabilities</string> - - <!-- Title of the permission dialog for accessibility purposes- spoken to the user. [CHAR LIMIT=none] --> - <string name="permission_request_title">Permission request</string> - - <!-- Title for the dialog that warns the user they need to turn off screen overlays - before permissions can be changed. [CHAR LIMIT=NONE] --> - <string name="screen_overlay_title">Screen overlay detected</string> - - <!-- Message for the dialog that warns the user they need to turn off screen overlays - before permissions can be changed. The "Settings > Apps" conveys to the user to - go to Settings and click on apps, this may need updates in RTL languages. [CHAR LIMIT=NONE] --> - <string name="screen_overlay_message">To change this permission setting, you first have to turn off the screen overlay from Settings \u003e Apps</string> - - <!-- Button for the dialog that warns the user they need to turn off screen overlays - before permissions can be changed. [CHAR LIMIT=NONE] --> - <string name="screen_overlay_button">Open settings</string> - <!-- Title of dialog telling users that Install/Uninstall action is not supported on Android Wear. [CHAR LIMIT=30] --> <string name="wear_not_allowed_dlg_title">Android Wear</string> <!-- Title of dialog telling users that Install/Uninstall action is not supported on Android Wear. [CHAR LIMIT=none] --> <string name="wear_not_allowed_dlg_text">Install/Uninstall actions not supported on Wear.</string> - <!-- Review of runtime permissions for legacy apps --> - - <!-- Template for the screen title when app permissions are reviewed on install. [CHAR LIMIT=none] --> - <string name="permission_review_title_template_install">Choose what to allow - <b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g></b> to access</string> - - <!-- Template for the screen title when app permissions are reviewed on update. [CHAR LIMIT=none] --> - <string name="permission_review_title_template_update"> - <b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g></b> has been updated. - Choose what to allow this app to access.</string> - - <!-- Title for the dialog button to cancel the detailed permission review. [CHAR LIMIT=15] --> - <string name="review_button_cancel">Cancel</string> - - <!-- Title for the dialog button to continue accepting the detailed permission review. [CHAR LIMIT=15] --> - <string name="review_button_continue">Continue</string> - - <!-- Title for the category listing the new permissions used by an app. [CHAR LIMIT=30] --> - <string name="new_permissions_category">New permissions</string> - - <!-- Title for the category listing the current permissions used by an app. [CHAR LIMIT=30] --> - <string name="current_permissions_category">Current permissions</string> - <!-- Message that the app to be installed is being staged [CHAR LIMIT=50] --> <string name="message_staging">Staging app…</string> diff --git a/packages/PackageInstaller/res/values/themes.xml b/packages/PackageInstaller/res/values/themes.xml index 3ddb6a7a9444..6df6246ff560 100644 --- a/packages/PackageInstaller/res/values/themes.xml +++ b/packages/PackageInstaller/res/values/themes.xml @@ -17,28 +17,6 @@ <resources> - <style name="Settings" - parent="@android:style/Theme.DeviceDefault.Settings"> - </style> - - <style name="CarSettingTheme" parent="Theme.Car.Light.NoActionBar"> - <item name="android:background">@color/car_card</item> - </style> - - <style name="Settings.NoActionBar" parent="@style/Settings"> - <item name="android:windowActionBar">false</item> - <item name="android:windowNoTitle">true</item> - <item name="preferenceTheme">@style/PreferenceThemeOverlay.SettingsBase</item> - </style> - - <style name="GrantPermissions" - parent="@*android:style/Theme.DeviceDefault.Light.Panel.PermissionGrantApp"> - <!-- The following attributes change the behavior of the dialog, hence they should not be - themed --> - <item name="android:windowIsTranslucent">true</item> - <item name="android:windowCloseOnTouchOutside">@*android:bool/config_closeDialogWhenTouchOutside</item> - </style> - <style name="DialogWhenLarge" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar"> <item name="android:textAppearanceMedium">@style/MediumText</item> diff --git a/packages/PackageInstaller/res/xml-watch/watch_permissions.xml b/packages/PackageInstaller/res/xml-watch/watch_permissions.xml deleted file mode 100644 index 8ec8d196fe00..000000000000 --- a/packages/PackageInstaller/res/xml-watch/watch_permissions.xml +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2016 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. ---> -<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" - android:title="@string/app_permissions" - android:orderingFromXml="true"> - <Preference - android:key="no_permissions" - android:title="@string/no_permissions" /> -</PreferenceScreen> diff --git a/packages/PackageInstaller/res/xml/all_permissions.xml b/packages/PackageInstaller/res/xml/all_permissions.xml deleted file mode 100644 index 5f7f847bafbd..000000000000 --- a/packages/PackageInstaller/res/xml/all_permissions.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2015 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. ---> - -<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" - android:title="@string/all_permissions"> - - <PreferenceCategory - android:key="other_perms" - android:title="@string/other_permissions" /> - -</PreferenceScreen> diff --git a/packages/PackageInstaller/src/android/support/wearable/view/AcceptDenyDialog.java b/packages/PackageInstaller/src/android/support/wearable/view/AcceptDenyDialog.java deleted file mode 100644 index f2129b8f4b17..000000000000 --- a/packages/PackageInstaller/src/android/support/wearable/view/AcceptDenyDialog.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2016 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 androidx.wear.ble.view; - -import android.annotation.TargetApi; -import android.app.Dialog; -import android.content.Context; -import android.content.DialogInterface; -import android.graphics.drawable.Drawable; -import android.os.Build; -import androidx.annotation.StyleRes; -import android.view.View; -import android.widget.ImageButton; -import android.widget.ImageView; -import android.widget.Space; -import android.widget.TextView; - -import com.android.packageinstaller.R; - -/** - * A dialog to display a title, a message, and/or an icon with a positive and a negative button. - * - * <p>The buttons are hidden away unless there is a listener attached to the button. Since there's - * no click listener attached by default, the buttons are hidden be default. - */ -@TargetApi(Build.VERSION_CODES.LOLLIPOP) -public class AcceptDenyDialog extends Dialog { - /** Icon at the top of the dialog. */ - protected ImageView mIcon; - /** Title at the top of the dialog. */ - protected TextView mTitle; - /** Message content of the dialog. */ - protected TextView mMessage; - /** Panel containing the buttons. */ - protected View mButtonPanel; - /** Positive button in the button panel. */ - protected ImageButton mPositiveButton; - /** Negative button in the button panel. */ - protected ImageButton mNegativeButton; - /** - * Click listener for the positive button. Positive button should hide if this is <code>null - * </code>. - */ - protected DialogInterface.OnClickListener mPositiveButtonListener; - /** - * Click listener for the negative button. Negative button should hide if this is <code>null - * </code>. - */ - protected DialogInterface.OnClickListener mNegativeButtonListener; - /** Spacer between the positive and negative button. Hidden if one button is hidden. */ - protected View mSpacer; - - private final View.OnClickListener mButtonHandler = (v) -> { - if (v == mPositiveButton && mPositiveButtonListener != null) { - mPositiveButtonListener.onClick(this, DialogInterface.BUTTON_POSITIVE); - dismiss(); - } else if (v == mNegativeButton && mNegativeButtonListener != null) { - mNegativeButtonListener.onClick(this, DialogInterface.BUTTON_NEGATIVE); - dismiss(); - } - }; - - public AcceptDenyDialog(Context context) { - this(context, 0 /* use default context theme */); - } - - public AcceptDenyDialog(Context context, @StyleRes int themeResId) { - super(context, themeResId); - - setContentView(R.layout.accept_deny_dialog); - - mTitle = (TextView) findViewById(android.R.id.title); - mMessage = (TextView) findViewById(android.R.id.message); - mIcon = (ImageView) findViewById(android.R.id.icon); - mPositiveButton = (ImageButton) findViewById(android.R.id.button1); - mPositiveButton.setOnClickListener(mButtonHandler); - mNegativeButton = (ImageButton) findViewById(android.R.id.button2); - mNegativeButton.setOnClickListener(mButtonHandler); - mSpacer = (Space) findViewById(R.id.spacer); - mButtonPanel = findViewById(R.id.buttonPanel); - } - - public ImageButton getButton(int whichButton) { - switch (whichButton) { - case DialogInterface.BUTTON_POSITIVE: - return mPositiveButton; - case DialogInterface.BUTTON_NEGATIVE: - return mNegativeButton; - default: - return null; - } - } - - public void setIcon(Drawable icon) { - mIcon.setVisibility(icon == null ? View.GONE : View.VISIBLE); - mIcon.setImageDrawable(icon); - } - - /** - * @param resId the resourceId of the drawable to use as the icon or 0 if you don't want an icon. - */ - public void setIcon(int resId) { - mIcon.setVisibility(resId == 0 ? View.GONE : View.VISIBLE); - mIcon.setImageResource(resId); - } - - /** @param message the content message text of the dialog. */ - public void setMessage(CharSequence message) { - mMessage.setText(message); - mMessage.setVisibility(message == null ? View.GONE : View.VISIBLE); - } - - /** @param title the title text of the dialog. */ - @Override - public void setTitle(CharSequence title) { - mTitle.setText(title); - } - - /** - * Sets a click listener for a button. - * - * <p>Will hide button bar if all buttons are hidden (i.e. their click listeners are <code>null - * </code>). - * - * @param whichButton {@link DialogInterface.BUTTON_POSITIVE} or {@link - * DialogInterface.BUTTON_NEGATIVE} - * @param listener the listener to set for the button. Hide button if <code>null</code>. - */ - public void setButton(int whichButton, DialogInterface.OnClickListener listener) { - switch (whichButton) { - case DialogInterface.BUTTON_POSITIVE: - mPositiveButtonListener = listener; - break; - case DialogInterface.BUTTON_NEGATIVE: - mNegativeButtonListener = listener; - break; - default: - return; - } - - mSpacer.setVisibility(mPositiveButtonListener == null || mNegativeButtonListener == null - ? View.GONE : View.INVISIBLE); - mPositiveButton.setVisibility( - mPositiveButtonListener == null ? View.GONE : View.VISIBLE); - mNegativeButton.setVisibility( - mNegativeButtonListener == null ? View.GONE : View.VISIBLE); - mButtonPanel.setVisibility( - mPositiveButtonListener == null && mNegativeButtonListener == null - ? View.GONE : View.VISIBLE); - } - - /** - * Convenience method for <code>setButton(DialogInterface.BUTTON_POSITIVE, listener)</code>. - * - * @param listener the listener for the positive button. - */ - public void setPositiveButton(DialogInterface.OnClickListener listener) { - setButton(DialogInterface.BUTTON_POSITIVE, listener); - } - - /** - * Convenience method for <code>setButton(DialogInterface.BUTTON_NEGATIVE, listener)</code>. - * - * @param listener the listener for the positive button. - */ - public void setNegativeButton(DialogInterface.OnClickListener listener) { - setButton(DialogInterface.BUTTON_NEGATIVE, listener); - } -} diff --git a/packages/PackageInstaller/src/android/support/wearable/view/CircledImageView.java b/packages/PackageInstaller/src/android/support/wearable/view/CircledImageView.java deleted file mode 100644 index 0ae344663bf2..000000000000 --- a/packages/PackageInstaller/src/android/support/wearable/view/CircledImageView.java +++ /dev/null @@ -1,603 +0,0 @@ -/* - * Copyright (C) 2015 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 androidx.wear.ble.view; - -import android.animation.ArgbEvaluator; -import android.animation.ValueAnimator; -import android.animation.ValueAnimator.AnimatorUpdateListener; -import android.annotation.TargetApi; -import android.content.Context; -import android.content.res.ColorStateList; -import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Paint.Style; -import android.graphics.RadialGradient; -import android.graphics.Rect; -import android.graphics.RectF; -import android.graphics.Shader; -import android.graphics.drawable.Drawable; -import android.os.Build; -import android.util.AttributeSet; -import android.view.View; - -import java.util.Objects; -import com.android.packageinstaller.R; - -import com.android.packageinstaller.R; - -/** - * An image view surrounded by a circle. - */ -@TargetApi(Build.VERSION_CODES.LOLLIPOP) -public class CircledImageView extends View { - - private static final ArgbEvaluator ARGB_EVALUATOR = new ArgbEvaluator(); - - private Drawable mDrawable; - - private final RectF mOval; - private final Paint mPaint; - - private ColorStateList mCircleColor; - - private float mCircleRadius; - private float mCircleRadiusPercent; - - private float mCircleRadiusPressed; - private float mCircleRadiusPressedPercent; - - private float mRadiusInset; - - private int mCircleBorderColor; - - private float mCircleBorderWidth; - private float mProgress = 1f; - private final float mShadowWidth; - - private float mShadowVisibility; - private boolean mCircleHidden = false; - - private float mInitialCircleRadius; - - private boolean mPressed = false; - - private boolean mProgressIndeterminate; - private ProgressDrawable mIndeterminateDrawable; - private Rect mIndeterminateBounds = new Rect(); - private long mColorChangeAnimationDurationMs = 0; - - private float mImageCirclePercentage = 1f; - private float mImageHorizontalOffcenterPercentage = 0f; - private Integer mImageTint; - - private final Drawable.Callback mDrawableCallback = new Drawable.Callback() { - @Override - public void invalidateDrawable(Drawable drawable) { - invalidate(); - } - - @Override - public void scheduleDrawable(Drawable drawable, Runnable runnable, long l) { - // Not needed. - } - - @Override - public void unscheduleDrawable(Drawable drawable, Runnable runnable) { - // Not needed. - } - }; - - private int mCurrentColor; - - private final AnimatorUpdateListener mAnimationListener = new AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - int color = (int) animation.getAnimatedValue(); - if (color != CircledImageView.this.mCurrentColor) { - CircledImageView.this.mCurrentColor = color; - CircledImageView.this.invalidate(); - } - } - }; - - private ValueAnimator mColorAnimator; - - public CircledImageView(Context context) { - this(context, null); - } - - public CircledImageView(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public CircledImageView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - - TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CircledImageView); - mDrawable = a.getDrawable(R.styleable.CircledImageView_android_src); - - mCircleColor = a.getColorStateList(R.styleable.CircledImageView_circle_color); - if (mCircleColor == null) { - mCircleColor = ColorStateList.valueOf(android.R.color.darker_gray); - } - - mCircleRadius = a.getDimension( - R.styleable.CircledImageView_circle_radius, 0); - mInitialCircleRadius = mCircleRadius; - mCircleRadiusPressed = a.getDimension( - R.styleable.CircledImageView_circle_radius_pressed, mCircleRadius); - mCircleBorderColor = a.getColor( - R.styleable.CircledImageView_circle_border_color, Color.BLACK); - mCircleBorderWidth = a.getDimension(R.styleable.CircledImageView_circle_border_width, 0); - - if (mCircleBorderWidth > 0) { - mRadiusInset += mCircleBorderWidth; - } - - float circlePadding = a.getDimension(R.styleable.CircledImageView_circle_padding, 0); - if (circlePadding > 0) { - mRadiusInset += circlePadding; - } - mShadowWidth = a.getDimension(R.styleable.CircledImageView_shadow_width, 0); - - mImageCirclePercentage = a.getFloat( - R.styleable.CircledImageView_image_circle_percentage, 0f); - - mImageHorizontalOffcenterPercentage = a.getFloat( - R.styleable.CircledImageView_image_horizontal_offcenter_percentage, 0f); - - if (a.hasValue(R.styleable.CircledImageView_image_tint)) { - mImageTint = a.getColor(R.styleable.CircledImageView_image_tint, 0); - } - - mCircleRadiusPercent = a.getFraction(R.styleable.CircledImageView_circle_radius_percent, - 1, 1, 0f); - - mCircleRadiusPressedPercent = a.getFraction( - R.styleable.CircledImageView_circle_radius_pressed_percent, 1, 1, - mCircleRadiusPercent); - - a.recycle(); - - mOval = new RectF(); - mPaint = new Paint(); - mPaint.setAntiAlias(true); - - mIndeterminateDrawable = new ProgressDrawable(); - // {@link #mDrawableCallback} must be retained as a member, as Drawable callback - // is held by weak reference, we must retain it for it to continue to be called. - mIndeterminateDrawable.setCallback(mDrawableCallback); - - setWillNotDraw(false); - - setColorForCurrentState(); - } - - public void setCircleHidden(boolean circleHidden) { - if (circleHidden != mCircleHidden) { - mCircleHidden = circleHidden; - invalidate(); - } - } - - - @Override - protected boolean onSetAlpha(int alpha) { - return true; - } - - @Override - protected void onDraw(Canvas canvas) { - int paddingLeft = getPaddingLeft(); - int paddingTop = getPaddingTop(); - - - float circleRadius = mPressed ? getCircleRadiusPressed() : getCircleRadius(); - if (mShadowWidth > 0 && mShadowVisibility > 0) { - // First let's find the center of the view. - mOval.set(paddingLeft, paddingTop, getWidth() - getPaddingRight(), - getHeight() - getPaddingBottom()); - // Having the center, lets make the shadow start beyond the circled and possibly the - // border. - final float radius = circleRadius + mCircleBorderWidth + - mShadowWidth * mShadowVisibility; - mPaint.setColor(Color.BLACK); - mPaint.setAlpha(Math.round(mPaint.getAlpha() * getAlpha())); - mPaint.setStyle(Style.FILL); - // TODO: precalc and pre-allocate this - mPaint.setShader(new RadialGradient(mOval.centerX(), mOval.centerY(), radius, - new int[]{Color.BLACK, Color.TRANSPARENT}, new float[]{0.6f, 1f}, - Shader.TileMode.MIRROR)); - canvas.drawCircle(mOval.centerX(), mOval.centerY(), radius, mPaint); - mPaint.setShader(null); - } - if (mCircleBorderWidth > 0) { - // First let's find the center of the view. - mOval.set(paddingLeft, paddingTop, getWidth() - getPaddingRight(), - getHeight() - getPaddingBottom()); - // Having the center, lets make the border meet the circle. - mOval.set(mOval.centerX() - circleRadius, mOval.centerY() - circleRadius, - mOval.centerX() + circleRadius, mOval.centerY() + circleRadius); - mPaint.setColor(mCircleBorderColor); - // {@link #Paint.setAlpha} is a helper method that just sets the alpha portion of the - // color. {@link #Paint.setPaint} will clear any previously set alpha value. - mPaint.setAlpha(Math.round(mPaint.getAlpha() * getAlpha())); - mPaint.setStyle(Style.STROKE); - mPaint.setStrokeWidth(mCircleBorderWidth); - - if (mProgressIndeterminate) { - mOval.roundOut(mIndeterminateBounds); - mIndeterminateDrawable.setBounds(mIndeterminateBounds); - mIndeterminateDrawable.setRingColor(mCircleBorderColor); - mIndeterminateDrawable.setRingWidth(mCircleBorderWidth); - mIndeterminateDrawable.draw(canvas); - } else { - canvas.drawArc(mOval, -90, 360 * mProgress, false, mPaint); - } - } - if (!mCircleHidden) { - mOval.set(paddingLeft, paddingTop, getWidth() - getPaddingRight(), - getHeight() - getPaddingBottom()); - // {@link #Paint.setAlpha} is a helper method that just sets the alpha portion of the - // color. {@link #Paint.setPaint} will clear any previously set alpha value. - mPaint.setColor(mCurrentColor); - mPaint.setAlpha(Math.round(mPaint.getAlpha() * getAlpha())); - - mPaint.setStyle(Style.FILL); - float centerX = mOval.centerX(); - float centerY = mOval.centerY(); - - canvas.drawCircle(centerX, centerY, circleRadius, mPaint); - } - - if (mDrawable != null) { - mDrawable.setAlpha(Math.round(getAlpha() * 255)); - - if (mImageTint != null) { - mDrawable.setTint(mImageTint); - } - mDrawable.draw(canvas); - } - - super.onDraw(canvas); - } - - private void setColorForCurrentState() { - int newColor = mCircleColor.getColorForState(getDrawableState(), - mCircleColor.getDefaultColor()); - if (mColorChangeAnimationDurationMs > 0) { - if (mColorAnimator != null) { - mColorAnimator.cancel(); - } else { - mColorAnimator = new ValueAnimator(); - } - mColorAnimator.setIntValues(new int[] { - mCurrentColor, newColor }); - mColorAnimator.setEvaluator(ARGB_EVALUATOR); - mColorAnimator.setDuration(mColorChangeAnimationDurationMs); - mColorAnimator.addUpdateListener(this.mAnimationListener); - mColorAnimator.start(); - } else { - if (newColor != mCurrentColor) { - mCurrentColor = newColor; - invalidate(); - } - } - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - - final float radius = getCircleRadius() + mCircleBorderWidth + - mShadowWidth * mShadowVisibility; - float desiredWidth = radius * 2; - float desiredHeight = radius * 2; - - int widthMode = MeasureSpec.getMode(widthMeasureSpec); - int widthSize = MeasureSpec.getSize(widthMeasureSpec); - int heightMode = MeasureSpec.getMode(heightMeasureSpec); - int heightSize = MeasureSpec.getSize(heightMeasureSpec); - - int width; - int height; - - if (widthMode == MeasureSpec.EXACTLY) { - width = widthSize; - } else if (widthMode == MeasureSpec.AT_MOST) { - width = (int) Math.min(desiredWidth, widthSize); - } else { - width = (int) desiredWidth; - } - - if (heightMode == MeasureSpec.EXACTLY) { - height = heightSize; - } else if (heightMode == MeasureSpec.AT_MOST) { - height = (int) Math.min(desiredHeight, heightSize); - } else { - height = (int) desiredHeight; - } - - super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - if (mDrawable != null) { - // Retrieve the sizes of the drawable and the view. - final int nativeDrawableWidth = mDrawable.getIntrinsicWidth(); - final int nativeDrawableHeight = mDrawable.getIntrinsicHeight(); - final int viewWidth = getMeasuredWidth(); - final int viewHeight = getMeasuredHeight(); - final float imageCirclePercentage = mImageCirclePercentage > 0 - ? mImageCirclePercentage : 1; - - final float scaleFactor = Math.min(1f, - Math.min( - (float) nativeDrawableWidth != 0 - ? imageCirclePercentage * viewWidth / nativeDrawableWidth : 1, - (float) nativeDrawableHeight != 0 - ? imageCirclePercentage - * viewHeight / nativeDrawableHeight : 1)); - - // Scale the drawable down to fit the view, if needed. - final int drawableWidth = Math.round(scaleFactor * nativeDrawableWidth); - final int drawableHeight = Math.round(scaleFactor * nativeDrawableHeight); - - // Center the drawable within the view. - final int drawableLeft = (viewWidth - drawableWidth) / 2 - + Math.round(mImageHorizontalOffcenterPercentage * drawableWidth); - final int drawableTop = (viewHeight - drawableHeight) / 2; - - mDrawable.setBounds(drawableLeft, drawableTop, drawableLeft + drawableWidth, - drawableTop + drawableHeight); - } - - super.onLayout(changed, left, top, right, bottom); - } - - public void setImageDrawable(Drawable drawable) { - if (drawable != mDrawable) { - final Drawable existingDrawable = mDrawable; - mDrawable = drawable; - - final boolean skipLayout = drawable != null - && existingDrawable != null - && existingDrawable.getIntrinsicHeight() == drawable.getIntrinsicHeight() - && existingDrawable.getIntrinsicWidth() == drawable.getIntrinsicWidth(); - - if (skipLayout) { - mDrawable.setBounds(existingDrawable.getBounds()); - } else { - requestLayout(); - } - - invalidate(); - } - } - - public void setImageResource(int resId) { - setImageDrawable(resId == 0 ? null : getContext().getDrawable(resId)); - } - - public void setImageCirclePercentage(float percentage) { - float clamped = Math.max(0, Math.min(1, percentage)); - if (clamped != mImageCirclePercentage) { - mImageCirclePercentage = clamped; - invalidate(); - } - } - - public void setImageHorizontalOffcenterPercentage(float percentage) { - if (percentage != mImageHorizontalOffcenterPercentage) { - mImageHorizontalOffcenterPercentage = percentage; - invalidate(); - } - } - - public void setImageTint(int tint) { - if (tint != mImageTint) { - mImageTint = tint; - invalidate(); - } - } - - public float getCircleRadius() { - float radius = mCircleRadius; - if (mCircleRadius <= 0 && mCircleRadiusPercent > 0) { - radius = Math.max(getMeasuredHeight(), getMeasuredWidth()) * mCircleRadiusPercent; - } - - return radius - mRadiusInset; - } - - public float getCircleRadiusPercent() { - return mCircleRadiusPercent; - } - - public float getCircleRadiusPressed() { - float radius = mCircleRadiusPressed; - - if (mCircleRadiusPressed <= 0 && mCircleRadiusPressedPercent > 0) { - radius = Math.max(getMeasuredHeight(), getMeasuredWidth()) - * mCircleRadiusPressedPercent; - } - - return radius - mRadiusInset; - } - - public float getCircleRadiusPressedPercent() { - return mCircleRadiusPressedPercent; - } - - public void setCircleRadius(float circleRadius) { - if (circleRadius != mCircleRadius) { - mCircleRadius = circleRadius; - invalidate(); - } - } - - /** - * Sets the radius of the circle to be a percentage of the largest dimension of the view. - * @param circleRadiusPercent A {@code float} from 0 to 1 representing the radius percentage. - */ - public void setCircleRadiusPercent(float circleRadiusPercent) { - if (circleRadiusPercent != mCircleRadiusPercent) { - mCircleRadiusPercent = circleRadiusPercent; - invalidate(); - } - } - - public void setCircleRadiusPressed(float circleRadiusPressed) { - if (circleRadiusPressed != mCircleRadiusPressed) { - mCircleRadiusPressed = circleRadiusPressed; - invalidate(); - } - } - - /** - * Sets the radius of the circle to be a percentage of the largest dimension of the view when - * pressed. - * @param circleRadiusPressedPercent A {@code float} from 0 to 1 representing the radius - * percentage. - */ - public void setCircleRadiusPressedPercent(float circleRadiusPressedPercent) { - if (circleRadiusPressedPercent != mCircleRadiusPressedPercent) { - mCircleRadiusPressedPercent = circleRadiusPressedPercent; - invalidate(); - } - } - - @Override - protected void drawableStateChanged() { - super.drawableStateChanged(); - setColorForCurrentState(); - } - - public void setCircleColor(int circleColor) { - setCircleColorStateList(ColorStateList.valueOf(circleColor)); - } - - public void setCircleColorStateList(ColorStateList circleColor) { - if (!Objects.equals(circleColor, mCircleColor)) { - mCircleColor = circleColor; - setColorForCurrentState(); - invalidate(); - } - } - - public ColorStateList getCircleColorStateList() { - return mCircleColor; - } - - public int getDefaultCircleColor() { - return mCircleColor.getDefaultColor(); - } - - /** - * Show the circle border as an indeterminate progress spinner. - * The views circle border width and color must be set for this to have an effect. - * - * @param show true if the progress spinner is shown, false to hide it. - */ - public void showIndeterminateProgress(boolean show) { - mProgressIndeterminate = show; - if (show) { - mIndeterminateDrawable.startAnimation(); - } else { - mIndeterminateDrawable.stopAnimation(); - } - } - - @Override - protected void onVisibilityChanged(View changedView, int visibility) { - super.onVisibilityChanged(changedView, visibility); - if (visibility != View.VISIBLE) { - showIndeterminateProgress(false); - } else if (mProgressIndeterminate) { - showIndeterminateProgress(true); - } - } - - public void setProgress(float progress) { - if (progress != mProgress) { - mProgress = progress; - invalidate(); - } - } - - /** - * Set how much of the shadow should be shown. - * @param shadowVisibility Value between 0 and 1. - */ - public void setShadowVisibility(float shadowVisibility) { - if (shadowVisibility != mShadowVisibility) { - mShadowVisibility = shadowVisibility; - invalidate(); - } - } - - public float getInitialCircleRadius() { - return mInitialCircleRadius; - } - - public void setCircleBorderColor(int circleBorderColor) { - mCircleBorderColor = circleBorderColor; - } - - /** - * Set the border around the circle. - * @param circleBorderWidth Width of the border around the circle. - */ - public void setCircleBorderWidth(float circleBorderWidth) { - if (circleBorderWidth != mCircleBorderWidth) { - mCircleBorderWidth = circleBorderWidth; - invalidate(); - } - } - - @Override - public void setPressed(boolean pressed) { - super.setPressed(pressed); - if (pressed != mPressed) { - mPressed = pressed; - invalidate(); - } - } - - public Drawable getImageDrawable() { - return mDrawable; - } - - /** - * @return the milliseconds duration of the transition animation when the color changes. - */ - public long getColorChangeAnimationDuration() { - return mColorChangeAnimationDurationMs; - } - - /** - * @param mColorChangeAnimationDurationMs the milliseconds duration of the color change - * animation. The color change animation will run if the color changes with {@link #setCircleColor} - * or as a result of the active state changing. - */ - public void setColorChangeAnimationDuration(long mColorChangeAnimationDurationMs) { - this.mColorChangeAnimationDurationMs = mColorChangeAnimationDurationMs; - } -} diff --git a/packages/PackageInstaller/src/android/support/wearable/view/Gusterpolator.java b/packages/PackageInstaller/src/android/support/wearable/view/Gusterpolator.java deleted file mode 100644 index 6b17100fe9a8..000000000000 --- a/packages/PackageInstaller/src/android/support/wearable/view/Gusterpolator.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2015 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 androidx.wear.ble.view; - -import android.animation.TimeInterpolator; -import android.annotation.TargetApi; -import android.os.Build; - -/** - * Interpolator that uses a Bezier derived S shaped curve. - * @hide - */ -@TargetApi(Build.VERSION_CODES.KITKAT_WATCH) -class Gusterpolator implements TimeInterpolator { - - /** An instance of {@link androidx.wear.ble.view.Gusterpolator}. */ - public static final Gusterpolator INSTANCE = new Gusterpolator(); - - /** - * To avoid users of this class creating multiple copies needlessly, the constructor is - * private. - */ - private Gusterpolator() {} - - /** - * Lookup table values. - * Generated using a Bezier curve from (0,0) to (1,1) with control points: - * P0 (0,0) - * P1 (0.4, 0) - * P2 (0.2, 1.0) - * P3 (1.0, 1.0) - * - * Values sampled with x at regular intervals between 0 and 1. - */ - private static final float[] VALUES = new float[] { - 0.0f, 0.0002f, 0.0009f, 0.0019f, 0.0036f, 0.0059f, 0.0086f, 0.0119f, 0.0157f, 0.0209f, - 0.0257f, 0.0321f, 0.0392f, 0.0469f, 0.0566f, 0.0656f, 0.0768f, 0.0887f, 0.1033f, 0.1186f, - 0.1349f, 0.1519f, 0.1696f, 0.1928f, 0.2121f, 0.237f, 0.2627f, 0.2892f, 0.3109f, 0.3386f, - 0.3667f, 0.3952f, 0.4241f, 0.4474f, 0.4766f, 0.5f, 0.5234f, 0.5468f, 0.5701f, 0.5933f, - 0.6134f, 0.6333f, 0.6531f, 0.6698f, 0.6891f, 0.7054f, 0.7214f, 0.7346f, 0.7502f, 0.763f, - 0.7756f, 0.7879f, 0.8f, 0.8107f, 0.8212f, 0.8326f, 0.8415f, 0.8503f, 0.8588f, 0.8672f, - 0.8754f, 0.8833f, 0.8911f, 0.8977f, 0.9041f, 0.9113f, 0.9165f, 0.9232f, 0.9281f, 0.9328f, - 0.9382f, 0.9434f, 0.9476f, 0.9518f, 0.9557f, 0.9596f, 0.9632f, 0.9662f, 0.9695f, 0.9722f, - 0.9753f, 0.9777f, 0.9805f, 0.9826f, 0.9847f, 0.9866f, 0.9884f, 0.9901f, 0.9917f, 0.9931f, - 0.9944f, 0.9955f, 0.9964f, 0.9973f, 0.9981f, 0.9986f, 0.9992f, 0.9995f, 0.9998f, 1.0f, 1.0f - }; - - private static final float STEP_SIZE = 1.0f / (VALUES.length - 1); - - @Override - public float getInterpolation(float input) { - if (input >= 1.0f) { - return 1.0f; - } - - if (input <= 0f) { - return 0f; - } - - int position = Math.min( - (int)(input * (VALUES.length - 1)), - VALUES.length - 2); - - float quantized = position * STEP_SIZE; - float difference = input - quantized; - float weight = difference / STEP_SIZE; - - return VALUES[position] + weight * (VALUES[position + 1] - VALUES[position]); - } -} diff --git a/packages/PackageInstaller/src/android/support/wearable/view/ProgressDrawable.java b/packages/PackageInstaller/src/android/support/wearable/view/ProgressDrawable.java deleted file mode 100644 index 51ec8f07f103..000000000000 --- a/packages/PackageInstaller/src/android/support/wearable/view/ProgressDrawable.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2015 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 androidx.wear.ble.view; - -import android.animation.ObjectAnimator; -import android.animation.TimeInterpolator; -import android.animation.ValueAnimator; -import android.annotation.TargetApi; -import android.graphics.Canvas; -import android.graphics.ColorFilter; -import android.graphics.Paint; -import android.graphics.PixelFormat; -import android.graphics.RectF; -import android.graphics.drawable.Drawable; -import android.os.Build; -import android.util.Property; -import android.view.animation.LinearInterpolator; - -/** - * Drawable for showing an indeterminate progress indicator. - * - * TODO: When Material progress drawable is available in the support library stop using this. - * - * @hide - */ -@TargetApi(Build.VERSION_CODES.KITKAT_WATCH) -class ProgressDrawable extends Drawable { - - private static Property<ProgressDrawable, Integer> LEVEL = - new Property<ProgressDrawable, Integer>(Integer.class, "level") { - @Override - public Integer get(ProgressDrawable drawable) { - return drawable.getLevel(); - } - - @Override - public void set(ProgressDrawable drawable, Integer value) { - drawable.setLevel(value); - drawable.invalidateSelf(); - } - }; - /** Max level for a level drawable, as specified in developer docs for {@link Drawable}. */ - private static final int MAX_LEVEL = 10000; - - /** How many different sections are there, five gives us the material style star. **/ - private static final int NUMBER_OF_SEGMENTS = 5; - - private static final int LEVELS_PER_SEGMENT = MAX_LEVEL / NUMBER_OF_SEGMENTS; - private static final float STARTING_ANGLE = -90f; - private static final long ANIMATION_DURATION = 6000; - private static final int FULL_CIRCLE = 360; - private static final int MAX_SWEEP = 306; - private static final int CORRECTION_ANGLE = FULL_CIRCLE - MAX_SWEEP; - /** How far through each cycle does the bar stop growing and start shrinking, half way. **/ - private static final float GROW_SHRINK_RATIO = 0.5f; - // TODO: replace this with BakedBezierInterpolator when its available in support library. - private static final TimeInterpolator mInterpolator = Gusterpolator.INSTANCE; - - private final RectF mInnerCircleBounds = new RectF(); - private final Paint mPaint = new Paint(); - private final ObjectAnimator mAnimator; - private float mCircleBorderWidth; - private int mCircleBorderColor; - - public ProgressDrawable() { - mPaint.setAntiAlias(true); - mPaint.setStyle(Paint.Style.STROKE); - mAnimator = ObjectAnimator.ofInt(this, LEVEL, 0, MAX_LEVEL); - mAnimator.setRepeatCount(ValueAnimator.INFINITE); - mAnimator.setRepeatMode(ValueAnimator.RESTART); - mAnimator.setDuration(ANIMATION_DURATION); - mAnimator.setInterpolator(new LinearInterpolator()); - } - - public void setRingColor(int color) { - mCircleBorderColor = color; - } - - public void setRingWidth(float width) { - mCircleBorderWidth = width; - } - - public void startAnimation() { - mAnimator.start(); - } - - public void stopAnimation() { - mAnimator.cancel(); - } - - @Override - public void draw(Canvas canvas) { - canvas.save(); - mInnerCircleBounds.set(getBounds()); - mInnerCircleBounds.inset(mCircleBorderWidth / 2.0f, mCircleBorderWidth / 2.0f); - mPaint.setStrokeWidth(mCircleBorderWidth); - mPaint.setColor(mCircleBorderColor); - - float sweepAngle = FULL_CIRCLE; - boolean growing = false; - float correctionAngle = 0; - int level = getLevel(); - - int currentSegment = level / LEVELS_PER_SEGMENT; - int offset = currentSegment * LEVELS_PER_SEGMENT; - float progress = (level - offset) / (float) LEVELS_PER_SEGMENT; - - growing = progress < GROW_SHRINK_RATIO; - correctionAngle = CORRECTION_ANGLE * progress; - - if (growing) { - sweepAngle = MAX_SWEEP * mInterpolator.getInterpolation( - lerpInv(0f, GROW_SHRINK_RATIO, progress)); - } else { - sweepAngle = MAX_SWEEP * (1.0f - mInterpolator.getInterpolation( - lerpInv(GROW_SHRINK_RATIO, 1.0f, progress))); - } - - sweepAngle = Math.max(1, sweepAngle); - - canvas.rotate( - level * (1.0f / MAX_LEVEL) * 2 * FULL_CIRCLE + STARTING_ANGLE + correctionAngle, - mInnerCircleBounds.centerX(), - mInnerCircleBounds.centerY()); - canvas.drawArc(mInnerCircleBounds, - growing ? 0 : MAX_SWEEP - sweepAngle, - sweepAngle, - false, - mPaint); - canvas.restore(); - } - - @Override - public void setAlpha(int i) { - // Not supported. - } - - @Override - public void setColorFilter(ColorFilter colorFilter) { - // Not supported. - } - - @Override - public int getOpacity() { - return PixelFormat.OPAQUE; - } - - @Override - protected boolean onLevelChange(int level) { - return true; // Changing the level of this drawable does change its appearance. - } - - /** - * Returns the interpolation scalar (s) that satisfies the equation: - * {@code value = }lerp(a, b, s) - * - * <p>If {@code a == b}, then this function will return 0. - */ - private static float lerpInv(float a, float b, float value) { - return a != b ? ((value - a) / (b - a)) : 0.0f; - } -} diff --git a/packages/PackageInstaller/src/android/support/wearable/view/SimpleAnimatorListener.java b/packages/PackageInstaller/src/android/support/wearable/view/SimpleAnimatorListener.java deleted file mode 100644 index c8fe58c43f4e..000000000000 --- a/packages/PackageInstaller/src/android/support/wearable/view/SimpleAnimatorListener.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2015 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 androidx.wear.ble.view; - -import android.animation.Animator; -import android.annotation.TargetApi; -import android.os.Build; - -/** - * Convenience class for listening for Animator events that implements the AnimatorListener - * interface and allows extending only methods that are necessary. - */ -@TargetApi(Build.VERSION_CODES.KITKAT_WATCH) -public class SimpleAnimatorListener implements Animator.AnimatorListener { - - private boolean mWasCanceled; - - @Override - public void onAnimationCancel(Animator animator) { - mWasCanceled = true; - } - - @Override - public void onAnimationEnd(Animator animator) { - if (!mWasCanceled) { - onAnimationComplete(animator); - } - } - - @Override - public void onAnimationRepeat(Animator animator) { - } - - @Override - public void onAnimationStart(Animator animator) { - mWasCanceled = false; - } - - /** - * Called when the animation finishes. Not called if the animation was canceled. - */ - public void onAnimationComplete(Animator animator) { - } - - /** - * Provides information if the animation was cancelled. - * @return True if animation was cancelled. - */ - public boolean wasCanceled() { - return mWasCanceled; - } - -} diff --git a/packages/PackageInstaller/src/android/support/wearable/view/WearableDialogHelper.java b/packages/PackageInstaller/src/android/support/wearable/view/WearableDialogHelper.java deleted file mode 100644 index 0151ed573b04..000000000000 --- a/packages/PackageInstaller/src/android/support/wearable/view/WearableDialogHelper.java +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (C) 2016 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 androidx.wear.ble.view; - -import android.app.AlertDialog; -import android.content.Context; -import android.content.DialogInterface; -import android.content.res.Resources; -import android.graphics.drawable.Drawable; -import androidx.annotation.DrawableRes; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.VisibleForTesting; -import android.util.Log; -import android.widget.Button; - -/** - * Helper to add icons to AlertDialog buttons.AlertDialog buttons. - */ -public class WearableDialogHelper { - private static final String TAG = "WearableDialogHelper"; - - private int mPositiveIconId; - private Drawable mPositiveIcon; - - private int mNeutralIconId; - private Drawable mNeutralIcon; - - private int mNegativeIconId; - private Drawable mNegativeIcon; - - @VisibleForTesting /* package */ Resources mResources; - @VisibleForTesting /* package */ Resources.Theme mTheme; - - /** - * Convenience constructor, equivalent to {@code new WearableDialogHelper(context.getResources(), - * context.getTheme())}. - */ - public WearableDialogHelper(@NonNull Context context) { - this(context.getResources(), context.getTheme()); - } - - /** - * @param resources the Resources used to obtain Drawables from resource IDs. - * @param theme the Theme used to properly obtain Drawables from resource IDs. - */ - public WearableDialogHelper(@NonNull Resources resources, @NonNull Resources.Theme theme) { - mResources = resources; - mTheme = theme; - } - - @Nullable - public Drawable getPositiveIcon() { - return resolveDrawable(mPositiveIcon, mPositiveIconId); - } - - @Nullable - public Drawable getNegativeIcon() { - return resolveDrawable(mNegativeIcon, mNegativeIconId); - } - - @Nullable - public Drawable getNeutralIcon() { - return resolveDrawable(mNeutralIcon, mNeutralIconId); - } - - @NonNull - public WearableDialogHelper setPositiveIcon(@DrawableRes int resId) { - mPositiveIconId = resId; - mPositiveIcon = null; - return this; - } - - @NonNull - public WearableDialogHelper setPositiveIcon(@Nullable Drawable icon) { - mPositiveIcon = icon; - mPositiveIconId = 0; - return this; - } - - @NonNull - public WearableDialogHelper setNegativeIcon(@DrawableRes int resId) { - mNegativeIconId = resId; - mNegativeIcon = null; - return this; - } - - @NonNull - public WearableDialogHelper setNegativeIcon(@Nullable Drawable icon) { - mNegativeIcon = icon; - mNegativeIconId = 0; - return this; - } - - @NonNull - public WearableDialogHelper setNeutralIcon(@DrawableRes int resId) { - mNeutralIconId = resId; - mNeutralIcon = null; - return this; - } - - @NonNull - public WearableDialogHelper setNeutralIcon(@Nullable Drawable icon) { - mNeutralIcon = icon; - mNeutralIconId = 0; - return this; - } - - /** - * Applies the button icons setup in the helper to the buttons in the dialog. - * - * <p>Note that this should be called after {@code AlertDialog.create()}, NOT {@code - * AlertDialog.Builder.create()}. Calling {@code AlertDialog.Builder.show()} would also accomplish - * the same thing. - * - * @param dialog the AlertDialog to style with the helper. - */ - public void apply(@NonNull AlertDialog dialog) { - applyButton(dialog.getButton(DialogInterface.BUTTON_POSITIVE), getPositiveIcon()); - applyButton(dialog.getButton(DialogInterface.BUTTON_NEGATIVE), getNegativeIcon()); - applyButton(dialog.getButton(DialogInterface.BUTTON_NEUTRAL), getNeutralIcon()); - } - - /** Applies the specified drawable to the button. */ - @VisibleForTesting - /* package */ void applyButton(@Nullable Button button, @Nullable Drawable drawable) { - if (button != null) { - button.setCompoundDrawablesRelativeWithIntrinsicBounds(drawable, null, null, null); - button.setAllCaps(false); - } else if (drawable != null) { - Log.w(TAG, "non-null drawable used with missing button, did you call AlertDialog.create()?"); - } - } - - /** Obtain a drawable between a drawable and a resource ID. */ - @VisibleForTesting - /* package */ Drawable resolveDrawable(@Nullable Drawable drawable, @DrawableRes int resId) { - return drawable == null && resId != 0 ? mResources.getDrawable(resId, mTheme) : drawable; - } - - /** Convenience builder to generate an AlertDialog with icons in buttons. */ - public static class DialogBuilder extends AlertDialog.Builder { - private final WearableDialogHelper mHelper; - - public DialogBuilder(Context context) { - super(context); - mHelper = new WearableDialogHelper(context.getResources(), context.getTheme()); - } - - public DialogBuilder(Context context, int themeResId) { - super(context, themeResId); - mHelper = new WearableDialogHelper(context.getResources(), context.getTheme()); - } - - public WearableDialogHelper getHelper() { - return mHelper; - } - - public DialogBuilder setPositiveIcon(@DrawableRes int iconId) { - mHelper.setPositiveIcon(iconId); - return this; - } - - public DialogBuilder setPositiveIcon(@Nullable Drawable icon) { - mHelper.setPositiveIcon(icon); - return this; - } - - public DialogBuilder setNegativeIcon(@DrawableRes int iconId) { - mHelper.setNegativeIcon(iconId); - return this; - } - - public DialogBuilder setNegativeIcon(@Nullable Drawable icon) { - mHelper.setNegativeIcon(icon); - return this; - } - - public DialogBuilder setNeutralIcon(@DrawableRes int iconId) { - mHelper.setNeutralIcon(iconId); - return this; - } - - public DialogBuilder setNeutralIcon(@Nullable Drawable icon) { - mHelper.setNeutralIcon(icon); - return this; - } - - @Override - public AlertDialog create() { - final AlertDialog dialog = super.create(); - dialog.create(); - mHelper.apply(dialog); - return dialog; - } - - @Override - public AlertDialog show() { - final AlertDialog dialog = this.create(); - dialog.show(); - return dialog; - } - } -} diff --git a/packages/PackageInstaller/src/android/support/wearable/view/WearableListView.java b/packages/PackageInstaller/src/android/support/wearable/view/WearableListView.java deleted file mode 100644 index 956ff9e9e631..000000000000 --- a/packages/PackageInstaller/src/android/support/wearable/view/WearableListView.java +++ /dev/null @@ -1,1387 +0,0 @@ -/* - * Copyright (C) 2015 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 androidx.wear.ble.view; - -import android.animation.Animator; -import android.animation.AnimatorSet; -import android.animation.ObjectAnimator; -import android.annotation.TargetApi; -import android.content.Context; -import android.graphics.PointF; -import android.os.Build; -import android.os.Handler; -import androidx.recyclerview.widget.LinearSmoothScroller; -import androidx.recyclerview.widget.RecyclerView; -import android.util.AttributeSet; -import android.util.DisplayMetrics; -import android.util.Log; -import android.util.Property; -import android.view.KeyEvent; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewConfiguration; -import android.view.ViewGroup; -import android.widget.Scroller; - -import java.util.ArrayList; -import java.util.List; - -/** - * An alternative version of ListView that is optimized for ease of use on small screen wearable - * devices. It displays a vertically scrollable list of items, and automatically snaps to the - * nearest item when the user stops scrolling. - * - * <p> - * For a quick start, you will need to implement a subclass of {@link .Adapter}, - * which will create and bind your views to the {@link .ViewHolder} objects. If you want to add - * more visual treatment to your views when they become the central items of the - * WearableListView, have them implement the {@link .OnCenterProximityListener} interface. - * </p> - */ -@TargetApi(Build.VERSION_CODES.KITKAT_WATCH) -public class WearableListView extends RecyclerView { - @SuppressWarnings("unused") - private static final String TAG = "WearableListView"; - - private static final long FLIP_ANIMATION_DURATION_MS = 150; - private static final long CENTERING_ANIMATION_DURATION_MS = 150; - - private static final float TOP_TAP_REGION_PERCENTAGE = .33f; - private static final float BOTTOM_TAP_REGION_PERCENTAGE = .33f; - - // Each item will occupy one third of the height. - private static final int THIRD = 3; - - private final int mMinFlingVelocity; - private final int mMaxFlingVelocity; - - private boolean mMaximizeSingleItem; - private boolean mCanClick = true; - // WristGesture navigation signals are delivered as KeyEvents. Allow developer to disable them - // for this specific View. It might be cleaner to simply have users re-implement onKeyDown(). - // TOOD: Finalize the disabling mechanism here. - private boolean mGestureNavigationEnabled = true; - private int mTapPositionX; - private int mTapPositionY; - private ClickListener mClickListener; - - private Animator mScrollAnimator; - // This is a little hacky due to the fact that animator provides incremental values instead of - // deltas and scrolling code requires deltas. We animate WearableListView directly and use this - // field to calculate deltas. Obviously this means that only one scrolling algorithm can run at - // a time, but I don't think it would be wise to have more than one running. - private int mLastScrollChange; - - private SetScrollVerticallyProperty mSetScrollVerticallyProperty = - new SetScrollVerticallyProperty(); - - private final List<OnScrollListener> mOnScrollListeners = new ArrayList<OnScrollListener>(); - - private final List<OnCentralPositionChangedListener> mOnCentralPositionChangedListeners = - new ArrayList<OnCentralPositionChangedListener>(); - - private OnOverScrollListener mOverScrollListener; - - private boolean mGreedyTouchMode; - - private float mStartX; - - private float mStartY; - - private float mStartFirstTop; - - private final int mTouchSlop; - - private boolean mPossibleVerticalSwipe; - - private int mInitialOffset = 0; - - private Scroller mScroller; - - // Top and bottom boundaries for tap checking. Need to recompute by calling computeTapRegions - // before referencing. - private final float[] mTapRegions = new float[2]; - - private boolean mGestureDirectionLocked; - private int mPreviousCentral = 0; - - // Temp variable for storing locations on screen. - private final int[] mLocation = new int[2]; - - // TODO: Consider clearing this when underlying data set changes. If the data set changes, you - // can't safely assume that this pressed view is in the same place as it was before and it will - // receive setPressed(false) unnecessarily. In theory it should be fine, but in practice we - // have places like this: mIconView.setCircleColor(pressed ? mPressedColor : mSelectedColor); - // This might set selected color on non selected item. Our logic should be: if you change - // underlying data set, all best are off and you need to preserve the state; we will clear - // this field. However, I am not willing to introduce this so late in C development. - private View mPressedView = null; - - private final Runnable mPressedRunnable = new Runnable() { - @Override - public void run() { - if (getChildCount() > 0) { - mPressedView = getChildAt(findCenterViewIndex()); - mPressedView.setPressed(true); - } else { - Log.w(TAG, "mPressedRunnable: the children were removed, skipping."); - } - } - }; - - private final Runnable mReleasedRunnable = new Runnable() { - @Override - public void run() { - releasePressedItem(); - } - }; - - private Runnable mNotifyChildrenPostLayoutRunnable = new Runnable() { - @Override - public void run() { - notifyChildrenAboutProximity(false); - } - }; - - private final AdapterDataObserver mObserver = new AdapterDataObserver() { - @Override - public void onChanged() { - WearableListView.this.addOnLayoutChangeListener(new OnLayoutChangeListener() { - @Override - public void onLayoutChange(View v, int left, int top, int right, int bottom, - int oldLeft, int oldTop, int oldRight, int oldBottom) { - WearableListView.this.removeOnLayoutChangeListener(this); - if (WearableListView.this.getChildCount() > 0) { - WearableListView.this.animateToCenter(); - } - } - }); - } - }; - - public WearableListView(Context context) { - this(context, null); - } - - public WearableListView(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public WearableListView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - setHasFixedSize(true); - setOverScrollMode(View.OVER_SCROLL_NEVER); - setLayoutManager(new LayoutManager()); - - final RecyclerView.OnScrollListener onScrollListener = new RecyclerView.OnScrollListener() { - @Override - public void onScrollStateChanged(RecyclerView recyclerView, int newState) { - if (newState == RecyclerView.SCROLL_STATE_IDLE && getChildCount() > 0) { - handleTouchUp(null, newState); - } - for (OnScrollListener listener : mOnScrollListeners) { - listener.onScrollStateChanged(newState); - } - } - - @Override - public void onScrolled(RecyclerView recyclerView, int dx, int dy) { - onScroll(dy); - } - }; - setOnScrollListener(onScrollListener); - - final ViewConfiguration vc = ViewConfiguration.get(context); - mTouchSlop = vc.getScaledTouchSlop(); - - mMinFlingVelocity = vc.getScaledMinimumFlingVelocity(); - mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity(); - } - - @Override - public void setAdapter(RecyclerView.Adapter adapter) { - RecyclerView.Adapter currentAdapter = getAdapter(); - if (currentAdapter != null) { - currentAdapter.unregisterAdapterDataObserver(mObserver); - } - - super.setAdapter(adapter); - - if (adapter != null) { - adapter.registerAdapterDataObserver(mObserver); - } - } - - /** - * @return the position of the center child's baseline; -1 if no center child exists or if - * the center child does not return a valid baseline. - */ - @Override - public int getBaseline() { - // No children implies there is no center child for which a baseline can be computed. - if (getChildCount() == 0) { - return super.getBaseline(); - } - - // Compute the baseline of the center child. - final int centerChildIndex = findCenterViewIndex(); - final int centerChildBaseline = getChildAt(centerChildIndex).getBaseline(); - - // If the center child has no baseline, neither does this list view. - if (centerChildBaseline == -1) { - return super.getBaseline(); - } - - return getCentralViewTop() + centerChildBaseline; - } - - /** - * @return true if the list is scrolled all the way to the top. - */ - public boolean isAtTop() { - if (getChildCount() == 0) { - return true; - } - - int centerChildIndex = findCenterViewIndex(); - View centerView = getChildAt(centerChildIndex); - return getChildAdapterPosition(centerView) == 0 && - getScrollState() == RecyclerView.SCROLL_STATE_IDLE; - } - - /** - * Clears the state of the layout manager that positions list items. - */ - public void resetLayoutManager() { - setLayoutManager(new LayoutManager()); - } - - /** - * Controls whether WearableListView should intercept all touch events and also prevent the - * parent from receiving them. - * @param greedy If true it will intercept all touch events. - */ - public void setGreedyTouchMode(boolean greedy) { - mGreedyTouchMode = greedy; - } - - /** - * By default the first element of the list is initially positioned in the center of the screen. - * This method allows the developer to specify a different offset, e.g. to hide the - * WearableListView before the user is allowed to use it. - * - * @param top How far the elements should be pushed down. - */ - public void setInitialOffset(int top) { - mInitialOffset = top; - } - - @Override - public boolean onInterceptTouchEvent(MotionEvent event) { - if (!isEnabled()) { - return false; - } - - if (mGreedyTouchMode && getChildCount() > 0) { - int action = event.getActionMasked(); - if (action == MotionEvent.ACTION_DOWN) { - mStartX = event.getX(); - mStartY = event.getY(); - mStartFirstTop = getChildCount() > 0 ? getChildAt(0).getTop() : 0; - mPossibleVerticalSwipe = true; - mGestureDirectionLocked = false; - } else if (action == MotionEvent.ACTION_MOVE && mPossibleVerticalSwipe) { - handlePossibleVerticalSwipe(event); - } - getParent().requestDisallowInterceptTouchEvent(mPossibleVerticalSwipe); - } - return super.onInterceptTouchEvent(event); - } - - private boolean handlePossibleVerticalSwipe(MotionEvent event) { - if (mGestureDirectionLocked) { - return mPossibleVerticalSwipe; - } - float deltaX = Math.abs(mStartX - event.getX()); - float deltaY = Math.abs(mStartY - event.getY()); - float distance = (deltaX * deltaX) + (deltaY * deltaY); - // Verify that the distance moved in the combined x/y direction is at - // least touch slop before determining the gesture direction. - if (distance > (mTouchSlop * mTouchSlop)) { - if (deltaX > deltaY) { - mPossibleVerticalSwipe = false; - } - mGestureDirectionLocked = true; - } - return mPossibleVerticalSwipe; - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (!isEnabled()) { - return false; - } - - // super.onTouchEvent can change the state of the scroll, keep a copy so that handleTouchUp - // can exit early if scrollState != IDLE when the touch event started. - int scrollState = getScrollState(); - boolean result = super.onTouchEvent(event); - if (getChildCount() > 0) { - int action = event.getActionMasked(); - if (action == MotionEvent.ACTION_DOWN) { - handleTouchDown(event); - } else if (action == MotionEvent.ACTION_UP) { - handleTouchUp(event, scrollState); - getParent().requestDisallowInterceptTouchEvent(false); - } else if (action == MotionEvent.ACTION_MOVE) { - if (Math.abs(mTapPositionX - (int) event.getX()) >= mTouchSlop || - Math.abs(mTapPositionY - (int) event.getY()) >= mTouchSlop) { - releasePressedItem(); - mCanClick = false; - } - result |= handlePossibleVerticalSwipe(event); - getParent().requestDisallowInterceptTouchEvent(mPossibleVerticalSwipe); - } else if (action == MotionEvent.ACTION_CANCEL) { - getParent().requestDisallowInterceptTouchEvent(false); - mCanClick = true; - } - } - return result; - } - - private void releasePressedItem() { - if (mPressedView != null) { - mPressedView.setPressed(false); - mPressedView = null; - } - Handler handler = getHandler(); - if (handler != null) { - handler.removeCallbacks(mPressedRunnable); - } - } - - private void onScroll(int dy) { - for (OnScrollListener listener : mOnScrollListeners) { - listener.onScroll(dy); - } - notifyChildrenAboutProximity(true); - } - - /** - * Adds a listener that will be called when the content of the list view is scrolled. - */ - public void addOnScrollListener(OnScrollListener listener) { - mOnScrollListeners.add(listener); - } - - /** - * Removes listener for scroll events. - */ - public void removeOnScrollListener(OnScrollListener listener) { - mOnScrollListeners.remove(listener); - } - - /** - * Adds a listener that will be called when the central item of the list changes. - */ - public void addOnCentralPositionChangedListener(OnCentralPositionChangedListener listener) { - mOnCentralPositionChangedListeners.add(listener); - } - - /** - * Removes a listener that would be called when the central item of the list changes. - */ - public void removeOnCentralPositionChangedListener(OnCentralPositionChangedListener listener) { - mOnCentralPositionChangedListeners.remove(listener); - } - - /** - * Determines if navigation of list with wrist gestures is enabled. - */ - public boolean isGestureNavigationEnabled() { - return mGestureNavigationEnabled; - } - - /** - * Sets whether navigation of list with wrist gestures is enabled. - */ - public void setEnableGestureNavigation(boolean enabled) { - mGestureNavigationEnabled = enabled; - } - - @Override /* KeyEvent.Callback */ - public boolean onKeyDown(int keyCode, KeyEvent event) { - // Respond to keycodes (at least originally generated and injected by wrist gestures). - if (mGestureNavigationEnabled) { - switch (keyCode) { - case KeyEvent.KEYCODE_NAVIGATE_PREVIOUS: - fling(0, -mMinFlingVelocity); - return true; - case KeyEvent.KEYCODE_NAVIGATE_NEXT: - fling(0, mMinFlingVelocity); - return true; - case KeyEvent.KEYCODE_NAVIGATE_IN: - return tapCenterView(); - case KeyEvent.KEYCODE_NAVIGATE_OUT: - // Returing false leaves the action to the container of this WearableListView - // (e.g. finishing the activity containing this WearableListView). - return false; - } - } - return super.onKeyDown(keyCode, event); - } - - /** - * Simulate tapping the child view at the center of this list. - */ - private boolean tapCenterView() { - if (!isEnabled() || getVisibility() != View.VISIBLE) { - return false; - } - int index = findCenterViewIndex(); - View view = getChildAt(index); - ViewHolder holder = getChildViewHolder(view); - if (mClickListener != null) { - mClickListener.onClick(holder); - return true; - } - return false; - } - - private boolean checkForTap(MotionEvent event) { - // No taps are accepted if this view is disabled. - if (!isEnabled()) { - return false; - } - - float rawY = event.getRawY(); - int index = findCenterViewIndex(); - View view = getChildAt(index); - ViewHolder holder = getChildViewHolder(view); - computeTapRegions(mTapRegions); - if (rawY > mTapRegions[0] && rawY < mTapRegions[1]) { - if (mClickListener != null) { - mClickListener.onClick(holder); - } - return true; - } - if (index > 0 && rawY <= mTapRegions[0]) { - animateToMiddle(index - 1, index); - return true; - } - if (index < getChildCount() - 1 && rawY >= mTapRegions[1]) { - animateToMiddle(index + 1, index); - return true; - } - if (index == 0 && rawY <= mTapRegions[0] && mClickListener != null) { - // Special case: if the top third of the screen is empty and the touch event happens - // there, we don't want to immediately disallow the parent from using it. We tell - // parent to disallow intercept only after we locked a gesture. Before that he - // might do something with the action. - mClickListener.onTopEmptyRegionClick(); - return true; - } - return false; - } - - private void animateToMiddle(int newCenterIndex, int oldCenterIndex) { - if (newCenterIndex == oldCenterIndex) { - throw new IllegalArgumentException( - "newCenterIndex must be different from oldCenterIndex"); - } - List<Animator> animators = new ArrayList<Animator>(); - View child = getChildAt(newCenterIndex); - int scrollToMiddle = getCentralViewTop() - child.getTop(); - startScrollAnimation(animators, scrollToMiddle, FLIP_ANIMATION_DURATION_MS); - } - - private void startScrollAnimation(List<Animator> animators, int scroll, long duration) { - startScrollAnimation(animators, scroll, duration, 0); - } - - private void startScrollAnimation(List<Animator> animators, int scroll, long duration, - long delay) { - startScrollAnimation(animators, scroll, duration, delay, null); - } - - private void startScrollAnimation( - int scroll, long duration, long delay, Animator.AnimatorListener listener) { - startScrollAnimation(null, scroll, duration, delay, listener); - } - - private void startScrollAnimation(List<Animator> animators, int scroll, long duration, - long delay, Animator.AnimatorListener listener) { - if (mScrollAnimator != null) { - mScrollAnimator.cancel(); - } - - mLastScrollChange = 0; - ObjectAnimator scrollAnimator = ObjectAnimator.ofInt(this, mSetScrollVerticallyProperty, - 0, -scroll); - - if (animators != null) { - animators.add(scrollAnimator); - AnimatorSet animatorSet = new AnimatorSet(); - animatorSet.playTogether(animators); - mScrollAnimator = animatorSet; - } else { - mScrollAnimator = scrollAnimator; - } - mScrollAnimator.setDuration(duration); - if (listener != null) { - mScrollAnimator.addListener(listener); - } - if (delay > 0) { - mScrollAnimator.setStartDelay(delay); - } - mScrollAnimator.start(); - } - - @Override - public boolean fling(int velocityX, int velocityY) { - if (getChildCount() == 0) { - return false; - } - // If we are flinging towards empty space (before first element or after last), we reuse - // original flinging mechanism. - final int index = findCenterViewIndex(); - final View child = getChildAt(index); - int currentPosition = getChildPosition(child); - if ((currentPosition == 0 && velocityY < 0) || - (currentPosition == getAdapter().getItemCount() - 1 && velocityY > 0)) { - return super.fling(velocityX, velocityY); - } - - if (Math.abs(velocityY) < mMinFlingVelocity) { - return false; - } - velocityY = Math.max(Math.min(velocityY, mMaxFlingVelocity), -mMaxFlingVelocity); - - if (mScroller == null) { - mScroller = new Scroller(getContext(), null, true); - } - mScroller.fling(0, 0, 0, velocityY, Integer.MIN_VALUE, Integer.MAX_VALUE, - Integer.MIN_VALUE, Integer.MAX_VALUE); - int finalY = mScroller.getFinalY(); - int delta = finalY / (getPaddingTop() + getAdjustedHeight() / 2); - if (delta == 0) { - // If the fling would not be enough to change position, we increase it to satisfy user's - // intent of switching current position. - delta = velocityY > 0 ? 1 : -1; - } - int finalPosition = Math.max( - 0, Math.min(getAdapter().getItemCount() - 1, currentPosition + delta)); - smoothScrollToPosition(finalPosition); - return true; - } - - public void smoothScrollToPosition(int position, RecyclerView.SmoothScroller smoothScroller) { - LayoutManager layoutManager = (LayoutManager) getLayoutManager(); - layoutManager.setCustomSmoothScroller(smoothScroller); - smoothScrollToPosition(position); - layoutManager.clearCustomSmoothScroller(); - } - - @Override - public ViewHolder getChildViewHolder(View child) { - return (ViewHolder) super.getChildViewHolder(child); - } - - /** - * Adds a listener that will be called when the user taps on the WearableListView or its items. - */ - public void setClickListener(ClickListener clickListener) { - mClickListener = clickListener; - } - - /** - * Adds a listener that will be called when the user drags the top element below its allowed - * bottom position. - * - * @hide - */ - public void setOverScrollListener(OnOverScrollListener listener) { - mOverScrollListener = listener; - } - - private int findCenterViewIndex() { - // TODO(gruszczy): This could be easily optimized, so that we stop looking when we the - // distance starts growing again, instead of finding the closest. It would safe half of - // the loop. - int count = getChildCount(); - int index = -1; - int closest = Integer.MAX_VALUE; - int centerY = getCenterYPos(this); - for (int i = 0; i < count; ++i) { - final View child = getChildAt(i); - int childCenterY = getTop() + getCenterYPos(child); - final int distance = Math.abs(centerY - childCenterY); - if (distance < closest) { - closest = distance; - index = i; - } - } - if (index == -1) { - throw new IllegalStateException("Can't find central view."); - } - return index; - } - - private static int getCenterYPos(View v) { - return v.getTop() + v.getPaddingTop() + getAdjustedHeight(v) / 2; - } - - private void handleTouchUp(MotionEvent event, int scrollState) { - if (mCanClick && event != null && checkForTap(event)) { - Handler handler = getHandler(); - if (handler != null) { - handler.postDelayed(mReleasedRunnable, ViewConfiguration.getTapTimeout()); - } - return; - } - - if (scrollState != RecyclerView.SCROLL_STATE_IDLE) { - // We are flinging, so let's not start animations just yet. Instead we will start them - // when the fling finishes. - return; - } - - if (isOverScrolling()) { - mOverScrollListener.onOverScroll(); - } else { - animateToCenter(); - } - } - - private boolean isOverScrolling() { - return getChildCount() > 0 - // If first view top was below the central top, it means it was never centered. - // Don't allow overscroll, otherwise a simple touch (instead of a drag) will be - // enough to trigger overscroll. - && mStartFirstTop <= getCentralViewTop() - && getChildAt(0).getTop() >= getTopViewMaxTop() - && mOverScrollListener != null; - } - - private int getTopViewMaxTop() { - return getHeight() / 2; - } - - private int getItemHeight() { - // Round up so that the screen is fully occupied by 3 items. - return getAdjustedHeight() / THIRD + 1; - } - - /** - * Returns top of the central {@code View} in the list when such view is fully centered. - * - * This is a more or a less a static value that you can use to align other views with the - * central one. - */ - public int getCentralViewTop() { - return getPaddingTop() + getItemHeight(); - } - - /** - * Automatically starts an animation that snaps the list to center on the element closest to the - * middle. - */ - public void animateToCenter() { - final int index = findCenterViewIndex(); - final View child = getChildAt(index); - final int scrollToMiddle = getCentralViewTop() - child.getTop(); - startScrollAnimation(scrollToMiddle, CENTERING_ANIMATION_DURATION_MS, 0, - new SimpleAnimatorListener() { - @Override - public void onAnimationEnd(Animator animator) { - if (!wasCanceled()) { - mCanClick = true; - } - } - }); - } - - /** - * Animate the list so that the first view is back to its initial position. - * @param endAction Action to execute when the animation is done. - * @hide - */ - public void animateToInitialPosition(final Runnable endAction) { - final View child = getChildAt(0); - final int scrollToMiddle = getCentralViewTop() + mInitialOffset - child.getTop(); - startScrollAnimation(scrollToMiddle, CENTERING_ANIMATION_DURATION_MS, 0, - new SimpleAnimatorListener() { - @Override - public void onAnimationEnd(Animator animator) { - if (endAction != null) { - endAction.run(); - } - } - }); - } - - private void handleTouchDown(MotionEvent event) { - if (mCanClick) { - mTapPositionX = (int) event.getX(); - mTapPositionY = (int) event.getY(); - float rawY = event.getRawY(); - computeTapRegions(mTapRegions); - if (rawY > mTapRegions[0] && rawY < mTapRegions[1]) { - View view = getChildAt(findCenterViewIndex()); - if (view instanceof OnCenterProximityListener) { - Handler handler = getHandler(); - if (handler != null) { - handler.removeCallbacks(mReleasedRunnable); - handler.postDelayed(mPressedRunnable, ViewConfiguration.getTapTimeout()); - } - } - } - } - } - - private void setScrollVertically(int scroll) { - scrollBy(0, scroll - mLastScrollChange); - mLastScrollChange = scroll; - } - - private int getAdjustedHeight() { - return getAdjustedHeight(this); - } - - private static int getAdjustedHeight(View v) { - return v.getHeight() - v.getPaddingBottom() - v.getPaddingTop(); - } - - private void computeTapRegions(float[] tapRegions) { - mLocation[0] = mLocation[1] = 0; - getLocationOnScreen(mLocation); - int mScreenTop = mLocation[1]; - int height = getHeight(); - tapRegions[0] = mScreenTop + height * TOP_TAP_REGION_PERCENTAGE; - tapRegions[1] = mScreenTop + height * (1 - BOTTOM_TAP_REGION_PERCENTAGE); - } - - /** - * Determines if, when there is only one item in the WearableListView, that the single item - * is laid out so that it's height fills the entire WearableListView. - */ - public boolean getMaximizeSingleItem() { - return mMaximizeSingleItem; - } - - /** - * When set to true, if there is only one item in the WearableListView, it will fill the entire - * WearableListView. When set to false, the default behavior will be used and the single item - * will fill only a third of the screen. - */ - public void setMaximizeSingleItem(boolean maximizeSingleItem) { - mMaximizeSingleItem = maximizeSingleItem; - } - - private void notifyChildrenAboutProximity(boolean animate) { - LayoutManager layoutManager = (LayoutManager) getLayoutManager(); - int count = layoutManager.getChildCount(); - - if (count == 0) { - return; - } - - int index = layoutManager.findCenterViewIndex(); - for (int i = 0; i < count; ++i) { - final View view = layoutManager.getChildAt(i); - ViewHolder holder = getChildViewHolder(view); - holder.onCenterProximity(i == index, animate); - } - final int position = getChildViewHolder(getChildAt(index)).getPosition(); - if (position != mPreviousCentral) { - for (OnScrollListener listener : mOnScrollListeners) { - listener.onCentralPositionChanged(position); - } - for (OnCentralPositionChangedListener listener : - mOnCentralPositionChangedListeners) { - listener.onCentralPositionChanged(position); - } - mPreviousCentral = position; - } - } - - // TODO: Move this to a separate class, so it can't directly interact with the WearableListView. - private class LayoutManager extends RecyclerView.LayoutManager { - private int mFirstPosition; - - private boolean mPushFirstHigher; - - private int mAbsoluteScroll; - - private boolean mUseOldViewTop = true; - - private boolean mWasZoomedIn = false; - - private RecyclerView.SmoothScroller mSmoothScroller; - - private RecyclerView.SmoothScroller mDefaultSmoothScroller; - - // We need to have another copy of the same method, because this one uses - // LayoutManager.getChildCount/getChildAt instead of View.getChildCount/getChildAt and - // they return different values. - private int findCenterViewIndex() { - // TODO(gruszczy): This could be easily optimized, so that we stop looking when we the - // distance starts growing again, instead of finding the closest. It would safe half of - // the loop. - int count = getChildCount(); - int index = -1; - int closest = Integer.MAX_VALUE; - int centerY = getCenterYPos(WearableListView.this); - for (int i = 0; i < count; ++i) { - final View child = getLayoutManager().getChildAt(i); - int childCenterY = getTop() + getCenterYPos(child); - final int distance = Math.abs(centerY - childCenterY); - if (distance < closest) { - closest = distance; - index = i; - } - } - if (index == -1) { - throw new IllegalStateException("Can't find central view."); - } - return index; - } - - @Override - public void onLayoutChildren(RecyclerView.Recycler recycler, State state) { - final int parentBottom = getHeight() - getPaddingBottom(); - // By default we assume this is the first run and the first element will be centered - // with optional initial offset. - int oldTop = getCentralViewTop() + mInitialOffset; - // Here we handle any other situation where we relayout or we want to achieve a - // specific layout of children. - if (mUseOldViewTop && getChildCount() > 0) { - // We are performing a relayout after we already had some children, because e.g. the - // contents of an adapter has changed. First we want to check, if the central item - // from before the layout is still here, because we want to preserve it. - int index = findCenterViewIndex(); - int position = getPosition(getChildAt(index)); - if (position == NO_POSITION) { - // Central item was removed. Let's find the first surviving item and use it - // as an anchor. - for (int i = 0, N = getChildCount(); index + i < N || index - i >= 0; ++i) { - View child = getChildAt(index + i); - if (child != null) { - position = getPosition(child); - if (position != NO_POSITION) { - index = index + i; - break; - } - } - child = getChildAt(index - i); - if (child != null) { - position = getPosition(child); - if (position != NO_POSITION) { - index = index - i; - break; - } - } - } - } - if (position == NO_POSITION) { - // None of the children survives the relayout, let's just use the top of the - // first one. - oldTop = getChildAt(0).getTop(); - int count = state.getItemCount(); - // Lets first make sure that the first position is not above the last element, - // which can happen if elements were removed. - while (mFirstPosition >= count && mFirstPosition > 0) { - mFirstPosition--; - } - } else { - // Some of the children survived the relayout. We will keep it in its place, - // but go through previous children and maybe add them. - if (!mWasZoomedIn) { - // If we were previously zoomed-in on a single item, ignore this and just - // use the default value set above. Reasoning: if we are still zoomed-in, - // oldTop will be ignored when laying out the single child element. If we - // are no longer zoomed in, then we want to position items using the top - // of the single item as if the single item was not zoomed in, which is - // equal to the default value. - oldTop = getChildAt(index).getTop(); - } - while (oldTop > getPaddingTop() && position > 0) { - position--; - oldTop -= getItemHeight(); - } - if (position == 0 && oldTop > getCentralViewTop()) { - // We need to handle special case where the first, central item was removed - // and now the first element is hanging below, instead of being nicely - // centered. - oldTop = getCentralViewTop(); - } - mFirstPosition = position; - } - } else if (mPushFirstHigher) { - // We are trying to position elements ourselves, so we force position of the first - // one. - oldTop = getCentralViewTop() - getItemHeight(); - } - - performLayoutChildren(recycler, state, parentBottom, oldTop); - - // Since the content might have changed, we need to adjust the absolute scroll in case - // some elements have disappeared or were added. - if (getChildCount() == 0) { - setAbsoluteScroll(0); - } else { - View child = getChildAt(findCenterViewIndex()); - setAbsoluteScroll(child.getTop() - getCentralViewTop() + getPosition(child) * - getItemHeight()); - } - - mUseOldViewTop = true; - mPushFirstHigher = false; - } - - private void performLayoutChildren(Recycler recycler, State state, int parentBottom, - int top) { - detachAndScrapAttachedViews(recycler); - - if (mMaximizeSingleItem && state.getItemCount() == 1) { - performLayoutOneChild(recycler, parentBottom); - mWasZoomedIn = true; - } else { - performLayoutMultipleChildren(recycler, state, parentBottom, top); - mWasZoomedIn = false; - } - - if (getChildCount() > 0) { - post(mNotifyChildrenPostLayoutRunnable); - } - } - - private void performLayoutOneChild(Recycler recycler, int parentBottom) { - final int right = getWidth() - getPaddingRight(); - View v = recycler.getViewForPosition(getFirstPosition()); - addView(v, 0); - measureZoomView(v); - v.layout(getPaddingLeft(), getPaddingTop(), right, parentBottom); - } - - private void performLayoutMultipleChildren(Recycler recycler, State state, int parentBottom, - int top) { - int bottom; - final int left = getPaddingLeft(); - final int right = getWidth() - getPaddingRight(); - final int count = state.getItemCount(); - // If we are laying out children with center element being different than the first, we - // need to start with previous child which appears half visible at the top. - for (int i = 0; getFirstPosition() + i < count; i++, top = bottom) { - if (top >= parentBottom) { - break; - } - View v = recycler.getViewForPosition(getFirstPosition() + i); - addView(v, i); - measureThirdView(v); - bottom = top + getItemHeight(); - v.layout(left, top, right, bottom); - } - } - - private void setAbsoluteScroll(int absoluteScroll) { - mAbsoluteScroll = absoluteScroll; - for (OnScrollListener listener : mOnScrollListeners) { - listener.onAbsoluteScrollChange(mAbsoluteScroll); - } - } - - private void measureView(View v, int height) { - final LayoutParams lp = (LayoutParams) v.getLayoutParams(); - final int widthSpec = getChildMeasureSpec(getWidth(), - getPaddingLeft() + getPaddingRight() + lp.leftMargin + lp.rightMargin, lp.width, - canScrollHorizontally()); - final int heightSpec = getChildMeasureSpec(getHeight(), - getPaddingTop() + getPaddingBottom() + lp.topMargin + lp.bottomMargin, - height, canScrollVertically()); - v.measure(widthSpec, heightSpec); - } - - private void measureThirdView(View v) { - measureView(v, (int) (1 + (float) getHeight() / THIRD)); - } - - private void measureZoomView(View v) { - measureView(v, getHeight()); - } - - @Override - public RecyclerView.LayoutParams generateDefaultLayoutParams() { - return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT); - } - - @Override - public boolean canScrollVertically() { - // Disable vertical scrolling when zoomed. - return getItemCount() != 1 || !mWasZoomedIn; - } - - @Override - public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, State state) { - // TODO(gruszczy): This code is shit, needs to be rewritten. - if (getChildCount() == 0) { - return 0; - } - int scrolled = 0; - final int left = getPaddingLeft(); - final int right = getWidth() - getPaddingRight(); - if (dy < 0) { - while (scrolled > dy) { - final View topView = getChildAt(0); - if (getFirstPosition() > 0) { - final int hangingTop = Math.max(-topView.getTop(), 0); - final int scrollBy = Math.min(scrolled - dy, hangingTop); - scrolled -= scrollBy; - offsetChildrenVertical(scrollBy); - if (getFirstPosition() > 0 && scrolled > dy) { - mFirstPosition--; - View v = recycler.getViewForPosition(getFirstPosition()); - addView(v, 0); - measureThirdView(v); - final int bottom = topView.getTop(); - final int top = bottom - getItemHeight(); - v.layout(left, top, right, bottom); - } else { - break; - } - } else { - mPushFirstHigher = false; - int maxScroll = mOverScrollListener!= null ? - getHeight() : getTopViewMaxTop(); - final int scrollBy = Math.min(-dy + scrolled, maxScroll - topView.getTop()); - scrolled -= scrollBy; - offsetChildrenVertical(scrollBy); - break; - } - } - } else if (dy > 0) { - final int parentHeight = getHeight(); - while (scrolled < dy) { - final View bottomView = getChildAt(getChildCount() - 1); - if (state.getItemCount() > mFirstPosition + getChildCount()) { - final int hangingBottom = - Math.max(bottomView.getBottom() - parentHeight, 0); - final int scrollBy = -Math.min(dy - scrolled, hangingBottom); - scrolled -= scrollBy; - offsetChildrenVertical(scrollBy); - if (scrolled < dy) { - View v = recycler.getViewForPosition(mFirstPosition + getChildCount()); - final int top = getChildAt(getChildCount() - 1).getBottom(); - addView(v); - measureThirdView(v); - final int bottom = top + getItemHeight(); - v.layout(left, top, right, bottom); - } else { - break; - } - } else { - final int scrollBy = - Math.max(-dy + scrolled, getHeight() / 2 - bottomView.getBottom()); - scrolled -= scrollBy; - offsetChildrenVertical(scrollBy); - break; - } - } - } - recycleViewsOutOfBounds(recycler); - setAbsoluteScroll(mAbsoluteScroll + scrolled); - return scrolled; - } - - @Override - public void scrollToPosition(int position) { - mUseOldViewTop = false; - if (position > 0) { - mFirstPosition = position - 1; - mPushFirstHigher = true; - } else { - mFirstPosition = position; - mPushFirstHigher = false; - } - requestLayout(); - } - - public void setCustomSmoothScroller(RecyclerView.SmoothScroller smoothScroller) { - mSmoothScroller = smoothScroller; - } - - public void clearCustomSmoothScroller() { - mSmoothScroller = null; - } - - public RecyclerView.SmoothScroller getDefaultSmoothScroller(RecyclerView recyclerView) { - if (mDefaultSmoothScroller == null) { - mDefaultSmoothScroller = new SmoothScroller( - recyclerView.getContext(), this); - } - return mDefaultSmoothScroller; - } - @Override - public void smoothScrollToPosition(RecyclerView recyclerView, State state, - int position) { - RecyclerView.SmoothScroller scroller = mSmoothScroller; - if (scroller == null) { - scroller = getDefaultSmoothScroller(recyclerView); - } - scroller.setTargetPosition(position); - startSmoothScroll(scroller); - } - - private void recycleViewsOutOfBounds(RecyclerView.Recycler recycler) { - final int childCount = getChildCount(); - final int parentWidth = getWidth(); - // Here we want to use real height, so we don't remove views that are only visible in - // padded section. - final int parentHeight = getHeight(); - boolean foundFirst = false; - int first = 0; - int last = 0; - for (int i = 0; i < childCount; i++) { - final View v = getChildAt(i); - if (v.hasFocus() || (v.getRight() >= 0 && v.getLeft() <= parentWidth && - v.getBottom() >= 0 && v.getTop() <= parentHeight)) { - if (!foundFirst) { - first = i; - foundFirst = true; - } - last = i; - } - } - for (int i = childCount - 1; i > last; i--) { - removeAndRecycleViewAt(i, recycler); - } - for (int i = first - 1; i >= 0; i--) { - removeAndRecycleViewAt(i, recycler); - } - if (getChildCount() == 0) { - mFirstPosition = 0; - } else if (first > 0) { - mPushFirstHigher = true; - mFirstPosition += first; - } - } - - public int getFirstPosition() { - return mFirstPosition; - } - - @Override - public void onAdapterChanged(RecyclerView.Adapter oldAdapter, - RecyclerView.Adapter newAdapter) { - removeAllViews(); - } - } - - /** - * Interface for receiving callbacks when WearableListView children become or cease to be the - * central item. - */ - public interface OnCenterProximityListener { - /** - * Called when this view becomes central item of the WearableListView. - * - * @param animate Whether you should animate your transition of the View to become the - * central item. If false, this is the initial setting and you should - * transition immediately. - */ - void onCenterPosition(boolean animate); - - /** - * Called when this view stops being the central item of the WearableListView. - * @param animate Whether you should animate your transition of the View to being - * non central item. If false, this is the initial setting and you should - * transition immediately. - */ - void onNonCenterPosition(boolean animate); - } - - /** - * Interface for listening for click events on WearableListView. - */ - public interface ClickListener { - /** - * Called when the central child of the WearableListView is tapped. - * @param view View that was clicked. - */ - public void onClick(ViewHolder view); - - /** - * Called when the user taps the top third of the WearableListView and no item is present - * there. This can happen when you are in initial state and the first, top-most item of the - * WearableListView is centered. - */ - public void onTopEmptyRegionClick(); - } - - /** - * @hide - */ - public interface OnOverScrollListener { - public void onOverScroll(); - } - - /** - * Interface for listening to WearableListView content scrolling. - */ - public interface OnScrollListener { - /** - * Called when the content is scrolled, reporting the relative scroll value. - * @param scroll Amount the content was scrolled. This is a delta from the previous - * position to the new position. - */ - public void onScroll(int scroll); - - /** - * Called when the content is scrolled, reporting the absolute scroll value. - * - * @deprecated BE ADVISED DO NOT USE THIS This might provide wrong values when contents - * of a RecyclerView change. - * - * @param scroll Absolute scroll position of the content inside the WearableListView. - */ - @Deprecated - public void onAbsoluteScrollChange(int scroll); - - /** - * Called when WearableListView's scroll state changes. - * - * @param scrollState The updated scroll state. One of {@link #SCROLL_STATE_IDLE}, - * {@link #SCROLL_STATE_DRAGGING} or {@link #SCROLL_STATE_SETTLING}. - */ - public void onScrollStateChanged(int scrollState); - - /** - * Called when the central item of the WearableListView changes. - * - * @param centralPosition Position of the item in the Adapter. - */ - public void onCentralPositionChanged(int centralPosition); - } - - /** - * A listener interface that can be added to the WearableListView to get notified when the - * central item is changed. - */ - public interface OnCentralPositionChangedListener { - /** - * Called when the central item of the WearableListView changes. - * - * @param centralPosition Position of the item in the Adapter. - */ - void onCentralPositionChanged(int centralPosition); - } - - /** - * Base class for adapters providing data for the WearableListView. For details refer to - * RecyclerView.Adapter. - */ - public static abstract class Adapter extends RecyclerView.Adapter<ViewHolder> { - } - - private static class SmoothScroller extends LinearSmoothScroller { - - private static final float MILLISECONDS_PER_INCH = 100f; - - private final LayoutManager mLayoutManager; - - public SmoothScroller(Context context, WearableListView.LayoutManager manager) { - super(context); - mLayoutManager = manager; - } - - @Override - protected void onStart() { - super.onStart(); - } - - // TODO: (mindyp): when flinging, return the dydt that triggered the fling. - @Override - protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) { - return MILLISECONDS_PER_INCH / displayMetrics.densityDpi; - } - - @Override - public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd, int - snapPreference) { - // Snap to center. - return (boxStart + boxEnd) / 2 - (viewStart + viewEnd) / 2; - } - - @Override - public PointF computeScrollVectorForPosition(int targetPosition) { - if (targetPosition < mLayoutManager.getFirstPosition()) { - return new PointF(0, -1); - } else { - return new PointF(0, 1); - } - } - } - - /** - * Wrapper around items displayed in the list view. {@link .Adapter} must return objects that - * are instances of this class. Consider making the wrapped View implement - * {@link .OnCenterProximityListener} if you want to receive a callback when it becomes or - * ceases to be the central item in the WearableListView. - */ - public static class ViewHolder extends RecyclerView.ViewHolder { - public ViewHolder(View itemView) { - super(itemView); - } - - /** - * Called when the wrapped view is becoming or ceasing to be the central item of the - * WearableListView. - * - * Retained as protected for backwards compatibility. - * - * @hide - */ - protected void onCenterProximity(boolean isCentralItem, boolean animate) { - if (!(itemView instanceof OnCenterProximityListener)) { - return; - } - OnCenterProximityListener item = (OnCenterProximityListener) itemView; - if (isCentralItem) { - item.onCenterPosition(animate); - } else { - item.onNonCenterPosition(animate); - } - } - } - - private class SetScrollVerticallyProperty extends Property<WearableListView, Integer> { - public SetScrollVerticallyProperty() { - super(Integer.class, "scrollVertically"); - } - - @Override - public Integer get(WearableListView wearableListView) { - return wearableListView.mLastScrollChange; - } - - @Override - public void set(WearableListView wearableListView, Integer value) { - wearableListView.setScrollVertically(value); - } - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/model/AppPermissionGroup.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/model/AppPermissionGroup.java deleted file mode 100644 index 6b3a76071f58..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/model/AppPermissionGroup.java +++ /dev/null @@ -1,1001 +0,0 @@ -/* - * Copyright (C) 2015 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.packageinstaller.permission.model; - -import static android.app.AppOpsManager.MODE_ALLOWED; -import static android.app.AppOpsManager.MODE_FOREGROUND; -import static android.app.AppOpsManager.MODE_IGNORED; - -import android.annotation.StringRes; -import android.annotation.SystemApi; -import android.app.ActivityManager; -import android.app.AppOpsManager; -import android.content.Context; -import android.content.pm.PackageInfo; -import android.content.pm.PackageItemInfo; -import android.content.pm.PackageManager; -import android.content.pm.PermissionGroupInfo; -import android.content.pm.PermissionInfo; -import android.content.res.ResourceId; -import android.os.Build; -import android.os.Process; -import android.os.UserHandle; -import android.util.ArrayMap; - -import com.android.packageinstaller.R; -import com.android.packageinstaller.permission.utils.ArrayUtils; -import com.android.packageinstaller.permission.utils.LocationUtils; - -import java.text.Collator; -import java.util.ArrayList; -import java.util.List; - -/** - * All permissions of a permission group that are requested by an app. - * - * <p>Some permissions only grant access to the protected resource while the app is running in the - * foreground. These permissions are considered "split" into this foreground and a matching - * "background" permission. - * - * <p>All background permissions of the group are not in the main group and will not be affected - * by operations on the group. The background permissions can be found in the {@link - * #getBackgroundPermissions() background permissions group}. - */ -public final class AppPermissionGroup implements Comparable<AppPermissionGroup> { - private static final String PLATFORM_PACKAGE_NAME = "android"; - - private static final String KILL_REASON_APP_OP_CHANGE = "Permission related app op changed"; - - private final Context mContext; - private final UserHandle mUserHandle; - private final PackageManager mPackageManager; - private final AppOpsManager mAppOps; - private final ActivityManager mActivityManager; - private final Collator mCollator; - - private final PackageInfo mPackageInfo; - private final String mName; - private final String mDeclaringPackage; - private final CharSequence mLabel; - private final @StringRes int mRequest; - private final @StringRes int mRequestDetail; - private final @StringRes int mBackgroundRequest; - private final @StringRes int mBackgroundRequestDetail; - private final CharSequence mDescription; - private final ArrayMap<String, Permission> mPermissions = new ArrayMap<>(); - private final String mIconPkg; - private final int mIconResId; - - /** - * Some permissions are split into foreground and background permission. All non-split and - * foreground permissions are in {@link #mPermissions}, all background permissions are in - * this field. - */ - private AppPermissionGroup mBackgroundPermissions; - - private final boolean mAppSupportsRuntimePermissions; - private final boolean mIsEphemeralApp; - private boolean mContainsEphemeralPermission; - private boolean mContainsPreRuntimePermission; - - /** - * Does this group contain at least one permission that is split into a foreground and - * background permission? This does not necessarily mean that the app also requested the - * background permission. - */ - private boolean mHasPermissionWithBackgroundMode; - - public static AppPermissionGroup create(Context context, PackageInfo packageInfo, - String permissionName) { - PermissionInfo permissionInfo; - try { - permissionInfo = context.getPackageManager().getPermissionInfo(permissionName, 0); - } catch (PackageManager.NameNotFoundException e) { - return null; - } - - if ((permissionInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) - != PermissionInfo.PROTECTION_DANGEROUS - || (permissionInfo.flags & PermissionInfo.FLAG_INSTALLED) == 0 - || (permissionInfo.flags & PermissionInfo.FLAG_REMOVED) != 0) { - return null; - } - - PackageItemInfo groupInfo = permissionInfo; - if (permissionInfo.group != null) { - try { - groupInfo = context.getPackageManager().getPermissionGroupInfo( - permissionInfo.group, 0); - } catch (PackageManager.NameNotFoundException e) { - /* ignore */ - } - } - - List<PermissionInfo> permissionInfos = null; - if (groupInfo instanceof PermissionGroupInfo) { - try { - permissionInfos = context.getPackageManager().queryPermissionsByGroup( - groupInfo.name, 0); - } catch (PackageManager.NameNotFoundException e) { - /* ignore */ - } - } - - return create(context, packageInfo, groupInfo, permissionInfos, - Process.myUserHandle()); - } - - public static AppPermissionGroup create(Context context, PackageInfo packageInfo, - PackageItemInfo groupInfo, List<PermissionInfo> permissionInfos, - UserHandle userHandle) { - - AppPermissionGroup group = new AppPermissionGroup(context, packageInfo, groupInfo.name, - groupInfo.packageName, groupInfo.loadLabel(context.getPackageManager()), - loadGroupDescription(context, groupInfo), getRequest(groupInfo), - getRequestDetail(groupInfo), getBackgroundRequest(groupInfo), - getBackgroundRequestDetail(groupInfo), groupInfo.packageName, groupInfo.icon, - userHandle); - - if (groupInfo instanceof PermissionInfo) { - permissionInfos = new ArrayList<>(); - permissionInfos.add((PermissionInfo) groupInfo); - } - - if (permissionInfos == null || permissionInfos.isEmpty()) { - return null; - } - - // Parse and create permissions reqested by the app - ArrayMap<String, Permission> allPermissions = new ArrayMap<>(); - final int permissionCount = packageInfo.requestedPermissions.length; - for (int i = 0; i < permissionCount; i++) { - String requestedPermission = packageInfo.requestedPermissions[i]; - - PermissionInfo requestedPermissionInfo = null; - - for (PermissionInfo permissionInfo : permissionInfos) { - if (requestedPermission.equals(permissionInfo.name)) { - requestedPermissionInfo = permissionInfo; - break; - } - } - - if (requestedPermissionInfo == null) { - continue; - } - - // Collect only runtime permissions. - if ((requestedPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) - != PermissionInfo.PROTECTION_DANGEROUS) { - continue; - } - - // Don't allow toggling non-platform permission groups for legacy apps via app ops. - if (packageInfo.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1 - && !PLATFORM_PACKAGE_NAME.equals(groupInfo.packageName)) { - continue; - } - - final boolean granted = (packageInfo.requestedPermissionsFlags[i] - & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0; - - final String appOp = PLATFORM_PACKAGE_NAME.equals(requestedPermissionInfo.packageName) - ? AppOpsManager.permissionToOp(requestedPermissionInfo.name) : null; - - final boolean appOpAllowed = appOp != null - && context.getSystemService(AppOpsManager.class).checkOpNoThrow(appOp, - packageInfo.applicationInfo.uid, packageInfo.packageName) - == MODE_ALLOWED; - - final int flags = context.getPackageManager().getPermissionFlags( - requestedPermission, packageInfo.packageName, userHandle); - - Permission permission = new Permission(requestedPermission, - requestedPermissionInfo.backgroundPermission, granted, - appOp, appOpAllowed, flags, requestedPermissionInfo.protectionLevel); - - if (requestedPermissionInfo.backgroundPermission != null) { - group.mHasPermissionWithBackgroundMode = true; - } - - allPermissions.put(requestedPermission, permission); - } - - int numPermissions = allPermissions.size(); - if (numPermissions == 0) { - return null; - } - - // Link up foreground and background permissions - for (int i = 0; i < allPermissions.size(); i++) { - Permission permission = allPermissions.valueAt(i); - - if (permission.getBackgroundPermissionName() != null) { - Permission backgroundPermission = allPermissions.get( - permission.getBackgroundPermissionName()); - - if (backgroundPermission != null) { - backgroundPermission.addForegroundPermissions(permission); - permission.setBackgroundPermission(backgroundPermission); - } - } - } - - // Add permissions found to this group - for (int i = 0; i < numPermissions; i++) { - Permission permission = allPermissions.valueAt(i); - - if (permission.isBackgroundPermission()) { - if (group.getBackgroundPermissions() == null) { - group.mBackgroundPermissions = new AppPermissionGroup(group.mContext, - group.getApp(), group.getName(), group.getDeclaringPackage(), - group.getLabel(), group.getDescription(), group.getRequest(), - group.getRequestDetail(), group.getBackgroundRequest(), - group.getBackgroundRequestDetail(), group.getIconPkg(), - group.getIconResId(), UserHandle.of(group.getUserId())); - } - - group.getBackgroundPermissions().addPermission(permission); - } else { - group.addPermission(permission); - } - } - - return group; - } - - private static @StringRes int getRequest(PackageItemInfo group) { - if (group instanceof PermissionGroupInfo) { - return ((PermissionGroupInfo) group).requestRes; - } else if (group instanceof PermissionInfo) { - return ((PermissionInfo) group).requestRes; - } else { - return 0; - } - } - - private static CharSequence loadGroupDescription(Context context, PackageItemInfo group) { - CharSequence description = null; - if (group instanceof PermissionGroupInfo) { - description = ((PermissionGroupInfo) group).loadDescription( - context.getPackageManager()); - } else if (group instanceof PermissionInfo) { - description = ((PermissionInfo) group).loadDescription( - context.getPackageManager()); - } - - if (description == null || description.length() <= 0) { - description = context.getString(R.string.default_permission_description); - } - - return description; - } - - private AppPermissionGroup(Context context, PackageInfo packageInfo, String name, - String declaringPackage, CharSequence label, CharSequence description, - @StringRes int request, @StringRes int requestDetail, - @StringRes int backgroundRequest, @StringRes int backgroundRequestDetail, - String iconPkg, int iconResId, UserHandle userHandle) { - mContext = context; - mUserHandle = userHandle; - mPackageManager = mContext.getPackageManager(); - mPackageInfo = packageInfo; - mAppSupportsRuntimePermissions = packageInfo.applicationInfo - .targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1; - mIsEphemeralApp = packageInfo.applicationInfo.isInstantApp(); - mAppOps = context.getSystemService(AppOpsManager.class); - mActivityManager = context.getSystemService(ActivityManager.class); - mDeclaringPackage = declaringPackage; - mName = name; - mLabel = label; - mDescription = description; - mCollator = Collator.getInstance( - context.getResources().getConfiguration().getLocales().get(0)); - mRequest = request; - mRequestDetail = requestDetail; - mBackgroundRequest = backgroundRequest; - mBackgroundRequestDetail = backgroundRequestDetail; - if (iconResId != 0) { - mIconPkg = iconPkg; - mIconResId = iconResId; - } else { - mIconPkg = context.getPackageName(); - mIconResId = R.drawable.ic_perm_device_info; - } - } - - public boolean doesSupportRuntimePermissions() { - return mAppSupportsRuntimePermissions; - } - - public boolean isGrantingAllowed() { - return (!mIsEphemeralApp || mContainsEphemeralPermission) - && (mAppSupportsRuntimePermissions || mContainsPreRuntimePermission); - } - - public boolean isReviewRequired() { - if (mAppSupportsRuntimePermissions) { - return false; - } - final int permissionCount = mPermissions.size(); - for (int i = 0; i < permissionCount; i++) { - Permission permission = mPermissions.valueAt(i); - if (permission.isReviewRequired()) { - return true; - } - } - return false; - } - - public void resetReviewRequired() { - final int permissionCount = mPermissions.size(); - for (int i = 0; i < permissionCount; i++) { - Permission permission = mPermissions.valueAt(i); - if (permission.isReviewRequired()) { - permission.resetReviewRequired(); - mPackageManager.updatePermissionFlags(permission.getName(), - mPackageInfo.packageName, - PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED, - 0, mUserHandle); - } - } - } - - public boolean hasGrantedByDefaultPermission() { - final int permissionCount = mPermissions.size(); - for (int i = 0; i < permissionCount; i++) { - Permission permission = mPermissions.valueAt(i); - if (permission.isGrantedByDefault()) { - return true; - } - } - return false; - } - - public PackageInfo getApp() { - return mPackageInfo; - } - - public String getName() { - return mName; - } - - public String getDeclaringPackage() { - return mDeclaringPackage; - } - - public String getIconPkg() { - return mIconPkg; - } - - public int getIconResId() { - return mIconResId; - } - - public CharSequence getLabel() { - return mLabel; - } - - /** - * @hide - * @return The resource Id of the request string. - */ - @SystemApi - public @StringRes int getRequest() { - return mRequest; - } - - /** - * Extract the (subtitle) message explaining to the user that the permission is only granted to - * the apps running in the foreground. - * - * @param info The package item info to extract the message from - * - * @return the message of {@link ResourceId#ID_NULL} if unset - */ - private static @StringRes int getRequestDetail(PackageItemInfo info) { - if (info instanceof PermissionGroupInfo) { - return ((PermissionGroupInfo) info).requestDetailResourceId; - } else { - return ResourceId.ID_NULL; - } - } - - /** - * Get the (subtitle) message explaining to the user that the permission is only granted to - * the apps running in the foreground. - * - * @return the message of {@link ResourceId#ID_NULL} if unset - */ - public @StringRes int getRequestDetail() { - return mRequestDetail; - } - - /** - * Extract the title of the dialog explaining to the user that the permission is granted while - * the app is in background and in foreground. - * - * @param info The package item info to extract the message from - * - * @return the message of {@link ResourceId#ID_NULL} if unset - */ - private static @StringRes int getBackgroundRequest(PackageItemInfo info) { - if (info instanceof PermissionGroupInfo) { - return ((PermissionGroupInfo) info).backgroundRequestResourceId; - } else { - return ResourceId.ID_NULL; - } - } - - /** - * Get the title of the dialog explaining to the user that the permission is granted while - * the app is in background and in foreground. - * - * @return the message of {@link ResourceId#ID_NULL} if unset - */ - public @StringRes int getBackgroundRequest() { - return mBackgroundRequest; - } - - /** - * Extract the (subtitle) message explaining to the user that the she/he is about to allow the - * app to have background access. - * - * @param info The package item info to extract the message from - * - * @return the message of {@link ResourceId#ID_NULL} if unset - */ - private static @StringRes int getBackgroundRequestDetail(PackageItemInfo info) { - if (info instanceof PermissionGroupInfo) { - return ((PermissionGroupInfo) info).backgroundRequestDetailResourceId; - } else { - return ResourceId.ID_NULL; - } - } - - /** - * Get the (subtitle) message explaining to the user that the she/he is about to allow the - * app to have background access. - * - * @return the message of {@link ResourceId#ID_NULL} if unset - */ - public @StringRes int getBackgroundRequestDetail() { - return mBackgroundRequestDetail; - } - - public CharSequence getDescription() { - return mDescription; - } - - public int getUserId() { - return mUserHandle.getIdentifier(); - } - - public boolean hasPermission(String permission) { - return mPermissions.get(permission) != null; - } - - public boolean areRuntimePermissionsGranted() { - return areRuntimePermissionsGranted(null); - } - - public boolean areRuntimePermissionsGranted(String[] filterPermissions) { - if (LocationUtils.isLocationGroupAndProvider(mName, mPackageInfo.packageName)) { - return LocationUtils.isLocationEnabled(mContext); - } - final int permissionCount = mPermissions.size(); - for (int i = 0; i < permissionCount; i++) { - Permission permission = mPermissions.valueAt(i); - if (filterPermissions != null - && !ArrayUtils.contains(filterPermissions, permission.getName())) { - continue; - } - if (mAppSupportsRuntimePermissions) { - if (permission.isGranted()) { - return true; - } - } else if (permission.isGranted() - && (!permission.affectsAppOp() || permission.isAppOpAllowed()) - && !permission.isReviewRequired()) { - return true; - } - } - return false; - } - - public boolean grantRuntimePermissions(boolean fixedByTheUser) { - return grantRuntimePermissions(fixedByTheUser, null); - } - - /** - * Allow the app op for a permission/uid. - * - * <p>There are three cases: - * <dl> - * <dt>The permission is not split into foreground/background</dt> - * <dd>The app op matching the permission will be set to {@link AppOpsManager#MODE_ALLOWED}</dd> - * <dt>The permission is a foreground permission:</dt> - * <dd><dl><dt>The background permission permission is granted</dt> - * <dd>The app op matching the permission will be set to {@link AppOpsManager#MODE_ALLOWED}</dd> - * <dt>The background permission permission is <u>not</u> granted</dt> - * <dd>The app op matching the permission will be set to - * {@link AppOpsManager#MODE_FOREGROUND}</dd> - * </dl></dd> - * <dt>The permission is a background permission:</dt> - * <dd>All granted foreground permissions for this background permission will be set to - * {@link AppOpsManager#MODE_ALLOWED}</dd> - * </dl> - * - * @param permission The permission which has an appOps that should be allowed - * @param uid The uid of the process the app op if for - */ - private void allowAppOp(Permission permission, int uid) { - if (permission.isBackgroundPermission()) { - ArrayList<Permission> foregroundPermissions = permission.getForegroundPermissions(); - - int numForegroundPermissions = foregroundPermissions.size(); - for (int i = 0; i < numForegroundPermissions; i++) { - Permission foregroundPermission = foregroundPermissions.get(i); - if (foregroundPermission.isAppOpAllowed()) { - mAppOps.setUidMode(foregroundPermission.getAppOp(), uid, MODE_ALLOWED); - } - } - } else { - if (permission.hasBackgroundPermission()) { - Permission backgroundPermission = permission.getBackgroundPermission(); - - if (backgroundPermission == null) { - // The app requested a permission that has a background permission but it did - // not request the background permission, hence it can never get background - // access - mAppOps.setUidMode(permission.getAppOp(), uid, MODE_FOREGROUND); - } else { - if (backgroundPermission.isAppOpAllowed()) { - mAppOps.setUidMode(permission.getAppOp(), uid, MODE_ALLOWED); - } else { - mAppOps.setUidMode(permission.getAppOp(), uid, MODE_FOREGROUND); - } - } - } else { - mAppOps.setUidMode(permission.getAppOp(), uid, MODE_ALLOWED); - } - } - } - - /** - * Grant permissions of the group. - * - * <p>This also automatically grants all app ops for permissions that have app ops. - * <p>This does <u>only</u> grant permissions in {@link #mPermissions}, i.e. usually not - * the background permissions. - * - * @param fixedByTheUser If the user requested that she/he does not want to be asked again - * @param filterPermissions If {@code null} all permissions of the group will be granted. - * Otherwise only permissions in {@code filterPermissions} will be - * granted. - * - * @return {@code true} iff all permissions of this group could be granted. - */ - public boolean grantRuntimePermissions(boolean fixedByTheUser, String[] filterPermissions) { - final int uid = mPackageInfo.applicationInfo.uid; - - // We toggle permissions only to apps that support runtime - // permissions, otherwise we toggle the app op corresponding - // to the permission if the permission is granted to the app. - for (Permission permission : mPermissions.values()) { - if (filterPermissions != null - && !ArrayUtils.contains(filterPermissions, permission.getName())) { - continue; - } - - if (!permission.isGrantingAllowed(mIsEphemeralApp, mAppSupportsRuntimePermissions)) { - // Skip unallowed permissions. - continue; - } - - if (mAppSupportsRuntimePermissions) { - // Do not touch permissions fixed by the system. - if (permission.isSystemFixed()) { - return false; - } - - // Ensure the permission app op enabled before the permission grant. - if (permission.affectsAppOp() && !permission.isAppOpAllowed()) { - permission.setAppOpAllowed(true); - allowAppOp(permission, uid); - } - - // Grant the permission if needed. - if (!permission.isGranted()) { - permission.setGranted(true); - mPackageManager.grantRuntimePermission(mPackageInfo.packageName, - permission.getName(), mUserHandle); - } - - // Update the permission flags. - if (!fixedByTheUser) { - // Now the apps can ask for the permission as the user - // no longer has it fixed in a denied state. - if (permission.isUserFixed() || permission.isUserSet()) { - permission.setUserFixed(false); - permission.setUserSet(false); - mPackageManager.updatePermissionFlags(permission.getName(), - mPackageInfo.packageName, - PackageManager.FLAG_PERMISSION_USER_FIXED - | PackageManager.FLAG_PERMISSION_USER_SET, - 0, mUserHandle); - } - } - } else { - // Legacy apps cannot have a not granted permission but just in case. - if (!permission.isGranted()) { - continue; - } - - int killUid = -1; - int mask = 0; - - // If the permissions has no corresponding app op, then it is a - // third-party one and we do not offer toggling of such permissions. - if (permission.affectsAppOp()) { - if (!permission.isAppOpAllowed()) { - permission.setAppOpAllowed(true); - allowAppOp(permission, uid); - - // Legacy apps do not know that they have to retry access to a - // resource due to changes in runtime permissions (app ops in this - // case). Therefore, we restart them on app op change, so they - // can pick up the change. - killUid = uid; - } - - // Mark that the permission should not be be granted on upgrade - // when the app begins supporting runtime permissions. - if (permission.shouldRevokeOnUpgrade()) { - permission.setRevokeOnUpgrade(false); - mask |= PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE; - } - } - - // Granting a permission explicitly means the user already - // reviewed it so clear the review flag on every grant. - if (permission.isReviewRequired()) { - permission.resetReviewRequired(); - mask |= PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED; - } - - if (mask != 0) { - mPackageManager.updatePermissionFlags(permission.getName(), - mPackageInfo.packageName, mask, 0, mUserHandle); - } - - if (killUid != -1) { - mActivityManager.killUid(uid, KILL_REASON_APP_OP_CHANGE); - } - } - } - - return true; - } - - public boolean revokeRuntimePermissions(boolean fixedByTheUser) { - return revokeRuntimePermissions(fixedByTheUser, null); - } - - /** - * Disallow the app op for a permission/uid. - * - * <p>There are three cases: - * <dl> - * <dt>The permission is not split into foreground/background</dt> - * <dd>The app op matching the permission will be set to {@link AppOpsManager#MODE_IGNORED}</dd> - * <dt>The permission is a foreground permission:</dt> - * <dd>The app op matching the permission will be set to {@link AppOpsManager#MODE_IGNORED}</dd> - * <dt>The permission is a background permission:</dt> - * <dd>All granted foreground permissions for this background permission will be set to - * {@link AppOpsManager#MODE_FOREGROUND}</dd> - * </dl> - * - * @param permission The permission which has an appOps that should be disallowed - * @param uid The uid of the process the app op if for - */ - private void disallowAppOp(Permission permission, int uid) { - if (permission.isBackgroundPermission()) { - ArrayList<Permission> foregroundPermissions = permission.getForegroundPermissions(); - - int numForegroundPermissions = foregroundPermissions.size(); - for (int i = 0; i < numForegroundPermissions; i++) { - Permission foregroundPermission = foregroundPermissions.get(i); - if (foregroundPermission.isAppOpAllowed()) { - mAppOps.setUidMode(foregroundPermission.getAppOp(), uid, MODE_FOREGROUND); - } - } - } else { - mAppOps.setUidMode(permission.getAppOp(), uid, MODE_IGNORED); - } - } - - /** - * Revoke permissions of the group. - * - * <p>This also disallows all app ops for permissions that have app ops. - * <p>This does <u>only</u> revoke permissions in {@link #mPermissions}, i.e. usually not - * the background permissions. - * - * @param fixedByTheUser If the user requested that she/he does not want to be asked again - * @param filterPermissions If {@code null} all permissions of the group will be revoked. - * Otherwise only permissions in {@code filterPermissions} will be - * revoked. - * - * @return {@code true} iff all permissions of this group could be revoked. - */ - public boolean revokeRuntimePermissions(boolean fixedByTheUser, String[] filterPermissions) { - final int uid = mPackageInfo.applicationInfo.uid; - - // We toggle permissions only to apps that support runtime - // permissions, otherwise we toggle the app op corresponding - // to the permission if the permission is granted to the app. - for (Permission permission : mPermissions.values()) { - if (filterPermissions != null - && !ArrayUtils.contains(filterPermissions, permission.getName())) { - continue; - } - - if (mAppSupportsRuntimePermissions) { - // Do not touch permissions fixed by the system. - if (permission.isSystemFixed()) { - return false; - } - - // Revoke the permission if needed. - if (permission.isGranted()) { - permission.setGranted(false); - mPackageManager.revokeRuntimePermission(mPackageInfo.packageName, - permission.getName(), mUserHandle); - } - - // Update the permission flags. - if (fixedByTheUser) { - // Take a note that the user fixed the permission. - if (permission.isUserSet() || !permission.isUserFixed()) { - permission.setUserSet(false); - permission.setUserFixed(true); - mPackageManager.updatePermissionFlags(permission.getName(), - mPackageInfo.packageName, - PackageManager.FLAG_PERMISSION_USER_SET - | PackageManager.FLAG_PERMISSION_USER_FIXED, - PackageManager.FLAG_PERMISSION_USER_FIXED, - mUserHandle); - } - } else { - if (!permission.isUserSet() || permission.isUserFixed()) { - permission.setUserSet(true); - permission.setUserFixed(false); - // Take a note that the user already chose once. - mPackageManager.updatePermissionFlags(permission.getName(), - mPackageInfo.packageName, - PackageManager.FLAG_PERMISSION_USER_SET - | PackageManager.FLAG_PERMISSION_USER_FIXED, - PackageManager.FLAG_PERMISSION_USER_SET, - mUserHandle); - } - } - - if (permission.affectsAppOp()) { - permission.setAppOpAllowed(false); - disallowAppOp(permission, uid); - } - } else { - // Legacy apps cannot have a non-granted permission but just in case. - if (!permission.isGranted()) { - continue; - } - - int mask = 0; - int flags = 0; - int killUid = -1; - - // If the permission has no corresponding app op, then it is a - // third-party one and we do not offer toggling of such permissions. - if (permission.affectsAppOp()) { - if (permission.isAppOpAllowed()) { - permission.setAppOpAllowed(false); - disallowAppOp(permission, uid); - - // Disabling an app op may put the app in a situation in which it - // has a handle to state it shouldn't have, so we have to kill the - // app. This matches the revoke runtime permission behavior. - killUid = uid; - } - - // Mark that the permission should not be granted on upgrade - // when the app begins supporting runtime permissions. - if (!permission.shouldRevokeOnUpgrade()) { - permission.setRevokeOnUpgrade(true); - mask |= PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE; - flags |= PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE; - } - } - - if (mask != 0) { - mPackageManager.updatePermissionFlags(permission.getName(), - mPackageInfo.packageName, mask, flags, mUserHandle); - } - - if (killUid != -1) { - mActivityManager.killUid(uid, KILL_REASON_APP_OP_CHANGE); - } - } - } - - return true; - } - - public void setPolicyFixed() { - final int permissionCount = mPermissions.size(); - for (int i = 0; i < permissionCount; i++) { - Permission permission = mPermissions.valueAt(i); - permission.setPolicyFixed(true); - mPackageManager.updatePermissionFlags(permission.getName(), - mPackageInfo.packageName, - PackageManager.FLAG_PERMISSION_POLICY_FIXED, - PackageManager.FLAG_PERMISSION_POLICY_FIXED, - mUserHandle); - } - } - - public ArrayList<Permission> getPermissions() { - return new ArrayList<>(mPermissions.values()); - } - - /** - * @return An {@link AppPermissionGroup}-object that contains all background permissions for - * this group. - */ - public AppPermissionGroup getBackgroundPermissions() { - return mBackgroundPermissions; - } - - /** - * @return {@code true} iff the app request at least one permission in this group that has a - * background permission. It is possible that the app does not request the matching background - * permission and hence will only ever get foreground access, never background access. - */ - public boolean hasPermissionWithBackgroundMode() { - return mHasPermissionWithBackgroundMode; - } - - /** - * Whether this is group that contains all the background permission for regular permission - * group. - * - * @return {@code true} iff this is a background permission group. - * - * @see #getBackgroundPermissions() - */ - public boolean isBackgroundGroup() { - return mPermissions.valueAt(0).isBackgroundPermission(); - } - - public int getFlags() { - int flags = 0; - final int permissionCount = mPermissions.size(); - for (int i = 0; i < permissionCount; i++) { - Permission permission = mPermissions.valueAt(i); - flags |= permission.getFlags(); - } - return flags; - } - - public boolean isUserFixed() { - final int permissionCount = mPermissions.size(); - for (int i = 0; i < permissionCount; i++) { - Permission permission = mPermissions.valueAt(i); - if (permission.isUserFixed()) { - return true; - } - } - return false; - } - - public boolean isPolicyFixed() { - final int permissionCount = mPermissions.size(); - for (int i = 0; i < permissionCount; i++) { - Permission permission = mPermissions.valueAt(i); - if (permission.isPolicyFixed()) { - return true; - } - } - return false; - } - - public boolean isUserSet() { - final int permissionCount = mPermissions.size(); - for (int i = 0; i < permissionCount; i++) { - Permission permission = mPermissions.valueAt(i); - if (permission.isUserSet()) { - return true; - } - } - return false; - } - - public boolean isSystemFixed() { - final int permissionCount = mPermissions.size(); - for (int i = 0; i < permissionCount; i++) { - Permission permission = mPermissions.valueAt(i); - if (permission.isSystemFixed()) { - return true; - } - } - return false; - } - - @Override - public int compareTo(AppPermissionGroup another) { - final int result = mCollator.compare(mLabel.toString(), another.mLabel.toString()); - if (result == 0) { - // Unbadged before badged. - return mPackageInfo.applicationInfo.uid - - another.mPackageInfo.applicationInfo.uid; - } - return result; - } - - @Override - public boolean equals(Object o) { - if (o == null || !(o instanceof AppPermissionGroup)) { - return false; - } - - AppPermissionGroup other = (AppPermissionGroup) o; - return mName.equals(other.mName) - && mPackageInfo.packageName.equals(other.mPackageInfo.packageName) - && mUserHandle.equals(other.mUserHandle); - } - - @Override - public int hashCode() { - return mName.hashCode() + mPackageInfo.packageName.hashCode() + mUserHandle.hashCode(); - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append(getClass().getSimpleName()); - builder.append("{name=").append(mName); - if (mBackgroundPermissions != null) { - builder.append(", <has background permissions>}"); - } - if (!mPermissions.isEmpty()) { - builder.append(", <has permissions>}"); - } else { - builder.append('}'); - } - return builder.toString(); - } - - private void addPermission(Permission permission) { - mPermissions.put(permission.getName(), permission); - if (permission.isEphemeral()) { - mContainsEphemeralPermission = true; - } - if (!permission.isRuntimeOnly()) { - mContainsPreRuntimePermission = true; - } - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/model/AppPermissions.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/model/AppPermissions.java deleted file mode 100644 index 880ff26ebec4..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/model/AppPermissions.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (C) 2015 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.packageinstaller.permission.model; - -import android.content.Context; -import android.content.pm.PackageInfo; -import android.content.pm.PackageItemInfo; -import android.content.pm.PackageManager; -import android.text.BidiFormatter; -import android.util.ArrayMap; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * An app that requests permissions. - * - * <p>Allows to query all permission groups of the app and which permission belongs to which group. - */ -public final class AppPermissions { - /** - * All permission groups the app requests. Background permission groups are attached to their - * foreground groups. - */ - private final ArrayList<AppPermissionGroup> mGroups = new ArrayList<>(); - - /** Cache: group name -> group */ - private final ArrayMap<String, AppPermissionGroup> mGroupNameToGroup = new ArrayMap<>(); - - /** Cache: permission name -> group. Might point to background group */ - private final ArrayMap<String, AppPermissionGroup> mPermissionNameToGroup = new ArrayMap<>(); - - private final Context mContext; - - private final CharSequence mAppLabel; - - private final Runnable mOnErrorCallback; - - private final boolean mSortGroups; - - private PackageInfo mPackageInfo; - - public AppPermissions(Context context, PackageInfo packageInfo, boolean sortGroups, - Runnable onErrorCallback) { - mContext = context; - mPackageInfo = packageInfo; - mAppLabel = BidiFormatter.getInstance().unicodeWrap( - packageInfo.applicationInfo.loadSafeLabel(context.getPackageManager(), - PackageItemInfo.DEFAULT_MAX_LABEL_SIZE_PX, - PackageItemInfo.SAFE_LABEL_FLAG_TRIM - | PackageItemInfo.SAFE_LABEL_FLAG_FIRST_LINE) - .toString()); - mSortGroups = sortGroups; - mOnErrorCallback = onErrorCallback; - loadPermissionGroups(); - } - - public PackageInfo getPackageInfo() { - return mPackageInfo; - } - - public void refresh() { - loadPackageInfo(); - loadPermissionGroups(); - } - - public CharSequence getAppLabel() { - return mAppLabel; - } - - public AppPermissionGroup getPermissionGroup(String name) { - return mGroupNameToGroup.get(name); - } - - public List<AppPermissionGroup> getPermissionGroups() { - return mGroups; - } - - public boolean isReviewRequired() { - final int groupCount = mGroups.size(); - for (int i = 0; i < groupCount; i++) { - AppPermissionGroup group = mGroups.get(i); - if (group.isReviewRequired()) { - return true; - } - } - return false; - } - - private void loadPackageInfo() { - try { - mPackageInfo = mContext.getPackageManager().getPackageInfo( - mPackageInfo.packageName, PackageManager.GET_PERMISSIONS); - } catch (PackageManager.NameNotFoundException e) { - if (mOnErrorCallback != null) { - mOnErrorCallback.run(); - } - } - } - - /** - * Add all individual permissions of the {@code group} to the {@link #mPermissionNameToGroup} - * lookup table. - * - * @param group The group of permissions to add - */ - private void addAllPermissions(AppPermissionGroup group) { - ArrayList<Permission> perms = group.getPermissions(); - - int numPerms = perms.size(); - for (int permNum = 0; permNum < numPerms; permNum++) { - mPermissionNameToGroup.put(perms.get(permNum).getName(), group); - } - } - - private void loadPermissionGroups() { - mGroups.clear(); - mGroupNameToGroup.clear(); - mPermissionNameToGroup.clear(); - - if (mPackageInfo.requestedPermissions != null) { - for (String requestedPerm : mPackageInfo.requestedPermissions) { - if (getGroupForPermission(requestedPerm) == null) { - AppPermissionGroup group = AppPermissionGroup.create(mContext, mPackageInfo, - requestedPerm); - if (group == null) { - continue; - } - - mGroups.add(group); - mGroupNameToGroup.put(group.getName(), group); - - addAllPermissions(group); - - AppPermissionGroup backgroundGroup = group.getBackgroundPermissions(); - if (backgroundGroup != null) { - addAllPermissions(backgroundGroup); - } - } - } - - if (mSortGroups) { - Collections.sort(mGroups); - } - } - } - - /** - * Find the group a permission belongs to. - * - * <p>The group found might be a background group. - * - * @param permission The name of the permission - * - * @return The group the permission belongs to - */ - public AppPermissionGroup getGroupForPermission(String permission) { - return mPermissionNameToGroup.get(permission); - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/model/Permission.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/model/Permission.java deleted file mode 100644 index 2e555f32e289..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/model/Permission.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (C) 2015 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.packageinstaller.permission.model; - -import android.content.pm.PackageManager; -import android.content.pm.PermissionInfo; - -import java.util.ArrayList; - -/** - * A permission and it's properties. - * - * @see AppPermissionGroup - */ -public final class Permission { - private final String mName; - private final String mBackgroundPermissionName; - private final String mAppOp; - - private boolean mGranted; - private boolean mAppOpAllowed; - private int mFlags; - private boolean mIsEphemeral; - private boolean mIsRuntimeOnly; - private Permission mBackgroundPermission; - private ArrayList<Permission> mForegroundPermissions; - - public Permission(String name, String backgroundPermissionName, boolean granted, - String appOp, boolean appOpAllowed, int flags, int protectionLevel) { - mName = name; - mBackgroundPermissionName = backgroundPermissionName; - mGranted = granted; - mAppOp = appOp; - mAppOpAllowed = appOpAllowed; - mFlags = flags; - mIsEphemeral = (protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTANT) != 0; - mIsRuntimeOnly = (protectionLevel & PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) != 0; - } - - /** - * Mark this permission as background permission for {@code foregroundPermissions}. - * - * @param foregroundPermission The foreground permission - */ - public void addForegroundPermissions(Permission foregroundPermission) { - if (mForegroundPermissions == null) { - mForegroundPermissions = new ArrayList<>(1); - } - mForegroundPermissions.add(foregroundPermission); - } - - /** - * Mark this permission as foreground permission for {@code backgroundPermission}. - * - * @param backgroundPermission The background permission - */ - public void setBackgroundPermission(Permission backgroundPermission) { - mBackgroundPermission = backgroundPermission; - } - - public String getName() { - return mName; - } - - public String getAppOp() { - return mAppOp; - } - - public int getFlags() { - return mFlags; - } - - /** - * Does this permission affect app ops. - * - * <p>I.e. does this permission have a matching app op or is this a background permission. All - * background permissions affect the app op of it's assigned foreground permission. - * - * @return {@code true} if this permission affects app ops - */ - public boolean affectsAppOp() { - return mAppOp != null || isBackgroundPermission(); - } - - public boolean isGranted() { - return mGranted; - } - - public boolean isReviewRequired() { - return (mFlags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0; - } - - public void resetReviewRequired() { - mFlags &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED; - } - - public void setGranted(boolean mGranted) { - this.mGranted = mGranted; - } - - public boolean isAppOpAllowed() { - return mAppOpAllowed; - } - - public boolean isUserFixed() { - return (mFlags & PackageManager.FLAG_PERMISSION_USER_FIXED) != 0; - } - - public void setUserFixed(boolean userFixed) { - if (userFixed) { - mFlags |= PackageManager.FLAG_PERMISSION_USER_FIXED; - } else { - mFlags &= ~PackageManager.FLAG_PERMISSION_USER_FIXED; - } - } - - public boolean isSystemFixed() { - return (mFlags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0; - } - - public boolean isPolicyFixed() { - return (mFlags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0; - } - - public boolean isUserSet() { - return (mFlags & PackageManager.FLAG_PERMISSION_USER_SET) != 0; - } - - public boolean isGrantedByDefault() { - return (mFlags & PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT) != 0; - } - - /** - * If this permission is split into a foreground and background permission, this is the name - * of the background permission. - * - * @return The name of the background permission or {@code null} if the permission is not split - */ - public String getBackgroundPermissionName() { - return mBackgroundPermissionName; - } - - /** - * @return If this permission is split into a foreground and background permission, - * returns the background permission - */ - public Permission getBackgroundPermission() { - return mBackgroundPermission; - } - - /** - * @return If this permission is split into a foreground and background permission, - * returns the foreground permission - */ - public ArrayList<Permission> getForegroundPermissions() { - return mForegroundPermissions; - } - - /** - * @return {@code true} iff this is the foreground permission of a background-foreground-split - * permission - */ - public boolean hasBackgroundPermission() { - return mBackgroundPermissionName != null; - } - - /** - * @return {@code true} iff this is the background permission of a background-foreground-split - * permission - */ - public boolean isBackgroundPermission() { - return mForegroundPermissions != null; - } - - public void setUserSet(boolean userSet) { - if (userSet) { - mFlags |= PackageManager.FLAG_PERMISSION_USER_SET; - } else { - mFlags &= ~PackageManager.FLAG_PERMISSION_USER_SET; - } - } - - public void setPolicyFixed(boolean policyFixed) { - if (policyFixed) { - mFlags |= PackageManager.FLAG_PERMISSION_POLICY_FIXED; - } else { - mFlags &= ~PackageManager.FLAG_PERMISSION_POLICY_FIXED; - } - } - - public boolean shouldRevokeOnUpgrade() { - return (mFlags & PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE) != 0; - } - - public void setRevokeOnUpgrade(boolean revokeOnUpgrade) { - if (revokeOnUpgrade) { - mFlags |= PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE; - } else { - mFlags &= ~PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE; - } - } - - public void setAppOpAllowed(boolean mAppOpAllowed) { - this.mAppOpAllowed = mAppOpAllowed; - } - - public boolean isEphemeral() { - return mIsEphemeral; - } - - public boolean isRuntimeOnly() { - return mIsRuntimeOnly; - } - - public boolean isGrantingAllowed(boolean isEphemeralApp, boolean supportsRuntimePermissions) { - return (!isEphemeralApp || isEphemeral()) - && (supportsRuntimePermissions || !isRuntimeOnly()); - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/model/PermissionApps.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/model/PermissionApps.java deleted file mode 100644 index d0bf5853b77b..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/model/PermissionApps.java +++ /dev/null @@ -1,441 +0,0 @@ -/* - * Copyright (C) 2015 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.packageinstaller.permission.model; - -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageItemInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.pm.PermissionInfo; -import android.graphics.drawable.Drawable; -import android.os.AsyncTask; -import android.os.UserHandle; -import android.os.UserManager; -import android.util.ArrayMap; -import android.util.ArraySet; -import android.util.IconDrawableFactory; -import android.util.Log; -import android.util.SparseArray; - -import com.android.packageinstaller.R; -import com.android.packageinstaller.permission.utils.Utils; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class PermissionApps { - private static final String LOG_TAG = "PermissionApps"; - - private final Context mContext; - private final String mGroupName; - private final PackageManager mPm; - private final Callback mCallback; - - private final PmCache mCache; - - private CharSequence mLabel; - private Drawable mIcon; - private List<PermissionApp> mPermApps; - // Map (pkg|uid) -> AppPermission - private ArrayMap<String, PermissionApp> mAppLookup; - - private boolean mSkipUi; - private boolean mRefreshing; - - public PermissionApps(Context context, String groupName, Callback callback) { - this(context, groupName, callback, null); - } - - public PermissionApps(Context context, String groupName, Callback callback, PmCache cache) { - mCache = cache; - mContext = context; - mPm = mContext.getPackageManager(); - mGroupName = groupName; - mCallback = callback; - loadGroupInfo(); - } - - public String getGroupName() { - return mGroupName; - } - - public void loadNowWithoutUi() { - mSkipUi = true; - createMap(loadPermissionApps()); - } - - /** - * Start an async refresh and call back the registered call back once done. - * - * @param getUiInfo If the UI info should be updated - */ - public void refresh(boolean getUiInfo) { - if (mCallback == null) { - throw new IllegalStateException("callback needs to be set"); - } - - if (!mRefreshing) { - mRefreshing = true; - mSkipUi = !getUiInfo; - new PermissionAppsLoader().execute(); - } - } - - /** - * Refresh the state and do not return until it finishes. Should not be called while an {@link - * #refresh async referesh} is in progress. - */ - public void refreshSync() { - mSkipUi = true; - createMap(loadPermissionApps()); - } - - public int getGrantedCount(ArraySet<String> launcherPkgs) { - int count = 0; - for (PermissionApp app : mPermApps) { - if (!Utils.shouldShowPermission(app.getPermissionGroup())) { - continue; - } - if (Utils.isSystem(app, launcherPkgs)) { - // We default to not showing system apps, so hide them from count. - continue; - } - if (app.areRuntimePermissionsGranted()) { - count++; - } - } - return count; - } - - public int getTotalCount(ArraySet<String> launcherPkgs) { - int count = 0; - for (PermissionApp app : mPermApps) { - if (!Utils.shouldShowPermission(app.getPermissionGroup())) { - continue; - } - if (Utils.isSystem(app, launcherPkgs)) { - // We default to not showing system apps, so hide them from count. - continue; - } - count++; - } - return count; - } - - public List<PermissionApp> getApps() { - return mPermApps; - } - - public PermissionApp getApp(String key) { - return mAppLookup.get(key); - } - - public CharSequence getLabel() { - return mLabel; - } - - public Drawable getIcon() { - return mIcon; - } - - private List<PermissionApp> loadPermissionApps() { - PackageItemInfo groupInfo = getGroupInfo(mGroupName); - if (groupInfo == null) { - return Collections.emptyList(); - } - - List<PermissionInfo> groupPermInfos = getGroupPermissionInfos(mGroupName); - if (groupPermInfos == null) { - return Collections.emptyList(); - } - - ArrayList<PermissionApp> permApps = new ArrayList<>(); - IconDrawableFactory iconFactory = IconDrawableFactory.newInstance(mContext); - - UserManager userManager = mContext.getSystemService(UserManager.class); - for (UserHandle user : userManager.getUserProfiles()) { - List<PackageInfo> apps = mCache != null ? mCache.getPackages(user.getIdentifier()) - : mPm.getInstalledPackagesAsUser(PackageManager.GET_PERMISSIONS, - user.getIdentifier()); - - final int N = apps.size(); - for (int i = 0; i < N; i++) { - PackageInfo app = apps.get(i); - if (app.requestedPermissions == null) { - continue; - } - - for (int j = 0; j < app.requestedPermissions.length; j++) { - String requestedPerm = app.requestedPermissions[j]; - - PermissionInfo requestedPermissionInfo = null; - - for (PermissionInfo groupPermInfo : groupPermInfos) { - if (requestedPerm.equals(groupPermInfo.name)) { - requestedPermissionInfo = groupPermInfo; - break; - } - } - - if (requestedPermissionInfo == null) { - continue; - } - - if ((requestedPermissionInfo.protectionLevel - & PermissionInfo.PROTECTION_MASK_BASE) - != PermissionInfo.PROTECTION_DANGEROUS - || (requestedPermissionInfo.flags - & PermissionInfo.FLAG_INSTALLED) == 0 - || (requestedPermissionInfo.flags - & PermissionInfo.FLAG_REMOVED) != 0) { - continue; - } - - AppPermissionGroup group = AppPermissionGroup.create(mContext, - app, groupInfo, groupPermInfos, user); - - if (group == null) { - continue; - } - - String label = mSkipUi ? app.packageName - : app.applicationInfo.loadLabel(mPm).toString(); - - Drawable icon = null; - if (!mSkipUi) { - icon = iconFactory.getBadgedIcon(app.applicationInfo, - UserHandle.getUserId(group.getApp().applicationInfo.uid)); - } - - PermissionApp permApp = new PermissionApp(app.packageName, group, label, icon, - app.applicationInfo); - - permApps.add(permApp); - break; // move to the next app. - } - } - } - - Collections.sort(permApps); - - return permApps; - } - - private void createMap(List<PermissionApp> result) { - mAppLookup = new ArrayMap<>(); - for (PermissionApp app : result) { - mAppLookup.put(app.getKey(), app); - } - mPermApps = result; - } - - private PackageItemInfo getGroupInfo(String groupName) { - try { - return mContext.getPackageManager().getPermissionGroupInfo(groupName, 0); - } catch (NameNotFoundException e) { - /* ignore */ - } - try { - return mContext.getPackageManager().getPermissionInfo(groupName, 0); - } catch (NameNotFoundException e2) { - /* ignore */ - } - return null; - } - - private List<PermissionInfo> getGroupPermissionInfos(String groupName) { - try { - return mContext.getPackageManager().queryPermissionsByGroup(groupName, 0); - } catch (NameNotFoundException e) { - /* ignore */ - } - try { - PermissionInfo permissionInfo = mContext.getPackageManager() - .getPermissionInfo(groupName, 0); - List<PermissionInfo> permissions = new ArrayList<>(); - permissions.add(permissionInfo); - return permissions; - } catch (NameNotFoundException e2) { - /* ignore */ - } - return null; - } - - private void loadGroupInfo() { - PackageItemInfo info; - try { - info = mPm.getPermissionGroupInfo(mGroupName, 0); - } catch (PackageManager.NameNotFoundException e) { - try { - PermissionInfo permInfo = mPm.getPermissionInfo(mGroupName, 0); - if ((permInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) - != PermissionInfo.PROTECTION_DANGEROUS) { - Log.w(LOG_TAG, mGroupName + " is not a runtime permission"); - return; - } - info = permInfo; - } catch (NameNotFoundException reallyNotFound) { - Log.w(LOG_TAG, "Can't find permission: " + mGroupName, reallyNotFound); - return; - } - } - mLabel = info.loadLabel(mPm); - if (info.icon != 0) { - mIcon = info.loadUnbadgedIcon(mPm); - } else { - mIcon = mContext.getDrawable(R.drawable.ic_perm_device_info); - } - mIcon = Utils.applyTint(mContext, mIcon, android.R.attr.colorControlNormal); - } - - public static class PermissionApp implements Comparable<PermissionApp> { - private final String mPackageName; - private final AppPermissionGroup mAppPermissionGroup; - private final String mLabel; - private final Drawable mIcon; - private final ApplicationInfo mInfo; - - public PermissionApp(String packageName, AppPermissionGroup appPermissionGroup, - String label, Drawable icon, ApplicationInfo info) { - mPackageName = packageName; - mAppPermissionGroup = appPermissionGroup; - mLabel = label; - mIcon = icon; - mInfo = info; - } - - public ApplicationInfo getAppInfo() { - return mInfo; - } - - public String getKey() { - return mPackageName + getUid(); - } - - public String getLabel() { - return mLabel; - } - - public Drawable getIcon() { - return mIcon; - } - - public boolean areRuntimePermissionsGranted() { - return mAppPermissionGroup.areRuntimePermissionsGranted(); - } - - public boolean isReviewRequired() { - return mAppPermissionGroup.isReviewRequired(); - } - - public void grantRuntimePermissions() { - mAppPermissionGroup.grantRuntimePermissions(false); - } - - public void revokeRuntimePermissions() { - mAppPermissionGroup.revokeRuntimePermissions(false); - } - - public boolean isPolicyFixed() { - return mAppPermissionGroup.isPolicyFixed(); - } - - public boolean isSystemFixed() { - return mAppPermissionGroup.isSystemFixed(); - } - - public boolean hasGrantedByDefaultPermissions() { - return mAppPermissionGroup.hasGrantedByDefaultPermission(); - } - - public boolean doesSupportRuntimePermissions() { - return mAppPermissionGroup.doesSupportRuntimePermissions(); - } - - public int getUserId() { - return mAppPermissionGroup.getUserId(); - } - - public String getPackageName() { - return mPackageName; - } - - public AppPermissionGroup getPermissionGroup() { - return mAppPermissionGroup; - } - - @Override - public int compareTo(PermissionApp another) { - final int result = mLabel.compareTo(another.mLabel); - if (result == 0) { - // Unbadged before badged. - return getKey().compareTo(another.getKey()); - } - return result; - } - - public int getUid() { - return mAppPermissionGroup.getApp().applicationInfo.uid; - } - } - - private class PermissionAppsLoader extends AsyncTask<Void, Void, List<PermissionApp>> { - - @Override - protected List<PermissionApp> doInBackground(Void... args) { - return loadPermissionApps(); - } - - @Override - protected void onPostExecute(List<PermissionApp> result) { - mRefreshing = false; - createMap(result); - if (mCallback != null) { - mCallback.onPermissionsLoaded(PermissionApps.this); - } - } - } - - /** - * Class used to reduce the number of calls to the package manager. - * This caches app information so it should only be used across parallel PermissionApps - * instances, and should not be retained across UI refresh. - */ - public static class PmCache { - private final SparseArray<List<PackageInfo>> mPackageInfoCache = new SparseArray<>(); - private final PackageManager mPm; - - public PmCache(PackageManager pm) { - mPm = pm; - } - - public synchronized List<PackageInfo> getPackages(int userId) { - List<PackageInfo> ret = mPackageInfoCache.get(userId); - if (ret == null) { - ret = mPm.getInstalledPackagesAsUser(PackageManager.GET_PERMISSIONS, userId); - mPackageInfoCache.put(userId, ret); - } - return ret; - } - } - - public interface Callback { - void onPermissionsLoaded(PermissionApps permissionApps); - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/model/PermissionGroup.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/model/PermissionGroup.java deleted file mode 100644 index ebef732f1d59..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/model/PermissionGroup.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2015 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.packageinstaller.permission.model; - -import android.graphics.drawable.Drawable; - -/** - * A permission group with runtime permission as defined in an app's manifest as - * {@code android:permission-group}. - * - * <p>For individual permissions that are not part of any group a {@link PermissionGroup} is created - * dynamically with the name and icon of the individual permission. - */ -public final class PermissionGroup implements Comparable<PermissionGroup> { - private final String mName; - private final String mDeclaringPackage; - private final CharSequence mLabel; - private final Drawable mIcon; - private final int mTotal; - private final int mGranted; - - PermissionGroup(String name, String declaringPackage, CharSequence label, Drawable icon, - int total, int granted) { - mDeclaringPackage = declaringPackage; - mName = name; - mLabel = label; - mIcon = icon; - mTotal = total; - mGranted = granted; - } - - public String getName() { - return mName; - } - - public String getDeclaringPackage() { - return mDeclaringPackage; - } - - public CharSequence getLabel() { - return mLabel; - } - - public Drawable getIcon() { - return mIcon; - } - - /** - * @return The number of apps that might request permissions of this group - */ - public int getTotal() { - return mTotal; - } - - /** - * @return The number of apps that were granted permissions of this group - */ - public int getGranted() { - return mGranted; - } - - @Override - public int compareTo(PermissionGroup another) { - return mLabel.toString().compareTo(another.mLabel.toString()); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj == null) { - return false; - } - - if (getClass() != obj.getClass()) { - return false; - } - - PermissionGroup other = (PermissionGroup) obj; - - if (mName == null) { - if (other.mName != null) { - return false; - } - } else if (!mName.equals(other.mName)) { - return false; - } - - if (mTotal != other.mTotal) { - return false; - } - - if (mGranted != other.mGranted) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - return mName != null ? mName.hashCode() + mTotal + mGranted : mTotal + mGranted; - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/model/PermissionGroups.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/model/PermissionGroups.java deleted file mode 100644 index 491b059909f1..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/model/PermissionGroups.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright (C) 2015 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.packageinstaller.permission.model; - -import static android.content.pm.PackageItemInfo.SAFE_LABEL_FLAG_FIRST_LINE; -import static android.content.pm.PackageItemInfo.SAFE_LABEL_FLAG_TRIM; - -import android.app.LoaderManager; -import android.app.LoaderManager.LoaderCallbacks; -import android.content.AsyncTaskLoader; -import android.content.Context; -import android.content.Loader; -import android.content.pm.PackageInfo; -import android.content.pm.PackageItemInfo; -import android.content.pm.PackageManager; -import android.content.pm.PermissionGroupInfo; -import android.content.pm.PermissionInfo; -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import android.util.ArraySet; - -import com.android.packageinstaller.R; -import com.android.packageinstaller.permission.utils.Utils; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Set; - -/** - * All {@link PermissionGroup permission groups} defined by any app. - */ -public final class PermissionGroups implements LoaderCallbacks<List<PermissionGroup>> { - private final ArrayList<PermissionGroup> mGroups = new ArrayList<>(); - private final Context mContext; - private final LoaderManager mLoaderManager; - private final PermissionsGroupsChangeCallback mCallback; - - public interface PermissionsGroupsChangeCallback { - public void onPermissionGroupsChanged(); - } - - public PermissionGroups(Context context, LoaderManager loaderManager, - PermissionsGroupsChangeCallback callback) { - mContext = context; - mLoaderManager = loaderManager; - mCallback = callback; - mLoaderManager.initLoader(0, null, this); - } - - @Override - public Loader<List<PermissionGroup>> onCreateLoader(int id, Bundle args) { - return new PermissionsLoader(mContext); - } - - @Override - public void onLoadFinished(Loader<List<PermissionGroup>> loader, - List<PermissionGroup> groups) { - if (mGroups.equals(groups)) { - return; - } - mGroups.clear(); - mGroups.addAll(groups); - mCallback.onPermissionGroupsChanged(); - } - - @Override - public void onLoaderReset(Loader<List<PermissionGroup>> loader) { - mGroups.clear(); - mCallback.onPermissionGroupsChanged(); - } - - public List<PermissionGroup> getGroups() { - return mGroups; - } - - public PermissionGroup getGroup(String name) { - for (PermissionGroup group : mGroups) { - if (group.getName().equals(name)) { - return group; - } - } - return null; - } - - private static final class PermissionsLoader extends AsyncTaskLoader<List<PermissionGroup>> - implements PackageManager.OnPermissionsChangedListener { - - public PermissionsLoader(Context context) { - super(context); - } - - @Override - protected void onStartLoading() { - getContext().getPackageManager().addOnPermissionsChangeListener(this); - forceLoad(); - } - - @Override - protected void onStopLoading() { - getContext().getPackageManager().removeOnPermissionsChangeListener(this); - } - - @Override - public List<PermissionGroup> loadInBackground() { - ArraySet<String> launcherPkgs = Utils.getLauncherPackages(getContext()); - PermissionApps.PmCache pmCache = new PermissionApps.PmCache( - getContext().getPackageManager()); - - List<PermissionGroup> groups = new ArrayList<>(); - Set<String> seenPermissions = new ArraySet<>(); - - PackageManager packageManager = getContext().getPackageManager(); - List<PermissionGroupInfo> groupInfos = packageManager.getAllPermissionGroups(0); - - for (PermissionGroupInfo groupInfo : groupInfos) { - // Mare sure we respond to cancellation. - if (isLoadInBackgroundCanceled()) { - return Collections.emptyList(); - } - - // Get the permissions in this group. - final List<PermissionInfo> groupPermissions; - try { - groupPermissions = packageManager.queryPermissionsByGroup(groupInfo.name, 0); - } catch (PackageManager.NameNotFoundException e) { - continue; - } - - boolean hasRuntimePermissions = false; - - // Cache seen permissions and see if group has runtime permissions. - for (PermissionInfo groupPermission : groupPermissions) { - seenPermissions.add(groupPermission.name); - if ((groupPermission.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) - == PermissionInfo.PROTECTION_DANGEROUS - && (groupPermission.flags & PermissionInfo.FLAG_INSTALLED) != 0 - && (groupPermission.flags & PermissionInfo.FLAG_REMOVED) == 0) { - hasRuntimePermissions = true; - } - } - - // No runtime permissions - not interesting for us. - if (!hasRuntimePermissions) { - continue; - } - - CharSequence label = loadItemInfoLabel(groupInfo); - Drawable icon = loadItemInfoIcon(groupInfo); - - PermissionApps permApps = new PermissionApps(getContext(), groupInfo.name, null, - pmCache); - permApps.refreshSync(); - - // Create the group and add to the list. - PermissionGroup group = new PermissionGroup(groupInfo.name, - groupInfo.packageName, label, icon, permApps.getTotalCount(launcherPkgs), - permApps.getGrantedCount(launcherPkgs)); - groups.add(group); - } - - - // Make sure we add groups for lone runtime permissions. - List<PackageInfo> installedPackages = getContext().getPackageManager() - .getInstalledPackages(PackageManager.GET_PERMISSIONS); - - - // We will filter out permissions that no package requests. - Set<String> requestedPermissions = new ArraySet<>(); - for (PackageInfo installedPackage : installedPackages) { - if (installedPackage.requestedPermissions == null) { - continue; - } - for (String requestedPermission : installedPackage.requestedPermissions) { - requestedPermissions.add(requestedPermission); - } - } - - for (PackageInfo installedPackage : installedPackages) { - if (installedPackage.permissions == null) { - continue; - } - - for (PermissionInfo permissionInfo : installedPackage.permissions) { - // If we have handled this permission, no more work to do. - if (!seenPermissions.add(permissionInfo.name)) { - continue; - } - - // We care only about installed runtime permissions. - if ((permissionInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) - != PermissionInfo.PROTECTION_DANGEROUS - || (permissionInfo.flags & PermissionInfo.FLAG_INSTALLED) == 0) { - continue; - } - - // If no app uses this permission, - if (!requestedPermissions.contains(permissionInfo.name)) { - continue; - } - - CharSequence label = loadItemInfoLabel(permissionInfo); - Drawable icon = loadItemInfoIcon(permissionInfo); - - PermissionApps permApps = new PermissionApps(getContext(), permissionInfo.name, - null, pmCache); - permApps.refreshSync(); - - // Create the group and add to the list. - PermissionGroup group = new PermissionGroup(permissionInfo.name, - permissionInfo.packageName, label, icon, - permApps.getTotalCount(launcherPkgs), - permApps.getGrantedCount(launcherPkgs)); - groups.add(group); - } - } - - Collections.sort(groups); - return groups; - } - - private CharSequence loadItemInfoLabel(PackageItemInfo itemInfo) { - CharSequence label = itemInfo.loadSafeLabel(getContext().getPackageManager(), 0, - SAFE_LABEL_FLAG_FIRST_LINE | SAFE_LABEL_FLAG_TRIM); - if (label == null) { - label = itemInfo.name; - } - return label; - } - - private Drawable loadItemInfoIcon(PackageItemInfo itemInfo) { - Drawable icon = null; - if (itemInfo.icon > 0) { - icon = Utils.loadDrawable(getContext().getPackageManager(), - itemInfo.packageName, itemInfo.icon); - } - if (icon == null) { - icon = getContext().getDrawable(R.drawable.ic_perm_device_info); - } - return icon; - } - - @Override - public void onPermissionsChanged(int uid) { - forceLoad(); - } - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/service/RuntimePermissionPresenterServiceImpl.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/service/RuntimePermissionPresenterServiceImpl.java deleted file mode 100644 index ab19fa11a613..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/service/RuntimePermissionPresenterServiceImpl.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2016 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.packageinstaller.permission.service; - -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.permission.RuntimePermissionPresentationInfo; -import android.permissionpresenterservice.RuntimePermissionPresenterService; -import android.util.Log; - -import com.android.packageinstaller.permission.model.AppPermissionGroup; -import com.android.packageinstaller.permission.model.AppPermissions; -import com.android.packageinstaller.permission.utils.Utils; - -import java.util.ArrayList; -import java.util.List; - -/** - * Service that provides presentation information for runtime permissions. - */ -public final class RuntimePermissionPresenterServiceImpl extends RuntimePermissionPresenterService { - private static final String LOG_TAG = "PermissionPresenter"; - - @Override - public List<RuntimePermissionPresentationInfo> onGetAppPermissions(String packageName) { - final PackageInfo packageInfo; - try { - packageInfo = getPackageManager().getPackageInfo(packageName, - PackageManager.GET_PERMISSIONS); - } catch (PackageManager.NameNotFoundException e) { - Log.e(LOG_TAG, "Error getting package:" + packageName, e); - return null; - } - - List<RuntimePermissionPresentationInfo> permissions = new ArrayList<>(); - - AppPermissions appPermissions = new AppPermissions(this, packageInfo, false, null); - for (AppPermissionGroup group : appPermissions.getPermissionGroups()) { - if (Utils.shouldShowPermission(group)) { - final boolean granted = group.areRuntimePermissionsGranted(); - final boolean standard = Utils.OS_PKG.equals(group.getDeclaringPackage()); - RuntimePermissionPresentationInfo permission = - new RuntimePermissionPresentationInfo(group.getLabel(), - granted, standard); - permissions.add(permission); - } - } - - return permissions; - } - - @Override - public void onRevokeRuntimePermission(String packageName, String permissionName) { - try { - final PackageInfo packageInfo = getPackageManager().getPackageInfo(packageName, - PackageManager.GET_PERMISSIONS); - final AppPermissions appPermissions = new AppPermissions(this, packageInfo, false, - null); - - final AppPermissionGroup appPermissionGroup = appPermissions.getGroupForPermission( - permissionName); - - if (appPermissionGroup != null) { - appPermissionGroup.revokeRuntimePermissions(false); - } - } catch (PackageManager.NameNotFoundException e) { - Log.e(LOG_TAG, "Error getting package:" + packageName, e); - } - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/ButtonBarLayout.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/ButtonBarLayout.java deleted file mode 100644 index 8b0f219b9bf4..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/ButtonBarLayout.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2015 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.packageinstaller.permission.ui; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.Gravity; -import android.view.View; -import android.widget.LinearLayout; - -import com.android.packageinstaller.R; - -/** - * An extension of LinearLayout that automatically switches to vertical - * orientation when it can't fit its child views horizontally. - */ -public class ButtonBarLayout extends LinearLayout { - /** Whether the current configuration allows stacking. */ - private boolean mAllowStacking; - - private int mLastWidthSize = -1; - - public ButtonBarLayout(Context context, AttributeSet attrs) { - super(context, attrs); - mAllowStacking = true; - } - - public void setAllowStacking(boolean allowStacking) { - if (mAllowStacking != allowStacking) { - mAllowStacking = allowStacking; - if (!mAllowStacking && getOrientation() == LinearLayout.VERTICAL) { - setStacked(false); - } - requestLayout(); - } - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - final int widthSize = MeasureSpec.getSize(widthMeasureSpec); - - if (mAllowStacking) { - if (widthSize > mLastWidthSize && isStacked()) { - // We're being measured wider this time, try un-stacking. - setStacked(false); - } - - mLastWidthSize = widthSize; - } - - boolean needsRemeasure = false; - - // If we're not stacked, make sure the measure spec is AT_MOST rather - // than EXACTLY. This ensures that we'll still get TOO_SMALL so that we - // know to stack the buttons. - final int initialWidthMeasureSpec; - if (!isStacked() && MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY) { - initialWidthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.AT_MOST); - - // We'll need to remeasure again to fill excess space. - needsRemeasure = true; - } else { - initialWidthMeasureSpec = widthMeasureSpec; - } - - super.onMeasure(initialWidthMeasureSpec, heightMeasureSpec); - - if (mAllowStacking && !isStacked()) { - final int measuredWidth = getMeasuredWidthAndState(); - final int measuredWidthState = measuredWidth & MEASURED_STATE_MASK; - if (measuredWidthState == MEASURED_STATE_TOO_SMALL) { - setStacked(true); - - // Measure again in the new orientation. - needsRemeasure = true; - } - } - - if (needsRemeasure) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } - } - - private void setStacked(boolean stacked) { - setOrientation(stacked ? LinearLayout.VERTICAL : LinearLayout.HORIZONTAL); - setGravity(stacked ? Gravity.END : Gravity.BOTTOM); - - final View spacer = findViewById(R.id.spacer); - if (spacer != null) { - spacer.setVisibility(stacked ? View.GONE : View.INVISIBLE); - } - } - - private boolean isStacked() { - return getOrientation() == LinearLayout.VERTICAL; - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/ConfirmActionDialogFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/ConfirmActionDialogFragment.java deleted file mode 100644 index c13f63098230..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/ConfirmActionDialogFragment.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2015 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.packageinstaller.permission.ui; - -import android.app.Activity; -import android.app.AlertDialog; -import android.app.Dialog; -import android.os.Bundle; - -import androidx.fragment.app.DialogFragment; - -import com.android.packageinstaller.R; - -public final class ConfirmActionDialogFragment extends DialogFragment { - public static final String ARG_MESSAGE = "MESSAGE"; - public static final String ARG_ACTION = "ACTION"; - - public interface OnActionConfirmedListener { - void onActionConfirmed(String action); - } - - public static ConfirmActionDialogFragment newInstance(CharSequence message, String action) { - Bundle arguments = new Bundle(); - arguments.putCharSequence(ARG_MESSAGE, message); - arguments.putString(ARG_ACTION, action); - ConfirmActionDialogFragment fragment = new ConfirmActionDialogFragment(); - fragment.setArguments(arguments); - return fragment; - } - - @Override - public Dialog onCreateDialog(Bundle bundle) { - return new AlertDialog.Builder(getContext()) - .setMessage(getArguments().getString(ARG_MESSAGE)) - .setNegativeButton(R.string.cancel, null) - .setPositiveButton(R.string.grant_dialog_button_deny_anyway, - (dialog, which) -> { - Activity activity = getActivity(); - if (activity instanceof OnActionConfirmedListener) { - String groupName = getArguments().getString(ARG_ACTION); - ((OnActionConfirmedListener) activity) - .onActionConfirmed(groupName); - } - }) - .create(); - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java deleted file mode 100644 index 51bd2836a282..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java +++ /dev/null @@ -1,834 +0,0 @@ -/* - * Copyright (C) 2015 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.packageinstaller.permission.ui; - -import static android.content.pm.PackageManager.PERMISSION_DENIED; - -import static com.android.packageinstaller.permission.ui.GrantPermissionsViewHandler.DENIED; -import static com.android.packageinstaller.permission.ui.GrantPermissionsViewHandler - .DENIED_DO_NOT_ASK_AGAIN; -import static com.android.packageinstaller.permission.ui.GrantPermissionsViewHandler.GRANTED_ALWAYS; -import static com.android.packageinstaller.permission.ui.GrantPermissionsViewHandler - .GRANTED_FOREGROUND_ONLY; -import static com.android.packageinstaller.permission.utils.Utils.getRequestMessage; - -import android.app.admin.DevicePolicyManager; -import android.content.Intent; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.pm.PackageParser; -import android.content.res.Resources; -import android.graphics.drawable.Icon; -import android.os.Build; -import android.os.Bundle; -import android.text.Html; -import android.text.Spanned; -import android.util.ArrayMap; -import android.util.Log; -import android.util.Pair; -import android.view.KeyEvent; -import android.view.MotionEvent; -import android.view.View; -import android.view.Window; -import android.view.WindowManager; - -import com.android.internal.content.PackageMonitor; -import com.android.internal.logging.nano.MetricsProto; -import com.android.packageinstaller.DeviceUtils; -import com.android.packageinstaller.R; -import com.android.packageinstaller.permission.model.AppPermissionGroup; -import com.android.packageinstaller.permission.model.AppPermissions; -import com.android.packageinstaller.permission.model.Permission; -import com.android.packageinstaller.permission.ui.auto.GrantPermissionsAutoViewHandler; -import com.android.packageinstaller.permission.utils.ArrayUtils; -import com.android.packageinstaller.permission.utils.EventLogger; -import com.android.packageinstaller.permission.utils.SafetyNetLogger; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class GrantPermissionsActivity extends OverlayTouchActivity - implements GrantPermissionsViewHandler.ResultListener { - - private static final String LOG_TAG = "GrantPermissionsActivity"; - - private String[] mRequestedPermissions; - - private ArrayMap<Pair<String, Boolean>, GroupState> mRequestGrantPermissionGroups = - new ArrayMap<>(); - - private GrantPermissionsViewHandler mViewHandler; - private AppPermissions mAppPermissions; - - boolean mResultSet; - - private PackageManager.OnPermissionsChangedListener mPermissionChangeListener; - private PackageMonitor mPackageMonitor; - - private String mCallingPackage; - - private int getPermissionPolicy() { - DevicePolicyManager devicePolicyManager = getSystemService(DevicePolicyManager.class); - return devicePolicyManager.getPermissionPolicy(null); - } - - /** - * Try to add a single permission that is requested to be granted. - * - * <p>This does <u>not</u> expand the permissions into the {@link #computeAffectedPermissions - * affected permissions}. - * - * @param group The group the permission belongs to (might be a background permission group) - * @param permission The permission to add - * @param isFirstInstance Is this the first time the groupStates get created - */ - private void addRequestedPermissions(AppPermissionGroup group, String permission, - boolean isFirstInstance) { - if (!group.isGrantingAllowed()) { - // Skip showing groups that we know cannot be granted. - return; - } - - // We allow the user to choose only non-fixed permissions. A permission - // is fixed either by device policy or the user denying with prejudice. - if (!group.isUserFixed() && !group.isPolicyFixed()) { - Pair<String, Boolean> groupKey = new Pair<>(group.getName(), - group.isBackgroundGroup()); - - GroupState state = mRequestGrantPermissionGroups.get(groupKey); - if (state == null) { - state = new GroupState(group); - mRequestGrantPermissionGroups.put(groupKey, state); - } - state.affectedPermissions = ArrayUtils.appendString( - state.affectedPermissions, permission); - - boolean skipGroup = false; - switch (getPermissionPolicy()) { - case DevicePolicyManager.PERMISSION_POLICY_AUTO_GRANT: { - if (!group.areRuntimePermissionsGranted()) { - group.grantRuntimePermissions(false, new String[]{permission}); - } - state.mState = GroupState.STATE_ALLOWED; - group.setPolicyFixed(); - skipGroup = true; - } break; - - case DevicePolicyManager.PERMISSION_POLICY_AUTO_DENY: { - if (group.areRuntimePermissionsGranted()) { - group.revokeRuntimePermissions(false, new String[]{permission}); - } - state.mState = GroupState.STATE_DENIED; - group.setPolicyFixed(); - skipGroup = true; - } break; - - default: { - if (group.areRuntimePermissionsGranted()) { - group.grantRuntimePermissions(false, new String[]{permission}); - state.mState = GroupState.STATE_ALLOWED; - skipGroup = true; - } - } break; - } - - if (skipGroup && isFirstInstance) { - // Only allow to skip groups when this is the first time the dialog was created. - // Otherwise the number of groups changes between instances of the dialog. - state.mState = GroupState.STATE_SKIPPED; - } - } - } - - @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - - // Cache this as this can only read on onCreate, not later. - mCallingPackage = getCallingPackage(); - - mPackageMonitor = new PackageMonitor() { - @Override - public void onPackageRemoved(String packageName, int uid) { - if (mCallingPackage.equals(packageName)) { - Log.w(LOG_TAG, mCallingPackage + " was uninstalled"); - - finish(); - } - } - }; - - setFinishOnTouchOutside(false); - - getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); - getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); - - setTitle(R.string.permission_request_title); - - if (DeviceUtils.isTelevision(this)) { - mViewHandler = new com.android.packageinstaller.permission.ui.television - .GrantPermissionsViewHandlerImpl(this, - mCallingPackage).setResultListener(this); - } else if (DeviceUtils.isWear(this)) { - mViewHandler = new GrantPermissionsWatchViewHandler(this).setResultListener(this); - } else if (DeviceUtils.isAuto(this)) { - mViewHandler = new GrantPermissionsAutoViewHandler(this, mCallingPackage) - .setResultListener(this); - } else { - mViewHandler = new com.android.packageinstaller.permission.ui.handheld - .GrantPermissionsViewHandlerImpl(this, mCallingPackage) - .setResultListener(this); - } - - mRequestedPermissions = getIntent().getStringArrayExtra( - PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES); - if (mRequestedPermissions == null) { - mRequestedPermissions = new String[0]; - } - - final int requestedPermCount = mRequestedPermissions.length; - - if (requestedPermCount == 0) { - setResultAndFinish(); - return; - } - - try { - mPermissionChangeListener = new PermissionChangeListener(); - } catch (NameNotFoundException e) { - setResultAndFinish(); - return; - } - - PackageInfo callingPackageInfo = getCallingPackageInfo(); - - if (callingPackageInfo == null || callingPackageInfo.requestedPermissions == null - || callingPackageInfo.requestedPermissions.length <= 0) { - setResultAndFinish(); - return; - } - - // Don't allow legacy apps to request runtime permissions. - if (callingPackageInfo.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { - // Returning empty arrays means a cancellation. - mRequestedPermissions = new String[0]; - setResultAndFinish(); - return; - } - - mAppPermissions = new AppPermissions(this, callingPackageInfo, false, - new Runnable() { - @Override - public void run() { - setResultAndFinish(); - } - }); - - for (String requestedPermission : mRequestedPermissions) { - if (requestedPermission == null) { - continue; - } - - ArrayList<String> affectedPermissions = - computeAffectedPermissions(requestedPermission); - - int numAffectedPermissions = affectedPermissions.size(); - for (int i = 0; i < numAffectedPermissions; i++) { - AppPermissionGroup group = - mAppPermissions.getGroupForPermission(affectedPermissions.get(i)); - if (group == null) { - continue; - } - - addRequestedPermissions(group, affectedPermissions.get(i), icicle == null); - } - } - - int numGroupStates = mRequestGrantPermissionGroups.size(); - for (int groupStateNum = 0; groupStateNum < numGroupStates; groupStateNum++) { - GroupState groupState = mRequestGrantPermissionGroups.valueAt(groupStateNum); - AppPermissionGroup group = groupState.mGroup; - - // Restore permission group state after lifecycle events - if (icicle != null) { - groupState.mState = icicle.getInt( - getInstanceStateKey(mRequestGrantPermissionGroups.keyAt(groupStateNum)), - groupState.mState); - } - - // Do not attempt to grant background access if foreground access is not either already - // granted or requested - if (group.isBackgroundGroup()) { - // Check if a foreground permission is already granted - boolean foregroundGroupAlreadyGranted = mAppPermissions.getPermissionGroup( - group.getName()).areRuntimePermissionsGranted(); - boolean hasForegroundRequest = (getForegroundGroupState(group.getName()) != null); - - if (!foregroundGroupAlreadyGranted && !hasForegroundRequest) { - // The background permission cannot be granted at this time - int numPermissions = groupState.affectedPermissions.length; - for (int permissionNum = 0; permissionNum < numPermissions; permissionNum++) { - Log.w(LOG_TAG, - "Cannot grant " + groupState.affectedPermissions[permissionNum] - + " as the matching foreground permission is not already " - + "granted."); - } - - groupState.mState = GroupState.STATE_SKIPPED; - } - } - } - - setContentView(mViewHandler.createView()); - - Window window = getWindow(); - WindowManager.LayoutParams layoutParams = window.getAttributes(); - mViewHandler.updateWindowAttributes(layoutParams); - window.setAttributes(layoutParams); - - // Restore UI state after lifecycle events. This has to be before - // showNextPermissionGroupGrantRequest is called. showNextPermissionGroupGrantRequest might - // update the UI and the UI behaves differently for updates and initial creations. - if (icicle != null) { - mViewHandler.loadInstanceState(icicle); - } - - if (!showNextPermissionGroupGrantRequest()) { - setResultAndFinish(); - } else if (icicle == null) { - int numRequestedPermissions = mRequestedPermissions.length; - for (int permissionNum = 0; permissionNum < numRequestedPermissions; permissionNum++) { - String permission = mRequestedPermissions[permissionNum]; - - EventLogger.logPermission( - MetricsProto.MetricsEvent.ACTION_PERMISSION_REQUESTED, permission, - mAppPermissions.getPackageInfo().packageName); - } - } - } - - /** - * Update the {@link #mRequestedPermissions} if the system reports them as granted. - * - * <p>This also updates the {@link #mAppPermissions} state and switches to the next group grant - * request if the current group becomes granted. - */ - private void updateIfPermissionsWereGranted() { - PackageManager pm = getPackageManager(); - - boolean mightShowNextGroup = true; - int numGroupStates = mRequestGrantPermissionGroups.size(); - for (int i = 0; i < numGroupStates; i++) { - GroupState groupState = mRequestGrantPermissionGroups.valueAt(i); - - if (groupState == null || groupState.mState != GroupState.STATE_UNKNOWN) { - // Group has already been approved / denied via the UI by the user - continue; - } - - boolean allAffectedPermissionsOfThisGroupAreGranted = true; - - if (groupState.affectedPermissions == null) { - // It is not clear which permissions belong to this group, hence never skip this - // view - allAffectedPermissionsOfThisGroupAreGranted = false; - } else { - for (int permNum = 0; permNum < groupState.affectedPermissions.length; - permNum++) { - if (pm.checkPermission(groupState.affectedPermissions[permNum], mCallingPackage) - == PERMISSION_DENIED) { - allAffectedPermissionsOfThisGroupAreGranted = false; - break; - } - } - } - - if (allAffectedPermissionsOfThisGroupAreGranted) { - groupState.mState = GroupState.STATE_ALLOWED; - - if (mightShowNextGroup) { - // The UI currently displays the first group with - // mState == STATE_UNKNOWN. So we are switching to next group until we - // could not allow a group that was still unknown - if (!showNextPermissionGroupGrantRequest()) { - setResultAndFinish(); - } - } - } else { - mightShowNextGroup = false; - } - } - } - - @Override - protected void onStart() { - super.onStart(); - - PackageManager pm = getPackageManager(); - pm.addOnPermissionsChangeListener(mPermissionChangeListener); - - // get notified when the package is removed - mPackageMonitor.register(this, getMainLooper(), false); - - // check if the package was removed while this activity was not started - try { - pm.getPackageInfo(mCallingPackage, 0); - } catch (NameNotFoundException e) { - Log.w(LOG_TAG, mCallingPackage + " was uninstalled while this activity was stopped", e); - finish(); - } - - updateIfPermissionsWereGranted(); - } - - @Override - protected void onStop() { - super.onStop(); - - mPackageMonitor.unregister(); - - getPackageManager().removeOnPermissionsChangeListener(mPermissionChangeListener); - } - - @Override - public boolean dispatchTouchEvent(MotionEvent ev) { - View rootView = getWindow().getDecorView(); - if (rootView.getTop() != 0) { - // We are animating the top view, need to compensate for that in motion events. - ev.setLocation(ev.getX(), ev.getY() - rootView.getTop()); - } - return super.dispatchTouchEvent(ev); - } - - /** - * Compose a key that stores the GroupState.mState in the instance state. - * - * @param requestGrantPermissionGroupsKey The key of the permission group - * - * @return A unique key to be used in the instance state - */ - private static String getInstanceStateKey( - Pair<String, Boolean> requestGrantPermissionGroupsKey) { - return GrantPermissionsActivity.class.getName() + "_" - + requestGrantPermissionGroupsKey.first + "_" - + requestGrantPermissionGroupsKey.second; - } - - @Override - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - - mViewHandler.saveInstanceState(outState); - - int numGroups = mRequestGrantPermissionGroups.size(); - for (int i = 0; i < numGroups; i++) { - int state = mRequestGrantPermissionGroups.valueAt(i).mState; - - if (state != GroupState.STATE_UNKNOWN) { - outState.putInt(getInstanceStateKey(mRequestGrantPermissionGroups.keyAt(i)), state); - } - } - } - - /** - * @return the background group state for the permission group with the {@code name} - */ - private GroupState getBackgroundGroupState(String name) { - return mRequestGrantPermissionGroups.get(new Pair<>(name, true)); - } - - /** - * @return the foreground group state for the permission group with the {@code name} - */ - private GroupState getForegroundGroupState(String name) { - return mRequestGrantPermissionGroups.get(new Pair<>(name, false)); - } - - private boolean shouldShowRequestForGroupState(GroupState groupState) { - if (groupState.mState == GroupState.STATE_SKIPPED) { - return false; - } - - GroupState foregroundGroup = getForegroundGroupState(groupState.mGroup.getName()); - if (groupState.mGroup.isBackgroundGroup() - && (foregroundGroup != null && shouldShowRequestForGroupState(foregroundGroup))) { - // If an app requests both foreground and background permissions of the same group, - // we only show one request - return false; - } - - return true; - } - - private boolean showNextPermissionGroupGrantRequest() { - int numGroupStates = mRequestGrantPermissionGroups.size(); - int numGrantRequests = 0; - for (int i = 0; i < numGroupStates; i++) { - if (shouldShowRequestForGroupState(mRequestGrantPermissionGroups.valueAt(i))) { - numGrantRequests++; - } - } - - int currentIndex = 0; - for (GroupState groupState : mRequestGrantPermissionGroups.values()) { - if (!shouldShowRequestForGroupState(groupState)) { - continue; - } - - if (groupState.mState == GroupState.STATE_UNKNOWN) { - GroupState foregroundGroupState; - GroupState backgroundGroupState; - if (groupState.mGroup.isBackgroundGroup()) { - backgroundGroupState = groupState; - foregroundGroupState = getForegroundGroupState(groupState.mGroup.getName()); - } else { - foregroundGroupState = groupState; - backgroundGroupState = getBackgroundGroupState(groupState.mGroup.getName()); - } - - CharSequence appLabel = mAppPermissions.getAppLabel(); - - // Set the new grant view - // TODO: Use a real message for the action. We need group action APIs - Resources resources; - try { - resources = getPackageManager().getResourcesForApplication( - groupState.mGroup.getIconPkg()); - } catch (NameNotFoundException e) { - // Fallback to system. - resources = Resources.getSystem(); - } - - Icon icon; - try { - icon = Icon.createWithResource(resources, groupState.mGroup.getIconResId()); - } catch (Resources.NotFoundException e) { - Log.e(LOG_TAG, "Cannot load icon for group" + groupState.mGroup.getName(), e); - icon = null; - } - - // If no background permissions are granted yet, we need to ask for background - // permissions - boolean needBackgroundPermission = false; - boolean isBackgroundPermissionUserSet = false; - if (backgroundGroupState != null) { - if (!backgroundGroupState.mGroup.areRuntimePermissionsGranted()) { - needBackgroundPermission = true; - isBackgroundPermissionUserSet = backgroundGroupState.mGroup.isUserSet(); - } - } - - // If no foreground permissions are granted yet, we need to ask for foreground - // permissions - boolean needForegroundPermission = false; - boolean isForegroundPermissionUserSet = false; - if (foregroundGroupState != null) { - if (!foregroundGroupState.mGroup.areRuntimePermissionsGranted()) { - needForegroundPermission = true; - isForegroundPermissionUserSet = foregroundGroupState.mGroup.isUserSet(); - } - } - - boolean showForegroundChooser = false; - int messageId; - int detailMessageId = 0; - if (needForegroundPermission) { - messageId = groupState.mGroup.getRequest(); - - if (needBackgroundPermission) { - showForegroundChooser = true; - } else { - if (foregroundGroupState.mGroup.hasPermissionWithBackgroundMode()) { - detailMessageId = groupState.mGroup.getRequestDetail(); - } - } - } else { - if (needBackgroundPermission) { - messageId = groupState.mGroup.getBackgroundRequest(); - detailMessageId = groupState.mGroup.getBackgroundRequestDetail(); - } else { - // Not reached as the permissions should be auto-granted - return false; - } - } - - CharSequence message = getRequestMessage(appLabel, groupState.mGroup, this, - messageId); - - Spanned detailMessage = null; - if (detailMessageId != 0) { - try { - detailMessage = Html.fromHtml( - getPackageManager().getResourcesForApplication( - groupState.mGroup.getDeclaringPackage()).getString( - detailMessageId), 0); - } catch (NameNotFoundException ignored) { - } - } - - // Set the permission message as the title so it can be announced. - setTitle(message); - - mViewHandler.updateUi(groupState.mGroup.getName(), numGrantRequests, currentIndex, - icon, message, detailMessage, showForegroundChooser, - isForegroundPermissionUserSet || isBackgroundPermissionUserSet); - - return true; - } - - if (groupState.mState != GroupState.STATE_SKIPPED) { - currentIndex++; - } - } - - return false; - } - - @Override - public void onPermissionGrantResult(String name, - @GrantPermissionsViewHandler.Result int result) { - GroupState foregroundGroupState = getForegroundGroupState(name); - GroupState backgroundGroupState = getBackgroundGroupState(name); - - switch (result) { - case GRANTED_ALWAYS : - if (foregroundGroupState != null) { - onPermissionGrantResultSingleState(foregroundGroupState, true, false); - } - if (backgroundGroupState != null) { - onPermissionGrantResultSingleState(backgroundGroupState, true, false); - } - break; - case GRANTED_FOREGROUND_ONLY : - if (foregroundGroupState != null) { - onPermissionGrantResultSingleState(foregroundGroupState, true, false); - } - if (backgroundGroupState != null) { - onPermissionGrantResultSingleState(backgroundGroupState, false, false); - } - break; - case DENIED : - if (foregroundGroupState != null) { - onPermissionGrantResultSingleState(foregroundGroupState, false, false); - } - if (backgroundGroupState != null) { - onPermissionGrantResultSingleState(backgroundGroupState, false, false); - } - break; - case DENIED_DO_NOT_ASK_AGAIN : - if (foregroundGroupState != null) { - onPermissionGrantResultSingleState(foregroundGroupState, false, true); - } - if (backgroundGroupState != null) { - onPermissionGrantResultSingleState(backgroundGroupState, false, true); - } - break; - } - - if (!showNextPermissionGroupGrantRequest()) { - setResultAndFinish(); - } - } - - /** - * Grants or revoked the affected permissions for a single {@link groupState}. - * - * @param groupState The group state with the permissions to grant/revoke - * @param granted {@code true} if the permissions should be granted, {@code false} if they - * should be revoked - * @param doNotAskAgain if the permissions should be revoked should be app be allowed to ask - * again for the same permissions? - */ - private void onPermissionGrantResultSingleState(GroupState groupState, boolean granted, - boolean doNotAskAgain) { - if (groupState != null && groupState.mGroup != null) { - if (granted) { - groupState.mGroup.grantRuntimePermissions(doNotAskAgain, - groupState.affectedPermissions); - groupState.mState = GroupState.STATE_ALLOWED; - } else { - groupState.mGroup.revokeRuntimePermissions(doNotAskAgain, - groupState.affectedPermissions); - groupState.mState = GroupState.STATE_DENIED; - - int numRequestedPermissions = mRequestedPermissions.length; - for (int i = 0; i < numRequestedPermissions; i++) { - String permission = mRequestedPermissions[i]; - - if (groupState.mGroup.hasPermission(permission)) { - EventLogger.logPermission( - MetricsProto.MetricsEvent.ACTION_PERMISSION_DENIED, permission, - mAppPermissions.getPackageInfo().packageName); - } - } - } - } - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - // We do not allow backing out. - return keyCode == KeyEvent.KEYCODE_BACK; - } - - @Override - public boolean onKeyUp(int keyCode, KeyEvent event) { - // We do not allow backing out. - return keyCode == KeyEvent.KEYCODE_BACK; - } - - @Override - public void finish() { - setResultIfNeeded(RESULT_CANCELED); - super.finish(); - } - - private PackageInfo getCallingPackageInfo() { - try { - return getPackageManager().getPackageInfo(mCallingPackage, - PackageManager.GET_PERMISSIONS); - } catch (NameNotFoundException e) { - Log.i(LOG_TAG, "No package: " + mCallingPackage, e); - return null; - } - } - - private void setResultIfNeeded(int resultCode) { - if (!mResultSet) { - mResultSet = true; - logRequestedPermissionGroups(); - Intent result = new Intent(PackageManager.ACTION_REQUEST_PERMISSIONS); - result.putExtra(PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES, mRequestedPermissions); - - PackageManager pm = getPackageManager(); - int numRequestedPermissions = mRequestedPermissions.length; - int[] grantResults = new int[numRequestedPermissions]; - for (int i = 0; i < numRequestedPermissions; i++) { - grantResults[i] = pm.checkPermission(mRequestedPermissions[i], mCallingPackage); - } - - result.putExtra(PackageManager.EXTRA_REQUEST_PERMISSIONS_RESULTS, grantResults); - setResult(resultCode, result); - } - } - - private void setResultAndFinish() { - setResultIfNeeded(RESULT_OK); - finish(); - } - - private void logRequestedPermissionGroups() { - if (mRequestGrantPermissionGroups.isEmpty()) { - return; - } - - final int groupCount = mRequestGrantPermissionGroups.size(); - List<AppPermissionGroup> groups = new ArrayList<>(groupCount); - for (GroupState groupState : mRequestGrantPermissionGroups.values()) { - groups.add(groupState.mGroup); - } - - SafetyNetLogger.logPermissionsRequested(mAppPermissions.getPackageInfo(), groups); - } - - /** - * Get the actually requested permissions when a permission is requested. - * - * <p>>In some cases requesting to grant a single permission requires the system to grant - * additional permissions. E.g. before N-MR1 a single permission of a group caused the whole - * group to be granted. Another case are permissions that are split into two. For apps that - * target an SDK before the split, this method automatically adds the split off permission. - * - * @param permission The requested permission - * - * @return The actually requested permissions - */ - private ArrayList<String> computeAffectedPermissions(String permission) { - int requestingAppTargetSDK = - mAppPermissions.getPackageInfo().applicationInfo.targetSdkVersion; - - // If a permission is split, all permissions the original permission is split into are - // affected - ArrayList<String> splitPerms = new ArrayList<>(); - splitPerms.add(permission); - for (PackageParser.SplitPermissionInfo splitPerm : PackageParser.SPLIT_PERMISSIONS) { - if (requestingAppTargetSDK < splitPerm.targetSdk - && permission.equals(splitPerm.rootPerm)) { - Collections.addAll(splitPerms, splitPerm.newPerms); - } - } - - // For <= N_MR1 apps all permissions of the groups of the requested permissions are affected - if (requestingAppTargetSDK <= Build.VERSION_CODES.N_MR1) { - ArrayList<String> extendedPermissions = new ArrayList<>(); - - int numSplitPerms = splitPerms.size(); - for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) { - AppPermissionGroup group = mAppPermissions.getGroupForPermission( - splitPerms.get(splitPermNum)); - - if (group == null) { - continue; - } - - ArrayList<Permission> permissionsInGroup = group.getPermissions(); - int numPermissionsInGroup = permissionsInGroup.size(); - for (int permNum = 0; permNum < numPermissionsInGroup; permNum++) { - extendedPermissions.add(permissionsInGroup.get(permNum).getName()); - } - } - - return extendedPermissions; - } else { - return splitPerms; - } - } - - private static final class GroupState { - static final int STATE_UNKNOWN = 0; - static final int STATE_ALLOWED = 1; - static final int STATE_DENIED = 2; - static final int STATE_SKIPPED = 3; - - final AppPermissionGroup mGroup; - int mState = STATE_UNKNOWN; - - /** Permissions of this group that need to be granted, null == no permissions of group */ - String[] affectedPermissions; - - GroupState(AppPermissionGroup group) { - mGroup = group; - } - } - - private class PermissionChangeListener implements PackageManager.OnPermissionsChangedListener { - final int mCallingPackageUid; - - PermissionChangeListener() throws NameNotFoundException { - mCallingPackageUid = getPackageManager().getPackageUid(mCallingPackage, 0); - } - - @Override - public void onPermissionsChanged(int uid) { - if (uid == mCallingPackageUid) { - updateIfPermissionsWereGranted(); - } - } - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/GrantPermissionsViewHandler.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/GrantPermissionsViewHandler.java deleted file mode 100644 index 3f637f0f2334..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/GrantPermissionsViewHandler.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2015 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.packageinstaller.permission.ui; - -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import android.graphics.drawable.Icon; -import android.os.Bundle; -import android.view.View; -import android.view.WindowManager; - -import androidx.annotation.IntDef; - -import java.lang.annotation.Retention; - -/** - * Class for managing the presentation and user interaction of the "grant - * permissions" user interface. - */ -public interface GrantPermissionsViewHandler { - @Retention(SOURCE) - @IntDef({GRANTED_ALWAYS, GRANTED_FOREGROUND_ONLY, DENIED, DENIED_DO_NOT_ASK_AGAIN}) - @interface Result {} - int GRANTED_ALWAYS = 0; - int GRANTED_FOREGROUND_ONLY = 1; - int DENIED = 2; - int DENIED_DO_NOT_ASK_AGAIN = 3; - - /** - * Listener interface for getting notified when the user responds to a - * permissions grant request. - */ - interface ResultListener { - void onPermissionGrantResult(String groupName, @Result int result); - } - - /** - * Creates and returns the view hierarchy that is managed by this view - * handler. This must be called before {@link #updateUi}. - */ - View createView(); - - /** - * Updates the layout attributes of the current window. This is an optional - * operation; implementations only need to do work in this method if they - * need to alter the default styles provided by the activity's theme. - */ - void updateWindowAttributes(WindowManager.LayoutParams outLayoutParams); - - /** - * Updates the view hierarchy to reflect the specified state. - * <p> - * Note that this must be called at least once before showing the UI to - * the user to properly initialize the UI. - * - * @param groupName the name of the permission group - * @param groupCount the total number of groups that are being requested - * @param groupIndex the index of the current group being requested - * @param icon the icon representation of the current group - * @param message the message to display the user - * @param detailMessage another message to display to the user. This clarifies "message" in more - * detail - * @param showForegroundChooser whether to show the "only in foreground / always" option - * @param showDoNotAsk whether to show the "do not ask again" option - */ - void updateUi(String groupName, int groupCount, int groupIndex, Icon icon, - CharSequence message, CharSequence detailMessage, boolean showForegroundChooser, - boolean showDoNotAsk); - - /** - * Sets the result listener that will be notified when the user responds - * to a permissions grant request. - */ - GrantPermissionsViewHandler setResultListener(ResultListener listener); - - /** - * Called by {@link GrantPermissionsActivity} to save the state of this - * view handler to the specified bundle. - */ - void saveInstanceState(Bundle outState); - - /** - * Called by {@link GrantPermissionsActivity} to load the state of this - * view handler from the specified bundle. - */ - void loadInstanceState(Bundle savedInstanceState); - - /** - * Gives a chance for handling the back key. - */ - void onBackPressed(); -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/GrantPermissionsWatchViewHandler.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/GrantPermissionsWatchViewHandler.java deleted file mode 100644 index f2251c1f3e7f..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/GrantPermissionsWatchViewHandler.java +++ /dev/null @@ -1,216 +0,0 @@ -package com.android.packageinstaller.permission.ui; - -import android.app.AlertDialog; -import android.app.Dialog; -import android.content.Context; -import android.content.DialogInterface; -import android.content.res.TypedArray; -import android.graphics.PixelFormat; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.Icon; -import android.os.Bundle; -import android.text.SpannableStringBuilder; -import android.text.Spanned; -import android.text.TextUtils; -import android.text.style.TextAppearanceSpan; -import android.util.Log; -import android.view.View; -import android.view.WindowManager; -import android.widget.Space; - -import androidx.wear.ble.view.AcceptDenyDialog; -import androidx.wear.ble.view.WearableDialogHelper; - -import com.android.packageinstaller.R; - -/** - * Watch-specific view handler for the grant permissions activity. - */ -final class GrantPermissionsWatchViewHandler implements GrantPermissionsViewHandler, - DialogInterface.OnClickListener { - private static final String TAG = "GrantPermsWatchViewH"; - - private static final String WATCH_HANDLER_BUNDLE = "watch_handler_bundle"; - private static final String DIALOG_BUNDLE = "dialog_bundle"; - private static final String GROUP_NAME = "group_name"; - private static final String SHOW_DO_NOT_ASK = "show_do_not_ask"; - private static final String ICON = "icon"; - private static final String MESSAGE = "message"; - private static final String CURRENT_PAGE_TEXT = "current_page_text"; - - private final Context mContext; - - private ResultListener mResultListener; - - private Dialog mDialog; - - private String mGroupName; - private boolean mShowDoNotAsk; - - private CharSequence mMessage; - private String mCurrentPageText; - private Icon mIcon; - - GrantPermissionsWatchViewHandler(Context context) { - mContext = context; - } - - @Override - public GrantPermissionsWatchViewHandler setResultListener(ResultListener listener) { - mResultListener = listener; - return this; - } - - @Override - public View createView() { - return new Space(mContext); - } - - @Override - public void updateWindowAttributes(WindowManager.LayoutParams outLayoutParams) { - outLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT; - outLayoutParams.height = WindowManager.LayoutParams.MATCH_PARENT; - outLayoutParams.format = PixelFormat.OPAQUE; - outLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG; - outLayoutParams.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; - } - - @Override - public void updateUi(String groupName, int groupCount, int groupIndex, Icon icon, - CharSequence message, CharSequence detailMessage, boolean showForegroundChooser, - boolean showDoNotAsk) { - // TODO: Handle detailMessage - // TODO: Handle showForegroundChooser - - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "updateUi() - groupName: " + groupName - + ", groupCount: " + groupCount - + ", groupIndex: " + groupIndex - + ", icon: " + icon - + ", message: " + message - + ", showDoNotAsk: " + showDoNotAsk); - } - - mGroupName = groupName; - mShowDoNotAsk = showDoNotAsk; - mMessage = message; - mIcon = icon; - mCurrentPageText = groupCount > 1 - ? mContext.getString(R.string.current_permission_template, - groupIndex + 1, groupCount) - : null; - showDialog(null); - } - - private void showDialog(Bundle savedInstanceState) { - TypedArray a = mContext.obtainStyledAttributes( - new int[] { android.R.attr.textColorPrimary }); - int color = a.getColor(0, mContext.getColor(android.R.color.white)); - a.recycle(); - Drawable drawable = mIcon == null ? null : mIcon.setTint(color).loadDrawable(mContext); - - SpannableStringBuilder ssb = new SpannableStringBuilder(); - if (!TextUtils.isEmpty(mCurrentPageText)) { - ssb.append(mCurrentPageText, new TextAppearanceSpan(mContext, R.style.BreadcrumbText), - Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - ssb.append('\n'); - } - if (!TextUtils.isEmpty(mMessage)) { - ssb.append(mMessage, new TextAppearanceSpan(mContext, R.style.TitleText), - Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - } - - if (mDialog != null) { - mDialog.dismiss(); - mDialog = null; - } - - if (mShowDoNotAsk) { - AlertDialog alertDialog = new WearableDialogHelper.DialogBuilder(mContext) - .setPositiveIcon(R.drawable.confirm_button) - .setNeutralIcon(R.drawable.cancel_button) - .setNegativeIcon(R.drawable.deny_button) - .setTitle(ssb) - .setIcon(drawable) - .setPositiveButton(R.string.grant_dialog_button_allow, this) - .setNeutralButton(R.string.grant_dialog_button_deny, this) - .setNegativeButton(R.string.grant_dialog_button_deny_dont_ask_again, this) - .show(); - alertDialog.getButton(DialogInterface.BUTTON_POSITIVE) - .setId(R.id.permission_allow_button); - alertDialog.getButton(DialogInterface.BUTTON_NEUTRAL) - .setId(R.id.permission_deny_button); - alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE) - .setId(R.id.permission_deny_dont_ask_again_button); - - mDialog = alertDialog; - } else { - AcceptDenyDialog acceptDenyDialog = new AcceptDenyDialog(mContext); - acceptDenyDialog.setTitle(ssb); - acceptDenyDialog.setIcon(drawable); - acceptDenyDialog.setPositiveButton(this); - acceptDenyDialog.setNegativeButton(this); - acceptDenyDialog.show(); - acceptDenyDialog.getButton(DialogInterface.BUTTON_POSITIVE) - .setId(R.id.permission_allow_button); - acceptDenyDialog.getButton(DialogInterface.BUTTON_NEGATIVE) - .setId(R.id.permission_deny_button); - - mDialog = acceptDenyDialog; - } - mDialog.setCancelable(false); - - if (savedInstanceState != null) { - mDialog.onRestoreInstanceState(savedInstanceState); - } - } - - @Override - public void saveInstanceState(Bundle outState) { - Bundle b = new Bundle(); - b.putByte(SHOW_DO_NOT_ASK, (byte) (mShowDoNotAsk ? 1 : 0)); - b.putString(GROUP_NAME, mGroupName); - b.putBundle(DIALOG_BUNDLE, mDialog.onSaveInstanceState()); - - outState.putBundle(WATCH_HANDLER_BUNDLE, b); - } - - @Override - public void loadInstanceState(Bundle savedInstanceState) { - Bundle b = savedInstanceState.getBundle(WATCH_HANDLER_BUNDLE); - mShowDoNotAsk = b.getByte(SHOW_DO_NOT_ASK) == 1; - mGroupName = b.getString(GROUP_NAME); - showDialog(b.getBundle(DIALOG_BUNDLE)); - } - - @Override - public void onBackPressed() { - notifyListener(DENIED); - } - - @Override - public void onClick(DialogInterface dialog, int which) { - switch (which) { - case DialogInterface.BUTTON_POSITIVE: - notifyListener(GRANTED_ALWAYS); - break; - case DialogInterface.BUTTON_NEUTRAL: - notifyListener(DENIED); - break; - case DialogInterface.BUTTON_NEGATIVE: - /* In AlertDialog, the negative button is also a don't ask again button. */ - if (dialog instanceof AlertDialog) { - notifyListener(DENIED_DO_NOT_ASK_AGAIN); - } else { - notifyListener(DENIED); - } - break; - } - } - - private void notifyListener(@Result int result) { - if (mResultListener != null) { - mResultListener.onPermissionGrantResult(mGroupName, result); - } - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/ManagePermissionsActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/ManagePermissionsActivity.java deleted file mode 100644 index 712b860c5047..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/ManagePermissionsActivity.java +++ /dev/null @@ -1,128 +0,0 @@ -/* -* Copyright (C) 2015 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.packageinstaller.permission.ui; - -import android.app.Fragment; -import android.content.Intent; -import android.os.Bundle; -import android.util.Log; -import android.view.MenuItem; - -import com.android.packageinstaller.DeviceUtils; -import com.android.packageinstaller.R; -import com.android.packageinstaller.permission.ui.handheld.ManageStandardPermissionsFragment; -import com.android.packageinstaller.permission.ui.wear.AppPermissionsFragmentWear; - -public final class ManagePermissionsActivity extends OverlayTouchActivity { - private static final String LOG_TAG = "ManagePermissionsActivity"; - - public static final String EXTRA_ALL_PERMISSIONS = - "com.android.packageinstaller.extra.ALL_PERMISSIONS"; - - @Override - public void onCreate(Bundle savedInstanceState) { - if (DeviceUtils.isAuto(this)) { - setTheme(R.style.CarSettingTheme); - } - super.onCreate(savedInstanceState); - - if (savedInstanceState != null) { - return; - } - - Fragment fragment; - String action = getIntent().getAction(); - - switch (action) { - case Intent.ACTION_MANAGE_PERMISSIONS: { - if (DeviceUtils.isTelevision(this)) { - fragment = com.android.packageinstaller.permission.ui.television - .ManagePermissionsFragment.newInstance(); - } else { - fragment = ManageStandardPermissionsFragment.newInstance(); - } - } break; - - case Intent.ACTION_MANAGE_APP_PERMISSIONS: { - String packageName = getIntent().getStringExtra(Intent.EXTRA_PACKAGE_NAME); - if (packageName == null) { - Log.i(LOG_TAG, "Missing mandatory argument EXTRA_PACKAGE_NAME"); - finish(); - return; - } - if (DeviceUtils.isAuto(this)) { - fragment = com.android.packageinstaller.permission.ui.auto - .AppPermissionsFragment.newInstance(packageName); - } else if (DeviceUtils.isWear(this)) { - fragment = AppPermissionsFragmentWear.newInstance(packageName); - } else if (DeviceUtils.isTelevision(this)) { - fragment = com.android.packageinstaller.permission.ui.television - .AppPermissionsFragment.newInstance(packageName); - } else { - final boolean allPermissions = getIntent().getBooleanExtra( - EXTRA_ALL_PERMISSIONS, false); - if (allPermissions) { - fragment = com.android.packageinstaller.permission.ui.handheld - .AllAppPermissionsFragment.newInstance(packageName); - } else { - fragment = com.android.packageinstaller.permission.ui.handheld - .AppPermissionsFragment.newInstance(packageName); - } - } - } break; - - case Intent.ACTION_MANAGE_PERMISSION_APPS: { - String permissionName = getIntent().getStringExtra(Intent.EXTRA_PERMISSION_NAME); - if (permissionName == null) { - Log.i(LOG_TAG, "Missing mandatory argument EXTRA_PERMISSION_NAME"); - finish(); - return; - } - if (DeviceUtils.isTelevision(this)) { - fragment = com.android.packageinstaller.permission.ui.television - .PermissionAppsFragment.newInstance(permissionName); - } else { - fragment = com.android.packageinstaller.permission.ui.handheld - .PermissionAppsFragment.newInstance(permissionName); - } - } break; - - default: { - Log.w(LOG_TAG, "Unrecognized action " + action); - finish(); - return; - } - } - - getFragmentManager().beginTransaction().replace(android.R.id.content, fragment).commit(); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - // in automotive mode, there's no system wide back button, so need to add that - if (DeviceUtils.isAuto(this)) { - switch (item.getItemId()) { - case android.R.id.home: - onBackPressed(); - return true; - default: - return super.onOptionsItemSelected(item); - } - } - return super.onOptionsItemSelected(item); - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/ManualLayoutFrame.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/ManualLayoutFrame.java deleted file mode 100644 index 0b07c806e5e6..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/ManualLayoutFrame.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2015 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.packageinstaller.permission.ui; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.View; -import android.view.ViewGroup; - -public class ManualLayoutFrame extends ViewGroup { - private int mContentBottom; - private int mWidth; - - public ManualLayoutFrame(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public void onConfigurationChanged() { - mContentBottom = 0; - mWidth = 0; - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - if (mWidth != 0) { - int newWidth = mWidth; - final int widthMode = MeasureSpec.getMode(widthMeasureSpec); - switch (widthMode) { - case MeasureSpec.AT_MOST: { - newWidth = Math.min(mWidth, MeasureSpec.getSize(widthMeasureSpec)); - } break; - case MeasureSpec.EXACTLY: { - newWidth = MeasureSpec.getSize(widthMeasureSpec); - } break; - } - if (newWidth != mWidth) { - mWidth = newWidth; - } - widthMeasureSpec = MeasureSpec.makeMeasureSpec(mWidth, MeasureSpec.EXACTLY); - } - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - if (mWidth == 0) { - mWidth = getMeasuredWidth(); - } - - measureChild(getChildAt(0), widthMeasureSpec, heightMeasureSpec); - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - // We want to keep the content bottom at the same place to avoid movement of the "Allow" - // button. - // Try to keep the content bottom at the same height. If this would move the dialog out of - // the top of the screen move it down as much as possible, then keep it at that position for - // the rest of the sequence of permission dialogs. - View content = getChildAt(0); - if (mContentBottom == 0 || content.getMeasuredHeight() > mContentBottom) { - mContentBottom = (getMeasuredHeight() + content.getMeasuredHeight()) / 2; - } - final int contentLeft = (getMeasuredWidth() - content.getMeasuredWidth()) / 2; - final int contentTop = mContentBottom - content.getMeasuredHeight(); - final int contentRight = contentLeft + content.getMeasuredWidth(); - content.layout(contentLeft, contentTop, contentRight, mContentBottom); - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/OverlayWarningDialog.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/OverlayWarningDialog.java deleted file mode 100644 index 61734b470c78..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/OverlayWarningDialog.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2015 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.packageinstaller.permission.ui; - -import android.app.Activity; -import android.app.AlertDialog; -import android.content.ActivityNotFoundException; -import android.content.DialogInterface; -import android.content.DialogInterface.OnClickListener; -import android.content.DialogInterface.OnDismissListener; -import android.content.Intent; -import android.os.Bundle; -import android.provider.Settings; -import android.util.Log; - -import com.android.packageinstaller.R; - -public class OverlayWarningDialog extends Activity implements OnClickListener, OnDismissListener { - - private static final String TAG = "OverlayWarningDialog"; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - new AlertDialog.Builder(this) - .setTitle(R.string.screen_overlay_title) - .setMessage(R.string.screen_overlay_message) - .setPositiveButton(R.string.screen_overlay_button, this) - .setOnDismissListener(this) - .show(); - } - - @Override - public void onDismiss(DialogInterface dialog) { - finish(); - } - - @Override - public void onClick(DialogInterface dialog, int which) { - finish(); - try { - startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION)); - } catch (ActivityNotFoundException e) { - Log.w(TAG, "No manage overlay settings", e); - } - } - -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/PreferenceImageView.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/PreferenceImageView.java deleted file mode 100644 index c3f516744ce2..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/PreferenceImageView.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2014 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.packageinstaller.permission.ui; - -import android.content.Context; -import android.util.AttributeSet; -import android.widget.ImageView; - -/** - * Extension of ImageView that correctly applies maxWidth and maxHeight. - */ -public class PreferenceImageView extends ImageView { - - public PreferenceImageView(Context context) { - this(context, null); - } - - public PreferenceImageView(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public PreferenceImageView(Context context, AttributeSet attrs, int defStyleAttr) { - this(context, attrs, defStyleAttr, 0); - } - - public PreferenceImageView(Context context, AttributeSet attrs, int defStyleAttr, - int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - final int widthMode = MeasureSpec.getMode(widthMeasureSpec); - if (widthMode == MeasureSpec.AT_MOST || widthMode == MeasureSpec.UNSPECIFIED) { - final int widthSize = MeasureSpec.getSize(widthMeasureSpec); - final int maxWidth = getMaxWidth(); - if (maxWidth != Integer.MAX_VALUE - && (maxWidth < widthSize || widthMode == MeasureSpec.UNSPECIFIED)) { - widthMeasureSpec = MeasureSpec.makeMeasureSpec(maxWidth, MeasureSpec.AT_MOST); - } - } - - final int heightMode = MeasureSpec.getMode(heightMeasureSpec); - if (heightMode == MeasureSpec.AT_MOST || heightMode == MeasureSpec.UNSPECIFIED) { - final int heightSize = MeasureSpec.getSize(heightMeasureSpec); - final int maxHeight = getMaxHeight(); - if (maxHeight != Integer.MAX_VALUE - && (maxHeight < heightSize || heightMode == MeasureSpec.UNSPECIFIED)) { - heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST); - } - } - - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/ReviewPermissionsActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/ReviewPermissionsActivity.java deleted file mode 100644 index e4929c7e947e..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/ReviewPermissionsActivity.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2015 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.packageinstaller.permission.ui; - -import android.content.Intent; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.os.Bundle; -import android.text.TextUtils; - -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentActivity; - -import com.android.packageinstaller.DeviceUtils; -import com.android.packageinstaller.R; -import com.android.packageinstaller.permission.ui.ConfirmActionDialogFragment - .OnActionConfirmedListener; -import com.android.packageinstaller.permission.ui.handheld.ReviewPermissionsFragment; -import com.android.packageinstaller.permission.ui.wear.ReviewPermissionsWearFragment; - -public final class ReviewPermissionsActivity extends FragmentActivity - implements OnActionConfirmedListener { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - PackageInfo packageInfo = getTargetPackageInfo(); - if (packageInfo == null) { - finish(); - return; - } - - if (DeviceUtils.isWear(this)) { - Fragment fragment = ReviewPermissionsWearFragment.newInstance(packageInfo); - getSupportFragmentManager().beginTransaction() - .replace(android.R.id.content, fragment).commit(); - } else { - setContentView(R.layout.review_permissions); - if (getSupportFragmentManager().findFragmentById(R.id.preferences_frame) == null) { - getSupportFragmentManager().beginTransaction().add(R.id.preferences_frame, - ReviewPermissionsFragment.newInstance(packageInfo)).commit(); - } - } - } - - @Override - public void onActionConfirmed(String action) { - Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.preferences_frame); - if (fragment instanceof OnActionConfirmedListener) { - ((OnActionConfirmedListener) fragment).onActionConfirmed(action); - } - } - - private PackageInfo getTargetPackageInfo() { - String packageName = getIntent().getStringExtra(Intent.EXTRA_PACKAGE_NAME); - if (TextUtils.isEmpty(packageName)) { - return null; - } - try { - return getPackageManager().getPackageInfo(packageName, - PackageManager.GET_PERMISSIONS); - } catch (PackageManager.NameNotFoundException e) { - return null; - } - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/auto/AppPermissionsFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/auto/AppPermissionsFragment.java deleted file mode 100644 index 9bc75fc4ea7f..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/auto/AppPermissionsFragment.java +++ /dev/null @@ -1,204 +0,0 @@ -/** - * Copyright (C) 2017 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.packageinstaller.permission.ui.auto; - - -import android.app.Activity; -import android.app.AlertDialog; -import android.app.Fragment; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.os.Bundle; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Toast; - -import androidx.car.widget.ListItem; -import androidx.car.widget.ListItemAdapter; -import androidx.car.widget.ListItemProvider; -import androidx.car.widget.PagedListView; -import androidx.car.widget.TextListItem; - -import com.android.packageinstaller.R; -import com.android.packageinstaller.permission.model.AppPermissionGroup; -import com.android.packageinstaller.permission.model.AppPermissions; -import com.android.packageinstaller.permission.utils.Utils; - -import java.util.ArrayList; - -/** - * Contains all permissions in a list for a given application. - */ -public final class AppPermissionsFragment extends Fragment{ - - private static final String LOG_TAG = "ManagePermsFragment"; - public static final String EXTRA_LAYOUT = "extra_layout"; - - private AppPermissions mAppPermissions; - - private String mPackageName; - - protected PagedListView mListView; - protected ListItemAdapter mPagedListAdapter; - - - /** - * Creates a new instance. - * @param packageName the packageName of the application that we are listing the - * permissions here. - */ - public static AppPermissionsFragment newInstance(String packageName) { - AppPermissionsFragment fragment = new AppPermissionsFragment(); - Bundle arguments = new Bundle(); - arguments.putInt(EXTRA_LAYOUT, R.layout.car_app_permissions); - arguments.putString(Intent.EXTRA_PACKAGE_NAME, packageName); - fragment.setArguments(arguments); - return fragment; - } - - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - getView().findViewById(R.id.action_bar_icon_container).setOnClickListener( - v -> getActivity().onBackPressed()); - - mListView = (PagedListView) getView().findViewById(R.id.list); - mPagedListAdapter = new ListItemAdapter(getContext(), getItemProvider()); - mListView.setAdapter(mPagedListAdapter); - } - - protected void notifyDataSetChanged() { - mPagedListAdapter.notifyDataSetChanged(); - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (savedInstanceState != null - && savedInstanceState.containsKey(Intent.EXTRA_PACKAGE_NAME)) { - mPackageName = savedInstanceState.getString(Intent.EXTRA_PACKAGE_NAME); - } else if (getArguments() != null - && getArguments().containsKey(Intent.EXTRA_PACKAGE_NAME)) { - mPackageName = getArguments().getString(Intent.EXTRA_PACKAGE_NAME); - } - - if (mPackageName == null) { - Log.e(LOG_TAG, "package name is missing"); - return; - } - Activity activity = getActivity(); - PackageInfo packageInfo = getPackageInfo(activity, mPackageName); - if (packageInfo == null) { - Toast.makeText(activity, R.string.app_not_found_dlg_title, Toast.LENGTH_LONG).show(); - activity.finish(); - return; - } - - mAppPermissions = new AppPermissions(activity, packageInfo, true, new Runnable() { - @Override - public void run() { - activity.finish(); - } - }); - } - - @Override - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - outState.putString(Intent.EXTRA_PACKAGE_NAME, mPackageName); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - return inflater.inflate(getArguments().getInt(EXTRA_LAYOUT), container, false); - } - - @Override - public void onResume() { - super.onResume(); - mAppPermissions.refresh(); - } - - /** - * Gets the list of the LineItems to show up in the list - */ - public ListItemProvider getItemProvider() { - ArrayList<ListItem> items = new ArrayList<>(); - Context context = getContext(); - if (context == null) { - return new ListItemProvider.ListProvider(items); - } - - for (AppPermissionGroup group : mAppPermissions.getPermissionGroups()) { - if (!Utils.shouldShowPermission(group)) { - continue; - } - items.add(new PermissionLineItem(group, context)); - } - return new ListItemProvider.ListProvider(items); - } - - private static PackageInfo getPackageInfo(Activity activity, String packageName) { - try { - return activity.getPackageManager().getPackageInfo( - packageName, PackageManager.GET_PERMISSIONS); - } catch (PackageManager.NameNotFoundException e) { - if (Log.isLoggable(LOG_TAG, Log.INFO)) { - Log.i(LOG_TAG, "No package:" + activity.getCallingPackage(), e); - } - return null; - } - } - - private class PermissionLineItem extends TextListItem { - - PermissionLineItem(AppPermissionGroup permissionGroup, Context context) { - super(context); - setTitle(permissionGroup.getLabel().toString()); - setPrimaryActionIcon(permissionGroup.getIconResId(), /* useLargeIcon= */ false); - setSwitch( - permissionGroup.areRuntimePermissionsGranted(), - /* showDivider= */ false, - (button, isChecked) -> { - if (isChecked) { - permissionGroup.grantRuntimePermissions(/* fixedByTheUser= */ false); - return; - } - boolean grantedByDefault = permissionGroup.hasGrantedByDefaultPermission(); - if (!grantedByDefault && permissionGroup.doesSupportRuntimePermissions()) { - permissionGroup.revokeRuntimePermissions(/* fixedByTheUser= */ false); - return; - } - new AlertDialog.Builder(context) - .setMessage(grantedByDefault - ? R.string.system_warning - : R.string.old_sdk_deny_warning) - .setNegativeButton(R.string.cancel, /* listener= */ null) - .setPositiveButton(R.string.grant_dialog_button_deny_anyway, - (dialog, which) -> - permissionGroup.revokeRuntimePermissions( - /* fixedByTheUser= */ false)) - .show(); - }); - } - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/auto/GrantPermissionsAutoViewHandler.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/auto/GrantPermissionsAutoViewHandler.java deleted file mode 100644 index 9e40d6643970..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/auto/GrantPermissionsAutoViewHandler.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2016 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.packageinstaller.permission.ui.auto; - -import android.app.Activity; -import android.view.WindowManager; - -import com.android.packageinstaller.permission.ui.handheld.GrantPermissionsViewHandlerImpl; - -/** - * A {@link com.android.packageinstaller.permission.ui.GrantPermissionsViewHandler} that is - * specific for the auto use-case. In this case, the permissions dialog needs to be larger to make - * clicking and reading safer in the car. Otherwise, the UI remains the same. - * - * <p>The reason this class extends {@link GrantPermissionsViewHandlerImpl} is so that it can - * change the window params to allow the dialog's width to be larger. - */ -public class GrantPermissionsAutoViewHandler extends GrantPermissionsViewHandlerImpl { - public GrantPermissionsAutoViewHandler(Activity activity, String appPackageName) { - super(activity, appPackageName); - } - - /** - * Update the given {@link android.view.WindowManager.LayoutParams} to allow the dialog to take - * up the entirety of the width. - */ - @Override - public void updateWindowAttributes(WindowManager.LayoutParams outLayoutParams) { - outLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT; - outLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT; - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/AllAppPermissionsFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/AllAppPermissionsFragment.java deleted file mode 100644 index 1d8e5adfcaf0..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/AllAppPermissionsFragment.java +++ /dev/null @@ -1,378 +0,0 @@ -/* -* Copyright (C) 2015 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.packageinstaller.permission.ui.handheld; - -import android.app.ActionBar; -import android.app.AlertDialog; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageItemInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.pm.PermissionGroupInfo; -import android.content.pm.PermissionInfo; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.preference.Preference; -import android.preference.PreferenceCategory; -import android.preference.PreferenceGroup; -import android.provider.Settings; -import android.util.IconDrawableFactory; -import android.util.Log; -import android.view.MenuItem; -import android.widget.Switch; - -import com.android.packageinstaller.R; -import com.android.packageinstaller.permission.model.AppPermissionGroup; -import com.android.packageinstaller.permission.model.Permission; -import com.android.packageinstaller.permission.utils.ArrayUtils; -import com.android.packageinstaller.permission.utils.Utils; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -/** - * Show and manage individual permissions for an app. - * - * <p>Shows the list of individual runtime and non-runtime permissions the app has requested. - */ -public final class AllAppPermissionsFragment extends SettingsWithHeader { - - private static final String LOG_TAG = "AllAppPermissionsFragment"; - - private static final String KEY_OTHER = "other_perms"; - - private static final String EXTRA_FILTER_GROUP = - "com.android.packageinstaller.extra.FILTER_GROUP"; - - private List<AppPermissionGroup> mGroups; - - public static AllAppPermissionsFragment newInstance(String packageName) { - return newInstance(packageName, null); - } - - public static AllAppPermissionsFragment newInstance(String packageName, String filterGroup) { - AllAppPermissionsFragment instance = new AllAppPermissionsFragment(); - Bundle arguments = new Bundle(); - arguments.putString(Intent.EXTRA_PACKAGE_NAME, packageName); - arguments.putString(EXTRA_FILTER_GROUP, filterGroup); - instance.setArguments(arguments); - return instance; - } - - @Override - public void onStart() { - super.onStart(); - - final ActionBar ab = getActivity().getActionBar(); - if (ab != null) { - // If we target a group make this look like app permissions. - if (getArguments().getString(EXTRA_FILTER_GROUP) == null) { - ab.setTitle(R.string.all_permissions); - } else { - ab.setTitle(R.string.app_permissions); - } - ab.setDisplayHomeAsUpEnabled(true); - } - - setHasOptionsMenu(true); - - updateUi(); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: { - getFragmentManager().popBackStack(); - return true; - } - } - return super.onOptionsItemSelected(item); - } - - private void updateUi() { - if (getPreferenceScreen() != null) { - getPreferenceScreen().removeAll(); - } - addPreferencesFromResource(R.xml.all_permissions); - PreferenceGroup otherGroup = (PreferenceGroup) findPreference(KEY_OTHER); - ArrayList<Preference> prefs = new ArrayList<>(); // Used for sorting. - prefs.add(otherGroup); - String pkg = getArguments().getString(Intent.EXTRA_PACKAGE_NAME); - String filterGroup = getArguments().getString(EXTRA_FILTER_GROUP); - otherGroup.removeAll(); - PackageManager pm = getContext().getPackageManager(); - - try { - PackageInfo info = pm.getPackageInfo(pkg, PackageManager.GET_PERMISSIONS); - - ApplicationInfo appInfo = info.applicationInfo; - final Drawable icon = - IconDrawableFactory.newInstance(getContext()).getBadgedIcon(appInfo); - final CharSequence label = appInfo.loadLabel(pm); - Intent infoIntent = null; - if (!getActivity().getIntent().getBooleanExtra( - AppPermissionsFragment.EXTRA_HIDE_INFO_BUTTON, false)) { - infoIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) - .setData(Uri.fromParts("package", pkg, null)); - } - setHeader(icon, label, infoIntent); - - if (info.requestedPermissions != null) { - for (int i = 0; i < info.requestedPermissions.length; i++) { - PermissionInfo perm; - try { - perm = pm.getPermissionInfo(info.requestedPermissions[i], 0); - } catch (NameNotFoundException e) { - Log.e(LOG_TAG, - "Can't get permission info for " + info.requestedPermissions[i], e); - continue; - } - - if ((perm.flags & PermissionInfo.FLAG_INSTALLED) == 0 - || (perm.flags & PermissionInfo.FLAG_REMOVED) != 0) { - continue; - } - - if (appInfo.isInstantApp() - && (perm.protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTANT) - == 0) { - continue; - } - if (appInfo.targetSdkVersion < Build.VERSION_CODES.M - && (perm.protectionLevel & PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) - != 0) { - continue; - } - - if ((perm.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) - == PermissionInfo.PROTECTION_DANGEROUS) { - PackageItemInfo group = getGroup(perm.group, pm); - if (group == null) { - group = perm; - } - // If we show a targeted group, then ignore everything else. - if (filterGroup != null && !group.name.equals(filterGroup)) { - continue; - } - PreferenceGroup pref = findOrCreate(group, pm, prefs); - pref.addPreference(getPreference(info, perm, group, pm)); - } else if (filterGroup == null) { - if ((perm.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) - == PermissionInfo.PROTECTION_NORMAL) { - PermissionGroupInfo group = getGroup(perm.group, pm); - otherGroup.addPreference(getPreference(info, - perm, group, pm)); - } - } - - // If we show a targeted group, then don't show 'other' permissions. - if (filterGroup != null) { - getPreferenceScreen().removePreference(otherGroup); - } - } - } - } catch (NameNotFoundException e) { - Log.e(LOG_TAG, "Problem getting package info for " + pkg, e); - } - // Sort an ArrayList of the groups and then set the order from the sorting. - Collections.sort(prefs, new Comparator<Preference>() { - @Override - public int compare(Preference lhs, Preference rhs) { - String lKey = lhs.getKey(); - String rKey = rhs.getKey(); - if (lKey.equals(KEY_OTHER)) { - return 1; - } else if (rKey.equals(KEY_OTHER)) { - return -1; - } else if (Utils.isModernPermissionGroup(lKey) - != Utils.isModernPermissionGroup(rKey)) { - return Utils.isModernPermissionGroup(lKey) ? -1 : 1; - } - return lhs.getTitle().toString().compareTo(rhs.getTitle().toString()); - } - }); - for (int i = 0; i < prefs.size(); i++) { - prefs.get(i).setOrder(i); - } - } - - private PermissionGroupInfo getGroup(String group, PackageManager pm) { - try { - return pm.getPermissionGroupInfo(group, 0); - } catch (NameNotFoundException e) { - return null; - } - } - - private PreferenceGroup findOrCreate(PackageItemInfo group, PackageManager pm, - ArrayList<Preference> prefs) { - PreferenceGroup pref = (PreferenceGroup) findPreference(group.name); - if (pref == null) { - pref = new PreferenceCategory(getContext()); - pref.setKey(group.name); - pref.setTitle(group.loadLabel(pm)); - prefs.add(pref); - getPreferenceScreen().addPreference(pref); - } - return pref; - } - - private Preference getPreference(PackageInfo packageInfo, PermissionInfo perm, - PackageItemInfo group, PackageManager pm) { - final Preference pref; - - // We allow individual permission control for some permissions if review enabled - final boolean mutable = Utils.isPermissionIndividuallyControlled(getContext(), perm.name); - if (mutable) { - pref = new MyMultiTargetSwitchPreference(getContext(), perm.name, - getPermissionForegroundGroup(packageInfo, perm.name)); - } else { - pref = new Preference(getContext()); - } - - Drawable icon = null; - if (perm.icon != 0) { - icon = perm.loadIcon(pm); - } else if (group != null && group.icon != 0) { - icon = group.loadIcon(pm); - } else { - icon = getContext().getDrawable(R.drawable.ic_perm_device_info); - } - pref.setIcon(Utils.applyTint(getContext(), icon, android.R.attr.colorControlNormal)); - pref.setTitle(perm.loadSafeLabel(pm, 20000, PackageItemInfo.SAFE_LABEL_FLAG_TRIM)); - pref.setSingleLineTitle(false); - final CharSequence desc = perm.loadDescription(pm); - - pref.setOnPreferenceClickListener((Preference preference) -> { - new AlertDialog.Builder(getContext()) - .setMessage(desc) - .setPositiveButton(android.R.string.ok, null) - .show(); - return mutable; - }); - - return pref; - } - - /** - * Return the (foreground-) {@link AppPermissionGroup group} a permission belongs to. - * - * <p>For foreground or non background-foreground permissions this returns the group - * {@link AppPermissionGroup} the permission is in. For background permisisons this returns - * the group the matching foreground - * - * @param packageInfo Package information about the app - * @param permission The permission that belongs to a group - * - * @return the group the permissions belongs to - */ - private AppPermissionGroup getPermissionForegroundGroup(PackageInfo packageInfo, - String permission) { - AppPermissionGroup appPermissionGroup = null; - if (mGroups != null) { - final int groupCount = mGroups.size(); - for (int i = 0; i < groupCount; i++) { - AppPermissionGroup currentPermissionGroup = mGroups.get(i); - if (currentPermissionGroup.hasPermission(permission)) { - appPermissionGroup = currentPermissionGroup; - break; - } - if (currentPermissionGroup.getBackgroundPermissions() != null - && currentPermissionGroup.getBackgroundPermissions().hasPermission( - permission)) { - appPermissionGroup = currentPermissionGroup.getBackgroundPermissions(); - break; - } - } - } - if (appPermissionGroup == null) { - appPermissionGroup = AppPermissionGroup.create( - getContext(), packageInfo, permission); - if (mGroups == null) { - mGroups = new ArrayList<>(); - } - mGroups.add(appPermissionGroup); - } - return appPermissionGroup; - } - - private static final class MyMultiTargetSwitchPreference extends MultiTargetSwitchPreference { - MyMultiTargetSwitchPreference(Context context, String permission, - AppPermissionGroup appPermissionGroup) { - super(context); - - setChecked(appPermissionGroup.areRuntimePermissionsGranted( - new String[] {permission})); - - setSwitchOnClickListener(v -> { - Switch switchView = (Switch) v; - if (switchView.isChecked()) { - appPermissionGroup.grantRuntimePermissions(false, - new String[]{permission}); - // We are granting a permission from a group but since this is an - // individual permission control other permissions in the group may - // be revoked, hence we need to mark them user fixed to prevent the - // app from requesting a non-granted permission and it being granted - // because another permission in the group is granted. This applies - // only to apps that support runtime permissions. - if (appPermissionGroup.doesSupportRuntimePermissions()) { - int grantedCount = 0; - String[] revokedPermissionsToFix = null; - final int permissionCount = appPermissionGroup.getPermissions().size(); - for (int i = 0; i < permissionCount; i++) { - Permission current = appPermissionGroup.getPermissions().get(i); - if (!current.isGranted()) { - if (!current.isUserFixed()) { - revokedPermissionsToFix = ArrayUtils.appendString( - revokedPermissionsToFix, current.getName()); - } - } else { - grantedCount++; - } - } - if (revokedPermissionsToFix != null) { - // If some permissions were not granted then they should be fixed. - appPermissionGroup.revokeRuntimePermissions(true, - revokedPermissionsToFix); - } else if (appPermissionGroup.getPermissions().size() == grantedCount) { - // If all permissions are granted then they should not be fixed. - appPermissionGroup.grantRuntimePermissions(false); - } - } - } else { - appPermissionGroup.revokeRuntimePermissions(true, - new String[]{permission}); - // If we just revoked the last permission we need to clear - // the user fixed state as now the app should be able to - // request them at runtime if supported. - if (appPermissionGroup.doesSupportRuntimePermissions() - && !appPermissionGroup.areRuntimePermissionsGranted()) { - appPermissionGroup.revokeRuntimePermissions(false); - } - } - }); - } - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/AppPermissionsFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/AppPermissionsFragment.java deleted file mode 100644 index 917f238b8111..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/AppPermissionsFragment.java +++ /dev/null @@ -1,331 +0,0 @@ -/* -* Copyright (C) 2015 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.packageinstaller.permission.ui.handheld; - -import android.app.ActionBar; -import android.app.Activity; -import android.app.Fragment; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.Bundle; -import android.preference.Preference; -import android.preference.Preference.OnPreferenceClickListener; -import android.preference.PreferenceScreen; -import android.provider.Settings; -import android.util.ArraySet; -import android.util.IconDrawableFactory; -import android.util.Log; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.widget.Toast; - -import com.android.packageinstaller.R; -import com.android.packageinstaller.permission.model.AppPermissionGroup; -import com.android.packageinstaller.permission.model.AppPermissions; -import com.android.packageinstaller.permission.utils.SafetyNetLogger; -import com.android.packageinstaller.permission.utils.Utils; -import com.android.settingslib.HelpUtils; - -/** - * Show and manage permission groups for an app. - * - * <p>Shows the list of permission groups the app has requested at one permission for. - */ -public final class AppPermissionsFragment extends SettingsWithHeader - implements PermissionPreference.PermissionPreferenceChangeListener, - PermissionPreference.PermissionPreferenceOwnerFragment { - - private static final String LOG_TAG = "ManagePermsFragment"; - - static final String EXTRA_HIDE_INFO_BUTTON = "hideInfoButton"; - - private static final int MENU_ALL_PERMS = 0; - - private ArraySet<AppPermissionGroup> mToggledGroups; - private AppPermissions mAppPermissions; - private PreferenceScreen mExtraScreen; - - private boolean mHasConfirmedRevoke; - - public static AppPermissionsFragment newInstance(String packageName) { - return setPackageName(new AppPermissionsFragment(), packageName); - } - - private static <T extends Fragment> T setPackageName(T fragment, String packageName) { - Bundle arguments = new Bundle(); - arguments.putString(Intent.EXTRA_PACKAGE_NAME, packageName); - fragment.setArguments(arguments); - return fragment; - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setLoading(true /* loading */, false /* animate */); - setHasOptionsMenu(true); - final ActionBar ab = getActivity().getActionBar(); - if (ab != null) { - ab.setDisplayHomeAsUpEnabled(true); - } - - String packageName = getArguments().getString(Intent.EXTRA_PACKAGE_NAME); - Activity activity = getActivity(); - PackageInfo packageInfo = getPackageInfo(activity, packageName); - if (packageInfo == null) { - Toast.makeText(activity, R.string.app_not_found_dlg_title, Toast.LENGTH_LONG).show(); - activity.finish(); - return; - } - - mAppPermissions = new AppPermissions(activity, packageInfo, true, new Runnable() { - @Override - public void run() { - getActivity().finish(); - } - }); - updatePreferences(); - } - - @Override - public void onResume() { - super.onResume(); - mAppPermissions.refresh(); - updatePreferences(); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: { - getActivity().finish(); - return true; - } - - case MENU_ALL_PERMS: { - showAllPermissions(null); - return true; - } - } - return super.onOptionsItemSelected(item); - } - - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - if (mAppPermissions != null) { - bindUi(this, mAppPermissions.getPackageInfo()); - } - } - - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - super.onCreateOptionsMenu(menu, inflater); - menu.add(Menu.NONE, MENU_ALL_PERMS, Menu.NONE, R.string.all_permissions); - HelpUtils.prepareHelpMenuItem(getActivity(), menu, R.string.help_app_permissions, - getClass().getName()); - } - - private void showAllPermissions(String filterGroup) { - Fragment frag = AllAppPermissionsFragment.newInstance( - getArguments().getString(Intent.EXTRA_PACKAGE_NAME), - filterGroup); - getFragmentManager().beginTransaction() - .replace(android.R.id.content, frag) - .addToBackStack("AllPerms") - .commit(); - } - - private static void bindUi(SettingsWithHeader fragment, PackageInfo packageInfo) { - Activity activity = fragment.getActivity(); - PackageManager pm = activity.getPackageManager(); - ApplicationInfo appInfo = packageInfo.applicationInfo; - Intent infoIntent = null; - if (!activity.getIntent().getBooleanExtra(EXTRA_HIDE_INFO_BUTTON, false)) { - infoIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) - .setData(Uri.fromParts("package", packageInfo.packageName, null)); - } - - Drawable icon = IconDrawableFactory.newInstance(activity).getBadgedIcon(appInfo); - CharSequence label = appInfo.loadLabel(pm); - fragment.setHeader(icon, label, infoIntent); - - ActionBar ab = activity.getActionBar(); - if (ab != null) { - ab.setTitle(R.string.app_permissions); - } - } - - private void updatePreferences() { - Context context = getActivity(); - if (context == null) { - return; - } - - PreferenceScreen screen = getPreferenceScreen(); - if (screen == null) { - screen = getPreferenceManager().createPreferenceScreen(getActivity()); - setPreferenceScreen(screen); - } - - screen.removeAll(); - - if (mExtraScreen != null) { - mExtraScreen.removeAll(); - } - - final Preference extraPerms = new Preference(context); - extraPerms.setIcon(R.drawable.ic_toc); - extraPerms.setTitle(R.string.additional_permissions); - - for (AppPermissionGroup group : mAppPermissions.getPermissionGroups()) { - if (!Utils.shouldShowPermission(group)) { - continue; - } - - boolean isPlatform = group.getDeclaringPackage().equals(Utils.OS_PKG); - - PermissionPreference preference = new PermissionPreference(this, group, this); - preference.setKey(group.getName()); - Drawable icon = Utils.loadDrawable(context.getPackageManager(), - group.getIconPkg(), group.getIconResId()); - preference.setIcon(Utils.applyTint(getContext(), icon, - android.R.attr.colorControlNormal)); - preference.setTitle(group.getLabel()); - - if (isPlatform) { - screen.addPreference(preference); - } else { - if (mExtraScreen == null) { - mExtraScreen = getPreferenceManager().createPreferenceScreen(context); - } - mExtraScreen.addPreference(preference); - } - } - - if (mExtraScreen != null) { - extraPerms.setOnPreferenceClickListener(new OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - AdditionalPermissionsFragment frag = new AdditionalPermissionsFragment(); - setPackageName(frag, getArguments().getString(Intent.EXTRA_PACKAGE_NAME)); - frag.setTargetFragment(AppPermissionsFragment.this, 0); - getFragmentManager().beginTransaction() - .replace(android.R.id.content, frag) - .addToBackStack(null) - .commit(); - return true; - } - }); - int count = mExtraScreen.getPreferenceCount(); - extraPerms.setSummary(getResources().getQuantityString( - R.plurals.additional_permissions_more, count, count)); - screen.addPreference(extraPerms); - } - - setLoading(false /* loading */, true /* animate */); - } - - @Override - public void onPreferenceChanged(String key) { - if (mToggledGroups == null) { - mToggledGroups = new ArraySet<>(); - } - mToggledGroups.add(mAppPermissions.getPermissionGroup(key)); - } - - @Override - public void onPause() { - super.onPause(); - logToggledGroups(); - } - - private void logToggledGroups() { - if (mToggledGroups != null) { - SafetyNetLogger.logPermissionsToggled(mToggledGroups); - mToggledGroups = null; - } - } - - private static PackageInfo getPackageInfo(Activity activity, String packageName) { - try { - return activity.getPackageManager().getPackageInfo( - packageName, PackageManager.GET_PERMISSIONS); - } catch (PackageManager.NameNotFoundException e) { - Log.i(LOG_TAG, "No package:" + activity.getCallingPackage(), e); - return null; - } - } - - @Override - public boolean shouldConfirmDefaultPermissionRevoke() { - return !mHasConfirmedRevoke; - } - - @Override - public void hasConfirmDefaultPermissionRevoke() { - mHasConfirmedRevoke = true; - } - - @Override - public void onBackgroundAccessChosen(String key, int chosenItem) { - ((PermissionPreference) getPreferenceScreen().findPreference(key)) - .onBackgroundAccessChosen(chosenItem); - } - - @Override - public void onDenyAnyWay(String key, @PermissionPreference.ChangeTarget int changeTarget) { - ((PermissionPreference) getPreferenceScreen().findPreference(key)).onDenyAnyWay( - changeTarget); - } - - public static class AdditionalPermissionsFragment extends SettingsWithHeader { - AppPermissionsFragment mOuterFragment; - - @Override - public void onCreate(Bundle savedInstanceState) { - mOuterFragment = (AppPermissionsFragment) getTargetFragment(); - super.onCreate(savedInstanceState); - setHeader(mOuterFragment.mIcon, mOuterFragment.mLabel, mOuterFragment.mInfoIntent); - setHasOptionsMenu(true); - setPreferenceScreen(mOuterFragment.mExtraScreen); - } - - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - String packageName = getArguments().getString(Intent.EXTRA_PACKAGE_NAME); - bindUi(this, getPackageInfo(getActivity(), packageName)); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - getFragmentManager().popBackStack(); - return true; - } - return super.onOptionsItemSelected(item); - } - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/GrantPermissionsViewHandlerImpl.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/GrantPermissionsViewHandlerImpl.java deleted file mode 100644 index a9e5fc7f3411..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/GrantPermissionsViewHandlerImpl.java +++ /dev/null @@ -1,446 +0,0 @@ -/* - * Copyright (C) 2015 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.packageinstaller.permission.ui.handheld; - -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.animation.ValueAnimator; -import android.app.Activity; -import android.content.Intent; -import android.graphics.drawable.Icon; -import android.os.Bundle; -import android.transition.ChangeBounds; -import android.transition.Transition; -import android.transition.TransitionManager; -import android.transition.TransitionSet; -import android.transition.TransitionValues; -import android.transition.Visibility; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.view.WindowManager.LayoutParams; -import android.view.accessibility.AccessibilityNodeInfo; -import android.view.animation.AnimationUtils; -import android.widget.Button; -import android.widget.CheckBox; -import android.widget.ImageView; -import android.widget.RadioButton; -import android.widget.RadioGroup; -import android.widget.Space; -import android.widget.TextView; - -import com.android.packageinstaller.R; -import com.android.packageinstaller.permission.ui.ButtonBarLayout; -import com.android.packageinstaller.permission.ui.GrantPermissionsViewHandler; -import com.android.packageinstaller.permission.ui.ManagePermissionsActivity; -import com.android.packageinstaller.permission.ui.ManualLayoutFrame; - -public class GrantPermissionsViewHandlerImpl implements GrantPermissionsViewHandler, - OnClickListener, RadioGroup.OnCheckedChangeListener { - - public static final String ARG_GROUP_NAME = "ARG_GROUP_NAME"; - public static final String ARG_GROUP_COUNT = "ARG_GROUP_COUNT"; - public static final String ARG_GROUP_INDEX = "ARG_GROUP_INDEX"; - public static final String ARG_GROUP_ICON = "ARG_GROUP_ICON"; - public static final String ARG_GROUP_MESSAGE = "ARG_GROUP_MESSAGE"; - private static final String ARG_GROUP_DETAIL_MESSAGE = "ARG_GROUP_DETAIL_MESSAGE"; - - public static final String ARG_GROUP_SHOW_DO_NOT_ASK = "ARG_GROUP_SHOW_DO_NOT_ASK"; - private static final String ARG_GROUP_SHOW_FOREGOUND_CHOOSER = - "ARG_GROUP_SHOW_FOREGOUND_CHOOSER"; - - public static final String ARG_GROUP_DO_NOT_ASK_CHECKED = "ARG_GROUP_DO_NOT_ASK_CHECKED"; - private static final String ARG_GROUP_ALWAYS_OPTION_CHECKED = "ARG_GROUP_ALWAYS_OPTION_CHECKED"; - - // Animation parameters. - private static final long SWITCH_TIME_MILLIS = 75; - private static final long ANIMATION_DURATION_MILLIS = 200; - - private final Activity mActivity; - private final String mAppPackageName; - private final boolean mPermissionsIndividuallyControlled; - - private ResultListener mResultListener; - - // Configuration of the current dialog - private String mGroupName; - private int mGroupCount; - private int mGroupIndex; - private Icon mGroupIcon; - private CharSequence mGroupMessage; - private CharSequence mDetailMessage; - - private boolean mShowDonNotAsk; - private boolean mShowForegroundChooser; - - // Views - private ImageView mIconView; - private TextView mCurrentGroupView; - private TextView mMessageView; - private TextView mDetailMessageView; - private CheckBox mDoNotAskCheckbox; - private RadioGroup mForegroundChooser; - private RadioButton mForegroundOnlyOption; - private RadioButton mAlwaysOption; - private RadioButton mDenyAndDontAskAgainOption; - private Button mAllowButton; - private Button mMoreInfoButton; - private ManualLayoutFrame mRootView; - private ViewGroup mContentContainer; - private Space mSpacer; - - public GrantPermissionsViewHandlerImpl(Activity activity, String appPackageName) { - mActivity = activity; - mAppPackageName = appPackageName; - mPermissionsIndividuallyControlled = - activity.getPackageManager().arePermissionsIndividuallyControlled(); - } - - @Override - public GrantPermissionsViewHandlerImpl setResultListener(ResultListener listener) { - mResultListener = listener; - return this; - } - - @Override - public void saveInstanceState(Bundle arguments) { - arguments.putString(ARG_GROUP_NAME, mGroupName); - arguments.putInt(ARG_GROUP_COUNT, mGroupCount); - arguments.putInt(ARG_GROUP_INDEX, mGroupIndex); - arguments.putParcelable(ARG_GROUP_ICON, mGroupIcon); - arguments.putCharSequence(ARG_GROUP_MESSAGE, mGroupMessage); - arguments.putCharSequence(ARG_GROUP_DETAIL_MESSAGE, mDetailMessage); - - arguments.putBoolean(ARG_GROUP_SHOW_DO_NOT_ASK, mShowDonNotAsk); - arguments.putBoolean(ARG_GROUP_SHOW_FOREGOUND_CHOOSER, mShowForegroundChooser); - - arguments.putBoolean(ARG_GROUP_DO_NOT_ASK_CHECKED, isDoNotAskAgainChecked()); - arguments.putBoolean(ARG_GROUP_ALWAYS_OPTION_CHECKED, mAlwaysOption.isSelected()); - } - - @Override - public void loadInstanceState(Bundle savedInstanceState) { - mGroupName = savedInstanceState.getString(ARG_GROUP_NAME); - mGroupMessage = savedInstanceState.getCharSequence(ARG_GROUP_MESSAGE); - mGroupIcon = savedInstanceState.getParcelable(ARG_GROUP_ICON); - mGroupCount = savedInstanceState.getInt(ARG_GROUP_COUNT); - mGroupIndex = savedInstanceState.getInt(ARG_GROUP_INDEX); - mDetailMessage = savedInstanceState.getCharSequence(ARG_GROUP_DETAIL_MESSAGE); - - mShowDonNotAsk = savedInstanceState.getBoolean(ARG_GROUP_SHOW_DO_NOT_ASK); - mShowForegroundChooser = savedInstanceState.getBoolean(ARG_GROUP_SHOW_FOREGOUND_CHOOSER); - - updateAll(savedInstanceState.getBoolean(ARG_GROUP_DO_NOT_ASK_CHECKED), - savedInstanceState.getBoolean(ARG_GROUP_ALWAYS_OPTION_CHECKED)); - } - - @Override - public void updateUi(String groupName, int groupCount, int groupIndex, Icon icon, - CharSequence message, CharSequence detailMessage, boolean showForegroundChooser, - boolean showDonNotAsk) { - boolean isNewGroup = mGroupIndex != groupIndex; - boolean isDoNotAskAgainChecked = mDoNotAskCheckbox.isChecked(); - boolean isAlwaysOptionChecked = mAlwaysOption.isChecked(); - if (isNewGroup) { - isDoNotAskAgainChecked = false; - isAlwaysOptionChecked = false; - } - - mGroupName = groupName; - mGroupCount = groupCount; - mGroupIndex = groupIndex; - mGroupIcon = icon; - mGroupMessage = message; - mShowDonNotAsk = showDonNotAsk; - mDetailMessage = detailMessage; - mShowForegroundChooser = showForegroundChooser; - - // If this is a second (or later) permission and the views exist, then animate. - if (mIconView != null) { - if (isNewGroup) { - animateToPermission(isDoNotAskAgainChecked, isAlwaysOptionChecked); - } else { - updateAll(isDoNotAskAgainChecked, isAlwaysOptionChecked); - } - } - } - - private void updateAll(boolean isDoNotAskAgainChecked, boolean isAlwaysOptionChecked) { - updateDescription(); - updateDetailDescription(); - updateGroup(); - updateDoNotAskCheckBoxAndForegroundOption(isDoNotAskAgainChecked, isAlwaysOptionChecked); - } - - private void animateToPermission(boolean isDoNotAskAgainChecked, - boolean isAlwaysOptionChecked) { - final View newContent = bindNewContent(); - - updateDescription(); - updateDetailDescription(); - updateDoNotAskCheckBoxAndForegroundOption(isDoNotAskAgainChecked, isAlwaysOptionChecked); - // Update group when the content changes (in onAppear below) - - final View oldView = mContentContainer.getChildAt(0); - - // Grow or shrink the content container to size of new content - ChangeBounds growShrinkToNewContentSize = new ChangeBounds(); - growShrinkToNewContentSize.setDuration(ANIMATION_DURATION_MILLIS); - growShrinkToNewContentSize.setInterpolator(AnimationUtils.loadInterpolator(mActivity, - android.R.interpolator.fast_out_slow_in)); - - // With a delay hide the old content and show the new content - Visibility changeContent = new Visibility() { - @Override - public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues, - TransitionValues endValues) { - view.setVisibility(View.INVISIBLE); - - ValueAnimator v = ValueAnimator.ofFloat(0, 1); - - v.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - view.setVisibility(View.VISIBLE); - updateGroup(); - } - }); - - return v; - } - - @Override - public Animator onDisappear(ViewGroup sceneRoot, final View view, - TransitionValues startValues, TransitionValues endValues) { - ValueAnimator v = ValueAnimator.ofFloat(0, 1); - - int[] location = new int[2]; - // The removed view is put into the overlay that is relative to the window. Hence - // it does not get moved along with the changing parent view. This is done manually - // here. - v.addUpdateListener(animation -> { - mContentContainer.getLocationInWindow(location); - view.setTop(location[1]); - }); - - return v; - } - }; - changeContent.setDuration(SWITCH_TIME_MILLIS); - - TransitionSet combinedAnimation = new TransitionSet(); - combinedAnimation.addTransition(growShrinkToNewContentSize); - combinedAnimation.addTransition(changeContent); - combinedAnimation.setOrdering(TransitionSet.ORDERING_TOGETHER); - combinedAnimation.setMatchOrder(Transition.MATCH_INSTANCE); - - TransitionManager.beginDelayedTransition(mRootView, combinedAnimation); - mContentContainer.removeView(oldView); - mContentContainer.addView(newContent); - } - - /** - * Update this objects fields to point to the a content view. A content view encapsulates the - * permission request message, the detail message, the always deny checkbox, and the foreground - * chooser. - * - * @return The new content view - */ - private View bindNewContent() { - ViewGroup content = (ViewGroup) LayoutInflater.from(mActivity) - .inflate(R.layout.grant_permissions_content, mContentContainer, false); - - mMessageView = content.requireViewById(R.id.permission_message); - mDetailMessageView = content.requireViewById(R.id.detail_message); - mIconView = content.requireViewById(R.id.permission_icon); - mDoNotAskCheckbox = content.requireViewById(R.id.do_not_ask_checkbox); - mSpacer = content.requireViewById(R.id.detail_message_do_not_ask_checkbox_space); - mForegroundChooser = content.requireViewById(R.id.foreground_or_always_radiogroup); - mForegroundOnlyOption = content.requireViewById(R.id.foreground_only_radio_button); - mAlwaysOption = content.requireViewById(R.id.always_radio_button); - mDenyAndDontAskAgainOption = content.requireViewById(R.id.deny_dont_ask_again_radio_button); - - mDoNotAskCheckbox.setOnClickListener(this); - mDenyAndDontAskAgainOption.setOnClickListener(this); - mForegroundChooser.setOnCheckedChangeListener(this); - - return content; - } - - @Override - public View createView() { - mRootView = (ManualLayoutFrame) LayoutInflater.from(mActivity) - .inflate(R.layout.grant_permissions, null); - mContentContainer = mRootView.requireViewById(R.id.content_container); - mContentContainer.removeAllViews(); - mContentContainer.addView(bindNewContent()); - - mCurrentGroupView = (TextView) mRootView.findViewById(R.id.current_page_text); - mAllowButton = (Button) mRootView.findViewById(R.id.permission_allow_button); - mAllowButton.setOnClickListener(this); - - if (mPermissionsIndividuallyControlled) { - mMoreInfoButton = (Button) mRootView.findViewById(R.id.permission_more_info_button); - mMoreInfoButton.setVisibility(View.VISIBLE); - mMoreInfoButton.setOnClickListener(this); - } - - mRootView.findViewById(R.id.permission_deny_button).setOnClickListener(this); - - ((ButtonBarLayout) mRootView.requireViewById(R.id.button_group)).setAllowStacking(true); - - if (mGroupName != null) { - updateAll(false, false); - } - - return mRootView; - } - - @Override - public void updateWindowAttributes(LayoutParams outLayoutParams) { - // No-op - } - - private void updateDescription() { - if (mGroupIcon != null) { - mIconView.setImageDrawable(mGroupIcon.loadDrawable(mActivity)); - } - mMessageView.setText(mGroupMessage); - } - - private void updateDetailDescription() { - if (mDetailMessage == null) { - mDetailMessageView.setVisibility(View.GONE); - mSpacer.setVisibility(View.GONE); - } else { - if (mShowDonNotAsk) { - mSpacer.setVisibility(View.VISIBLE); - } else { - mSpacer.setVisibility(View.GONE); - } - - mDetailMessageView.setText(mDetailMessage); - mDetailMessageView.setVisibility(View.VISIBLE); - } - } - - private void updateGroup() { - if (mGroupCount > 1) { - mCurrentGroupView.setVisibility(View.VISIBLE); - mCurrentGroupView.setText(mActivity.getString(R.string.current_permission_template, - mGroupIndex + 1, mGroupCount)); - } else { - mCurrentGroupView.setVisibility(View.GONE); - } - } - - private void updateDoNotAskCheckBoxAndForegroundOption(boolean isDoNotAskAgainChecked, - boolean isAlwaysSelected) { - if (mShowForegroundChooser) { - mForegroundChooser.setVisibility(View.VISIBLE); - mDoNotAskCheckbox.setVisibility(View.GONE); - - if (isAlwaysSelected) { - mAlwaysOption.setSelected(true); - } - - if (mShowDonNotAsk) { - mDenyAndDontAskAgainOption.setSelected(isDoNotAskAgainChecked); - mDenyAndDontAskAgainOption.setVisibility(View.VISIBLE); - } else { - mDenyAndDontAskAgainOption.setVisibility(View.GONE); - } - } else { - mForegroundChooser.setVisibility(View.GONE); - if (mShowDonNotAsk) { - mDoNotAskCheckbox.setVisibility(View.VISIBLE); - mDoNotAskCheckbox.setChecked(isDoNotAskAgainChecked); - } else { - mDoNotAskCheckbox.setVisibility(View.GONE); - } - } - - mAllowButton.setEnabled(!isDoNotAskAgainChecked() && isOptionChosenIfNeeded()); - } - - private boolean isDoNotAskAgainChecked() { - return (mDoNotAskCheckbox.getVisibility() == View.VISIBLE - && mDoNotAskCheckbox.isChecked()) - || (mDenyAndDontAskAgainOption.getVisibility() == View.VISIBLE - && mDenyAndDontAskAgainOption.isChecked()); - } - - private boolean isOptionChosenIfNeeded() { - return !mShowForegroundChooser - || (mForegroundOnlyOption.isChecked() - || (mDenyAndDontAskAgainOption.getVisibility() == View.VISIBLE - && mDenyAndDontAskAgainOption.isChecked()) - || (mAlwaysOption.getVisibility() == View.VISIBLE && mAlwaysOption.isChecked())); - } - - @Override - public void onClick(View view) { - switch (view.getId()) { - case R.id.permission_allow_button: - if (mResultListener != null) { - view.performAccessibilityAction( - AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null); - if (mShowForegroundChooser && mForegroundOnlyOption.isChecked()) { - mResultListener.onPermissionGrantResult(mGroupName, - GRANTED_FOREGROUND_ONLY); - } else { - mResultListener.onPermissionGrantResult(mGroupName, GRANTED_ALWAYS); - } - } - break; - case R.id.permission_deny_button: - if (mResultListener != null) { - view.performAccessibilityAction( - AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null); - if (isDoNotAskAgainChecked()) { - mResultListener.onPermissionGrantResult(mGroupName, - DENIED_DO_NOT_ASK_AGAIN); - } else { - mResultListener.onPermissionGrantResult(mGroupName, DENIED); - } - } - break; - case R.id.permission_more_info_button: - Intent intent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS); - intent.putExtra(Intent.EXTRA_PACKAGE_NAME, mAppPackageName); - intent.putExtra(ManagePermissionsActivity.EXTRA_ALL_PERMISSIONS, true); - mActivity.startActivity(intent); - break; - } - - mAllowButton.setEnabled(!isDoNotAskAgainChecked() && isOptionChosenIfNeeded()); - - } - - @Override - public void onBackPressed() { - if (mResultListener != null) { - mResultListener.onPermissionGrantResult(mGroupName, DENIED); - } - } - - @Override - public void onCheckedChanged(RadioGroup group, int checkedId) { - mAllowButton.setEnabled(!isDoNotAskAgainChecked() && isOptionChosenIfNeeded()); - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/ManageCustomPermissionsFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/ManageCustomPermissionsFragment.java deleted file mode 100644 index 4f740e2c0cfd..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/ManageCustomPermissionsFragment.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2016 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.packageinstaller.permission.ui.handheld; - -import android.view.MenuItem; - -/** - * Fragment that allows the user to manage custom permissions. - */ -public class ManageCustomPermissionsFragment extends ManagePermissionsFragment { - @Override - public void onStart() { - super.onStart(); - - getActivity().setTitle(com.android.packageinstaller.R.string.additional_permissions); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - getFragmentManager().popBackStack(); - return true; - } - return super.onOptionsItemSelected(item); - } - - @Override - protected void updatePermissionsUi() { - updatePermissionsUi(false); - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/ManagePermissionsFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/ManagePermissionsFragment.java deleted file mode 100644 index e50a1d89ff76..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/ManagePermissionsFragment.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2015 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.packageinstaller.permission.ui.handheld; - -import android.app.ActionBar; -import android.content.ActivityNotFoundException; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.preference.Preference; -import android.preference.PreferenceScreen; -import android.util.ArraySet; -import android.util.Log; - -import com.android.packageinstaller.R; -import com.android.packageinstaller.permission.model.PermissionApps.PmCache; -import com.android.packageinstaller.permission.model.PermissionGroup; -import com.android.packageinstaller.permission.model.PermissionGroups; -import com.android.packageinstaller.permission.utils.Utils; - -import java.util.List; - -/** - * Superclass for fragments allowing the user to manage permissions. - */ -abstract class ManagePermissionsFragment extends PermissionsFrameFragment - implements PermissionGroups.PermissionsGroupsChangeCallback, - Preference.OnPreferenceClickListener { - private static final String LOG_TAG = "ManagePermissionsFragment"; - - static final String OS_PKG = "android"; - - private ArraySet<String> mLauncherPkgs; - - private PermissionGroups mPermissions; - - @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - setLoading(true /* loading */, false /* animate */); - setHasOptionsMenu(true); - final ActionBar ab = getActivity().getActionBar(); - if (ab != null) { - ab.setDisplayHomeAsUpEnabled(true); - } - mLauncherPkgs = Utils.getLauncherPackages(getContext()); - mPermissions = new PermissionGroups(getContext(), getLoaderManager(), this); - } - - @Override - public boolean onPreferenceClick(Preference preference) { - String key = preference.getKey(); - - PermissionGroup group = mPermissions.getGroup(key); - if (group == null) { - return false; - } - - Intent intent = new Intent(Intent.ACTION_MANAGE_PERMISSION_APPS) - .putExtra(Intent.EXTRA_PERMISSION_NAME, key); - try { - getActivity().startActivity(intent); - } catch (ActivityNotFoundException e) { - Log.w(LOG_TAG, "No app to handle " + intent); - } - - return true; - } - - /** - * @return the permissions - */ - protected PermissionGroups getPermissions() { - return mPermissions; - } - - @Override - public void onPermissionGroupsChanged() { - updatePermissionsUi(); - } - - /** - * Update the preferences to show the new {@link #getPermissions() permissions}. - */ - protected abstract void updatePermissionsUi(); - - /** - * Add preferences for all permissions of a type to the preference screen. - * - * @param addSystemPermissions If the permissions added should be system permissions or not - * - * @return The preference screen the permissions were added to - */ - protected PreferenceScreen updatePermissionsUi(boolean addSystemPermissions) { - Context context = getActivity(); - if (context == null) { - return null; - } - - List<PermissionGroup> groups = mPermissions.getGroups(); - PreferenceScreen screen = getPreferenceScreen(); - if (screen == null) { - screen = getPreferenceManager().createPreferenceScreen(getActivity()); - setPreferenceScreen(screen); - } else { - screen.removeAll(); - } - - // Use this to speed up getting the info for all of the PermissionApps below. - // Create a new one for each refresh to make sure it has fresh data. - PmCache cache = new PmCache(getContext().getPackageManager()); - for (PermissionGroup group : groups) { - boolean isSystemPermission = group.getDeclaringPackage().equals(OS_PKG); - - if (addSystemPermissions == isSystemPermission) { - Preference preference = findPreference(group.getName()); - - if (preference == null) { - preference = new Preference(context); - preference.setOnPreferenceClickListener(this); - preference.setKey(group.getName()); - preference.setIcon(Utils.applyTint(context, group.getIcon(), - android.R.attr.colorControlNormal)); - preference.setTitle(group.getLabel()); - // Set blank summary so that no resizing/jumping happens when the summary is - // loaded. - preference.setSummary(" "); - preference.setPersistent(false); - screen.addPreference(preference); - } - preference.setSummary(getString(R.string.app_permissions_group_summary, - group.getGranted(), group.getTotal())); - } - } - if (screen.getPreferenceCount() != 0) { - setLoading(false /* loading */, true /* animate */); - } - - return screen; - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/ManageStandardPermissionsFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/ManageStandardPermissionsFragment.java deleted file mode 100644 index 075ab3ce609e..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/ManageStandardPermissionsFragment.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2016 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.packageinstaller.permission.ui.handheld; - -import android.app.FragmentTransaction; -import android.preference.Preference; -import android.preference.PreferenceScreen; -import android.view.MenuItem; - -import com.android.packageinstaller.R; -import com.android.packageinstaller.permission.model.PermissionGroup; -import com.android.packageinstaller.permission.utils.Utils; - -import java.util.List; - -/** - * Fragment that allows the user to manage standard permissions. - */ -public final class ManageStandardPermissionsFragment extends ManagePermissionsFragment { - private static final String EXTRA_PREFS_KEY = "extra_prefs_key"; - - /** - * @return A new fragment - */ - public static ManageStandardPermissionsFragment newInstance() { - return new ManageStandardPermissionsFragment(); - } - - @Override - public void onStart() { - super.onStart(); - - getActivity().setTitle(com.android.packageinstaller.R.string.app_permissions); - } - - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == android.R.id.home) { - getActivity().finish(); - return true; - } - return super.onOptionsItemSelected(item); - } - - @Override - protected void updatePermissionsUi() { - PreferenceScreen screen = updatePermissionsUi(true); - if (screen == null) { - return; - } - - // Check if we need an additional permissions preference - List<PermissionGroup> groups = getPermissions().getGroups(); - int numExtraPermissions = 0; - for (PermissionGroup group : groups) { - if (!group.getDeclaringPackage().equals(ManagePermissionsFragment.OS_PKG)) { - numExtraPermissions++; - } - } - - Preference additionalPermissionsPreference = screen.findPreference(EXTRA_PREFS_KEY); - if (numExtraPermissions == 0) { - if (additionalPermissionsPreference != null) { - screen.removePreference(additionalPermissionsPreference); - } - } else { - if (additionalPermissionsPreference == null) { - additionalPermissionsPreference = new Preference(getActivity()); - additionalPermissionsPreference.setKey(EXTRA_PREFS_KEY); - additionalPermissionsPreference.setIcon(Utils.applyTint(getActivity(), - R.drawable.ic_more_items, - android.R.attr.colorControlNormal)); - additionalPermissionsPreference.setTitle(R.string.additional_permissions); - additionalPermissionsPreference.setOnPreferenceClickListener(preference -> { - ManageCustomPermissionsFragment frag = - new ManageCustomPermissionsFragment(); - frag.setTargetFragment(ManageStandardPermissionsFragment.this, 0); - FragmentTransaction ft = getFragmentManager().beginTransaction(); - ft.replace(android.R.id.content, frag); - ft.addToBackStack(null); - ft.commit(); - return true; - }); - - screen.addPreference(additionalPermissionsPreference); - } - - additionalPermissionsPreference.setSummary(getResources().getQuantityString( - R.plurals.additional_permissions_more, numExtraPermissions, - numExtraPermissions)); - } - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/MultiTargetSwitchPreference.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/MultiTargetSwitchPreference.java deleted file mode 100644 index dfd721a29d6c..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/MultiTargetSwitchPreference.java +++ /dev/null @@ -1,60 +0,0 @@ -/* -* Copyright (C) 2016 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.packageinstaller.permission.ui.handheld; - -import android.content.Context; -import android.preference.SwitchPreference; -import android.view.View; -import android.widget.Switch; - -class MultiTargetSwitchPreference extends SwitchPreference { - private View.OnClickListener mSwitchOnClickLister; - - public MultiTargetSwitchPreference(Context context) { - super(context); - } - - public void setCheckedOverride(boolean checked) { - super.setChecked(checked); - } - - @Override - public void setChecked(boolean checked) { - // If double target behavior is enabled do nothing - if (mSwitchOnClickLister == null) { - super.setChecked(checked); - } - } - - public void setSwitchOnClickListener(View.OnClickListener listener) { - mSwitchOnClickLister = listener; - } - - @Override - protected void onBindView(View view) { - super.onBindView(view); - Switch switchView = (Switch) view.findViewById( - com.android.internal.R.id.switch_widget); - switchView.setOnClickListener(mSwitchOnClickLister); - - if (mSwitchOnClickLister != null) { - final int padding = (int) ((view.getMeasuredHeight() - - switchView.getMeasuredHeight()) / 2 + 0.5f); - switchView.setPadding(padding, padding, 0, padding); - } - } -} \ No newline at end of file diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/PermissionAppsFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/PermissionAppsFragment.java deleted file mode 100644 index b2a37ac53214..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/PermissionAppsFragment.java +++ /dev/null @@ -1,390 +0,0 @@ -/* - * Copyright (C) 2015 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.packageinstaller.permission.ui.handheld; - -import android.app.ActionBar; -import android.app.Fragment; -import android.content.Context; -import android.content.Intent; -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import android.preference.Preference; -import android.preference.Preference.OnPreferenceClickListener; -import android.preference.PreferenceScreen; -import android.preference.SwitchPreference; -import android.util.ArraySet; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; - -import com.android.packageinstaller.DeviceUtils; -import com.android.packageinstaller.R; -import com.android.packageinstaller.permission.model.AppPermissionGroup; -import com.android.packageinstaller.permission.model.PermissionApps; -import com.android.packageinstaller.permission.model.PermissionApps.Callback; -import com.android.packageinstaller.permission.model.PermissionApps.PermissionApp; -import com.android.packageinstaller.permission.utils.SafetyNetLogger; -import com.android.packageinstaller.permission.utils.Utils; -import com.android.settingslib.HelpUtils; - -/** - * Show and manage apps which request a single permission group. - * - * <p>Shows a list of apps which request at least on permission of this group. - */ -public final class PermissionAppsFragment extends PermissionsFrameFragment implements Callback, - PermissionPreference.PermissionPreferenceOwnerFragment, - PermissionPreference.PermissionPreferenceChangeListener { - - private static final int MENU_SHOW_SYSTEM = Menu.FIRST; - private static final int MENU_HIDE_SYSTEM = Menu.FIRST + 1; - private static final String KEY_SHOW_SYSTEM_PREFS = "_showSystem"; - - private static final String SHOW_SYSTEM_KEY = PermissionAppsFragment.class.getName() - + KEY_SHOW_SYSTEM_PREFS; - - public static PermissionAppsFragment newInstance(String permissionName) { - return setPermissionName(new PermissionAppsFragment(), permissionName); - } - - private static <T extends Fragment> T setPermissionName(T fragment, String permissionName) { - Bundle arguments = new Bundle(); - arguments.putString(Intent.EXTRA_PERMISSION_NAME, permissionName); - fragment.setArguments(arguments); - return fragment; - } - - private PermissionApps mPermissionApps; - - private PreferenceScreen mExtraScreen; - - private ArraySet<AppPermissionGroup> mToggledGroups; - private ArraySet<String> mLauncherPkgs; - private boolean mHasConfirmedRevoke; - - private boolean mShowSystem; - private boolean mHasSystemApps; - private MenuItem mShowSystemMenu; - private MenuItem mHideSystemMenu; - - private Callback mOnPermissionsLoadedListener; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - if (savedInstanceState != null) { - mShowSystem = savedInstanceState.getBoolean(SHOW_SYSTEM_KEY); - } - - setLoading(true /* loading */, false /* animate */); - setHasOptionsMenu(true); - final ActionBar ab = getActivity().getActionBar(); - if (ab != null) { - ab.setDisplayHomeAsUpEnabled(true); - } - mLauncherPkgs = Utils.getLauncherPackages(getContext()); - - String groupName = getArguments().getString(Intent.EXTRA_PERMISSION_NAME); - mPermissionApps = new PermissionApps(getActivity(), groupName, this); - mPermissionApps.refresh(true); - } - - @Override - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - - outState.putBoolean(SHOW_SYSTEM_KEY, mShowSystem); - } - - @Override - public void onResume() { - super.onResume(); - mPermissionApps.refresh(true); - } - - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - if (mHasSystemApps) { - mShowSystemMenu = menu.add(Menu.NONE, MENU_SHOW_SYSTEM, Menu.NONE, - R.string.menu_show_system); - mHideSystemMenu = menu.add(Menu.NONE, MENU_HIDE_SYSTEM, Menu.NONE, - R.string.menu_hide_system); - updateMenu(); - } - - HelpUtils.prepareHelpMenuItem(getActivity(), menu, R.string.help_app_permissions, - getClass().getName()); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - getActivity().finish(); - return true; - case MENU_SHOW_SYSTEM: - case MENU_HIDE_SYSTEM: - mShowSystem = item.getItemId() == MENU_SHOW_SYSTEM; - if (mPermissionApps.getApps() != null) { - onPermissionsLoaded(mPermissionApps); - } - updateMenu(); - break; - } - return super.onOptionsItemSelected(item); - } - - private void updateMenu() { - mShowSystemMenu.setVisible(!mShowSystem); - mHideSystemMenu.setVisible(mShowSystem); - } - - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - bindUi(this, mPermissionApps); - } - - private static void bindUi(Fragment fragment, PermissionApps permissionApps) { - final Drawable icon = permissionApps.getIcon(); - final CharSequence label = permissionApps.getLabel(); - final ActionBar ab = fragment.getActivity().getActionBar(); - if (ab != null) { - ab.setTitle(label); - } - } - - private void setOnPermissionsLoadedListener(Callback callback) { - mOnPermissionsLoadedListener = callback; - } - - @Override - public void onPermissionsLoaded(PermissionApps permissionApps) { - Context context = getActivity(); - - if (context == null) { - return; - } - - boolean isTelevision = DeviceUtils.isTelevision(context); - PreferenceScreen screen = getPreferenceScreen(); - if (screen == null) { - screen = getPreferenceManager().createPreferenceScreen(getActivity()); - setPreferenceScreen(screen); - } - - screen.setOrderingAsAdded(false); - - ArraySet<String> preferencesToRemove = new ArraySet<>(); - for (int i = 0, n = screen.getPreferenceCount(); i < n; i++) { - preferencesToRemove.add(screen.getPreference(i).getKey()); - } - if (mExtraScreen != null) { - for (int i = 0, n = mExtraScreen.getPreferenceCount(); i < n; i++) { - preferencesToRemove.add(mExtraScreen.getPreference(i).getKey()); - } - } - - mHasSystemApps = false; - boolean menuOptionsInvalided = false; - - for (PermissionApp app : permissionApps.getApps()) { - if (!Utils.shouldShowPermission(app.getPermissionGroup())) { - continue; - } - - if (!app.getAppInfo().enabled) { - continue; - } - - String key = app.getKey(); - preferencesToRemove.remove(key); - Preference existingPref = screen.findPreference(key); - if (existingPref == null && mExtraScreen != null) { - existingPref = mExtraScreen.findPreference(key); - } - - boolean isSystemApp = Utils.isSystem(app, mLauncherPkgs); - - if (isSystemApp && !menuOptionsInvalided) { - mHasSystemApps = true; - getActivity().invalidateOptionsMenu(); - menuOptionsInvalided = true; - } - - if (isSystemApp && !isTelevision && !mShowSystem) { - if (existingPref != null) { - screen.removePreference(existingPref); - } - continue; - } - - if (existingPref != null) { - ((PermissionPreference) existingPref).updateUi(); - continue; - } - - PermissionPreference pref = new PermissionPreference(this, app.getPermissionGroup(), - this); - pref.setKey(app.getKey()); - pref.setIcon(app.getIcon()); - pref.setTitle(app.getLabel()); - - if (isSystemApp && isTelevision) { - if (mExtraScreen == null) { - mExtraScreen = getPreferenceManager().createPreferenceScreen(context); - } - mExtraScreen.addPreference(pref); - } else { - screen.addPreference(pref); - } - } - - if (mExtraScreen != null) { - preferencesToRemove.remove(KEY_SHOW_SYSTEM_PREFS); - Preference pref = screen.findPreference(KEY_SHOW_SYSTEM_PREFS); - - if (pref == null) { - pref = new Preference(context); - pref.setKey(KEY_SHOW_SYSTEM_PREFS); - pref.setIcon(Utils.applyTint(context, R.drawable.ic_toc, - android.R.attr.colorControlNormal)); - pref.setTitle(R.string.preference_show_system_apps); - pref.setOnPreferenceClickListener(new OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - SystemAppsFragment frag = new SystemAppsFragment(); - setPermissionName(frag, getArguments().getString(Intent.EXTRA_PERMISSION_NAME)); - frag.setTargetFragment(PermissionAppsFragment.this, 0); - getFragmentManager().beginTransaction() - .replace(android.R.id.content, frag) - .addToBackStack("SystemApps") - .commit(); - return true; - } - }); - screen.addPreference(pref); - } - - int grantedCount = 0; - for (int i = 0, n = mExtraScreen.getPreferenceCount(); i < n; i++) { - if (((SwitchPreference) mExtraScreen.getPreference(i)).isChecked()) { - grantedCount++; - } - } - pref.setSummary(getString(R.string.app_permissions_group_summary, - grantedCount, mExtraScreen.getPreferenceCount())); - } - - for (String key : preferencesToRemove) { - Preference pref = screen.findPreference(key); - if (pref != null) { - screen.removePreference(pref); - } else if (mExtraScreen != null) { - pref = mExtraScreen.findPreference(key); - if (pref != null) { - mExtraScreen.removePreference(pref); - } - } - } - - setLoading(false /* loading */, true /* animate */); - - if (mOnPermissionsLoadedListener != null) { - mOnPermissionsLoadedListener.onPermissionsLoaded(permissionApps); - } - } - - @Override - public void onPreferenceChanged(String key) { - if (mToggledGroups == null) { - mToggledGroups = new ArraySet<>(); - } - mToggledGroups.add(mPermissionApps.getApp(key).getPermissionGroup()); - } - - @Override - public void onPause() { - super.onPause(); - logToggledGroups(); - } - - private void logToggledGroups() { - if (mToggledGroups != null) { - SafetyNetLogger.logPermissionsToggled(mToggledGroups); - mToggledGroups = null; - } - } - - @Override - public void onBackgroundAccessChosen(String key, int chosenItem) { - ((PermissionPreference) getPreferenceScreen().findPreference(key)) - .onBackgroundAccessChosen(chosenItem); - } - - @Override - public void onDenyAnyWay(String key, @PermissionPreference.ChangeTarget int changeTarget) { - ((PermissionPreference) getPreferenceScreen().findPreference(key)).onDenyAnyWay( - changeTarget); - } - - @Override - public boolean shouldConfirmDefaultPermissionRevoke() { - return !mHasConfirmedRevoke; - } - - @Override - public void hasConfirmDefaultPermissionRevoke() { - mHasConfirmedRevoke = true; - } - - public static class SystemAppsFragment extends PermissionsFrameFragment implements Callback { - PermissionAppsFragment mOuterFragment; - - @Override - public void onCreate(Bundle savedInstanceState) { - mOuterFragment = (PermissionAppsFragment) getTargetFragment(); - setLoading(true /* loading */, false /* animate */); - super.onCreate(savedInstanceState); - if (mOuterFragment.mExtraScreen != null) { - setPreferenceScreen(); - } else { - mOuterFragment.setOnPermissionsLoadedListener(this); - } - } - - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - String groupName = getArguments().getString(Intent.EXTRA_PERMISSION_NAME); - PermissionApps permissionApps = new PermissionApps(getActivity(), groupName, null); - bindUi(this, permissionApps); - } - - @Override - public void onPermissionsLoaded(PermissionApps permissionApps) { - setPreferenceScreen(); - mOuterFragment.setOnPermissionsLoadedListener(null); - } - - private void setPreferenceScreen() { - setPreferenceScreen(mOuterFragment.mExtraScreen); - setLoading(false /* loading */, true /* animate */); - } - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/PermissionPreference.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/PermissionPreference.java deleted file mode 100644 index 8563705b4f9a..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/PermissionPreference.java +++ /dev/null @@ -1,581 +0,0 @@ -/* - * Copyright (C) 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. - */ - -package com.android.packageinstaller.permission.ui.handheld; - -import static com.android.packageinstaller.permission.utils.Utils.getRequestMessage; - -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import android.app.AlertDialog; -import android.app.Dialog; -import android.app.DialogFragment; -import android.app.Fragment; -import android.content.DialogInterface; -import android.content.pm.PackageItemInfo; -import android.os.Bundle; -import android.text.BidiFormatter; -import android.widget.Switch; - -import androidx.annotation.IntDef; - -import com.android.packageinstaller.R; -import com.android.packageinstaller.permission.model.AppPermissionGroup; -import com.android.packageinstaller.permission.model.Permission; -import com.android.packageinstaller.permission.utils.LocationUtils; -import com.android.packageinstaller.permission.utils.Utils; -import com.android.settingslib.RestrictedLockUtils; - -import java.lang.annotation.Retention; -import java.util.List; - -/** - * A preference for representing a permission group requested by an app. - */ -class PermissionPreference extends RestrictedSwitchPreference { - @Retention(SOURCE) - @IntDef(value = {CHANGE_FOREGROUND, CHANGE_BACKGROUND}, flag = true) - @interface ChangeTarget {} - static final int CHANGE_FOREGROUND = 1; - static final int CHANGE_BACKGROUND = 2; - static final int CHANGE_BOTH = CHANGE_FOREGROUND | CHANGE_BACKGROUND; - - private final AppPermissionGroup mGroup; - private final Fragment mFragment; - private final PermissionPreferenceChangeListener mCallBacks; - - /** Callbacks for the permission to the fragment showing a list of permissions */ - interface PermissionPreferenceChangeListener { - /** - * Checks if the user has to confirm a revocation of a permission granted by default. - * - * @return {@code true} iff the user has to confirm it - */ - boolean shouldConfirmDefaultPermissionRevoke(); - - /** - * Notify the listener that the user confirmed that she/he wants to revoke permissions that - * were granted by default. - */ - void hasConfirmDefaultPermissionRevoke(); - - /** - * Notify the listener that this preference has changed. - * - * @param key The key uniquely identifying this preference - */ - void onPreferenceChanged(String key); - } - - /** - * Callbacks from dialogs to the fragment. These callbacks are supposed to directly cycle back - * to the permission tha created the dialog. - */ - interface PermissionPreferenceOwnerFragment { - /** - * The {@link DefaultDenyDialog} can only interact with the fragment, not the preference - * that created it. Hence this call goes to the fragment, which then finds the preference an - * calls {@link #onDenyAnyWay(int)}. - * - * @param key Key uniquely identifying the preference that created the default deny dialog - * @param changeTarget Whether background or foreground permissions should be changed - * - * @see #showDefaultDenyDialog(int) - */ - void onDenyAnyWay(String key, @ChangeTarget int changeTarget); - - /** - * The {@link BackgroundAccessChooser} can only interact with the fragment, not the - * preference that created it. Hence this call goes to the fragment, which then finds the - * preference an calls {@link #onBackgroundAccessChosen(int)}}. - * - * @param key Key uniquely identifying the preference that created the background access - * chooser - * @param chosenItem The index of the item selected by the user. - * - * @see #showBackgroundChooserDialog() - */ - void onBackgroundAccessChosen(String key, int chosenItem); - } - - PermissionPreference(Fragment fragment, AppPermissionGroup group, - PermissionPreferenceChangeListener callbacks) { - super(fragment.getContext()); - - mFragment = fragment; - mGroup = group; - mCallBacks = callbacks; - - setPersistent(false); - updateUi(); - } - - /** - * Update the preference after the state might have changed. - */ - void updateUi() { - boolean arePermissionsIndividuallyControlled = - Utils.areGroupPermissionsIndividuallyControlled(getContext(), mGroup.getName()); - RestrictedLockUtils.EnforcedAdmin admin = - RestrictedLockUtils.getProfileOrDeviceOwner(getContext(), mGroup.getUserId()); - boolean isForegroundPolicyFixed = mGroup.isPolicyFixed(); - boolean isBackgroundPolicyFixed = mGroup.getBackgroundPermissions() == null - || mGroup.getBackgroundPermissions().isPolicyFixed(); - boolean isAdminFixed = admin != null; - boolean isPolicyFixed = (isForegroundPolicyFixed && isBackgroundPolicyFixed) - && !isAdminFixed; - - // Reset ui state - setDisabledByAdmin(null); - setEnabled(true); - setOnPreferenceClickListener(null); - setSwitchOnClickListener(null); - setSummary(null); - - setChecked(mGroup.areRuntimePermissionsGranted()); - - if (isAdminFixed) { - setDisabledByAdmin(admin); - setSummary(R.string.permission_summary_enforced_by_admin); - setEnabled(false); - } else if (isPolicyFixed) { - // Both foreground and background filed - setSummary(R.string.permission_summary_enforced_by_policy); - setEnabled(false); - } else if (arePermissionsIndividuallyControlled) { - setOnPreferenceClickListener((pref) -> { - showAllPermissions(mGroup.getName()); - return false; - }); - - setSwitchOnClickListener(v -> { - Switch switchView = (Switch) v; - requestChange(switchView.isChecked(), CHANGE_BOTH); - - // Update UI as the switch widget might be in wrong state - updateUi(); - }); - - updateSummaryForIndividuallyControlledPermissionGroup(); - } else { - if (mGroup.hasPermissionWithBackgroundMode()) { - if (mGroup.getBackgroundPermissions() == null) { - // The group has background permissions but the app did not request any. I.e. - // The app can only switch between 'never" and "only in foreground". - setOnPreferenceChangeListener((pref, newValue) -> - requestChange((Boolean) newValue, CHANGE_FOREGROUND)); - - updateSummaryForPermissionGroupWithBackgroundPermission(); - } else { - AppPermissionGroup backgroundGroup = mGroup.getBackgroundPermissions(); - - if (isBackgroundPolicyFixed) { - setOnPreferenceChangeListener((pref, newValue) -> - requestChange((Boolean) newValue, CHANGE_FOREGROUND)); - - if (backgroundGroup.areRuntimePermissionsGranted()) { - setSummary(R.string - .permission_summary_enabled_by_policy_background_only); - } else { - setSummary(R.string - .permission_summary_disabled_by_policy_background_only); - } - } else if (isForegroundPolicyFixed) { - if (mGroup.areRuntimePermissionsGranted()) { - setOnPreferenceChangeListener((pref, newValue) -> - requestChange((Boolean) newValue, CHANGE_BACKGROUND)); - - setSummary(R.string - .permission_summary_enabled_by_policy_foreground_only); - } else { - // Background access can only be enabled once foreground access is - // enabled. Hence if foreground access can never be enabled, there is - // no point allowing background access to be enabled - setSummary(R.string.permission_summary_enforced_by_policy); - setEnabled(false); - } - } else { - updateSummaryForPermissionGroupWithBackgroundPermission(); - - setOnPreferenceClickListener((pref) -> { - showBackgroundChooserDialog(); - return true; - }); - - setSwitchOnClickListener(v -> { - Switch switchView = (Switch) v; - - if (switchView.isChecked()) { - showBackgroundChooserDialog(); - } else { - requestChange(false, CHANGE_BOTH); - } - - // Update UI as the switch widget might be in wrong state - updateUi(); - }); - } - } - } else { - setOnPreferenceChangeListener((pref, newValue) -> - requestChange((Boolean) newValue, CHANGE_BOTH)); - } - } - } - - /** - * Update the summary in the case the permission group has individually controlled permissions. - */ - private void updateSummaryForIndividuallyControlledPermissionGroup() { - int revokedCount = 0; - List<Permission> permissions = mGroup.getPermissions(); - final int permissionCount = permissions.size(); - for (int i = 0; i < permissionCount; i++) { - Permission permission = permissions.get(i); - if (mGroup.doesSupportRuntimePermissions() - ? !permission.isGranted() : (!permission.isAppOpAllowed() - || permission.isReviewRequired())) { - revokedCount++; - } - } - - final int resId; - if (revokedCount == 0) { - resId = R.string.permission_revoked_none; - } else if (revokedCount == permissionCount) { - resId = R.string.permission_revoked_all; - } else { - resId = R.string.permission_revoked_count; - } - - String summary = getContext().getString(resId, revokedCount); - setSummary(summary); - } - - /** - * Update the summary of a permission group that has background permission. - * - * <p>This does not apply to permission groups that are fixed by policy</p> - */ - private void updateSummaryForPermissionGroupWithBackgroundPermission() { - AppPermissionGroup backgroundGroup = mGroup.getBackgroundPermissions(); - - if (mGroup.areRuntimePermissionsGranted()) { - if (backgroundGroup == null) { - setSummary(R.string.permission_access_only_foreground); - } else { - if (backgroundGroup.areRuntimePermissionsGranted()) { - setSummary(R.string.permission_access_always); - } else { - setSummary(R.string.permission_access_only_foreground); - } - } - } else { - setSummary(R.string.permission_access_never); - } - } - - /** - * Show all individual permissions in this group in a new fragment. - */ - private void showAllPermissions(String filterGroup) { - Fragment frag = AllAppPermissionsFragment.newInstance(mGroup.getApp().packageName, - filterGroup); - mFragment.getFragmentManager().beginTransaction() - .replace(android.R.id.content, frag) - .addToBackStack("AllPerms") - .commit(); - } - - /** - * Get the label of the app the permission group belongs to. (App permission groups are all - * permissions of a group an app has requested.) - * - * @return The label of the app - */ - private String getAppLabel() { - return BidiFormatter.getInstance().unicodeWrap( - mGroup.getApp().applicationInfo.loadSafeLabel(getContext().getPackageManager(), - PackageItemInfo.DEFAULT_MAX_LABEL_SIZE_PX, - PackageItemInfo.SAFE_LABEL_FLAG_TRIM - | PackageItemInfo.SAFE_LABEL_FLAG_FIRST_LINE) - .toString()); - } - - /** - * Request to grant/revoke permissions group. - * - * <p>Does <u>not</u> handle: - * <ul> - * <li>Individually granted permissions</li> - * <li>Permission groups with background permissions</li> - * </ul> - * <p><u>Does</u> handle: - * <ul> - * <li>Default grant permissions</li> - * </ul> - * - * @param requestGrant If this group should be granted - * @param changeTarget Which permission group (foreground/background/both) should be changed - * @return If the request was processed. - */ - private boolean requestChange(boolean requestGrant, @ChangeTarget int changeTarget) { - if (LocationUtils.isLocationGroupAndProvider(mGroup.getName(), - mGroup.getApp().packageName)) { - LocationUtils.showLocationDialog(getContext(), getAppLabel()); - return false; - } - if (requestGrant) { - mCallBacks.onPreferenceChanged(getKey()); - - if ((changeTarget & CHANGE_FOREGROUND) != 0) { - mGroup.grantRuntimePermissions(false); - } - if ((changeTarget & CHANGE_BACKGROUND) != 0) { - if (mGroup.getBackgroundPermissions() != null) { - mGroup.getBackgroundPermissions().grantRuntimePermissions(false); - } - } - } else { - boolean requestToRevokeGrantedByDefault = false; - if ((changeTarget & CHANGE_FOREGROUND) != 0) { - requestToRevokeGrantedByDefault = mGroup.hasGrantedByDefaultPermission(); - } - if ((changeTarget & CHANGE_BACKGROUND) != 0) { - if (mGroup.getBackgroundPermissions() != null) { - requestToRevokeGrantedByDefault |= - mGroup.getBackgroundPermissions().hasGrantedByDefaultPermission(); - } - } - - if ((requestToRevokeGrantedByDefault || !mGroup.doesSupportRuntimePermissions()) - && mCallBacks.shouldConfirmDefaultPermissionRevoke()) { - showDefaultDenyDialog(changeTarget); - return false; - } else { - mCallBacks.onPreferenceChanged(getKey()); - - if ((changeTarget & CHANGE_FOREGROUND) != 0) { - mGroup.revokeRuntimePermissions(false); - } - if ((changeTarget & CHANGE_BACKGROUND) != 0) { - if (mGroup.getBackgroundPermissions() != null) { - mGroup.getBackgroundPermissions().revokeRuntimePermissions(false); - } - } - } - } - - updateUi(); - - return true; - } - - /** - * Show a dialog that warns the user that she/he is about to revoke permissions that were - * granted by default. - * - * <p>The order of operation to revoke a permission granted by default is: - * <ol> - * <li>{@code showDefaultDenyDialog}</li> - * <li>{@link DefaultDenyDialog#onCreateDialog}</li> - * <li>{@link PermissionPreferenceOwnerFragment#onDenyAnyWay}</li> - * <li>{@link PermissionPreference#onDenyAnyWay}</li> - * </ol> - * - * @param changeTarget Whether background or foreground should be changed - */ - private void showDefaultDenyDialog(@ChangeTarget int changeTarget) { - Bundle args = new Bundle(); - - boolean showGrantedByDefaultWarning = false; - if ((changeTarget & CHANGE_FOREGROUND) != 0) { - showGrantedByDefaultWarning = mGroup.hasGrantedByDefaultPermission(); - } - if ((changeTarget & CHANGE_BACKGROUND) != 0) { - if (mGroup.getBackgroundPermissions() != null) { - showGrantedByDefaultWarning |= - mGroup.getBackgroundPermissions().hasGrantedByDefaultPermission(); - } - } - - args.putInt(DefaultDenyDialog.MSG, showGrantedByDefaultWarning ? R.string.system_warning - : R.string.old_sdk_deny_warning); - args.putString(DefaultDenyDialog.KEY, getKey()); - args.putInt(DefaultDenyDialog.CHANGE_TARGET, changeTarget); - - DefaultDenyDialog deaultDenyDialog = new DefaultDenyDialog(); - deaultDenyDialog.setArguments(args); - deaultDenyDialog.show(mFragment.getChildFragmentManager().beginTransaction(), - "denyDefault"); - } - - /** - * Show a dialog that asks the user if foreground/background/none access should be enabled. - * - * <p>The order of operation to grant foreground/background/none access is: - * <ol> - * <li>{@code showBackgroundChooserDialog}</li> - * <li>{@link BackgroundAccessChooser#onCreateDialog}</li> - * <li>{@link PermissionPreferenceOwnerFragment#onBackgroundAccessChosen}</li> - * <li>{@link PermissionPreference#onBackgroundAccessChosen}</li> - * </ol> - */ - private void showBackgroundChooserDialog() { - Bundle args = new Bundle(); - args.putCharSequence(BackgroundAccessChooser.TITLE, - getRequestMessage(getAppLabel(), mGroup, getContext(), mGroup.getRequest())); - args.putString(BackgroundAccessChooser.KEY, getKey()); - - - if (mGroup.areRuntimePermissionsGranted()) { - if (mGroup.getBackgroundPermissions().areRuntimePermissionsGranted()) { - args.putInt(BackgroundAccessChooser.SELECTION, - BackgroundAccessChooser.ALWAYS_OPTION); - } else { - args.putInt(BackgroundAccessChooser.SELECTION, - BackgroundAccessChooser.FOREGROUND_ONLY_OPTION); - } - } else { - args.putInt(BackgroundAccessChooser.SELECTION, BackgroundAccessChooser.NEVER_OPTION); - } - - BackgroundAccessChooser chooserDialog = new BackgroundAccessChooser(); - chooserDialog.setArguments(args); - chooserDialog.show(mFragment.getChildFragmentManager().beginTransaction(), - "backgroundChooser"); - } - - /** - * Once we user has confirmed that he/she wants to revoke a permission that was granted by - * default, actually revoke the permissions. - * - * @see #showDefaultDenyDialog(int) - */ - void onDenyAnyWay(@ChangeTarget int changeTarget) { - mCallBacks.onPreferenceChanged(getKey()); - - boolean hasDefaultPermissions = false; - if ((changeTarget & CHANGE_FOREGROUND) != 0) { - mGroup.revokeRuntimePermissions(false); - hasDefaultPermissions = mGroup.hasGrantedByDefaultPermission(); - } - if ((changeTarget & CHANGE_BACKGROUND) != 0) { - if (mGroup.getBackgroundPermissions() != null) { - mGroup.getBackgroundPermissions().revokeRuntimePermissions(false); - hasDefaultPermissions |= - mGroup.getBackgroundPermissions().hasGrantedByDefaultPermission(); - } - } - - if (hasDefaultPermissions) { - mCallBacks.hasConfirmDefaultPermissionRevoke(); - } - updateUi(); - } - - /** - * Process the return from a {@link BackgroundAccessChooser} dialog. - * - * <p>These dialog are started when the user want to grant a permission group that has - * background permissions. - * - * @param choosenItem The item that the user chose - */ - void onBackgroundAccessChosen(int choosenItem) { - AppPermissionGroup backgroundGroup = mGroup.getBackgroundPermissions(); - - switch (choosenItem) { - case BackgroundAccessChooser.ALWAYS_OPTION: - requestChange(true, CHANGE_BOTH); - break; - case BackgroundAccessChooser.FOREGROUND_ONLY_OPTION: - if (backgroundGroup.areRuntimePermissionsGranted()) { - requestChange(false, CHANGE_BACKGROUND); - } - requestChange(true, CHANGE_FOREGROUND); - break; - case BackgroundAccessChooser.NEVER_OPTION: - if (mGroup.areRuntimePermissionsGranted() - || mGroup.getBackgroundPermissions().areRuntimePermissionsGranted()) { - requestChange(false, CHANGE_BOTH); - } - break; - } - } - - /** - * A dialog warning the user that she/he is about to deny a permission that was granted by - * default. - * - * @see #showDefaultDenyDialog(int) - */ - public static class DefaultDenyDialog extends DialogFragment { - private static final String MSG = DefaultDenyDialog.class.getName() + ".arg.msg"; - private static final String CHANGE_TARGET = DefaultDenyDialog.class.getName() - + ".arg.changeTarget"; - private static final String KEY = DefaultDenyDialog.class.getName() + ".arg.key"; - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - AlertDialog.Builder b = new AlertDialog.Builder(getContext()) - .setMessage(getArguments().getInt(MSG)) - .setNegativeButton(R.string.cancel, null) - .setPositiveButton(R.string.grant_dialog_button_deny_anyway, - (DialogInterface dialog, int which) -> ( - (PermissionPreferenceOwnerFragment) getParentFragment()) - .onDenyAnyWay(getArguments().getString(KEY), - getArguments().getInt(CHANGE_TARGET))); - - return b.create(); - } - } - - /** - * If a permission group has background permission this chooser is used to let the user - * choose how the permission group should be granted. - * - * @see #showBackgroundChooserDialog() - */ - public static class BackgroundAccessChooser extends DialogFragment { - private static final String TITLE = BackgroundAccessChooser.class.getName() + ".arg.title"; - private static final String KEY = BackgroundAccessChooser.class.getName() + ".arg.key"; - private static final String SELECTION = BackgroundAccessChooser.class.getName() - + ".arg.selection"; - - // Needs to match the entries in R.array.background_access_chooser_dialog_choices - static final int ALWAYS_OPTION = 0; - static final int FOREGROUND_ONLY_OPTION = 1; - static final int NEVER_OPTION = 2; - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - AlertDialog.Builder b = new AlertDialog.Builder(getActivity()) - .setTitle(getArguments().getCharSequence(TITLE)) - .setSingleChoiceItems(R.array.background_access_chooser_dialog_choices, - getArguments().getInt(SELECTION), - (dialog, which) -> { - dismissAllowingStateLoss(); - ((PermissionPreferenceOwnerFragment) getParentFragment()) - .onBackgroundAccessChosen(getArguments().getString(KEY), - which); - } - ); - - return b.create(); - } - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/PermissionsFrameFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/PermissionsFrameFragment.java deleted file mode 100644 index e7f63b2387ff..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/PermissionsFrameFragment.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2015 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.packageinstaller.permission.ui.handheld; - -import android.os.Bundle; -import android.preference.PreferenceFragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.animation.Animation; -import android.view.animation.Animation.AnimationListener; -import android.view.animation.AnimationUtils; -import android.widget.ListView; -import android.widget.TextView; -import com.android.packageinstaller.R; - -public abstract class PermissionsFrameFragment extends PreferenceFragment { - private ViewGroup mPreferencesContainer; - - private View mLoadingView; - private ViewGroup mPrefsView; - private boolean mIsLoading; - - /** - * Returns the view group that holds the preferences objects. This will - * only be set after {@link #onCreateView} has been called. - */ - protected final ViewGroup getPreferencesContainer() { - return mPreferencesContainer; - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.permissions_frame, container, - false); - mPrefsView = (ViewGroup) rootView.findViewById(R.id.prefs_container); - if (mPrefsView == null) { - mPrefsView = rootView; - } - mLoadingView = rootView.findViewById(R.id.loading_container); - mPreferencesContainer = (ViewGroup) super.onCreateView( - inflater, mPrefsView, savedInstanceState); - setLoading(mIsLoading, false, true /* force */); - mPrefsView.addView(mPreferencesContainer); - return rootView; - } - - protected void setLoading(boolean loading, boolean animate) { - setLoading(loading, animate, false); - } - - private void setLoading(boolean loading, boolean animate, boolean force) { - if (mIsLoading != loading || force) { - mIsLoading = loading; - if (getView() == null) { - // If there is no created view, there is no reason to animate. - animate = false; - } - if (mPrefsView != null) { - setViewShown(mPrefsView, !loading, animate); - } - if (mLoadingView != null) { - setViewShown(mLoadingView, loading, animate); - } - } - } - - @Override - public ListView getListView() { - ListView listView = super.getListView(); - if (listView.getEmptyView() == null) { - TextView emptyView = (TextView) getView().findViewById(R.id.no_permissions); - listView.setEmptyView(emptyView); - } - return listView; - } - - private void setViewShown(final View view, boolean shown, boolean animate) { - if (animate) { - Animation animation = AnimationUtils.loadAnimation(getContext(), - shown ? android.R.anim.fade_in : android.R.anim.fade_out); - if (shown) { - view.setVisibility(View.VISIBLE); - } else { - animation.setAnimationListener(new AnimationListener() { - @Override - public void onAnimationStart(Animation animation) { - } - - @Override - public void onAnimationRepeat(Animation animation) { - } - - @Override - public void onAnimationEnd(Animation animation) { - view.setVisibility(View.INVISIBLE); - } - }); - } - view.startAnimation(animation); - } else { - view.clearAnimation(); - view.setVisibility(shown ? View.VISIBLE : View.INVISIBLE); - } - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/RestrictedSwitchPreference.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/RestrictedSwitchPreference.java deleted file mode 100644 index 30ccf3bfd561..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/RestrictedSwitchPreference.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2016 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.packageinstaller.permission.ui.handheld; - -import android.content.Context; -import android.preference.PreferenceScreen; -import android.view.View; -import android.widget.TextView; - -import com.android.packageinstaller.R; -import com.android.settingslib.RestrictedLockUtils; - -import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; - -public class RestrictedSwitchPreference extends MultiTargetSwitchPreference { - private final Context mContext; - private boolean mDisabledByAdmin; - private EnforcedAdmin mEnforcedAdmin; - private final int mSwitchWidgetResId; - - public RestrictedSwitchPreference(Context context) { - super(context); - mSwitchWidgetResId = getWidgetLayoutResource(); - mContext = context; - } - - @Override - public void onBindView(View view) { - super.onBindView(view); - if (mDisabledByAdmin) { - view.setEnabled(true); - } - if (mDisabledByAdmin) { - final TextView summaryView = (TextView) view.findViewById(android.R.id.summary); - if (summaryView != null) { - summaryView.setText( - isChecked() ? R.string.enabled_by_admin : R.string.disabled_by_admin); - summaryView.setVisibility(View.VISIBLE); - } - } - } - - @Override - public void setEnabled(boolean enabled) { - if (enabled && mDisabledByAdmin) { - setDisabledByAdmin(null); - } else { - super.setEnabled(enabled); - } - } - - public void setDisabledByAdmin(EnforcedAdmin admin) { - final boolean disabled = (admin != null ? true : false); - mEnforcedAdmin = admin; - if (mDisabledByAdmin != disabled) { - mDisabledByAdmin = disabled; - setWidgetLayoutResource(disabled ? R.layout.restricted_icon : mSwitchWidgetResId); - setEnabled(!disabled); - } - } - - @Override - public void performClick(PreferenceScreen preferenceScreen) { - if (mDisabledByAdmin) { - RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mContext, mEnforcedAdmin); - } else { - super.performClick(preferenceScreen); - } - } -} \ No newline at end of file diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/ReviewPermissionsFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/ReviewPermissionsFragment.java deleted file mode 100644 index 83fef0dbc13f..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/ReviewPermissionsFragment.java +++ /dev/null @@ -1,404 +0,0 @@ -/* - * Copyright (C) 2017 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.packageinstaller.permission.ui.handheld; - -import android.app.Activity; -import android.content.Intent; -import android.content.IntentSender; -import android.content.pm.PackageInfo; -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import android.os.RemoteCallback; -import android.text.Html; -import android.text.Spanned; -import android.view.View; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.fragment.app.DialogFragment; -import androidx.preference.Preference; -import androidx.preference.PreferenceCategory; -import androidx.preference.PreferenceFragmentCompat; -import androidx.preference.PreferenceGroup; -import androidx.preference.PreferenceScreen; -import androidx.preference.SwitchPreference; -import androidx.preference.TwoStatePreference; - -import com.android.packageinstaller.R; -import com.android.packageinstaller.permission.model.AppPermissionGroup; -import com.android.packageinstaller.permission.model.AppPermissions; -import com.android.packageinstaller.permission.model.Permission; -import com.android.packageinstaller.permission.ui.ConfirmActionDialogFragment; -import com.android.packageinstaller.permission.ui.ManagePermissionsActivity; -import com.android.packageinstaller.permission.utils.ArrayUtils; -import com.android.packageinstaller.permission.utils.Utils; - -import java.util.ArrayList; -import java.util.List; - -public final class ReviewPermissionsFragment extends PreferenceFragmentCompat - implements View.OnClickListener, Preference.OnPreferenceChangeListener, - ConfirmActionDialogFragment.OnActionConfirmedListener { - - private static final String EXTRA_PACKAGE_INFO = - "com.android.packageinstaller.permission.ui.extra.PACKAGE_INFO"; - - private AppPermissions mAppPermissions; - - private Button mContinueButton; - private Button mCancelButton; - private Button mMoreInfoButton; - - private PreferenceCategory mNewPermissionsCategory; - private PreferenceCategory mCurrentPermissionsCategory; - - private boolean mHasConfirmedRevoke; - - public static ReviewPermissionsFragment newInstance(PackageInfo packageInfo) { - Bundle arguments = new Bundle(); - arguments.putParcelable(ReviewPermissionsFragment.EXTRA_PACKAGE_INFO, packageInfo); - ReviewPermissionsFragment instance = new ReviewPermissionsFragment(); - instance.setArguments(arguments); - instance.setRetainInstance(true); - return instance; - } - - @Override - public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { - Activity activity = getActivity(); - if (activity == null) { - return; - } - - PackageInfo packageInfo = getArguments().getParcelable(EXTRA_PACKAGE_INFO); - if (packageInfo == null) { - activity.finish(); - return; - } - - mAppPermissions = new AppPermissions(activity, packageInfo, false, - () -> getActivity().finish()); - - if (mAppPermissions.getPermissionGroups().isEmpty()) { - activity.finish(); - return; - } - - boolean reviewRequired = false; - for (AppPermissionGroup group : mAppPermissions.getPermissionGroups()) { - if (group.isReviewRequired()) { - reviewRequired = true; - break; - } - } - - if (!reviewRequired) { - activity.finish(); - } - } - - @Override - public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - bindUi(); - } - - @Override - public void onResume() { - super.onResume(); - mAppPermissions.refresh(); - loadPreferences(); - } - - @Override - public void onClick(View view) { - Activity activity = getActivity(); - if (activity == null) { - return; - } - if (view == mContinueButton) { - confirmPermissionsReview(); - executeCallback(true); - } else if (view == mCancelButton) { - executeCallback(false); - activity.setResult(Activity.RESULT_CANCELED); - } else if (view == mMoreInfoButton) { - Intent intent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS); - intent.putExtra(Intent.EXTRA_PACKAGE_NAME, - mAppPermissions.getPackageInfo().packageName); - intent.putExtra(ManagePermissionsActivity.EXTRA_ALL_PERMISSIONS, true); - getActivity().startActivity(intent); - } - activity.finish(); - } - - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - if (mHasConfirmedRevoke) { - return true; - } - if (preference instanceof SwitchPreference) { - SwitchPreference switchPreference = (SwitchPreference) preference; - if (switchPreference.isChecked()) { - showWarnRevokeDialog(switchPreference.getKey()); - } else { - return true; - } - } - return false; - } - - @Override - public void onActionConfirmed(String action) { - Preference preference = getPreferenceManager().findPreference(action); - if (preference instanceof SwitchPreference) { - SwitchPreference switchPreference = (SwitchPreference) preference; - switchPreference.setChecked(false); - mHasConfirmedRevoke = true; - } - } - - private void showWarnRevokeDialog(final String groupName) { - DialogFragment fragment = ConfirmActionDialogFragment.newInstance( - getString(R.string.old_sdk_deny_warning), groupName); - fragment.show(getActivity().getSupportFragmentManager(), fragment.getClass().getName()); - } - - private void grantReviewedPermission(AppPermissionGroup group) { - String[] permissionsToGrant = null; - final int permissionCount = group.getPermissions().size(); - for (int j = 0; j < permissionCount; j++) { - final Permission permission = group.getPermissions().get(j); - if (permission.isReviewRequired()) { - permissionsToGrant = ArrayUtils.appendString( - permissionsToGrant, permission.getName()); - } - } - if (permissionsToGrant != null) { - group.grantRuntimePermissions(false, permissionsToGrant); - } - } - - private void confirmPermissionsReview() { - final List<PreferenceGroup> preferenceGroups = new ArrayList<>(); - if (mNewPermissionsCategory != null) { - preferenceGroups.add(mNewPermissionsCategory); - preferenceGroups.add(mCurrentPermissionsCategory); - } else { - preferenceGroups.add(getPreferenceScreen()); - } - - final int preferenceGroupCount = preferenceGroups.size(); - for (int groupNum = 0; groupNum < preferenceGroupCount; groupNum++) { - final PreferenceGroup preferenceGroup = preferenceGroups.get(groupNum); - - final int preferenceCount = preferenceGroup.getPreferenceCount(); - for (int prefNum = 0; prefNum < preferenceCount; prefNum++) { - Preference preference = preferenceGroup.getPreference(prefNum); - if (preference instanceof TwoStatePreference) { - TwoStatePreference twoStatePreference = (TwoStatePreference) preference; - String groupName = preference.getKey(); - AppPermissionGroup group = mAppPermissions.getPermissionGroup(groupName); - if (twoStatePreference.isChecked()) { - grantReviewedPermission(group); - - // TODO: Allow the user to only grant foreground permissions - if (group.getBackgroundPermissions() != null) { - grantReviewedPermission(group.getBackgroundPermissions()); - } - } else { - group.revokeRuntimePermissions(false); - if (group.getBackgroundPermissions() != null) { - group.getBackgroundPermissions().revokeRuntimePermissions(false); - } - } - group.resetReviewRequired(); - } - } - } - } - - private void bindUi() { - Activity activity = getActivity(); - if (activity == null) { - return; - } - - // Set icon - Drawable icon = mAppPermissions.getPackageInfo().applicationInfo.loadIcon( - activity.getPackageManager()); - ImageView iconView = activity.requireViewById(R.id.app_icon); - iconView.setImageDrawable(icon); - - // Set message - final int labelTemplateResId = isPackageUpdated() - ? R.string.permission_review_title_template_update - : R.string.permission_review_title_template_install; - Spanned message = Html.fromHtml(getString(labelTemplateResId, - mAppPermissions.getAppLabel()), 0); - - // Set the permission message as the title so it can be announced. - activity.setTitle(message.toString()); - - // Color the app name. - TextView permissionsMessageView = activity.requireViewById( - R.id.permissions_message); - permissionsMessageView.setText(message); - - mContinueButton = getActivity().requireViewById(R.id.continue_button); - mContinueButton.setOnClickListener(this); - - mCancelButton = getActivity().requireViewById(R.id.cancel_button); - mCancelButton.setOnClickListener(this); - - if (activity.getPackageManager().arePermissionsIndividuallyControlled()) { - mMoreInfoButton = getActivity().requireViewById( - R.id.permission_more_info_button); - mMoreInfoButton.setOnClickListener(this); - mMoreInfoButton.setVisibility(View.VISIBLE); - } - } - - private void loadPreferences() { - Activity activity = getActivity(); - if (activity == null) { - return; - } - - PreferenceScreen screen = getPreferenceScreen(); - if (screen == null) { - screen = getPreferenceManager().createPreferenceScreen(getActivity()); - setPreferenceScreen(screen); - } else { - screen.removeAll(); - } - - mCurrentPermissionsCategory = null; - PreferenceGroup oldNewPermissionsCategory = mNewPermissionsCategory; - mNewPermissionsCategory = null; - - final boolean isPackageUpdated = isPackageUpdated(); - - for (AppPermissionGroup group : mAppPermissions.getPermissionGroups()) { - if (!Utils.shouldShowPermission(group) - || !Utils.OS_PKG.equals(group.getDeclaringPackage())) { - continue; - } - - final SwitchPreference preference; - Preference cachedPreference = oldNewPermissionsCategory != null - ? oldNewPermissionsCategory.findPreference(group.getName()) : null; - if (cachedPreference instanceof SwitchPreference) { - preference = (SwitchPreference) cachedPreference; - } else { - preference = new SwitchPreference(getActivity()); - - preference.setKey(group.getName()); - Drawable icon = Utils.loadDrawable(activity.getPackageManager(), - group.getIconPkg(), group.getIconResId()); - preference.setIcon(Utils.applyTint(getContext(), icon, - android.R.attr.colorControlNormal)); - preference.setTitle(group.getLabel()); - preference.setSummary(group.getDescription()); - preference.setPersistent(false); - - preference.setOnPreferenceChangeListener(this); - } - - preference.setChecked(group.areRuntimePermissionsGranted() - || group.isReviewRequired()); - - // Mutable state - if (group.isPolicyFixed()) { - preference.setEnabled(false); - preference.setSummary(getString( - R.string.permission_summary_enforced_by_policy)); - } else { - preference.setEnabled(true); - } - - if (group.isReviewRequired()) { - if (!isPackageUpdated) { - screen.addPreference(preference); - } else { - if (mNewPermissionsCategory == null) { - mNewPermissionsCategory = new PreferenceCategory(activity); - mNewPermissionsCategory.setTitle(R.string.new_permissions_category); - mNewPermissionsCategory.setOrder(1); - screen.addPreference(mNewPermissionsCategory); - } - mNewPermissionsCategory.addPreference(preference); - } - } else { - if (mCurrentPermissionsCategory == null) { - mCurrentPermissionsCategory = new PreferenceCategory(activity); - mCurrentPermissionsCategory.setTitle(R.string.current_permissions_category); - mCurrentPermissionsCategory.setOrder(2); - screen.addPreference(mCurrentPermissionsCategory); - } - mCurrentPermissionsCategory.addPreference(preference); - } - } - } - - private boolean isPackageUpdated() { - List<AppPermissionGroup> groups = mAppPermissions.getPermissionGroups(); - final int groupCount = groups.size(); - for (int i = 0; i < groupCount; i++) { - AppPermissionGroup group = groups.get(i); - if (!group.isReviewRequired()) { - return true; - } - } - return false; - } - - private void executeCallback(boolean success) { - Activity activity = getActivity(); - if (activity == null) { - return; - } - if (success) { - IntentSender intent = activity.getIntent().getParcelableExtra(Intent.EXTRA_INTENT); - if (intent != null) { - try { - int flagMask = 0; - int flagValues = 0; - if (activity.getIntent().getBooleanExtra( - Intent.EXTRA_RESULT_NEEDED, false)) { - flagMask = Intent.FLAG_ACTIVITY_FORWARD_RESULT; - flagValues = Intent.FLAG_ACTIVITY_FORWARD_RESULT; - } - activity.startIntentSenderForResult(intent, -1, null, - flagMask, flagValues, 0); - } catch (IntentSender.SendIntentException e) { - /* ignore */ - } - return; - } - } - RemoteCallback callback = activity.getIntent().getParcelableExtra( - Intent.EXTRA_REMOTE_CALLBACK); - if (callback != null) { - Bundle result = new Bundle(); - result.putBoolean(Intent.EXTRA_RETURN_RESULT, success); - callback.sendResult(result); - } - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/SettingsWithHeader.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/SettingsWithHeader.java deleted file mode 100644 index d57757964a98..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/SettingsWithHeader.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2015 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.packageinstaller.permission.ui.handheld; - -import android.content.Intent; -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; - -import com.android.packageinstaller.DeviceUtils; -import com.android.packageinstaller.R; - -public abstract class SettingsWithHeader extends PermissionsFrameFragment - implements OnClickListener { - - private View mHeader; - protected Intent mInfoIntent; - protected Drawable mIcon; - protected CharSequence mLabel; - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - ViewGroup root = (ViewGroup) super.onCreateView(inflater, container, savedInstanceState); - - if (!DeviceUtils.isTelevision(getContext())) { - mHeader = inflater.inflate(R.layout.header, root, false); - getPreferencesContainer().addView(mHeader, 0); - updateHeader(); - } - - return root; - } - - public void setHeader(Drawable icon, CharSequence label, Intent infoIntent) { - mIcon = icon; - mLabel = label; - mInfoIntent = infoIntent; - updateHeader(); - } - - private void updateHeader() { - if (mHeader != null) { - final ImageView appIcon = (ImageView) mHeader.findViewById(R.id.icon); - appIcon.setImageDrawable(mIcon); - - final TextView appName = (TextView) mHeader.findViewById(R.id.name); - appName.setText(mLabel); - - final View info = mHeader.findViewById(R.id.info); - if (mInfoIntent == null) { - info.setVisibility(View.GONE); - } else { - info.setVisibility(View.VISIBLE); - info.setClickable(true); - info.setOnClickListener(this); - } - } - } - - @Override - public void onClick(View v) { - getActivity().startActivity(mInfoIntent); - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/television/AllAppPermissionsFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/television/AllAppPermissionsFragment.java deleted file mode 100644 index e56a1f7db537..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/television/AllAppPermissionsFragment.java +++ /dev/null @@ -1,319 +0,0 @@ -/* -* Copyright (C) 2015 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.packageinstaller.permission.ui.television; - -import android.Manifest; -import android.app.ActionBar; -import android.app.AlertDialog; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageItemInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.pm.PermissionGroupInfo; -import android.content.pm.PermissionInfo; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.provider.Settings; -import android.util.Log; -import android.view.MenuItem; - -import androidx.preference.Preference; -import androidx.preference.Preference.OnPreferenceChangeListener; -import androidx.preference.Preference.OnPreferenceClickListener; -import androidx.preference.PreferenceCategory; -import androidx.preference.PreferenceGroup; -import androidx.preference.SwitchPreference; - -import com.android.packageinstaller.R; -import com.android.packageinstaller.permission.model.AppPermissionGroup; -import com.android.packageinstaller.permission.model.AppPermissions; -import com.android.packageinstaller.permission.utils.Utils; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; - -public final class AllAppPermissionsFragment extends SettingsWithHeader { - - private static final String LOG_TAG = "AllAppPermissionsFragment"; - - private static final String KEY_OTHER = "other_perms"; - - private PackageInfo mPackageInfo; - - private AppPermissions mAppPermissions; - - public static AllAppPermissionsFragment newInstance(String packageName) { - AllAppPermissionsFragment instance = new AllAppPermissionsFragment(); - Bundle arguments = new Bundle(); - arguments.putString(Intent.EXTRA_PACKAGE_NAME, packageName); - instance.setArguments(arguments); - return instance; - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setHasOptionsMenu(true); - final ActionBar ab = getActivity().getActionBar(); - if (ab != null) { - ab.setTitle(R.string.all_permissions); - ab.setDisplayHomeAsUpEnabled(true); - } - - String pkg = getArguments().getString(Intent.EXTRA_PACKAGE_NAME); - try { - mPackageInfo = getActivity().getPackageManager().getPackageInfo(pkg, - PackageManager.GET_PERMISSIONS); - } catch (NameNotFoundException e) { - getActivity().finish(); - } - - mAppPermissions = new AppPermissions(getActivity(), mPackageInfo, false, - new Runnable() { - @Override - public void run() { - getActivity().finish(); - } - }); - } - - @Override - public void onResume() { - super.onResume(); - updateUi(); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: { - getFragmentManager().popBackStack(); - return true; - } - } - return super.onOptionsItemSelected(item); - } - - private PreferenceGroup getOtherGroup() { - PreferenceGroup otherGroup = (PreferenceGroup) findPreference(KEY_OTHER); - if (otherGroup == null) { - otherGroup = new PreferenceCategory(getPreferenceManager().getContext()); - otherGroup.setKey(KEY_OTHER); - otherGroup.setTitle(getString(R.string.other_permissions)); - getPreferenceScreen().addPreference(otherGroup); - } - return otherGroup; - } - - private void updateUi() { - getPreferenceScreen().removeAll(); - - ArrayList<Preference> prefs = new ArrayList<>(); // Used for sorting. - PackageManager pm = getActivity().getPackageManager(); - - ApplicationInfo appInfo = mPackageInfo.applicationInfo; - final Drawable icon = appInfo.loadIcon(pm); - final CharSequence label = appInfo.loadLabel(pm); - Intent infoIntent = null; - if (!getActivity().getIntent().getBooleanExtra( - AppPermissionsFragment.EXTRA_HIDE_INFO_BUTTON, false)) { - infoIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) - .setData(Uri.fromParts("package", mPackageInfo.packageName, null)); - } - setHeader(icon, label, infoIntent, null); - - if (mPackageInfo.requestedPermissions != null) { - for (int i = 0; i < mPackageInfo.requestedPermissions.length; i++) { - PermissionInfo perm; - try { - perm = pm.getPermissionInfo(mPackageInfo.requestedPermissions[i], 0); - } catch (NameNotFoundException e) { - Log.e(LOG_TAG, "Can't get permission info for " - + mPackageInfo.requestedPermissions[i], e); - continue; - } - - if ((perm.flags & PermissionInfo.FLAG_INSTALLED) == 0 - || (perm.flags & PermissionInfo.FLAG_REMOVED) != 0) { - continue; - } - if (appInfo.isInstantApp() - && (perm.protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTANT) == 0) { - continue; - } - if (appInfo.targetSdkVersion < Build.VERSION_CODES.M - && (perm.protectionLevel & PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) - != 0) { - continue; - } - - - PermissionGroupInfo group = getGroup(perm.group, pm); - if ((perm.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) - == PermissionInfo.PROTECTION_DANGEROUS) { - PreferenceGroup pref = findOrCreate(group != null ? group : perm, pm, prefs); - pref.addPreference(getPreference(perm, group)); - } else if ((perm.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) - == PermissionInfo.PROTECTION_NORMAL) { - PreferenceGroup otherGroup = getOtherGroup(); - if (prefs.indexOf(otherGroup) < 0) { - prefs.add(otherGroup); - } - getOtherGroup().addPreference(getPreference(perm, group)); - } - } - } - - // Sort an ArrayList of the groups and then set the order from the sorting. - Collections.sort(prefs, new Comparator<Preference>() { - @Override - public int compare(Preference lhs, Preference rhs) { - String lKey = lhs.getKey(); - String rKey = rhs.getKey(); - if (lKey.equals(KEY_OTHER)) { - return 1; - } else if (rKey.equals(KEY_OTHER)) { - return -1; - } else if (Utils.isModernPermissionGroup(lKey) - != Utils.isModernPermissionGroup(rKey)) { - return Utils.isModernPermissionGroup(lKey) ? -1 : 1; - } - return lhs.getTitle().toString().compareTo(rhs.getTitle().toString()); - } - }); - for (int i = 0; i < prefs.size(); i++) { - prefs.get(i).setOrder(i); - } - } - - private PermissionGroupInfo getGroup(String group, PackageManager pm) { - try { - return pm.getPermissionGroupInfo(group, 0); - } catch (NameNotFoundException e) { - return null; - } - } - - private PreferenceGroup findOrCreate(PackageItemInfo group, PackageManager pm, - ArrayList<Preference> prefs) { - PreferenceGroup pref = (PreferenceGroup) findPreference(group.name); - if (pref == null) { - pref = new PreferenceCategory(getActivity()); - pref.setKey(group.name); - pref.setLayoutResource(R.layout.preference_category_material); - pref.setTitle(group.loadLabel(pm)); - prefs.add(pref); - getPreferenceScreen().addPreference(pref); - } - return pref; - } - - private Preference getPreference(final PermissionInfo perm, final PermissionGroupInfo group) { - if (isMutableGranularPermission(perm.name)) { - return getMutablePreference(perm, group); - } else { - return getImmutablePreference(perm, group); - } - } - - private Preference getMutablePreference(final PermissionInfo perm, PermissionGroupInfo group) { - final AppPermissionGroup permGroup = mAppPermissions.getPermissionGroup(group.name); - final String[] filterPermissions = new String[]{perm.name}; - - // TODO: No hardcoded layouts - SwitchPreference pref = new SwitchPreference(getPreferenceManager().getContext()); - pref.setLayoutResource(R.layout.preference_permissions); - pref.setChecked(permGroup.areRuntimePermissionsGranted(filterPermissions)); - pref.setIcon(getTintedPermissionIcon(getActivity(), perm, group)); - pref.setTitle(perm.loadLabel(getActivity().getPackageManager())); - pref.setPersistent(false); - - pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object value) { - if (value == Boolean.TRUE) { - permGroup.grantRuntimePermissions(false, filterPermissions); - } else { - permGroup.revokeRuntimePermissions(false, filterPermissions); - } - return true; - } - }); - - return pref; - } - - private Preference getImmutablePreference(final PermissionInfo perm, - PermissionGroupInfo group) { - final PackageManager pm = getActivity().getPackageManager(); - - // TODO: No hardcoded layouts - Preference pref = new Preference(getActivity()); - pref.setLayoutResource(R.layout.preference_permissions); - pref.setIcon(getTintedPermissionIcon(getActivity(), perm, group)); - pref.setTitle(perm.loadLabel(pm)); - pref.setPersistent(false); - - pref.setOnPreferenceClickListener(new OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - new AlertDialog.Builder(getActivity()) - .setMessage(perm.loadDescription(pm)) - .setPositiveButton(android.R.string.ok, null) - .show(); - return true; - } - }); - - return pref; - } - - private static Drawable getTintedPermissionIcon(Context context, PermissionInfo perm, - PermissionGroupInfo group) { - final Drawable icon; - if (perm.icon != 0) { - icon = perm.loadIcon(context.getPackageManager()); - } else if (group != null && group.icon != 0) { - icon = group.loadIcon(context.getPackageManager()); - } else { - icon = context.getDrawable(R.drawable.ic_perm_device_info); - } - return Utils.applyTint(context, icon, android.R.attr.colorControlNormal); - } - - private boolean isMutableGranularPermission(String name) { - if (!getContext().getPackageManager().arePermissionsIndividuallyControlled()) { - return false; - } - switch (name) { - case Manifest.permission.READ_CONTACTS: - case Manifest.permission.WRITE_CONTACTS: - case Manifest.permission.READ_SMS: - case Manifest.permission.READ_CALL_LOG: - case Manifest.permission.CALL_PHONE: { - return true; - } - } - return false; - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/television/AppPermissionsFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/television/AppPermissionsFragment.java deleted file mode 100644 index 442ee92876b1..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/television/AppPermissionsFragment.java +++ /dev/null @@ -1,411 +0,0 @@ -/* -* Copyright (C) 2015 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.packageinstaller.permission.ui.television; - -import android.app.ActionBar; -import android.app.Activity; -import android.app.AlertDialog; -import android.app.Fragment; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.Bundle; -import android.provider.Settings; -import android.util.ArraySet; -import android.util.Log; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.widget.Toast; - -import androidx.preference.Preference; -import androidx.preference.Preference.OnPreferenceChangeListener; -import androidx.preference.PreferenceScreen; -import androidx.preference.PreferenceViewHolder; -import androidx.preference.SwitchPreference; - -import com.android.packageinstaller.R; -import com.android.packageinstaller.permission.model.AppPermissionGroup; -import com.android.packageinstaller.permission.model.AppPermissions; -import com.android.packageinstaller.permission.ui.ReviewPermissionsActivity; -import com.android.packageinstaller.permission.utils.LocationUtils; -import com.android.packageinstaller.permission.utils.SafetyNetLogger; -import com.android.packageinstaller.permission.utils.Utils; - -public final class AppPermissionsFragment extends SettingsWithHeader - implements OnPreferenceChangeListener { - - private static final String LOG_TAG = "ManagePermsFragment"; - - static final String EXTRA_HIDE_INFO_BUTTON = "hideInfoButton"; - - private static final int MENU_ALL_PERMS = 0; - - private ArraySet<AppPermissionGroup> mToggledGroups; - private AppPermissions mAppPermissions; - private PreferenceScreen mExtraScreen; - - private boolean mHasConfirmedRevoke; - - public static AppPermissionsFragment newInstance(String packageName) { - return setPackageName(new AppPermissionsFragment(), packageName); - } - - private static <T extends Fragment> T setPackageName(T fragment, String packageName) { - Bundle arguments = new Bundle(); - arguments.putString(Intent.EXTRA_PACKAGE_NAME, packageName); - fragment.setArguments(arguments); - return fragment; - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setLoading(true /* loading */, false /* animate */); - setHasOptionsMenu(true); - final ActionBar ab = getActivity().getActionBar(); - if (ab != null) { - ab.setDisplayHomeAsUpEnabled(true); - } - - String packageName = getArguments().getString(Intent.EXTRA_PACKAGE_NAME); - Activity activity = getActivity(); - PackageInfo packageInfo = getPackageInfo(activity, packageName); - if (packageInfo == null) { - Toast.makeText(activity, R.string.app_not_found_dlg_title, Toast.LENGTH_LONG).show(); - activity.finish(); - return; - } - - - mAppPermissions = new AppPermissions(activity, packageInfo, true, - () -> getActivity().finish()); - - if (mAppPermissions.isReviewRequired()) { - Intent intent = new Intent(getActivity(), ReviewPermissionsActivity.class); - intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName); - startActivity(intent); - getActivity().finish(); - return; - } - - loadPreferences(); - } - - @Override - public void onResume() { - super.onResume(); - mAppPermissions.refresh(); - loadPreferences(); - setPreferencesCheckedState(); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: { - getActivity().finish(); - return true; - } - - case MENU_ALL_PERMS: { - Fragment frag = AllAppPermissionsFragment.newInstance( - getArguments().getString(Intent.EXTRA_PACKAGE_NAME)); - getFragmentManager().beginTransaction() - .replace(android.R.id.content, frag) - .addToBackStack("AllPerms") - .commit(); - return true; - } - } - return super.onOptionsItemSelected(item); - } - - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - if (mAppPermissions != null) { - bindUi(this, mAppPermissions.getPackageInfo()); - } - } - - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - super.onCreateOptionsMenu(menu, inflater); - menu.add(Menu.NONE, MENU_ALL_PERMS, Menu.NONE, R.string.all_permissions); - } - - private static void bindUi(SettingsWithHeader fragment, PackageInfo packageInfo) { - Activity activity = fragment.getActivity(); - PackageManager pm = activity.getPackageManager(); - ApplicationInfo appInfo = packageInfo.applicationInfo; - Intent infoIntent = null; - if (!activity.getIntent().getBooleanExtra(EXTRA_HIDE_INFO_BUTTON, false)) { - infoIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) - .setData(Uri.fromParts("package", packageInfo.packageName, null)); - } - - Drawable icon = appInfo.loadIcon(pm); - CharSequence label = appInfo.loadLabel(pm); - fragment.setHeader(icon, label, infoIntent, fragment.getString( - R.string.app_permissions_decor_title)); - } - - private void loadPreferences() { - Context context = getPreferenceManager().getContext(); - if (context == null) { - return; - } - - PreferenceScreen screen = getPreferenceScreen(); - screen.removeAll(); - screen.addPreference(createHeaderLineTwoPreference(context)); - - if (mExtraScreen != null) { - mExtraScreen.removeAll(); - mExtraScreen = null; - } - - final Preference extraPerms = new Preference(context); - extraPerms.setIcon(R.drawable.ic_toc); - extraPerms.setTitle(R.string.additional_permissions); - - for (AppPermissionGroup group : mAppPermissions.getPermissionGroups()) { - if (!Utils.shouldShowPermission(group)) { - continue; - } - - boolean isPlatform = group.getDeclaringPackage().equals(Utils.OS_PKG); - - SwitchPreference preference = new SwitchPreference(context); - preference.setOnPreferenceChangeListener(this); - preference.setKey(group.getName()); - Drawable icon = Utils.loadDrawable(context.getPackageManager(), - group.getIconPkg(), group.getIconResId()); - preference.setIcon(Utils.applyTint(getContext(), icon, - android.R.attr.colorControlNormal)); - preference.setTitle(group.getLabel()); - if (group.isPolicyFixed()) { - preference.setSummary(getString(R.string.permission_summary_enforced_by_policy)); - } - preference.setPersistent(false); - preference.setEnabled(!group.isPolicyFixed()); - preference.setChecked(group.areRuntimePermissionsGranted()); - - if (isPlatform) { - screen.addPreference(preference); - } else { - if (mExtraScreen == null) { - mExtraScreen = getPreferenceManager().createPreferenceScreen(context); - mExtraScreen.addPreference(createHeaderLineTwoPreference(context)); - } - mExtraScreen.addPreference(preference); - } - } - - if (mExtraScreen != null) { - extraPerms.setOnPreferenceClickListener(preference -> { - AdditionalPermissionsFragment frag = new AdditionalPermissionsFragment(); - setPackageName(frag, getArguments().getString(Intent.EXTRA_PACKAGE_NAME)); - frag.setTargetFragment(AppPermissionsFragment.this, 0); - getFragmentManager().beginTransaction() - .replace(android.R.id.content, frag) - .addToBackStack(null) - .commit(); - return true; - }); - int count = mExtraScreen.getPreferenceCount() - 1; - extraPerms.setSummary(getResources().getQuantityString( - R.plurals.additional_permissions_more, count, count)); - screen.addPreference(extraPerms); - } - - setLoading(false /* loading */, true /* animate */); - } - - /** - * Creates a heading below decor_title and above the rest of the preferences. This heading - * displays the app name and banner icon. It's used in both system and additional permissions - * fragments for each app. The styling used is the same as a leanback preference with a - * customized background color - * @param context The context the preferences created on - * @return The preference header to be inserted as the first preference in the list. - */ - private Preference createHeaderLineTwoPreference(Context context) { - Preference headerLineTwo = new Preference(context) { - @Override - public void onBindViewHolder(PreferenceViewHolder holder) { - super.onBindViewHolder(holder); - holder.itemView.setBackgroundColor( - getResources().getColor(R.color.lb_header_banner_color)); - } - }; - headerLineTwo.setKey(HEADER_PREFERENCE_KEY); - headerLineTwo.setSelectable(false); - headerLineTwo.setTitle(mLabel); - headerLineTwo.setIcon(mIcon); - return headerLineTwo; - } - - @Override - public boolean onPreferenceChange(final Preference preference, Object newValue) { - String groupName = preference.getKey(); - final AppPermissionGroup group = mAppPermissions.getPermissionGroup(groupName); - - if (group == null) { - return false; - } - - addToggledGroup(group); - - if (LocationUtils.isLocationGroupAndProvider(group.getName(), group.getApp().packageName)) { - LocationUtils.showLocationDialog(getContext(), mAppPermissions.getAppLabel()); - return false; - } - if (newValue == Boolean.TRUE) { - group.grantRuntimePermissions(false); - } else { - final boolean grantedByDefault = group.hasGrantedByDefaultPermission(); - if (grantedByDefault || (!group.doesSupportRuntimePermissions() - && !mHasConfirmedRevoke)) { - new AlertDialog.Builder(getContext()) - .setMessage(grantedByDefault ? R.string.system_warning - : R.string.old_sdk_deny_warning) - .setNegativeButton(R.string.cancel, null) - .setPositiveButton(R.string.grant_dialog_button_deny_anyway, - (dialog, which) -> { - ((SwitchPreference) preference).setChecked(false); - group.revokeRuntimePermissions(false); - if (!grantedByDefault) { - mHasConfirmedRevoke = true; - } - }) - .show(); - return false; - } else { - group.revokeRuntimePermissions(false); - } - } - - return true; - } - - @Override - public void onPause() { - super.onPause(); - logToggledGroups(); - } - - private void addToggledGroup(AppPermissionGroup group) { - if (mToggledGroups == null) { - mToggledGroups = new ArraySet<>(); - } - mToggledGroups.add(group); - } - - private void logToggledGroups() { - if (mToggledGroups != null) { - SafetyNetLogger.logPermissionsToggled(mToggledGroups); - mToggledGroups = null; - } - } - - private void setPreferencesCheckedState() { - setPreferencesCheckedState(getPreferenceScreen()); - if (mExtraScreen != null) { - setPreferencesCheckedState(mExtraScreen); - } - } - - private void setPreferencesCheckedState(PreferenceScreen screen) { - int preferenceCount = screen.getPreferenceCount(); - for (int i = 0; i < preferenceCount; i++) { - Preference preference = screen.getPreference(i); - if (preference instanceof SwitchPreference) { - SwitchPreference switchPref = (SwitchPreference) preference; - AppPermissionGroup group = mAppPermissions.getPermissionGroup(switchPref.getKey()); - if (group != null) { - switchPref.setChecked(group.areRuntimePermissionsGranted()); - } - } - } - } - - private static PackageInfo getPackageInfo(Activity activity, String packageName) { - try { - return activity.getPackageManager().getPackageInfo( - packageName, PackageManager.GET_PERMISSIONS); - } catch (PackageManager.NameNotFoundException e) { - Log.i(LOG_TAG, "No package:" + activity.getCallingPackage(), e); - return null; - } - } - - public static class AdditionalPermissionsFragment extends SettingsWithHeader { - AppPermissionsFragment mOuterFragment; - - @Override - public void onCreate(Bundle savedInstanceState) { - mOuterFragment = (AppPermissionsFragment) getTargetFragment(); - super.onCreate(savedInstanceState); - setHasOptionsMenu(true); - } - - @Override - public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { - setPreferenceScreen(mOuterFragment.mExtraScreen); - } - - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - String packageName = getArguments().getString(Intent.EXTRA_PACKAGE_NAME); - bindUi(this, getPackageInfo(getActivity(), packageName)); - } - - private static void bindUi(SettingsWithHeader fragment, PackageInfo packageInfo) { - Activity activity = fragment.getActivity(); - PackageManager pm = activity.getPackageManager(); - ApplicationInfo appInfo = packageInfo.applicationInfo; - Intent infoIntent = null; - if (!activity.getIntent().getBooleanExtra(EXTRA_HIDE_INFO_BUTTON, false)) { - infoIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) - .setData(Uri.fromParts("package", packageInfo.packageName, null)); - } - - Drawable icon = appInfo.loadIcon(pm); - CharSequence label = appInfo.loadLabel(pm); - fragment.setHeader(icon, label, infoIntent, fragment.getString( - R.string.additional_permissions_decor_title)); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - getFragmentManager().popBackStack(); - return true; - } - return super.onOptionsItemSelected(item); - } - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/television/GrantPermissionsViewHandlerImpl.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/television/GrantPermissionsViewHandlerImpl.java deleted file mode 100644 index c71835734f5e..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/television/GrantPermissionsViewHandlerImpl.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.android.packageinstaller.permission.ui.television; - -import android.content.Context; -import android.graphics.PixelFormat; -import android.graphics.drawable.Icon; -import android.os.Bundle; -import android.view.Gravity; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.WindowManager; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -import com.android.packageinstaller.R; -import com.android.packageinstaller.permission.ui.GrantPermissionsViewHandler; - -/** - * TV-specific view handler for the grant permissions activity. - */ -public final class GrantPermissionsViewHandlerImpl implements GrantPermissionsViewHandler, OnClickListener { - - private static final String ARG_GROUP_NAME = "ARG_GROUP_NAME"; - - private final Context mContext; - - private ResultListener mResultListener; - - private String mGroupName; - - private LinearLayout mRootView; - private TextView mMessageView; - private ImageView mIconView; - private TextView mCurrentGroupView; - private Button mAllowButton; - private Button mSoftDenyButton; - private Button mHardDenyButton; - - public GrantPermissionsViewHandlerImpl(Context context, String appPackageName) { - mContext = context; - } - - @Override - public GrantPermissionsViewHandlerImpl setResultListener(ResultListener listener) { - mResultListener = listener; - return this; - } - - @Override - public View createView() { - mRootView = (LinearLayout) LayoutInflater.from(mContext) - .inflate(R.layout.grant_permissions, null); - - mMessageView = (TextView) mRootView.findViewById(R.id.permission_message); - mIconView = (ImageView) mRootView.findViewById(R.id.permission_icon); - mCurrentGroupView = (TextView) mRootView.findViewById(R.id.current_page_text); - mAllowButton = (Button) mRootView.findViewById(R.id.permission_allow_button); - mSoftDenyButton = (Button) mRootView.findViewById(R.id.permission_deny_button); - mHardDenyButton = (Button) mRootView.findViewById( - R.id.permission_deny_dont_ask_again_button); - - mAllowButton.setOnClickListener(this); - mSoftDenyButton.setOnClickListener(this); - mHardDenyButton.setOnClickListener(this); - - return mRootView; - } - - @Override - public void updateWindowAttributes(WindowManager.LayoutParams outLayoutParams) { - outLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT; - outLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT; - outLayoutParams.format = PixelFormat.OPAQUE; - outLayoutParams.gravity = Gravity.BOTTOM; - outLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG; - outLayoutParams.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; - } - - @Override - public void updateUi(String groupName, int groupCount, int groupIndex, Icon icon, - CharSequence message, CharSequence detailMessage, boolean showForegroundChooser, - boolean showDoNotAsk) { - // TODO: Handle detailMessage - // TODO: Handle showForegroundChooser - - mGroupName = groupName; - - mMessageView.setText(message); - - if (icon != null) { - mIconView.setImageIcon(icon); - } - - mHardDenyButton.setVisibility(showDoNotAsk ? View.VISIBLE : View.GONE); - if (groupCount > 1) { - mCurrentGroupView.setVisibility(View.VISIBLE); - mCurrentGroupView.setText(mContext.getString(R.string.current_permission_template, - groupIndex + 1, groupCount)); - } else { - mCurrentGroupView.setVisibility(View.INVISIBLE); - } - } - - @Override - public void saveInstanceState(Bundle outState) { - outState.putString(ARG_GROUP_NAME, mGroupName); - } - - @Override - public void loadInstanceState(Bundle savedInstanceState) { - mGroupName = savedInstanceState.getString(ARG_GROUP_NAME); - } - - @Override - public void onClick(View view) { - switch (view.getId()) { - case R.id.permission_allow_button: - mResultListener.onPermissionGrantResult(mGroupName, GRANTED_ALWAYS); - break; - case R.id.permission_deny_button: - mResultListener.onPermissionGrantResult(mGroupName, DENIED); - break; - case R.id.permission_deny_dont_ask_again_button: - mResultListener.onPermissionGrantResult(mGroupName, DENIED_DO_NOT_ASK_AGAIN); - break; - } - } - - @Override - public void onBackPressed() { - if (mResultListener != null) { - mResultListener.onPermissionGrantResult(mGroupName, DENIED); - } - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/television/ManagePermissionsFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/television/ManagePermissionsFragment.java deleted file mode 100644 index 19f01d0f91c6..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/television/ManagePermissionsFragment.java +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright (C) 2015 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.packageinstaller.permission.ui.television; - -import android.app.ActionBar; -import android.app.FragmentTransaction; -import android.content.ActivityNotFoundException; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import androidx.annotation.Nullable; -import androidx.preference.Preference; -import androidx.preference.Preference.OnPreferenceClickListener; -import androidx.preference.PreferenceScreen; -import android.util.ArraySet; -import android.util.Log; -import android.view.MenuItem; -import android.view.View; - -import com.android.packageinstaller.R; -import com.android.packageinstaller.permission.model.PermissionApps.PmCache; -import com.android.packageinstaller.permission.model.PermissionGroup; -import com.android.packageinstaller.permission.model.PermissionGroups; -import com.android.packageinstaller.permission.utils.Utils; - -import java.util.List; - -public final class ManagePermissionsFragment extends SettingsWithHeader - implements PermissionGroups.PermissionsGroupsChangeCallback, OnPreferenceClickListener { - private static final String LOG_TAG = "ManagePermissionsFragment"; - - private static final String OS_PKG = "android"; - - private static final String EXTRA_PREFS_KEY = "extra_prefs_key"; - - private ArraySet<String> mLauncherPkgs; - - private PermissionGroups mPermissions; - - private PreferenceScreen mExtraScreen; - - public static ManagePermissionsFragment newInstance() { - return new ManagePermissionsFragment(); - } - - @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - setLoading(true /* loading */, false /* animate */); - setHasOptionsMenu(true); - final ActionBar ab = getActivity().getActionBar(); - if (ab != null) { - ab.setDisplayHomeAsUpEnabled(true); - } - mLauncherPkgs = Utils.getLauncherPackages(getContext()); - mPermissions = new PermissionGroups(getContext(), getLoaderManager(), this); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == android.R.id.home) { - getActivity().finish(); - return true; - } - return super.onOptionsItemSelected(item); - } - - @Override - public boolean onPreferenceClick(Preference preference) { - String key = preference.getKey(); - - PermissionGroup group = mPermissions.getGroup(key); - if (group == null) { - return false; - } - - Intent intent = new Intent(Intent.ACTION_MANAGE_PERMISSION_APPS) - .putExtra(Intent.EXTRA_PERMISSION_NAME, key); - try { - getActivity().startActivity(intent); - } catch (ActivityNotFoundException e) { - Log.w(LOG_TAG, "No app to handle " + intent); - } - - return true; - } - - @Override - public void onPermissionGroupsChanged() { - updatePermissionsUi(); - } - - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - bindPermissionUi(this, getView()); - } - - private static void bindPermissionUi(SettingsWithHeader fragment, @Nullable View rootView) { - if (fragment == null || rootView == null) { - return; - } - fragment.setHeader(null, null, null, fragment.getString( - R.string.manage_permissions_decor_title)); - } - - private void updatePermissionsUi() { - Context context = getPreferenceManager().getContext(); - if (context == null) { - return; - } - - List<PermissionGroup> groups = mPermissions.getGroups(); - PreferenceScreen screen = getPreferenceScreen(); - - // Use this to speed up getting the info for all of the PermissionApps below. - // Create a new one for each refresh to make sure it has fresh data. - PmCache cache = new PmCache(getContext().getPackageManager()); - for (PermissionGroup group : groups) { - boolean isSystemPermission = group.getDeclaringPackage().equals(OS_PKG); - - Preference preference = findPreference(group.getName()); - if (preference == null && mExtraScreen != null) { - preference = mExtraScreen.findPreference(group.getName()); - } - if (preference == null) { - preference = new Preference(context); - preference.setOnPreferenceClickListener(this); - preference.setKey(group.getName()); - preference.setIcon(Utils.applyTint(context, group.getIcon(), - android.R.attr.colorControlNormal)); - preference.setTitle(group.getLabel()); - // Set blank summary so that no resizing/jumping happens when the summary is loaded. - preference.setSummary(" "); - preference.setPersistent(false); - if (isSystemPermission) { - screen.addPreference(preference); - } else { - if (mExtraScreen == null) { - mExtraScreen = getPreferenceManager().createPreferenceScreen(context); - } - mExtraScreen.addPreference(preference); - } - } - - preference.setSummary(getString(R.string.app_permissions_group_summary, - group.getGranted(), group.getTotal())); - } - - if (mExtraScreen != null && mExtraScreen.getPreferenceCount() > 0 - && screen.findPreference(EXTRA_PREFS_KEY) == null) { - Preference extraScreenPreference = new Preference(context); - extraScreenPreference.setKey(EXTRA_PREFS_KEY); - extraScreenPreference.setIcon(Utils.applyTint(context, - R.drawable.ic_more_items, - android.R.attr.colorControlNormal)); - extraScreenPreference.setTitle(R.string.additional_permissions); - extraScreenPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - AdditionalPermissionsFragment frag = new AdditionalPermissionsFragment(); - frag.setTargetFragment(ManagePermissionsFragment.this, 0); - FragmentTransaction ft = getFragmentManager().beginTransaction(); - ft.replace(android.R.id.content, frag); - ft.addToBackStack(null); - ft.commit(); - return true; - } - }); - int count = mExtraScreen.getPreferenceCount(); - extraScreenPreference.setSummary(getResources().getQuantityString( - R.plurals.additional_permissions_more, count, count)); - screen.addPreference(extraScreenPreference); - } - if (screen.getPreferenceCount() != 0) { - setLoading(false /* loading */, true /* animate */); - } - } - - public static class AdditionalPermissionsFragment extends SettingsWithHeader { - @Override - public void onCreate(Bundle icicle) { - setLoading(true /* loading */, false /* animate */); - super.onCreate(icicle); - getActivity().setTitle(R.string.additional_permissions); - setHasOptionsMenu(true); - } - - @Override - public void onDestroy() { - getActivity().setTitle(R.string.app_permissions); - super.onDestroy(); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - getFragmentManager().popBackStack(); - return true; - } - return super.onOptionsItemSelected(item); - } - - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - bindPermissionUi(this, getView()); - } - - private static void bindPermissionUi(SettingsWithHeader fragment, @Nullable View rootView) { - if (fragment == null || rootView == null) { - return; - } - fragment.setHeader(null, null, null, - fragment.getString(R.string.additional_permissions_decor_title)); - } - - @Override - public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { - setPreferenceScreen(((ManagePermissionsFragment) getTargetFragment()).mExtraScreen); - setLoading(false /* loading */, true /* animate */); - } - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/television/PermissionAppsFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/television/PermissionAppsFragment.java deleted file mode 100644 index 6a0a9e7c7275..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/television/PermissionAppsFragment.java +++ /dev/null @@ -1,438 +0,0 @@ -/* - * Copyright (C) 2015 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.packageinstaller.permission.ui.television; - -import android.app.ActionBar; -import android.app.AlertDialog; -import android.app.Fragment; -import android.content.Context; -import android.content.DialogInterface; -import android.content.DialogInterface.OnClickListener; -import android.content.Intent; -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import android.util.ArraySet; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.widget.TextView; - -import androidx.preference.Preference; -import androidx.preference.Preference.OnPreferenceChangeListener; -import androidx.preference.Preference.OnPreferenceClickListener; -import androidx.preference.PreferenceScreen; -import androidx.preference.SwitchPreference; - -import com.android.packageinstaller.DeviceUtils; -import com.android.packageinstaller.R; -import com.android.packageinstaller.permission.model.AppPermissionGroup; -import com.android.packageinstaller.permission.model.PermissionApps; -import com.android.packageinstaller.permission.model.PermissionApps.Callback; -import com.android.packageinstaller.permission.model.PermissionApps.PermissionApp; -import com.android.packageinstaller.permission.ui.ReviewPermissionsActivity; -import com.android.packageinstaller.permission.utils.LocationUtils; -import com.android.packageinstaller.permission.utils.SafetyNetLogger; -import com.android.packageinstaller.permission.utils.Utils; - -public final class PermissionAppsFragment extends SettingsWithHeader implements Callback, - OnPreferenceChangeListener { - - private static final int MENU_SHOW_SYSTEM = Menu.FIRST; - private static final int MENU_HIDE_SYSTEM = Menu.FIRST + 1; - private static final String KEY_SHOW_SYSTEM_PREFS = "_showSystem"; - - public static PermissionAppsFragment newInstance(String permissionName) { - return setPermissionName(new PermissionAppsFragment(), permissionName); - } - - private static <T extends Fragment> T setPermissionName(T fragment, String permissionName) { - Bundle arguments = new Bundle(); - arguments.putString(Intent.EXTRA_PERMISSION_NAME, permissionName); - fragment.setArguments(arguments); - return fragment; - } - - private PermissionApps mPermissionApps; - - private PreferenceScreen mExtraScreen; - - private ArraySet<AppPermissionGroup> mToggledGroups; - private ArraySet<String> mLauncherPkgs; - private boolean mHasConfirmedRevoke; - - private boolean mShowSystem; - private boolean mHasSystemApps; - private MenuItem mShowSystemMenu; - private MenuItem mHideSystemMenu; - - private Callback mOnPermissionsLoadedListener; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setLoading(true /* loading */, false /* animate */); - mLauncherPkgs = Utils.getLauncherPackages(getContext()); - String groupName = getArguments().getString(Intent.EXTRA_PERMISSION_NAME); - mPermissionApps = new PermissionApps(getActivity(), groupName, this); - } - - @Override - public void onStart() { - super.onStart(); - - setHasOptionsMenu(true); - final ActionBar ab = getActivity().getActionBar(); - if (ab != null) { - ab.setDisplayHomeAsUpEnabled(true); - } - - mPermissionApps.refresh(true); - } - - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - if (mHasSystemApps) { - mShowSystemMenu = menu.add(Menu.NONE, MENU_SHOW_SYSTEM, Menu.NONE, - R.string.menu_show_system); - mHideSystemMenu = menu.add(Menu.NONE, MENU_HIDE_SYSTEM, Menu.NONE, - R.string.menu_hide_system); - updateMenu(); - } - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - getActivity().finish(); - return true; - case MENU_SHOW_SYSTEM: - case MENU_HIDE_SYSTEM: - mShowSystem = item.getItemId() == MENU_SHOW_SYSTEM; - if (mPermissionApps.getApps() != null) { - onPermissionsLoaded(mPermissionApps); - } - updateMenu(); - break; - } - return super.onOptionsItemSelected(item); - } - - private void updateMenu() { - mShowSystemMenu.setVisible(!mShowSystem); - mHideSystemMenu.setVisible(mShowSystem); - } - - @Override - protected void onSetEmptyText(TextView textView) { - textView.setText(R.string.no_apps); - } - - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - bindUi(this, mPermissionApps); - } - - private static void bindUi(SettingsWithHeader fragment, PermissionApps permissionApps) { - final Drawable icon = permissionApps.getIcon(); - final CharSequence label = permissionApps.getLabel(); - - fragment.setHeader(null, null, null, - fragment.getString(R.string.permission_apps_decor_title, label)); - } - - private void setOnPermissionsLoadedListener(Callback callback) { - mOnPermissionsLoadedListener = callback; - } - - @Override - public void onPermissionsLoaded(PermissionApps permissionApps) { - Context context = getPreferenceManager().getContext(); - - if (context == null) { - return; - } - - boolean isTelevision = DeviceUtils.isTelevision(context); - PreferenceScreen screen = getPreferenceScreen(); - - ArraySet<String> preferencesToRemove = new ArraySet<>(); - for (int i = 0, n = screen.getPreferenceCount(); i < n; i++) { - preferencesToRemove.add(screen.getPreference(i).getKey()); - } - if (mExtraScreen != null) { - for (int i = 0, n = mExtraScreen.getPreferenceCount(); i < n; i++) { - preferencesToRemove.add(mExtraScreen.getPreference(i).getKey()); - } - } - - mHasSystemApps = false; - boolean menuOptionsInvalided = false; - - for (PermissionApp app : permissionApps.getApps()) { - if (!Utils.shouldShowPermission(app.getPermissionGroup())) { - continue; - } - - String key = app.getKey(); - preferencesToRemove.remove(key); - Preference existingPref = screen.findPreference(key); - if (existingPref == null && mExtraScreen != null) { - existingPref = mExtraScreen.findPreference(key); - } - - boolean isSystemApp = Utils.isSystem(app, mLauncherPkgs); - - if (isSystemApp && !menuOptionsInvalided) { - mHasSystemApps = true; - getActivity().invalidateOptionsMenu(); - menuOptionsInvalided = true; - } - - if (isSystemApp && !isTelevision && !mShowSystem) { - if (existingPref != null) { - screen.removePreference(existingPref); - } - continue; - } - - if (existingPref != null) { - // If existing preference - only update its state. - if (app.isPolicyFixed()) { - existingPref.setSummary(getString( - R.string.permission_summary_enforced_by_policy)); - } - existingPref.setPersistent(false); - existingPref.setEnabled(!app.isPolicyFixed()); - if (existingPref instanceof SwitchPreference) { - ((SwitchPreference) existingPref) - .setChecked(app.areRuntimePermissionsGranted()); - } - continue; - } - - SwitchPreference pref = new SwitchPreference(context); - pref.setOnPreferenceChangeListener(this); - pref.setKey(app.getKey()); - pref.setIcon(app.getIcon()); - pref.setTitle(app.getLabel()); - if (app.isPolicyFixed()) { - pref.setSummary(getString(R.string.permission_summary_enforced_by_policy)); - } - pref.setPersistent(false); - pref.setEnabled(!app.isPolicyFixed()); - pref.setChecked(app.areRuntimePermissionsGranted()); - - if (isSystemApp && isTelevision) { - if (mExtraScreen == null) { - mExtraScreen = getPreferenceManager().createPreferenceScreen(context); - } - mExtraScreen.addPreference(pref); - } else { - screen.addPreference(pref); - } - } - - if (mExtraScreen != null) { - preferencesToRemove.remove(KEY_SHOW_SYSTEM_PREFS); - Preference pref = screen.findPreference(KEY_SHOW_SYSTEM_PREFS); - - if (pref == null) { - pref = new Preference(context); - pref.setKey(KEY_SHOW_SYSTEM_PREFS); - pref.setIcon(Utils.applyTint(context, R.drawable.ic_toc, - android.R.attr.colorControlNormal)); - pref.setTitle(R.string.preference_show_system_apps); - pref.setOnPreferenceClickListener(new OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - SystemAppsFragment frag = new SystemAppsFragment(); - setPermissionName(frag, getArguments().getString( - Intent.EXTRA_PERMISSION_NAME)); - frag.setTargetFragment(PermissionAppsFragment.this, 0); - getFragmentManager().beginTransaction() - .replace(android.R.id.content, frag) - .addToBackStack("SystemApps") - .commit(); - return true; - } - }); - screen.addPreference(pref); - } - - int grantedCount = 0; - for (int i = 0, n = mExtraScreen.getPreferenceCount(); i < n; i++) { - if (((SwitchPreference) mExtraScreen.getPreference(i)).isChecked()) { - grantedCount++; - } - } - pref.setSummary(getString(R.string.app_permissions_group_summary, - grantedCount, mExtraScreen.getPreferenceCount())); - } - - for (String key : preferencesToRemove) { - Preference pref = screen.findPreference(key); - if (pref != null) { - screen.removePreference(pref); - } else if (mExtraScreen != null) { - pref = mExtraScreen.findPreference(key); - if (pref != null) { - mExtraScreen.removePreference(pref); - } - } - } - - setLoading(false /* loading */, true /* animate */); - - if (mOnPermissionsLoadedListener != null) { - mOnPermissionsLoadedListener.onPermissionsLoaded(permissionApps); - } - } - - @Override - public boolean onPreferenceChange(final Preference preference, Object newValue) { - String pkg = preference.getKey(); - final PermissionApp app = mPermissionApps.getApp(pkg); - - if (app == null) { - return false; - } - - if (LocationUtils.isLocationGroupAndProvider(mPermissionApps.getGroupName(), - app.getPackageName())) { - LocationUtils.showLocationDialog(getContext(), app.getLabel()); - return false; - } - - addToggledGroup(app.getPackageName(), app.getPermissionGroup()); - - if (app.isReviewRequired()) { - Intent intent = new Intent(getActivity(), ReviewPermissionsActivity.class); - intent.putExtra(Intent.EXTRA_PACKAGE_NAME, app.getPackageName()); - startActivity(intent); - return false; - } - - if (newValue == Boolean.TRUE) { - app.grantRuntimePermissions(); - } else { - final boolean grantedByDefault = app.hasGrantedByDefaultPermissions(); - if (grantedByDefault || (!app.doesSupportRuntimePermissions() - && !mHasConfirmedRevoke)) { - new AlertDialog.Builder(getContext()) - .setMessage(grantedByDefault ? R.string.system_warning - : R.string.old_sdk_deny_warning) - .setNegativeButton(R.string.cancel, null) - .setPositiveButton(R.string.grant_dialog_button_deny_anyway, - new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - ((SwitchPreference) preference).setChecked(false); - app.revokeRuntimePermissions(); - if (!grantedByDefault) { - mHasConfirmedRevoke = true; - } - } - }) - .show(); - return false; - } else { - app.revokeRuntimePermissions(); - } - } - return true; - } - - @Override - public void onStop() { - super.onStop(); - logToggledGroups(); - } - - private void addToggledGroup(String packageName, AppPermissionGroup group) { - if (mToggledGroups == null) { - mToggledGroups = new ArraySet<>(); - } - - mToggledGroups.add(group); - } - - private void logToggledGroups() { - if (mToggledGroups != null) { - SafetyNetLogger.logPermissionsToggled(mToggledGroups); - mToggledGroups = null; - } - } - - public static class SystemAppsFragment extends SettingsWithHeader implements Callback { - PermissionAppsFragment mOuterFragment; - - @Override - public void onCreate(Bundle savedInstanceState) { - mOuterFragment = (PermissionAppsFragment) getTargetFragment(); - setLoading(true /* loading */, false /* animate */); - super.onCreate(savedInstanceState); - } - - @Override - public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { - if (mOuterFragment.mExtraScreen != null) { - setPreferenceScreen(); - } else { - mOuterFragment.setOnPermissionsLoadedListener(this); - } - } - - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - String groupName = getArguments().getString(Intent.EXTRA_PERMISSION_NAME); - PermissionApps permissionApps = new PermissionApps(getActivity(), groupName, null); - bindUi(this, permissionApps); - } - - @Override - public void onResume() { - super.onResume(); - mOuterFragment.mPermissionApps.refresh(true); - } - - @Override - public void onDestroy() { - super.onDestroy(); - mOuterFragment.setOnPermissionsLoadedListener(null); - } - - - private static void bindUi(SettingsWithHeader fragment, PermissionApps permissionApps) { - final CharSequence label = permissionApps.getLabel(); - fragment.setHeader(null, null, null, - fragment.getString(R.string.system_apps_decor_title, label)); - } - - @Override - public void onPermissionsLoaded(PermissionApps permissionApps) { - setPreferenceScreen(); - } - - private void setPreferenceScreen() { - setPreferenceScreen(mOuterFragment.mExtraScreen); - setLoading(false /* loading */, true /* animate */); - } - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/television/PermissionsFrameFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/television/PermissionsFrameFragment.java deleted file mode 100644 index af4593ae0f64..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/television/PermissionsFrameFragment.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (C) 2015 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.packageinstaller.permission.ui.television; - -import android.os.Bundle; -import androidx.annotation.Nullable; -import androidx.preference.PreferenceFragment; -import androidx.leanback.widget.VerticalGridView; -import androidx.preference.PreferenceScreen; -import androidx.recyclerview.widget.RecyclerView; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.animation.Animation; -import android.view.animation.Animation.AnimationListener; -import android.view.animation.AnimationUtils; -import android.widget.TextView; - -import com.android.packageinstaller.R; - -public abstract class PermissionsFrameFragment extends PreferenceFragment { - - // Key identifying the preference used on TV as the extra header in a permission fragment. - // This is to distinguish it from the rest of the preferences - protected static final String HEADER_PREFERENCE_KEY = "HeaderPreferenceKey"; - - private ViewGroup mPreferencesContainer; - - // TV-specific instance variable - @Nullable private RecyclerView mGridView; - - private View mLoadingView; - private ViewGroup mPrefsView; - private boolean mIsLoading; - - /** - * Returns the view group that holds the preferences objects. This will - * only be set after {@link #onCreateView} has been called. - */ - protected final ViewGroup getPreferencesContainer() { - return mPreferencesContainer; - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.permissions_frame, container, - false); - mPrefsView = (ViewGroup) rootView.findViewById(R.id.prefs_container); - if (mPrefsView == null) { - mPrefsView = rootView; - } - mLoadingView = rootView.findViewById(R.id.loading_container); - mPreferencesContainer = (ViewGroup) super.onCreateView( - inflater, mPrefsView, savedInstanceState); - setLoading(mIsLoading, false, true /* force */); - mPrefsView.addView(mPreferencesContainer); - return rootView; - } - - @Override - public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { - PreferenceScreen preferences = getPreferenceScreen(); - if (preferences == null) { - preferences = getPreferenceManager().createPreferenceScreen(getActivity()); - setPreferenceScreen(preferences); - } - } - - protected void setLoading(boolean loading, boolean animate) { - setLoading(loading, animate, false); - } - - private void setLoading(boolean loading, boolean animate, boolean force) { - if (mIsLoading != loading || force) { - mIsLoading = loading; - if (getView() == null) { - // If there is no created view, there is no reason to animate. - animate = false; - } - if (mPrefsView != null) { - setViewShown(mPrefsView, !loading, animate); - } - if (mLoadingView != null) { - setViewShown(mLoadingView, loading, animate); - } - } - } - - private void setViewShown(final View view, boolean shown, boolean animate) { - if (animate) { - Animation animation = AnimationUtils.loadAnimation(getContext(), - shown ? android.R.anim.fade_in : android.R.anim.fade_out); - if (shown) { - view.setVisibility(View.VISIBLE); - } else { - animation.setAnimationListener(new AnimationListener() { - @Override - public void onAnimationStart(Animation animation) { - } - - @Override - public void onAnimationRepeat(Animation animation) { - } - - @Override - public void onAnimationEnd(Animation animation) { - view.setVisibility(View.INVISIBLE); - } - }); - } - view.startAnimation(animation); - } else { - view.clearAnimation(); - view.setVisibility(shown ? View.VISIBLE : View.INVISIBLE); - } - } - - @Override - public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent, - Bundle savedInstanceState) { - VerticalGridView verticalGridView = (VerticalGridView) inflater.inflate( - R.layout.leanback_preferences_list, parent, false); - verticalGridView.setWindowAlignment(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE); - verticalGridView.setFocusScrollStrategy(VerticalGridView.FOCUS_SCROLL_ALIGNED); - mGridView = verticalGridView; - return mGridView; - } - - @Override - protected RecyclerView.Adapter<?> onCreateAdapter(PreferenceScreen preferenceScreen) { - final RecyclerView.Adapter<?> adapter = super.onCreateAdapter(preferenceScreen); - - if (adapter != null) { - final TextView emptyView = (TextView) getView().findViewById(R.id.no_permissions); - onSetEmptyText(emptyView); - final RecyclerView recyclerView = getListView(); - adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() { - @Override - public void onChanged() { - checkEmpty(); - } - - @Override - public void onItemRangeInserted(int positionStart, int itemCount) { - checkEmpty(); - } - - @Override - public void onItemRangeRemoved(int positionStart, int itemCount) { - checkEmpty(); - } - - private void checkEmpty() { - boolean isEmpty = isPreferenceListEmpty(); - emptyView.setVisibility(isEmpty ? View.VISIBLE : View.GONE); - recyclerView.setVisibility(isEmpty && adapter.getItemCount() == 0 ? - View.GONE : View.VISIBLE); - if (!isEmpty && mGridView != null) { - mGridView.requestFocus(); - } - } - }); - - boolean isEmpty = isPreferenceListEmpty(); - emptyView.setVisibility(isEmpty ? View.VISIBLE : View.GONE); - recyclerView.setVisibility(isEmpty && adapter.getItemCount() == 0 ? - View.GONE : View.VISIBLE); - if (!isEmpty && mGridView != null) { - mGridView.requestFocus(); - } - } - - return adapter; - } - - private boolean isPreferenceListEmpty() { - PreferenceScreen screen = getPreferenceScreen(); - return screen.getPreferenceCount() == 0 || ( - screen.getPreferenceCount() == 1 && - (screen.findPreference(HEADER_PREFERENCE_KEY) != null)); - } - - /** - * Hook for subclasses to change the default text of the empty view. - * Base implementation leaves the default empty view text. - * - * @param textView the empty text view - */ - protected void onSetEmptyText(TextView textView) { - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/television/SettingsWithHeader.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/television/SettingsWithHeader.java deleted file mode 100644 index 06f7c1426af5..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/television/SettingsWithHeader.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2015 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.packageinstaller.permission.ui.television; - -import android.content.Intent; -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; -import com.android.packageinstaller.DeviceUtils; -import com.android.packageinstaller.R; - -public abstract class SettingsWithHeader extends PermissionsFrameFragment - implements OnClickListener { - - private View mHeader; - protected Intent mInfoIntent; - protected Drawable mIcon; - protected CharSequence mLabel; - protected CharSequence mDecorTitle; - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - ViewGroup root = (ViewGroup) super.onCreateView(inflater, container, savedInstanceState); - - mHeader = inflater.inflate(R.layout.header, root, false); - getPreferencesContainer().addView(mHeader, 0); - updateHeader(); - - return root; - } - - public void setHeader(Drawable icon, CharSequence label, Intent infoIntent, - CharSequence decorTitle) { - mIcon = icon; - mLabel = label; - mInfoIntent = infoIntent; - mDecorTitle = decorTitle; - updateHeader(); - } - - public View getHeader() { - return mHeader; - } - - protected void updateHeader() { - final TextView decorTitle = (TextView) mHeader.findViewById(R.id.decor_title); - decorTitle.setText(mDecorTitle); - } - - @Override - public void onClick(View v) { - getActivity().startActivity(mInfoIntent); - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/wear/AppPermissionsFragmentWear.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/wear/AppPermissionsFragmentWear.java deleted file mode 100644 index 20495aac2451..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/wear/AppPermissionsFragmentWear.java +++ /dev/null @@ -1,403 +0,0 @@ -/* -* Copyright (C) 2015 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.packageinstaller.permission.ui.wear; - -import android.app.Activity; -import android.app.Fragment; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.PermissionInfo; -import android.os.Build; -import android.os.Bundle; -import android.os.UserHandle; -import android.preference.Preference; -import android.preference.PreferenceFragment; -import android.preference.PreferenceScreen; -import android.preference.SwitchPreference; -import android.util.ArraySet; -import android.util.Log; -import android.widget.Toast; - -import androidx.wear.ble.view.WearableDialogHelper; - -import com.android.packageinstaller.R; -import com.android.packageinstaller.permission.model.AppPermissionGroup; -import com.android.packageinstaller.permission.model.AppPermissions; -import com.android.packageinstaller.permission.model.Permission; -import com.android.packageinstaller.permission.utils.ArrayUtils; -import com.android.packageinstaller.permission.utils.LocationUtils; -import com.android.packageinstaller.permission.utils.SafetyNetLogger; -import com.android.packageinstaller.permission.utils.Utils; -import com.android.settingslib.RestrictedLockUtils; -import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; - -import java.util.ArrayList; -import java.util.List; - -public final class AppPermissionsFragmentWear extends PreferenceFragment { - private static final String LOG_TAG = "AppPermFragWear"; - - private static final String KEY_NO_PERMISSIONS = "no_permissions"; - - public static AppPermissionsFragmentWear newInstance(String packageName) { - return setPackageName(new AppPermissionsFragmentWear(), packageName); - } - - private static <T extends Fragment> T setPackageName(T fragment, String packageName) { - Bundle arguments = new Bundle(); - arguments.putString(Intent.EXTRA_PACKAGE_NAME, packageName); - fragment.setArguments(arguments); - return fragment; - } - - private PackageManager mPackageManager; - private ArraySet<AppPermissionGroup> mToggledGroups; - private AppPermissions mAppPermissions; - - private boolean mHasConfirmedRevoke; - - /** - * Provides click behavior for disabled preferences. - * We can't use {@link PreferenceFragment#onPreferenceTreeClick}, as the base - * {@link SwitchPreference} doesn't delegate to that method if the preference is disabled. - */ - private static class PermissionSwitchPreference extends SwitchPreference { - - private final Activity mActivity; - - public PermissionSwitchPreference(Activity activity) { - super(activity); - this.mActivity = activity; - } - - @Override - public void performClick(PreferenceScreen preferenceScreen) { - super.performClick(preferenceScreen); - if (!isEnabled()) { - // If setting the permission is disabled, it must have been locked - // by the device or profile owner. So get that info and pass it to - // the support details dialog. - EnforcedAdmin deviceOrProfileOwner = RestrictedLockUtils.getProfileOrDeviceOwner( - mActivity, UserHandle.myUserId()); - RestrictedLockUtils.sendShowAdminSupportDetailsIntent( - mActivity, deviceOrProfileOwner); - } - } - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - String packageName = getArguments().getString(Intent.EXTRA_PACKAGE_NAME); - Activity activity = getActivity(); - mPackageManager = activity.getPackageManager(); - - PackageInfo packageInfo; - - try { - packageInfo = mPackageManager.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS); - } catch (PackageManager.NameNotFoundException e) { - Log.i(LOG_TAG, "No package:" + activity.getCallingPackage(), e); - packageInfo = null; - } - - if (packageInfo == null) { - Toast.makeText(activity, R.string.app_not_found_dlg_title, Toast.LENGTH_LONG).show(); - activity.finish(); - return; - } - - mAppPermissions = new AppPermissions( - activity, packageInfo, true, () -> getActivity().finish()); - - addPreferencesFromResource(R.xml.watch_permissions); - initializePermissionGroupList(); - } - - @Override - public void onResume() { - super.onResume(); - mAppPermissions.refresh(); - - // Also refresh the UI - for (final AppPermissionGroup group : mAppPermissions.getPermissionGroups()) { - if (Utils.areGroupPermissionsIndividuallyControlled(getContext(), group.getName())) { - for (PermissionInfo perm : getPermissionInfosFromGroup(group)) { - setPreferenceCheckedIfPresent(perm.name, - group.areRuntimePermissionsGranted(new String[]{ perm.name })); - } - } else { - setPreferenceCheckedIfPresent(group.getName(), group.areRuntimePermissionsGranted()); - } - } - } - - @Override - public void onPause() { - super.onPause(); - logAndClearToggledGroups(); - } - - private void initializePermissionGroupList() { - List<AppPermissionGroup> groups = mAppPermissions.getPermissionGroups(); - List<SwitchPreference> nonSystemPreferences = new ArrayList<>(); - - if (!groups.isEmpty()) { - getPreferenceScreen().removePreference(findPreference(KEY_NO_PERMISSIONS)); - } - - for (final AppPermissionGroup group : groups) { - if (!Utils.shouldShowPermission(group)) { - continue; - } - - boolean isPlatform = group.getDeclaringPackage().equals(Utils.OS_PKG); - - if (Utils.areGroupPermissionsIndividuallyControlled(getContext(), group.getName())) { - // If permission is controlled individually, we show all requested permission - // inside this group. - for (PermissionInfo perm : getPermissionInfosFromGroup(group)) { - final SwitchPreference pref = createSwitchPreferenceForPermission(group, perm); - showOrAddToNonSystemPreferences(pref, nonSystemPreferences, isPlatform); - } - } else { - final SwitchPreference pref = createSwitchPreferenceForGroup(group); - showOrAddToNonSystemPreferences(pref, nonSystemPreferences, isPlatform); - } - } - - // Now add the non-system settings to the end of the list - for (SwitchPreference nonSystemPreference : nonSystemPreferences) { - getPreferenceScreen().addPreference(nonSystemPreference); - } - } - - private void showOrAddToNonSystemPreferences(SwitchPreference pref, - List<SwitchPreference> nonSystemPreferences, // Mutate - boolean isPlatform) { - // The UI shows System settings first, then non-system settings - if (isPlatform) { - getPreferenceScreen().addPreference(pref); - } else { - nonSystemPreferences.add(pref); - } - } - - private SwitchPreference createSwitchPreferenceForPermission(AppPermissionGroup group, - PermissionInfo perm) { - final SwitchPreference pref = new PermissionSwitchPreference(getActivity()); - pref.setKey(perm.name); - pref.setTitle(perm.loadLabel(mPackageManager)); - pref.setChecked(group.areRuntimePermissionsGranted(new String[]{ perm.name })); - pref.setOnPreferenceChangeListener((p, newVal) -> { - if((Boolean) newVal) { - group.grantRuntimePermissions(false, new String[]{ perm.name }); - - if (Utils.areGroupPermissionsIndividuallyControlled(getContext(), group.getName()) - && group.doesSupportRuntimePermissions()) { - // We are granting a permission from a group but since this is an - // individual permission control other permissions in the group may - // be revoked, hence we need to mark them user fixed to prevent the - // app from requesting a non-granted permission and it being granted - // because another permission in the group is granted. This applies - // only to apps that support runtime permissions. - String[] revokedPermissionsToFix = null; - final int permissionCount = group.getPermissions().size(); - - for (int i = 0; i < permissionCount; i++) { - Permission current = group.getPermissions().get(i); - if (!current.isGranted() && !current.isUserFixed()) { - revokedPermissionsToFix = ArrayUtils.appendString( - revokedPermissionsToFix, current.getName()); - } - } - - if (revokedPermissionsToFix != null) { - // If some permissions were not granted then they should be fixed. - group.revokeRuntimePermissions(true, revokedPermissionsToFix); - } - } - } else { - final Permission appPerm = getPermissionFromGroup(group, perm.name); - if (appPerm == null) { - return false; - } - - final boolean grantedByDefault = appPerm.isGrantedByDefault(); - if (grantedByDefault - || (!group.doesSupportRuntimePermissions() && !mHasConfirmedRevoke)) { - showRevocationWarningDialog( - (dialog, which) -> { - revokePermissionInGroup(group, perm.name); - pref.setChecked(false); - if (!appPerm.isGrantedByDefault()) { - mHasConfirmedRevoke = true; - } - }, - grantedByDefault - ? R.string.system_warning - : R.string.old_sdk_deny_warning); - return false; - } else { - revokePermissionInGroup(group, perm.name); - } - } - - return true; - }); - return pref; - } - - private void showRevocationWarningDialog( - DialogInterface.OnClickListener confirmListener, - int warningMessageId) { - new WearableDialogHelper.DialogBuilder(getContext()) - .setNegativeIcon(R.drawable.confirm_button) - .setPositiveIcon(R.drawable.cancel_button) - .setNegativeButton(R.string.grant_dialog_button_deny_anyway, confirmListener) - .setPositiveButton(R.string.cancel, null) - .setMessage(warningMessageId) - .show(); - } - - private static Permission getPermissionFromGroup(AppPermissionGroup group, String permName) { - final int permissionCount = group.getPermissions().size(); - - for (int i = 0; i < permissionCount; i++) { - Permission currentPerm = group.getPermissions().get(i); - if(currentPerm.getName().equals(permName)) { - return currentPerm; - }; - } - - if ("user".equals(Build.TYPE)) { - Log.e(LOG_TAG, String.format("The impossible happens, permission %s is not in group %s.", - permName, group.getName())); - return null; - } else { - // This is impossible, throw a fatal error in non-user build. - throw new IllegalArgumentException( - String.format("Permission %s is not in group %s", permName, group.getName())); - } - } - - private void revokePermissionInGroup(AppPermissionGroup group, String permName) { - group.revokeRuntimePermissions(true, new String[]{ permName }); - - if (Utils.areGroupPermissionsIndividuallyControlled(getContext(), group.getName()) - && group.doesSupportRuntimePermissions() - && !group.areRuntimePermissionsGranted()) { - // If we just revoked the last permission we need to clear - // the user fixed state as now the app should be able to - // request them at runtime if supported. - group.revokeRuntimePermissions(false); - } - } - - private SwitchPreference createSwitchPreferenceForGroup(AppPermissionGroup group) { - final SwitchPreference pref = new PermissionSwitchPreference(getActivity()); - - pref.setKey(group.getName()); - pref.setTitle(group.getLabel()); - pref.setChecked(group.areRuntimePermissionsGranted()); - - if (group.isPolicyFixed()) { - pref.setEnabled(false); - } else { - pref.setOnPreferenceChangeListener((p, newVal) -> { - if (LocationUtils.isLocationGroupAndProvider( - group.getName(), group.getApp().packageName)) { - LocationUtils.showLocationDialog( - getContext(), mAppPermissions.getAppLabel()); - return false; - } - - if ((Boolean) newVal) { - setPermission(group, pref, true); - } else { - final boolean grantedByDefault = group.hasGrantedByDefaultPermission(); - if (grantedByDefault - || (!group.doesSupportRuntimePermissions() && !mHasConfirmedRevoke)) { - showRevocationWarningDialog( - (dialog, which) -> { - setPermission(group, pref, false); - if (!group.hasGrantedByDefaultPermission()) { - mHasConfirmedRevoke = true; - } - }, - grantedByDefault - ? R.string.system_warning - : R.string.old_sdk_deny_warning); - return false; - } else { - setPermission(group, pref, false); - } - } - - return true; - }); - } - return pref; - } - - private void setPermission(AppPermissionGroup group, SwitchPreference pref, boolean grant) { - if (grant) { - group.grantRuntimePermissions(false); - } else { - group.revokeRuntimePermissions(false); - } - addToggledGroup(group); - pref.setChecked(grant); - } - - private void addToggledGroup(AppPermissionGroup group) { - if (mToggledGroups == null) { - mToggledGroups = new ArraySet<>(); - } - - mToggledGroups.add(group); - } - - private void logAndClearToggledGroups() { - if (mToggledGroups != null) { - SafetyNetLogger.logPermissionsToggled(mToggledGroups); - mToggledGroups = null; - } - } - - private List<PermissionInfo> getPermissionInfosFromGroup(AppPermissionGroup group) { - ArrayList<PermissionInfo> permInfos = new ArrayList<>(group.getPermissions().size()); - for(Permission perm : group.getPermissions()) { - try { - permInfos.add(mPackageManager.getPermissionInfo(perm.getName(), 0)); - } catch (PackageManager.NameNotFoundException e) { - Log.w(LOG_TAG, "No permission:" + perm.getName()); - } - } - return permInfos; - } - - private void setPreferenceCheckedIfPresent(String preferenceKey, boolean checked) { - Preference pref = findPreference(preferenceKey); - if (pref instanceof SwitchPreference) { - ((SwitchPreference) pref).setChecked(checked); - } - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/wear/ReviewPermissionsWearFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/wear/ReviewPermissionsWearFragment.java deleted file mode 100644 index 5aa7cafec8a8..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/ui/wear/ReviewPermissionsWearFragment.java +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Copyright (C) 2017 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.packageinstaller.permission.ui.wear; - -import android.app.Activity; -import android.content.Intent; -import android.content.IntentSender; -import android.content.pm.PackageInfo; -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import android.os.RemoteCallback; -import android.text.SpannableString; -import android.text.style.ForegroundColorSpan; -import android.util.Log; -import android.util.TypedValue; - -import androidx.preference.Preference; -import androidx.preference.PreferenceCategory; -import androidx.preference.PreferenceFragmentCompat; -import androidx.preference.PreferenceGroup; -import androidx.preference.PreferenceScreen; -import androidx.preference.SwitchPreference; -import androidx.preference.TwoStatePreference; -import androidx.wear.ble.view.WearableDialogHelper; - -import com.android.packageinstaller.R; -import com.android.packageinstaller.permission.model.AppPermissionGroup; -import com.android.packageinstaller.permission.model.AppPermissions; -import com.android.packageinstaller.permission.utils.Utils; - -import java.util.List; - -public class ReviewPermissionsWearFragment extends PreferenceFragmentCompat - implements Preference.OnPreferenceChangeListener { - private static final String TAG = "ReviewPermWear"; - - private static final int ORDER_NEW_PERMS = 1; - private static final int ORDER_CURRENT_PERMS = 2; - // Category for showing actions should be displayed last. - private static final int ORDER_ACTION = 100000; - private static final int ORDER_PERM_OFFSET_START = 100; - - private static final String EXTRA_PACKAGE_INFO = - "com.android.packageinstaller.permission.ui.extra.PACKAGE_INFO"; - - public static ReviewPermissionsWearFragment newInstance(PackageInfo packageInfo) { - Bundle arguments = new Bundle(); - arguments.putParcelable(EXTRA_PACKAGE_INFO, packageInfo); - ReviewPermissionsWearFragment instance = new ReviewPermissionsWearFragment(); - instance.setArguments(arguments); - instance.setRetainInstance(true); - return instance; - } - - private AppPermissions mAppPermissions; - - private PreferenceCategory mNewPermissionsCategory; - - private boolean mHasConfirmedRevoke; - - @Override - public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { - Activity activity = getActivity(); - if (activity == null) { - return; - } - - PackageInfo packageInfo = getArguments().getParcelable(EXTRA_PACKAGE_INFO); - if (packageInfo == null) { - activity.finish(); - return; - } - - mAppPermissions = new AppPermissions(activity, packageInfo, false, - () -> getActivity().finish()); - - if (mAppPermissions.getPermissionGroups().isEmpty()) { - activity.finish(); - return; - } - - boolean reviewRequired = false; - for (AppPermissionGroup group : mAppPermissions.getPermissionGroups()) { - if (group.isReviewRequired()) { - reviewRequired = true; - break; - } - } - - if (!reviewRequired) { - activity.finish(); - } - } - - @Override - public void onResume() { - super.onResume(); - mAppPermissions.refresh(); - loadPreferences(); - } - - private void loadPreferences() { - Activity activity = getActivity(); - if (activity == null) { - return; - } - - PreferenceScreen screen = getPreferenceScreen(); - if (screen == null) { - screen = getPreferenceManager().createPreferenceScreen(getActivity()); - setPreferenceScreen(screen); - } else { - screen.removeAll(); - } - - PreferenceGroup currentPermissionsCategory = null; - PreferenceGroup oldNewPermissionsCategory = mNewPermissionsCategory; - mNewPermissionsCategory = null; - - final boolean isPackageUpdated = isPackageUpdated(); - int permOrder = ORDER_PERM_OFFSET_START; - - for (AppPermissionGroup group : mAppPermissions.getPermissionGroups()) { - if (!Utils.shouldShowPermission(group) - || !Utils.OS_PKG.equals(group.getDeclaringPackage())) { - continue; - } - - final SwitchPreference preference; - Preference cachedPreference = oldNewPermissionsCategory != null - ? oldNewPermissionsCategory.findPreference(group.getName()) : null; - if (cachedPreference instanceof SwitchPreference) { - preference = (SwitchPreference) cachedPreference; - } else { - preference = new SwitchPreference(getActivity()); - - preference.setKey(group.getName()); - preference.setTitle(group.getLabel()); - preference.setPersistent(false); - preference.setOrder(permOrder++); - - preference.setOnPreferenceChangeListener(this); - } - - preference.setChecked(group.areRuntimePermissionsGranted()); - - // Mutable state - if (group.isPolicyFixed()) { - preference.setEnabled(false); - } else { - preference.setEnabled(true); - } - - if (group.isReviewRequired()) { - if (!isPackageUpdated) { - // An app just being installed, which means all groups requiring reviews. - screen.addPreference(preference); - } else { - if (mNewPermissionsCategory == null) { - mNewPermissionsCategory = new PreferenceCategory(activity); - mNewPermissionsCategory.setTitle(R.string.new_permissions_category); - mNewPermissionsCategory.setOrder(ORDER_NEW_PERMS); - screen.addPreference(mNewPermissionsCategory); - } - mNewPermissionsCategory.addPreference(preference); - } - } else { - if (currentPermissionsCategory == null) { - currentPermissionsCategory = new PreferenceCategory(activity); - currentPermissionsCategory.setTitle(R.string.current_permissions_category); - currentPermissionsCategory.setOrder(ORDER_CURRENT_PERMS); - screen.addPreference(currentPermissionsCategory); - } - currentPermissionsCategory.addPreference(preference); - } - } - - addTitlePreferenceToScreen(screen); - addActionPreferencesToScreen(screen); - } - - private boolean isPackageUpdated() { - List<AppPermissionGroup> groups = mAppPermissions.getPermissionGroups(); - final int groupCount = groups.size(); - for (int i = 0; i < groupCount; i++) { - AppPermissionGroup group = groups.get(i); - if (!group.isReviewRequired()) { - return true; - } - } - return false; - } - - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - Log.d(TAG, "onPreferenceChange " + preference.getTitle()); - if (mHasConfirmedRevoke) { - return true; - } - if (preference instanceof SwitchPreference) { - SwitchPreference switchPreference = (SwitchPreference) preference; - if (switchPreference.isChecked()) { - showWarnRevokeDialog(switchPreference); - } else { - return true; - } - } - return false; - } - - private void showWarnRevokeDialog(final SwitchPreference preference) { - // When revoking, we set "confirm" as the negative icon to be shown at the bottom. - new WearableDialogHelper.DialogBuilder(getContext()) - .setPositiveIcon(R.drawable.cancel_button) - .setNegativeIcon(R.drawable.confirm_button) - .setPositiveButton(R.string.cancel, null) - .setNegativeButton(R.string.grant_dialog_button_deny_anyway, - (dialog, which) -> { - preference.setChecked(false); - mHasConfirmedRevoke = true; - }) - .setMessage(R.string.old_sdk_deny_warning) - .show(); - } - - private void confirmPermissionsReview() { - PreferenceGroup preferenceGroup = mNewPermissionsCategory != null - ? mNewPermissionsCategory : getPreferenceScreen(); - - final int preferenceCount = preferenceGroup.getPreferenceCount(); - for (int i = 0; i < preferenceCount; i++) { - Preference preference = preferenceGroup.getPreference(i); - if (preference instanceof TwoStatePreference) { - TwoStatePreference twoStatePreference = (TwoStatePreference) preference; - String groupName = preference.getKey(); - AppPermissionGroup group = mAppPermissions.getPermissionGroup(groupName); - if (twoStatePreference.isChecked()) { - group.grantRuntimePermissions(false); - } else { - group.revokeRuntimePermissions(false); - } - group.resetReviewRequired(); - } - } - } - - private void addTitlePreferenceToScreen(PreferenceScreen screen) { - Activity activity = getActivity(); - Preference titlePref = new Preference(activity); - screen.addPreference(titlePref); - - // Set icon - Drawable icon = mAppPermissions.getPackageInfo().applicationInfo.loadIcon( - activity.getPackageManager()); - titlePref.setIcon(icon); - - // Set message - String appLabel = mAppPermissions.getAppLabel().toString(); - final int labelTemplateResId = isPackageUpdated() - ? R.string.permission_review_title_template_update - : R.string.permission_review_title_template_install; - SpannableString message = new SpannableString(getString(labelTemplateResId, appLabel)); - - // Color the app name. - final int appLabelStart = message.toString().indexOf(appLabel, 0); - final int appLabelLength = appLabel.length(); - - TypedValue typedValue = new TypedValue(); - activity.getTheme().resolveAttribute(android.R.attr.colorAccent, typedValue, true); - final int color = activity.getColor(typedValue.resourceId); - - message.setSpan(new ForegroundColorSpan(color), appLabelStart, - appLabelStart + appLabelLength, 0); - - titlePref.setTitle(message); - - titlePref.setSelectable(false); - titlePref.setLayoutResource(R.layout.wear_review_permission_title_pref); - } - - private void addActionPreferencesToScreen(PreferenceScreen screen) { - final Activity activity = getActivity(); - - Preference cancelPref = new Preference(activity); - cancelPref.setTitle(R.string.review_button_cancel); - cancelPref.setOrder(ORDER_ACTION); - cancelPref.setEnabled(true); - cancelPref.setLayoutResource(R.layout.wear_review_permission_action_pref); - cancelPref.setOnPreferenceClickListener(p -> { - executeCallback(false); - activity.setResult(Activity.RESULT_CANCELED); - activity.finish(); - return true; - }); - screen.addPreference(cancelPref); - - Preference continuePref = new Preference(activity); - continuePref.setTitle(R.string.review_button_continue); - continuePref.setOrder(ORDER_ACTION + 1); - continuePref.setEnabled(true); - continuePref.setLayoutResource(R.layout.wear_review_permission_action_pref); - continuePref.setOnPreferenceClickListener(p -> { - confirmPermissionsReview(); - executeCallback(true); - getActivity().finish(); - return true; - }); - screen.addPreference(continuePref); - } - - private void executeCallback(boolean success) { - Activity activity = getActivity(); - if (activity == null) { - return; - } - if (success) { - IntentSender intent = activity.getIntent().getParcelableExtra(Intent.EXTRA_INTENT); - if (intent != null) { - try { - int flagMask = 0; - int flagValues = 0; - if (activity.getIntent().getBooleanExtra( - Intent.EXTRA_RESULT_NEEDED, false)) { - flagMask = Intent.FLAG_ACTIVITY_FORWARD_RESULT; - flagValues = Intent.FLAG_ACTIVITY_FORWARD_RESULT; - } - activity.startIntentSenderForResult(intent, -1, null, - flagMask, flagValues, 0); - } catch (IntentSender.SendIntentException e) { - /* ignore */ - } - return; - } - } - RemoteCallback callback = activity.getIntent().getParcelableExtra( - Intent.EXTRA_REMOTE_CALLBACK); - if (callback != null) { - Bundle result = new Bundle(); - result.putBoolean(Intent.EXTRA_RETURN_RESULT, success); - callback.sendResult(result); - } - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/utils/ArrayUtils.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/utils/ArrayUtils.java deleted file mode 100644 index 2af641bc321c..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/utils/ArrayUtils.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2016 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.packageinstaller.permission.utils; - -import android.text.TextUtils; - -import java.util.Objects; - -public final class ArrayUtils { - private ArrayUtils() { /* cannot be instantiated */ } - - /** - * Checks that value is present as at least one of the elements of the array. - * @param array the array to check in - * @param value the value to check for - * @return true if the value is present in the array - */ - public static <T> boolean contains(T[] array, T value) { - return indexOf(array, value) != -1; - } - - /** - * Return first index of {@code value} in {@code array}, or {@code -1} if - * not found. - */ - public static <T> int indexOf(T[] array, T value) { - if (array == null) return -1; - for (int i = 0; i < array.length; i++) { - if (Objects.equals(array[i], value)) return i; - } - return -1; - } - - public static String[] appendString(String[] cur, String val) { - if (cur == null) { - return new String[] { val }; - } - final int N = cur.length; - for (int i = 0; i < N; i++) { - if (TextUtils.equals(cur[i], val)) { - return cur; - } - } - String[] ret = new String[N + 1]; - System.arraycopy(cur, 0, ret, 0, N); - ret[N] = val; - return ret; - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/utils/EventLogger.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/utils/EventLogger.java deleted file mode 100644 index 7aff7ada792d..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/utils/EventLogger.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2016 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.packageinstaller.permission.utils; - -import android.metrics.LogMaker; -import androidx.annotation.NonNull; - -import com.android.internal.logging.MetricsLogger; -import com.android.internal.logging.nano.MetricsProto.MetricsEvent; - -public class EventLogger { - private static final MetricsLogger sMetricsLogger = new MetricsLogger(); - - /** - * Log that a permission was requested/denied. - * - * @param action the action performed - * @param name name of the permission - * @param packageName package permission is for - */ - public static void logPermission(int action, @NonNull String name, - @NonNull String packageName) { - final LogMaker log = new LogMaker(action); - log.setPackageName(packageName); - log.addTaggedData(MetricsEvent.FIELD_PERMISSION, name); - - sMetricsLogger.write(log); - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/utils/IoUtils.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/utils/IoUtils.java deleted file mode 100644 index ff7d1831519f..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/utils/IoUtils.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2016 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.packageinstaller.permission.utils; - -public final class IoUtils { - private IoUtils() { - } - - /** - * Closes 'closeable', ignoring any checked exceptions. Does nothing if 'closeable' is null. - */ - public static void closeQuietly(AutoCloseable closeable) { - if (closeable != null) { - try { - closeable.close(); - } catch (RuntimeException rethrown) { - throw rethrown; - } catch (Exception ignored) { - } - } - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/utils/LocationUtils.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/utils/LocationUtils.java deleted file mode 100644 index 0296ae80ad4c..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/utils/LocationUtils.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2015 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.packageinstaller.permission.utils; - -import android.Manifest; -import android.app.AlertDialog; -import android.content.Context; -import android.content.DialogInterface; -import android.content.DialogInterface.OnClickListener; -import android.content.Intent; -import android.content.res.Resources; -import android.location.ILocationManager; -import android.location.LocationManager; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.provider.Settings; - -import com.android.packageinstaller.R; - -import java.util.ArrayList; - -public class LocationUtils { - - public static final String LOCATION_PERMISSION = Manifest.permission_group.LOCATION; - - public static void showLocationDialog(final Context context, CharSequence label) { - new AlertDialog.Builder(context) - .setIcon(R.drawable.ic_dialog_alert_material) - .setTitle(android.R.string.dialog_alert_title) - .setMessage(context.getString(R.string.location_warning, label)) - .setNegativeButton(R.string.ok, null) - .setPositiveButton(R.string.location_settings, new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - context.startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)); - } - }) - .show(); - } - - public static boolean isLocationEnabled(Context context) { - return Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.LOCATION_MODE, - Settings.Secure.LOCATION_MODE_OFF) != Settings.Secure.LOCATION_MODE_OFF; - } - - public static boolean isLocationGroupAndProvider(String groupName, String packageName) { - return LOCATION_PERMISSION.equals(groupName) && isNetworkLocationProvider(packageName); - } - - private static boolean isNetworkLocationProvider(String packageName) { - ILocationManager locationService = ILocationManager.Stub.asInterface( - ServiceManager.getService(Context.LOCATION_SERVICE)); - try { - return packageName.equals(locationService.getNetworkProviderPackage()); - } catch (RemoteException e) { - return false; - } - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/utils/SafetyNetLogger.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/utils/SafetyNetLogger.java deleted file mode 100644 index 7773294b0998..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/utils/SafetyNetLogger.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2015 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.packageinstaller.permission.utils; - -import android.content.pm.PackageInfo; -import android.util.ArrayMap; -import android.util.ArraySet; -import android.util.EventLog; - -import com.android.packageinstaller.permission.model.AppPermissionGroup; -import com.android.packageinstaller.permission.model.Permission; - -import java.util.ArrayList; -import java.util.List; - -public final class SafetyNetLogger { - - // The log tag used by SafetyNet to pick entries from the event log. - private static final int SNET_NET_EVENT_LOG_TAG = 0x534e4554; - - // Log tag for the result of permissions request. - private static final String PERMISSIONS_REQUESTED = "individual_permissions_requested"; - - // Log tag for the result of permissions toggling. - private static final String PERMISSIONS_TOGGLED = "individual_permissions_toggled"; - - private SafetyNetLogger() { - /* do nothing */ - } - - public static void logPermissionsRequested(PackageInfo packageInfo, - List<AppPermissionGroup> groups) { - EventLog.writeEvent(SNET_NET_EVENT_LOG_TAG, PERMISSIONS_REQUESTED, - packageInfo.applicationInfo.uid, buildChangedPermissionForPackageMessage( - packageInfo.packageName, groups)); - } - - /** - * Log that permission groups have been toggled for the purpose of safety net. - * - * <p>The groups might refer to different permission groups and different apps. - * - * @param groups The groups toggled - */ - public static void logPermissionsToggled(ArraySet<AppPermissionGroup> groups) { - ArrayMap<String, ArrayList<AppPermissionGroup>> groupsByPackage = new ArrayMap<>(); - - int numGroups = groups.size(); - for (int i = 0; i < numGroups; i++) { - AppPermissionGroup group = groups.valueAt(i); - - ArrayList<AppPermissionGroup> groupsForThisPackage = groupsByPackage.get( - group.getApp().packageName); - if (groupsForThisPackage == null) { - groupsForThisPackage = new ArrayList<>(); - groupsByPackage.put(group.getApp().packageName, groupsForThisPackage); - } - - groupsForThisPackage.add(group); - if (group.getBackgroundPermissions() != null) { - groupsForThisPackage.add(group.getBackgroundPermissions()); - } - } - - int numPackages = groupsByPackage.size(); - for (int i = 0; i < numPackages; i++) { - EventLog.writeEvent(SNET_NET_EVENT_LOG_TAG, PERMISSIONS_TOGGLED, - android.os.Process.myUid(), buildChangedPermissionForPackageMessage( - groupsByPackage.keyAt(i), groupsByPackage.valueAt(i))); - } - } - - private static void buildChangedPermissionForGroup(AppPermissionGroup group, - StringBuilder builder) { - int permissionCount = group.getPermissions().size(); - for (int permissionNum = 0; permissionNum < permissionCount; permissionNum++) { - Permission permission = group.getPermissions().get(permissionNum); - - if (builder.length() > 0) { - builder.append(';'); - } - - builder.append(permission.getName()).append('|'); - - if (group.doesSupportRuntimePermissions()) { - builder.append(permission.isGranted()).append('|'); - } else { - builder.append(permission.isGranted() - && (!permission.affectsAppOp() || permission.isAppOpAllowed())).append('|'); - } - - builder.append(permission.getFlags()); - } - } - - private static String buildChangedPermissionForPackageMessage(String packageName, - List<AppPermissionGroup> groups) { - StringBuilder builder = new StringBuilder(); - - builder.append(packageName).append(':'); - - int groupCount = groups.size(); - for (int groupNum = 0; groupNum < groupCount; groupNum++) { - AppPermissionGroup group = groups.get(groupNum); - - buildChangedPermissionForGroup(group, builder); - if (group.getBackgroundPermissions() != null) { - buildChangedPermissionForGroup(group.getBackgroundPermissions(), builder); - } - } - - return builder.toString(); - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/permission/utils/Utils.java b/packages/PackageInstaller/src/com/android/packageinstaller/permission/utils/Utils.java deleted file mode 100644 index d7ee219b0e47..000000000000 --- a/packages/PackageInstaller/src/com/android/packageinstaller/permission/utils/Utils.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (C) 2015 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.packageinstaller.permission.utils; - -import android.Manifest; -import android.annotation.StringRes; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.res.Resources; -import android.content.res.Resources.Theme; -import android.graphics.drawable.Drawable; -import android.text.Html; -import android.util.ArraySet; -import android.util.Log; -import android.util.TypedValue; - -import com.android.packageinstaller.R; -import com.android.packageinstaller.permission.model.AppPermissionGroup; -import com.android.packageinstaller.permission.model.AppPermissions; -import com.android.packageinstaller.permission.model.PermissionApps.PermissionApp; - -import java.util.List; - -public final class Utils { - - private static final String LOG_TAG = "Utils"; - - public static final String OS_PKG = "android"; - - public static final String[] MODERN_PERMISSION_GROUPS = { - Manifest.permission_group.CALENDAR, - Manifest.permission_group.CALL_LOG, - Manifest.permission_group.CAMERA, - Manifest.permission_group.CONTACTS, - Manifest.permission_group.LOCATION, - Manifest.permission_group.SENSORS, - Manifest.permission_group.SMS, - Manifest.permission_group.PHONE, - Manifest.permission_group.MICROPHONE, - Manifest.permission_group.STORAGE - }; - - private static final Intent LAUNCHER_INTENT = new Intent(Intent.ACTION_MAIN, null) - .addCategory(Intent.CATEGORY_LAUNCHER); - - private Utils() { - /* do nothing - hide constructor */ - } - - public static Drawable loadDrawable(PackageManager pm, String pkg, int resId) { - try { - return pm.getResourcesForApplication(pkg).getDrawable(resId, null); - } catch (Resources.NotFoundException | PackageManager.NameNotFoundException e) { - Log.d(LOG_TAG, "Couldn't get resource", e); - return null; - } - } - - public static boolean isModernPermissionGroup(String name) { - for (String modernGroup : MODERN_PERMISSION_GROUPS) { - if (modernGroup.equals(name)) { - return true; - } - } - return false; - } - - /** - * Should UI show this permission. - * - * <p>If the user cannot change the group, it should not be shown. - * - * @param group The group that might need to be shown to the user - * - * @return - */ - public static boolean shouldShowPermission(AppPermissionGroup group) { - boolean isSystemFixed = group.isSystemFixed(); - if (group.getBackgroundPermissions() != null) { - // If the foreground mode is fixed to "enabled", the background mode might still be - // switchable. We only want to suppress the group if nothing can be switched - if (group.areRuntimePermissionsGranted()) { - isSystemFixed &= group.getBackgroundPermissions().isSystemFixed(); - } - } - - // We currently will not show permissions fixed by the system. - // which is what the system does for system components. - if (isSystemFixed && !LocationUtils.isLocationGroupAndProvider( - group.getName(), group.getApp().packageName)) { - return false; - } - - if (!group.isGrantingAllowed()) { - return false; - } - - final boolean isPlatformPermission = group.getDeclaringPackage().equals(OS_PKG); - // Show legacy permissions only if the user chose that. - if (isPlatformPermission - && !Utils.isModernPermissionGroup(group.getName())) { - return false; - } - return true; - } - - public static Drawable applyTint(Context context, Drawable icon, int attr) { - Theme theme = context.getTheme(); - TypedValue typedValue = new TypedValue(); - theme.resolveAttribute(attr, typedValue, true); - icon = icon.mutate(); - icon.setTint(context.getColor(typedValue.resourceId)); - return icon; - } - - public static Drawable applyTint(Context context, int iconResId, int attr) { - return applyTint(context, context.getDrawable(iconResId), attr); - } - - public static ArraySet<String> getLauncherPackages(Context context) { - ArraySet<String> launcherPkgs = new ArraySet<>(); - for (ResolveInfo info : - context.getPackageManager().queryIntentActivities(LAUNCHER_INTENT, 0)) { - launcherPkgs.add(info.activityInfo.packageName); - } - - return launcherPkgs; - } - - public static List<ApplicationInfo> getAllInstalledApplications(Context context) { - return context.getPackageManager().getInstalledApplications(0); - } - - public static boolean isSystem(PermissionApp app, ArraySet<String> launcherPkgs) { - return isSystem(app.getAppInfo(), launcherPkgs); - } - - public static boolean isSystem(AppPermissions app, ArraySet<String> launcherPkgs) { - return isSystem(app.getPackageInfo().applicationInfo, launcherPkgs); - } - - public static boolean isSystem(ApplicationInfo info, ArraySet<String> launcherPkgs) { - return info.isSystemApp() && (info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 0 - && !launcherPkgs.contains(info.packageName); - } - - public static boolean areGroupPermissionsIndividuallyControlled(Context context, String group) { - if (!context.getPackageManager().arePermissionsIndividuallyControlled()) { - return false; - } - return Manifest.permission_group.SMS.equals(group) - || Manifest.permission_group.PHONE.equals(group) - || Manifest.permission_group.CONTACTS.equals(group); - } - - public static boolean isPermissionIndividuallyControlled(Context context, String permission) { - if (!context.getPackageManager().arePermissionsIndividuallyControlled()) { - return false; - } - return Manifest.permission.READ_CONTACTS.equals(permission) - || Manifest.permission.WRITE_CONTACTS.equals(permission) - || Manifest.permission.SEND_SMS.equals(permission) - || Manifest.permission.RECEIVE_SMS.equals(permission) - || Manifest.permission.READ_SMS.equals(permission) - || Manifest.permission.RECEIVE_MMS.equals(permission) - || Manifest.permission.CALL_PHONE.equals(permission) - || Manifest.permission.READ_CALL_LOG.equals(permission) - || Manifest.permission.WRITE_CALL_LOG.equals(permission); - } - - /** - * Get the message shown to grant a permission group to an app. - * - * @param appLabel The label of the app - * @param group the group to be granted - * @param context A context to resolve resources - * @param requestRes The resource id of the grant request message - * - * @return The formatted message to be used as title when granting permissions - */ - public static CharSequence getRequestMessage(CharSequence appLabel, AppPermissionGroup group, - Context context, @StringRes int requestRes) { - if (requestRes != 0) { - try { - return Html.fromHtml(context.getPackageManager().getResourcesForApplication( - group.getDeclaringPackage()).getString(requestRes, appLabel), 0); - } catch (PackageManager.NameNotFoundException ignored) { - } - } - - return Html.fromHtml(context.getString(R.string.permission_warning_template, appLabel, - group.getDescription()), 0); - } -} diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index ac33454c84ad..d299930506d8 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -3241,7 +3241,7 @@ public class PackageManagerService extends IPackageManager.Stub mSharedSystemSharedLibraryPackageName = getRequiredSharedLibraryLPr( PackageManager.SYSTEM_SHARED_LIBRARY_SHARED, SharedLibraryInfo.VERSION_UNDEFINED); - mRequiredPermissionControllerPackage = getRequiredPermissionsControllerLPr(); + mRequiredPermissionControllerPackage = getRequiredPermissionControllerLPr(); } else { mRequiredVerifierPackage = null; mRequiredInstallerPackage = null; @@ -3598,7 +3598,7 @@ public class PackageManagerService extends IPackageManager.Stub return resolveInfo.getComponentInfo().packageName; } - private @NonNull String getRequiredPermissionsControllerLPr() { + private @NonNull String getRequiredPermissionControllerLPr() { final Intent intent = new Intent(Intent.ACTION_MANAGE_PERMISSIONS); intent.addCategory(Intent.CATEGORY_DEFAULT); @@ -23972,6 +23972,8 @@ public class PackageManagerService extends IPackageManager.Stub return mRequiredVerifierPackage; case PackageManagerInternal.PACKAGE_SYSTEM_TEXT_CLASSIFIER: return mSystemTextClassifierPackage; + case PackageManagerInternal.PACKAGE_PERMISSION_CONTROLLER: + return mRequiredPermissionControllerPackage; } return null; } diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 76832ed3f4f9..9dc0b296f97e 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -1267,9 +1267,15 @@ public class PermissionManagerService { // we still want to blindly grant it to old apps. allowed = true; } + // TODO (moltmann): The installer now shares the platforms signature. Hence it does not + // need a separate flag anymore. Hence we need to check which + // permissions are needed by the permission controller if (!allowed && bp.isInstaller() - && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName( - PackageManagerInternal.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM))) { + && (pkg.packageName.equals(mPackageManagerInt.getKnownPackageName( + PackageManagerInternal.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM)) + || pkg.packageName.equals(mPackageManagerInt.getKnownPackageName( + PackageManagerInternal.PACKAGE_PERMISSION_CONTROLLER, + UserHandle.USER_SYSTEM)))) { // If this permission is to be granted to the system installer and // this app is an installer, then it gets the permission. allowed = true; -- GitLab