summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSvetoslav <svetoslavganov@google.com>2015-10-29 13:14:27 -0700
committerSvetoslav Ganov <svetoslavganov@google.com>2015-11-18 20:03:50 +0000
commit2cf17ddcef3c8dd260bd3d174123842c81a7d025 (patch)
treebd6cf4fca561cb0c62767c1fd5781991cac171c3
parent30707bb7a27157d5124b0c648509c0e63d1da392 (diff)
downloadandroid_packages_apps_PackageInstaller-2cf17ddcef3c8dd260bd3d174123842c81a7d025.tar.gz
android_packages_apps_PackageInstaller-2cf17ddcef3c8dd260bd3d174123842c81a7d025.tar.bz2
android_packages_apps_PackageInstaller-2cf17ddcef3c8dd260bd3d174123842c81a7d025.zip
Clean up package installer styling
Package installer should be using exclusively the device defaut themes on handhelds (phones and tables) to allow OEMs customize its look and feel. Also for handhelds the installer should use the same preference framework as the settings app to ensure it looks like the settings app on an OEMs device. This change needs to be picked up by a GMS build to deliver to partners ensuring the installer UI is consistent with the device UI. bug:24286616 Change-Id: I92e39fd1488e76b0b23b7f1efa13e04ed5bbc7ba
-rw-r--r--res/drawable/header_background.xml21
-rw-r--r--res/drawable/ic_dialog_alert_material.xml25
-rw-r--r--res/drawable/ic_more_items.xml29
-rw-r--r--res/layout/app_details.xml8
-rw-r--r--res/layout/grant_permissions.xml19
-rw-r--r--res/layout/header.xml15
-rw-r--r--res/layout/install_confirm.xml3
-rw-r--r--res/layout/permission_description.xml5
-rw-r--r--res/layout/permissions_frame.xml4
-rw-r--r--res/layout/preference_permissions.xml2
-rw-r--r--res/layout/preference_permissions_switch.xml2
-rw-r--r--res/layout/uninstall_confirm.xml3
-rw-r--r--res/values-television/colors.xml7
-rw-r--r--res/values-television/styles.xml37
-rwxr-xr-xres/values/colors.xml31
-rwxr-xr-xres/values/styles.xml31
-rw-r--r--res/values/themes.xml10
-rw-r--r--src/com/android/packageinstaller/permission/model/PermissionApps.java3
-rw-r--r--src/com/android/packageinstaller/permission/ui/ButtonBarLayout.java117
-rw-r--r--src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java12
-rw-r--r--src/com/android/packageinstaller/permission/ui/GrantPermissionsViewHandler.java2
-rw-r--r--src/com/android/packageinstaller/permission/ui/ManagePermissionsActivity.java25
-rw-r--r--src/com/android/packageinstaller/permission/ui/OverlayWarningDialog.java1
-rw-r--r--src/com/android/packageinstaller/permission/ui/PreferenceImageView.java69
-rw-r--r--src/com/android/packageinstaller/permission/ui/handheld/AllAppPermissionsFragment.java214
-rw-r--r--src/com/android/packageinstaller/permission/ui/handheld/AppPermissionsFragment.java404
-rw-r--r--src/com/android/packageinstaller/permission/ui/handheld/GrantPermissionsViewHandlerImpl.java (renamed from src/com/android/packageinstaller/permission/ui/GrantPermissionsDefaultViewHandler.java)16
-rw-r--r--src/com/android/packageinstaller/permission/ui/handheld/ManagePermissionsFragment.java268
-rw-r--r--src/com/android/packageinstaller/permission/ui/handheld/PermissionAppsFragment.java427
-rw-r--r--src/com/android/packageinstaller/permission/ui/handheld/PermissionsFrameFragment.java121
-rw-r--r--src/com/android/packageinstaller/permission/ui/handheld/SettingsWithHeader.java (renamed from src/com/android/packageinstaller/permission/ui/SettingsWithHeader.java)3
-rw-r--r--src/com/android/packageinstaller/permission/ui/television/AllAppPermissionsFragment.java (renamed from src/com/android/packageinstaller/permission/ui/AllAppPermissionsFragment.java)2
-rw-r--r--src/com/android/packageinstaller/permission/ui/television/AppPermissionsFragment.java (renamed from src/com/android/packageinstaller/permission/ui/AppPermissionsFragment.java)3
-rw-r--r--src/com/android/packageinstaller/permission/ui/television/GrantPermissionsViewHandlerImpl.java (renamed from src/com/android/packageinstaller/permission/ui/GrantPermissionsTvViewHandler.java)9
-rw-r--r--src/com/android/packageinstaller/permission/ui/television/ManagePermissionsFragment.java (renamed from src/com/android/packageinstaller/permission/ui/ManagePermissionsFragment.java)4
-rw-r--r--src/com/android/packageinstaller/permission/ui/television/PermissionAppsFragment.java (renamed from src/com/android/packageinstaller/permission/ui/PermissionAppsFragment.java)3
-rw-r--r--src/com/android/packageinstaller/permission/ui/television/PermissionsFrameFragment.java (renamed from src/com/android/packageinstaller/permission/ui/PermissionsFrameFragment.java)18
-rw-r--r--src/com/android/packageinstaller/permission/ui/television/SettingsWithHeader.java85
-rw-r--r--src/com/android/packageinstaller/permission/utils/LocationUtils.java17
39 files changed, 1918 insertions, 157 deletions
diff --git a/res/drawable/header_background.xml b/res/drawable/header_background.xml
deleted file mode 100644
index 77db9e03..00000000
--- a/res/drawable/header_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.
--->
-
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="?android:attr/colorControlHighlight">
- <item android:drawable="@color/header_background_color" />
-</ripple>
-
diff --git a/res/drawable/ic_dialog_alert_material.xml b/res/drawable/ic_dialog_alert_material.xml
new file mode 100644
index 00000000..8bd2e0ba
--- /dev/null
+++ b/res/drawable/ic_dialog_alert_material.xml
@@ -0,0 +1,25 @@
+<!--
+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="?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/res/drawable/ic_more_items.xml b/res/drawable/ic_more_items.xml
new file mode 100644
index 00000000..5fdcdcef
--- /dev/null
+++ b/res/drawable/ic_more_items.xml
@@ -0,0 +1,29 @@
+<?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/res/layout/app_details.xml b/res/layout/app_details.xml
index 6a330c74..8f7d2cff 100644
--- a/res/layout/app_details.xml
+++ b/res/layout/app_details.xml
@@ -4,9 +4,9 @@
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.
@@ -32,7 +32,7 @@ installation screens
android:layout_width="32dip"
android:layout_height="32dip"
android:layout_marginStart="8dip"
- android:background="@color/transparent"
+ android:background="@android:color/transparent"
android:layout_alignParentStart="true"
android:gravity="start"
android:scaleType="centerCrop"/>
@@ -61,6 +61,6 @@ installation screens
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</FrameLayout>
-
+
</RelativeLayout>
diff --git a/res/layout/grant_permissions.xml b/res/layout/grant_permissions.xml
index b3565240..086a541a 100644
--- a/res/layout/grant_permissions.xml
+++ b/res/layout/grant_permissions.xml
@@ -18,6 +18,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
+
<LinearLayout
android:id="@+id/dialog_container"
android:layout_width="fill_parent"
@@ -46,7 +47,7 @@
android:visibility="gone">
</CheckBox>
- <com.android.internal.widget.ButtonBarLayout
+ <com.android.packageinstaller.permission.ui.ButtonBarLayout
android:id="@+id/button_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -62,8 +63,8 @@
android:paddingBottom="4dp"
android:paddingEnd="12dp"
android:singleLine="true"
- style="@android:style/TextAppearance.Material.Body2"
- android:textColor="@color/grant_permissions_progress_color"
+ style="?android:attr/textAppearanceSmall"
+ android:textColor="?android:attr/textColorSecondary"
android:visibility="invisible">
</TextView>
@@ -72,14 +73,16 @@
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"
- android:visibility="invisible" />
+ android:visibility="invisible" >
+ </Space>
<Button
android:id="@+id/permission_deny_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="?android:attr/buttonBarButtonStyle"
- android:text="@string/grant_dialog_button_deny" />
+ android:text="@string/grant_dialog_button_deny" >
+ </Button>
<Button
android:id="@+id/permission_allow_button"
@@ -87,9 +90,11 @@
android:layout_height="wrap_content"
style="?android:attr/buttonBarButtonStyle"
android:layout_marginStart="8dip"
- android:text="@string/grant_dialog_button_allow" />
+ android:text="@string/grant_dialog_button_allow" >
+ </Button>
- </com.android.internal.widget.ButtonBarLayout>
+ </com.android.packageinstaller.permission.ui.ButtonBarLayout>
</LinearLayout>
+
</com.android.packageinstaller.permission.ui.ManualLayoutFrame>
diff --git a/res/layout/header.xml b/res/layout/header.xml
index 0e000a4d..f158e442 100644
--- a/res/layout/header.xml
+++ b/res/layout/header.xml
@@ -17,9 +17,8 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
- android:background="@drawable/header_background"
- android:gravity="center_vertical"
- android:theme="@style/Theme.Header.Settings" >
+ android:background="?android:attr/colorPrimary"
+ android:gravity="center_vertical" >
<ImageView android:id="@+id/icon"
android:layout_width="@dimen/header_subsettings_margin_start"
@@ -31,12 +30,11 @@
android:id="@+id/name"
android:layout_height="wrap_content"
android:layout_width="match_parent"
- android:layout_toStartOf="@+id/app_settings"
android:layout_marginStart="@dimen/header_subsettings_margin_start"
android:layout_alignWithParentIfMissing="true"
android:layout_centerVertical="true"
android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="@android:color/white"
+ android:textColor="?android:attr/textColorPrimaryInverse"
android:textAlignment="viewStart" />
<ImageView
@@ -52,11 +50,4 @@
android:src="@drawable/ic_info"
style="?android:attr/borderlessButtonStyle" />
- <View
- android:id="@+id/row_divider"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="?android:attr/listDivider" />
-
</RelativeLayout>
-
diff --git a/res/layout/install_confirm.xml b/res/layout/install_confirm.xml
index 86ea1652..72d5e377 100644
--- a/res/layout/install_confirm.xml
+++ b/res/layout/install_confirm.xml
@@ -31,9 +31,10 @@
android:id="@+id/install_confirm_question"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:paddingStart="16dip"
+ android:paddingEnd="16dip"
android:text="@string/install_confirm_question"
android:textAppearance="?android:attr/textAppearanceMedium"
- style="@style/padded"
android:paddingTop="4dip" />
<ImageView
diff --git a/res/layout/permission_description.xml b/res/layout/permission_description.xml
index 3f1cf434..c9b60d64 100644
--- a/res/layout/permission_description.xml
+++ b/res/layout/permission_description.xml
@@ -26,15 +26,14 @@
android:layout_height="36dip"
android:layout_marginTop="3dp"
android:tint="?android:attr/colorAccent"
- android:scaleType="fitCenter" />
+ android:scaleType="fitCenter" >
+ </ImageView>
<TextView
android:id="@+id/permission_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/permission_icon"
- android:lineSpacingMultiplier="1.024"
- android:fontFamily="@*android:string/font_family_body_2_material"
android:paddingStart="16dip"
android:paddingEnd="8dip"
style="?android:attr/textAppearanceMedium">
diff --git a/res/layout/permissions_frame.xml b/res/layout/permissions_frame.xml
index 8f1f2789..156af57e 100644
--- a/res/layout/permissions_frame.xml
+++ b/res/layout/permissions_frame.xml
@@ -30,8 +30,8 @@
android:layout_height="match_parent"
android:text="@string/no_permissions"
android:gravity="center"
- android:textAppearance="@android:style/TextAppearance.Large"
- />
+ style="?android:attr/textAppearanceLarge">
+ </TextView>
</FrameLayout>
diff --git a/res/layout/preference_permissions.xml b/res/layout/preference_permissions.xml
index 67b4469c..631d56bd 100644
--- a/res/layout/preference_permissions.xml
+++ b/res/layout/preference_permissions.xml
@@ -37,7 +37,7 @@
android:paddingEnd="20dp"
android:paddingTop="4dp"
android:paddingBottom="4dp">
- <com.android.internal.widget.PreferenceImageView
+ <com.android.packageinstaller.permission.ui.PreferenceImageView
android:id="@android:id/icon"
android:layout_width="24dp"
android:layout_height="24dp"
diff --git a/res/layout/preference_permissions_switch.xml b/res/layout/preference_permissions_switch.xml
index cf444d96..78d2a4ef 100644
--- a/res/layout/preference_permissions_switch.xml
+++ b/res/layout/preference_permissions_switch.xml
@@ -37,7 +37,7 @@
android:paddingEnd="20dp"
android:paddingTop="4dp"
android:paddingBottom="4dp">
- <com.android.internal.widget.PreferenceImageView
+ <com.android.packageinstaller.permission.ui.PreferenceImageView
android:id="@android:id/icon"
android:layout_width="36dp"
android:layout_height="36dp"
diff --git a/res/layout/uninstall_confirm.xml b/res/layout/uninstall_confirm.xml
index f604023f..78270f60 100644
--- a/res/layout/uninstall_confirm.xml
+++ b/res/layout/uninstall_confirm.xml
@@ -40,9 +40,10 @@
android:id="@+id/activity_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:paddingStart="16dip"
+ android:paddingEnd="16dip"
android:textColor="?android:attr/textColorSecondary"
android:textAppearance="?android:attr/textAppearanceMedium"
- style="@style/padded"
android:visibility="gone" />
<!-- The snippet (title & icon) about the application being uninstalled. -->
diff --git a/res/values-television/colors.xml b/res/values-television/colors.xml
index eb6bfa7d..08209600 100644
--- a/res/values-television/colors.xml
+++ b/res/values-television/colors.xml
@@ -15,6 +15,13 @@
-->
<resources>
+
+ <color name="lb_content_title_text_color">#FFF1F1F1</color>
+ <color name="lb_content_breadcrumb_text_color">#88F1F1F1</color>
+ <color name="lb_content_description_text_color">#88F1F1F1</color>
+ <color name="lb_action_fragment_background">#FF111111</color>
+ <color name="lb_dialog_activity_background">#77000000</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>
diff --git a/res/values-television/styles.xml b/res/values-television/styles.xml
new file mode 100644
index 00000000..5f712f7d
--- /dev/null
+++ b/res/values-television/styles.xml
@@ -0,0 +1,37 @@
+<?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/res/values/colors.xml b/res/values/colors.xml
deleted file mode 100755
index 549f55fd..00000000
--- a/res/values/colors.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<resources>
- <color name="shadow">#cc222222</color>
- <color name="transparent">#00000000</color>
- <color name="header_background_color">#ff37474f</color>
- <color name="grant_permissions_app_color">@*android:color/primary_text_default_material_light</color>
- <color name="grant_permissions_progress_color">#60000000</color>
-
- <color name="lb_content_title_text_color">#FFF1F1F1</color>
- <color name="lb_content_breadcrumb_text_color">#88F1F1F1</color>
- <color name="lb_content_description_text_color">#88F1F1F1</color>
- <color name="lb_action_fragment_background">#FF111111</color>
- <color name="lb_dialog_activity_background">#77000000</color>
-
-</resources>
-
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 9c166971..7f6a4693 100755
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -15,37 +15,22 @@
-->
<resources>
- <style name="padded">
- <item name="android:paddingStart">16dip</item>
- <item name="android:paddingEnd">16dip</item>
- </style>
- <style name="Theme.DialogWhenLarge" parent="@android:style/Theme.DeviceDefault.Light.DialogWhenLarge.NoActionBar"/>
- <style name="Theme.AlertDialogActivity" parent="@android:style/Theme.DeviceDefault.Light.Panel">
- <item name="android:backgroundDimEnabled">true</item>
- </style>
-
- <style name="Theme.Header.Settings" parent="@android:style/Theme.DeviceDefault.Settings">
- </style>
- <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 name="Theme.DialogWhenLarge"
+ parent="@android:style/Theme.DeviceDefault.Light.DialogWhenLarge.NoActionBar">
</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 name="Theme.AlertDialogActivity"
+ parent="@android:style/Theme.DeviceDefault.Light.Panel">
+ <item name="android:backgroundDimEnabled">true</item>
</style>
- <style name="Preference.SwitchPreference.Permissions">
- <item name="layout">@layout/preference_permissions_switch</item>
+ <style name="Theme.Header.Settings"
+ parent="@android:style/Theme.DeviceDefault.Settings">
</style>
<style name="ActionBar" parent="@android:style/Widget.Material.ActionBar.Solid">
<item name="android:contentInsetStart">72dp</item>
</style>
+
</resources>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 2f9c2b55..026c77fa 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -16,11 +16,13 @@
-->
<resources>
- <style name="Settings" parent="@android:style/Theme.DeviceDefault.Settings">
- <item name="android:actionBarStyle">@style/ActionBar</item>
- <item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Permissions</item>
+
+ <style name="Settings"
+ parent="@android:style/Theme.DeviceDefault.Settings">
</style>
<style name="GrantPermissions"
- parent="@android:style/Theme.DeviceDefault.Light.Dialog.NoActionBar" />
+ parent="@android:style/Theme.DeviceDefault.Light.Dialog.NoActionBar">
+ </style>
+
</resources>
diff --git a/src/com/android/packageinstaller/permission/model/PermissionApps.java b/src/com/android/packageinstaller/permission/model/PermissionApps.java
index 9365bf13..e5d96d55 100644
--- a/src/com/android/packageinstaller/permission/model/PermissionApps.java
+++ b/src/com/android/packageinstaller/permission/model/PermissionApps.java
@@ -31,6 +31,7 @@ import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;
+import com.android.packageinstaller.R;
import com.android.packageinstaller.permission.utils.Utils;
import java.util.ArrayList;
@@ -275,7 +276,7 @@ public class PermissionApps {
if (info.icon != 0) {
mIcon = info.loadUnbadgedIcon(mPm);
} else {
- mIcon = mContext.getDrawable(com.android.internal.R.drawable.ic_perm_device_info);
+ mIcon = mContext.getDrawable(R.drawable.ic_perm_device_info);
}
mIcon = Utils.applyTint(mContext, mIcon, android.R.attr.colorControlNormal);
}
diff --git a/src/com/android/packageinstaller/permission/ui/ButtonBarLayout.java b/src/com/android/packageinstaller/permission/ui/ButtonBarLayout.java
new file mode 100644
index 00000000..59e54707
--- /dev/null
+++ b/src/com/android/packageinstaller/permission/ui/ButtonBarLayout.java
@@ -0,0 +1,117 @@
+/*
+ * 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.RIGHT : Gravity.BOTTOM);
+
+ final View spacer = findViewById(R.id.spacer);
+ if (spacer != null) {
+ spacer.setVisibility(stacked ? View.GONE : View.INVISIBLE);
+ }
+
+ // Reverse the child order. This is specific to the Material button
+ // bar's layout XML and will probably not generalize.
+ final int childCount = getChildCount();
+ for (int i = childCount - 2; i >= 0; i--) {
+ bringChildToFront(getChildAt(i));
+ }
+ }
+
+ private boolean isStacked() {
+ return getOrientation() == LinearLayout.VERTICAL;
+ }
+}
diff --git a/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java b/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java
index aaa65f9e..44bbcc9c 100644
--- a/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java
+++ b/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java
@@ -26,11 +26,12 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PermissionInfo;
import android.content.res.Resources;
+import android.graphics.Typeface;
import android.graphics.drawable.Icon;
import android.hardware.camera2.utils.ArrayUtils;
import android.os.Bundle;
import android.text.SpannableString;
-import android.text.style.ForegroundColorSpan;
+import android.text.style.StyleSpan;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -72,9 +73,11 @@ public class GrantPermissionsActivity extends OverlayTouchActivity
setTitle(R.string.permission_request_title);
if (Utils.isTelevision(this)) {
- mViewHandler = new GrantPermissionsTvViewHandler(this).setResultListener(this);
+ mViewHandler = new com.android.packageinstaller.permission.ui.television
+ .GrantPermissionsViewHandlerImpl(this).setResultListener(this);
} else {
- mViewHandler = new GrantPermissionsDefaultViewHandler(this).setResultListener(this);
+ mViewHandler = new com.android.packageinstaller.permission.ui.handheld
+ .GrantPermissionsViewHandlerImpl(this).setResultListener(this);
}
mRequestedPermissions = getIntent().getStringArrayExtra(
@@ -190,8 +193,7 @@ public class GrantPermissionsActivity extends OverlayTouchActivity
// Color the app name.
int appLabelStart = message.toString().indexOf(appLabel.toString(), 0);
int appLabelLength = appLabel.length();
- int color = getColor(R.color.grant_permissions_app_color);
- message.setSpan(new ForegroundColorSpan(color), appLabelStart,
+ message.setSpan(new StyleSpan(Typeface.BOLD), appLabelStart,
appLabelStart + appLabelLength, 0);
// Set the new grant view
diff --git a/src/com/android/packageinstaller/permission/ui/GrantPermissionsViewHandler.java b/src/com/android/packageinstaller/permission/ui/GrantPermissionsViewHandler.java
index 4032abb2..5e2259af 100644
--- a/src/com/android/packageinstaller/permission/ui/GrantPermissionsViewHandler.java
+++ b/src/com/android/packageinstaller/permission/ui/GrantPermissionsViewHandler.java
@@ -25,7 +25,7 @@ import android.view.WindowManager;
* Class for managing the presentation and user interaction of the "grant
* permissions" user interface.
*/
-interface GrantPermissionsViewHandler {
+public interface GrantPermissionsViewHandler {
/**
* Listener interface for getting notified when the user responds to a
diff --git a/src/com/android/packageinstaller/permission/ui/ManagePermissionsActivity.java b/src/com/android/packageinstaller/permission/ui/ManagePermissionsActivity.java
index 8ba6b127..f5703564 100644
--- a/src/com/android/packageinstaller/permission/ui/ManagePermissionsActivity.java
+++ b/src/com/android/packageinstaller/permission/ui/ManagePermissionsActivity.java
@@ -20,6 +20,7 @@ import android.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
+import com.android.packageinstaller.permission.utils.Utils;
public final class ManagePermissionsActivity extends OverlayTouchActivity {
private static final String LOG_TAG = "ManagePermissionsActivity";
@@ -37,7 +38,13 @@ public final class ManagePermissionsActivity extends OverlayTouchActivity {
switch (action) {
case Intent.ACTION_MANAGE_PERMISSIONS: {
- fragment = ManagePermissionsFragment.newInstance();
+ if (Utils.isTelevision(this)) {
+ fragment = com.android.packageinstaller.permission.ui.television
+ .ManagePermissionsFragment.newInstance();
+ } else {
+ fragment = com.android.packageinstaller.permission.ui.handheld
+ .ManagePermissionsFragment.newInstance();
+ }
} break;
case Intent.ACTION_MANAGE_APP_PERMISSIONS: {
@@ -47,7 +54,13 @@ public final class ManagePermissionsActivity extends OverlayTouchActivity {
finish();
return;
}
- fragment = AppPermissionsFragment.newInstance(packageName);
+ if (Utils.isTelevision(this)) {
+ fragment = com.android.packageinstaller.permission.ui.television
+ .AppPermissionsFragment.newInstance(packageName);
+ } else {
+ fragment = com.android.packageinstaller.permission.ui.handheld
+ .AppPermissionsFragment.newInstance(packageName);
+ }
} break;
case Intent.ACTION_MANAGE_PERMISSION_APPS: {
@@ -57,7 +70,13 @@ public final class ManagePermissionsActivity extends OverlayTouchActivity {
finish();
return;
}
- fragment = PermissionAppsFragment.newInstance(permissionName);
+ if (Utils.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: {
diff --git a/src/com/android/packageinstaller/permission/ui/OverlayWarningDialog.java b/src/com/android/packageinstaller/permission/ui/OverlayWarningDialog.java
index a7c1e2a1..61734b47 100644
--- a/src/com/android/packageinstaller/permission/ui/OverlayWarningDialog.java
+++ b/src/com/android/packageinstaller/permission/ui/OverlayWarningDialog.java
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package com.android.packageinstaller.permission.ui;
import android.app.Activity;
diff --git a/src/com/android/packageinstaller/permission/ui/PreferenceImageView.java b/src/com/android/packageinstaller/permission/ui/PreferenceImageView.java
new file mode 100644
index 00000000..c3f51674
--- /dev/null
+++ b/src/com/android/packageinstaller/permission/ui/PreferenceImageView.java
@@ -0,0 +1,69 @@
+/*
+ * 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/src/com/android/packageinstaller/permission/ui/handheld/AllAppPermissionsFragment.java b/src/com/android/packageinstaller/permission/ui/handheld/AllAppPermissionsFragment.java
new file mode 100644
index 00000000..b3b0895c
--- /dev/null
+++ b/src/com/android/packageinstaller/permission/ui/handheld/AllAppPermissionsFragment.java
@@ -0,0 +1,214 @@
+/*
+* 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.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.Bundle;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.preference.PreferenceCategory;
+import android.preference.PreferenceGroup;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.MenuItem;
+import com.android.packageinstaller.R;
+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";
+
+ 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);
+ }
+ }
+
+ @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 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);
+ otherGroup.removeAll();
+ PackageManager pm = getContext().getPackageManager();
+
+ try {
+ PackageInfo info = pm.getPackageInfo(pkg, PackageManager.GET_PERMISSIONS);
+
+ ApplicationInfo appInfo = info.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", 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_HIDDEN) != 0) {
+ continue;
+ }
+
+ if (perm.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
+ PermissionGroupInfo group = getGroup(perm.group, pm);
+ PreferenceGroup pref =
+ findOrCreate(group != null ? group : perm, pm, prefs);
+ pref.addPreference(getPreference(perm, group, pm));
+ } else if (perm.protectionLevel == PermissionInfo.PROTECTION_NORMAL) {
+ PermissionGroupInfo group = getGroup(perm.group, pm);
+ otherGroup.addPreference(getPreference(perm, group, pm));
+ }
+ }
+ }
+ } 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(PermissionInfo perm, PermissionGroupInfo group,
+ PackageManager pm) {
+ Preference 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.loadLabel(pm));
+ final CharSequence desc = perm.loadDescription(pm);
+ pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ new AlertDialog.Builder(getContext())
+ .setMessage(desc)
+ .setPositiveButton(android.R.string.ok, null)
+ .show();
+ return true;
+ }
+ });
+
+ return pref;
+ }
+} \ No newline at end of file
diff --git a/src/com/android/packageinstaller/permission/ui/handheld/AppPermissionsFragment.java b/src/com/android/packageinstaller/permission/ui/handheld/AppPermissionsFragment.java
new file mode 100644
index 00000000..f56cba70
--- /dev/null
+++ b/src/com/android/packageinstaller/permission/ui/handheld/AppPermissionsFragment.java
@@ -0,0 +1,404 @@
+/*
+* 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.annotation.Nullable;
+import android.app.ActionBar;
+import android.app.Activity;
+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.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.OnPreferenceChangeListener;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.preference.PreferenceScreen;
+import android.preference.SwitchPreference;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+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.ui.OverlayTouchActivity;
+import com.android.packageinstaller.permission.utils.LocationUtils;
+import com.android.packageinstaller.permission.utils.SafetyNetLogger;
+import com.android.packageinstaller.permission.utils.Utils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+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 List<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, null, true, new Runnable() {
+ @Override
+ public void run() {
+ getActivity().finish();
+ }
+ });
+ loadPreferences();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mAppPermissions.refresh();
+ 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, @Nullable 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);
+
+ ActionBar ab = activity.getActionBar();
+ if (ab != null) {
+ ab.setTitle(R.string.app_permissions);
+ }
+
+ ViewGroup rootView = (ViewGroup) fragment.getView();
+ ImageView iconView = (ImageView) rootView.findViewById(R.id.lb_icon);
+ if (iconView != null) {
+ iconView.setImageDrawable(icon);
+ }
+ TextView titleView = (TextView) rootView.findViewById(R.id.lb_title);
+ if (titleView != null) {
+ titleView.setText(R.string.app_permissions);
+ }
+ TextView breadcrumbView = (TextView) rootView.findViewById(R.id.lb_breadcrumb);
+ if (breadcrumbView != null) {
+ breadcrumbView.setText(label);
+ }
+ }
+
+ private void loadPreferences() {
+ 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, mAppPermissions.getPackageInfo().packageName)) {
+ 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(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 boolean onPreferenceChange(final Preference preference, Object newValue) {
+ String groupName = preference.getKey();
+ final AppPermissionGroup group = mAppPermissions.getPermissionGroup(groupName);
+
+ if (group == null) {
+ return false;
+ }
+
+ OverlayTouchActivity activity = (OverlayTouchActivity) getActivity();
+ if (activity.isObscuredTouch()) {
+ activity.showOverlayDialog();
+ 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.hasRuntimePermission() && !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,
+ new OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int 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 ArrayList<>();
+ }
+ // Double toggle is back to initial state.
+ if (mToggledGroups.contains(group)) {
+ mToggledGroups.remove(group);
+ } else {
+ mToggledGroups.add(group);
+ }
+ }
+
+ private void logToggledGroups() {
+ if (mToggledGroups != null) {
+ String packageName = mAppPermissions.getPackageInfo().packageName;
+ SafetyNetLogger.logPermissionsToggled(packageName, 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);
+ setHeader(mOuterFragment.mIcon, mOuterFragment.mLabel, mOuterFragment.mInfoIntent);
+ setHasOptionsMenu(true);
+ setPreferenceScreen(mOuterFragment.mExtraScreen);
+ }
+
+ @Override
+ public void onViewCreated(View view, @Nullable 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/src/com/android/packageinstaller/permission/ui/GrantPermissionsDefaultViewHandler.java b/src/com/android/packageinstaller/permission/ui/handheld/GrantPermissionsViewHandlerImpl.java
index c5d78784..2d27f069 100644
--- a/src/com/android/packageinstaller/permission/ui/GrantPermissionsDefaultViewHandler.java
+++ b/src/com/android/packageinstaller/permission/ui/handheld/GrantPermissionsViewHandlerImpl.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.packageinstaller.permission.ui;
+package com.android.packageinstaller.permission.ui.handheld;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -40,12 +40,14 @@ import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
-import com.android.internal.widget.ButtonBarLayout;
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.ManualLayoutFrame;
import java.util.ArrayList;
-final class GrantPermissionsDefaultViewHandler
+public final class GrantPermissionsViewHandlerImpl
implements GrantPermissionsViewHandler, OnClickListener {
public static final String ARG_GROUP_NAME = "ARG_GROUP_NAME";
@@ -101,12 +103,12 @@ final class GrantPermissionsDefaultViewHandler
}
};
- GrantPermissionsDefaultViewHandler(Context context) {
+ public GrantPermissionsViewHandlerImpl(Context context) {
mContext = context;
}
@Override
- public GrantPermissionsDefaultViewHandler setResultListener(ResultListener listener) {
+ public GrantPermissionsViewHandlerImpl setResultListener(ResultListener listener) {
mResultListener = listener;
return this;
}
@@ -314,9 +316,7 @@ final class GrantPermissionsDefaultViewHandler
public View createView() {
mRootView = (ManualLayoutFrame) LayoutInflater.from(mContext)
.inflate(R.layout.grant_permissions, null);
- ((ButtonBarLayout) mRootView.findViewById(R.id.button_group)).setAllowStacking(
- Resources.getSystem().getBoolean(
- com.android.internal.R.bool.allow_stacked_button_bar));
+ ((ButtonBarLayout) mRootView.findViewById(R.id.button_group)).setAllowStacking(true);
mDialogContainer = (ViewGroup) mRootView.findViewById(R.id.dialog_container);
mMessageView = (TextView) mRootView.findViewById(R.id.permission_message);
diff --git a/src/com/android/packageinstaller/permission/ui/handheld/ManagePermissionsFragment.java b/src/com/android/packageinstaller/permission/ui/handheld/ManagePermissionsFragment.java
new file mode 100644
index 00000000..c53da879
--- /dev/null
+++ b/src/com/android/packageinstaller/permission/ui/handheld/ManagePermissionsFragment.java
@@ -0,0 +1,268 @@
+/*
+ * 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.annotation.Nullable;
+import android.app.ActionBar;
+import android.app.FragmentTransaction;
+import android.content.ActivityNotFoundException;
+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.util.ArraySet;
+import android.util.Log;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+import com.android.packageinstaller.R;
+import com.android.packageinstaller.permission.model.PermissionApps;
+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 PermissionsFrameFragment
+ implements PermissionGroups.PermissionsGroupsChangeCallback,
+ Preference.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(getActivity(), getLoaderManager(), this);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mPermissions.refresh();
+ updatePermissionsUi();
+ }
+
+ @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, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ bindPermissionUi(getActivity(), getView());
+ }
+
+ private static void bindPermissionUi(@Nullable Context context, @Nullable View rootView) {
+ if (context == null || rootView == null) {
+ return;
+ }
+
+ ImageView iconView = (ImageView) rootView.findViewById(R.id.lb_icon);
+ if (iconView != null) {
+ // Set the icon as the background instead of the image because ImageView
+ // doesn't properly scale vector drawables beyond their intrinsic size
+ Drawable icon = context.getDrawable(R.drawable.ic_lock);
+ icon.setTint(context.getColor(R.color.off_white));
+ iconView.setBackground(icon);
+ }
+ TextView titleView = (TextView) rootView.findViewById(R.id.lb_title);
+ if (titleView != null) {
+ titleView.setText(R.string.app_permissions);
+ }
+ TextView breadcrumbView = (TextView) rootView.findViewById(R.id.lb_breadcrumb);
+ if (breadcrumbView != null) {
+ breadcrumbView.setText(R.string.app_permissions_breadcrumb);
+ }
+ }
+
+ private void updatePermissionsUi() {
+ Context context = getActivity();
+ if (context == null) {
+ return;
+ }
+
+ List<PermissionGroup> groups = mPermissions.getGroups();
+ PreferenceScreen screen = getPreferenceScreen();
+ if (screen == null) {
+ screen = getPreferenceManager().createPreferenceScreen(getActivity());
+ setPreferenceScreen(screen);
+ }
+
+ // 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);
+ }
+ }
+ final Preference finalPref = preference;
+
+ new PermissionApps(getContext(), group.getName(), new PermissionApps.Callback() {
+ @Override
+ public void onPermissionsLoaded(PermissionApps permissionApps) {
+ if (getActivity() == null) {
+ return;
+ }
+ int granted = permissionApps.getGrantedCount(mLauncherPkgs);
+ int total = permissionApps.getTotalCount(mLauncherPkgs);
+ finalPref.setSummary(getString(R.string.app_permissions_group_summary,
+ granted, total));
+ }
+ }, cache).refresh(false);
+ }
+
+ 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 PermissionsFrameFragment {
+ @Override
+ public void onCreate(Bundle icicle) {
+ setLoading(true /* loading */, false /* animate */);
+ super.onCreate(icicle);
+ getActivity().setTitle(R.string.additional_permissions);
+ setHasOptionsMenu(true);
+
+ setPreferenceScreen(((ManagePermissionsFragment) getTargetFragment()).mExtraScreen);
+ setLoading(false /* loading */, true /* animate */);
+ }
+
+ @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, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ bindPermissionUi(getActivity(), getView());
+ }
+ }
+}
diff --git a/src/com/android/packageinstaller/permission/ui/handheld/PermissionAppsFragment.java b/src/com/android/packageinstaller/permission/ui/handheld/PermissionAppsFragment.java
new file mode 100644
index 00000000..554830a7
--- /dev/null
+++ b/src/com/android/packageinstaller/permission/ui/handheld/PermissionAppsFragment.java
@@ -0,0 +1,427 @@
+/*
+ * 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.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.preference.Preference;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.preference.PreferenceScreen;
+import android.preference.SwitchPreference;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+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.OverlayTouchActivity;
+import com.android.packageinstaller.permission.utils.LocationUtils;
+import com.android.packageinstaller.permission.utils.SafetyNetLogger;
+import com.android.packageinstaller.permission.utils.Utils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public final class PermissionAppsFragment extends PermissionsFrameFragment implements Callback,
+ Preference.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 ArrayMap<String, AppPermissionGroup> mToggledGroups;
+ private ArraySet<String> mLauncherPkgs;
+ private boolean mHasConfirmedRevoke;
+
+ private boolean mShowSystem;
+ private MenuItem mShowSystemMenu;
+ private MenuItem mHideSystemMenu;
+
+ private Callback mOnPermissionsLoadedListener;
+
+ @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);
+ }
+ mLauncherPkgs = Utils.getLauncherPackages(getContext());
+
+ String groupName = getArguments().getString(Intent.EXTRA_PERMISSION_NAME);
+ mPermissionApps = new PermissionApps(getActivity(), groupName, this);
+ mPermissionApps.refresh(true);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mPermissionApps.refresh(true);
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ 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
+ 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(fragment.getString(R.string.permission_title, label));
+ }
+
+ final ViewGroup rootView = (ViewGroup) fragment.getView();
+ final ImageView iconView = (ImageView) rootView.findViewById(R.id.lb_icon);
+ if (iconView != null) {
+ // Set the icon as the background instead of the image because ImageView
+ // doesn't properly scale vector drawables beyond their intrinsic size
+ iconView.setBackground(icon);
+ }
+ final TextView titleView = (TextView) rootView.findViewById(R.id.lb_title);
+ if (titleView != null) {
+ titleView.setText(label);
+ }
+ final TextView breadcrumbView = (TextView) rootView.findViewById(R.id.lb_breadcrumb);
+ if (breadcrumbView != null) {
+ breadcrumbView.setText(R.string.app_permissions);
+ }
+ }
+
+ private void setOnPermissionsLoadedListener(Callback callback) {
+ mOnPermissionsLoadedListener = callback;
+ }
+
+ @Override
+ public void onPermissionsLoaded(PermissionApps permissionApps) {
+ Context context = getActivity();
+
+ if (context == null) {
+ return;
+ }
+
+ boolean isTelevision = Utils.isTelevision(context);
+ PreferenceScreen screen = getPreferenceScreen();
+ if (screen == null) {
+ screen = getPreferenceManager().createPreferenceScreen(getActivity());
+ setPreferenceScreen(screen);
+ }
+
+ 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());
+ }
+ }
+
+ for (PermissionApp app : permissionApps.getApps()) {
+ if (!Utils.shouldShowPermission(app)) {
+ 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 && !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;
+ }
+
+ OverlayTouchActivity activity = (OverlayTouchActivity) getActivity();
+ if (activity.isObscuredTouch()) {
+ activity.showOverlayDialog();
+ return false;
+ }
+
+ addToggledGroup(app.getPackageName(), app.getPermissionGroup());
+
+ if (LocationUtils.isLocationGroupAndProvider(mPermissionApps.getGroupName(),
+ app.getPackageName())) {
+ LocationUtils.showLocationDialog(getContext(), app.getLabel());
+ return false;
+ }
+ if (newValue == Boolean.TRUE) {
+ app.grantRuntimePermissions();
+ } else {
+ final boolean grantedByDefault = app.hasGrantedByDefaultPermissions();
+ if (grantedByDefault || (!app.hasRuntimePermissions() && !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,
+ 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 onPause() {
+ super.onPause();
+ logToggledGroups();
+ }
+
+ private void addToggledGroup(String packageName, AppPermissionGroup group) {
+ if (mToggledGroups == null) {
+ mToggledGroups = new ArrayMap<>();
+ }
+ // Double toggle is back to initial state.
+ if (mToggledGroups.containsKey(packageName)) {
+ mToggledGroups.remove(packageName);
+ } else {
+ mToggledGroups.put(packageName, group);
+ }
+ }
+
+ private void logToggledGroups() {
+ if (mToggledGroups != null) {
+ final int groupCount = mToggledGroups.size();
+ for (int i = 0; i < groupCount; i++) {
+ String packageName = mToggledGroups.keyAt(i);
+ List<AppPermissionGroup> groups = new ArrayList<>();
+ groups.add(mToggledGroups.valueAt(i));
+ SafetyNetLogger.logPermissionsToggled(packageName, groups);
+ }
+ mToggledGroups = null;
+ }
+ }
+
+ 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/src/com/android/packageinstaller/permission/ui/handheld/PermissionsFrameFragment.java b/src/com/android/packageinstaller/permission/ui/handheld/PermissionsFrameFragment.java
new file mode 100644
index 00000000..e7f63b23
--- /dev/null
+++ b/src/com/android/packageinstaller/permission/ui/handheld/PermissionsFrameFragment.java
@@ -0,0 +1,121 @@
+/*
+ * 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/src/com/android/packageinstaller/permission/ui/SettingsWithHeader.java b/src/com/android/packageinstaller/permission/ui/handheld/SettingsWithHeader.java
index 7b58fed1..acb3c61e 100644
--- a/src/com/android/packageinstaller/permission/ui/SettingsWithHeader.java
+++ b/src/com/android/packageinstaller/permission/ui/handheld/SettingsWithHeader.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.packageinstaller.permission.ui;
+package com.android.packageinstaller.permission.ui.handheld;
import android.content.Intent;
import android.graphics.drawable.Drawable;
@@ -81,5 +81,4 @@ public abstract class SettingsWithHeader extends PermissionsFrameFragment
public void onClick(View v) {
getActivity().startActivity(mInfoIntent);
}
-
}
diff --git a/src/com/android/packageinstaller/permission/ui/AllAppPermissionsFragment.java b/src/com/android/packageinstaller/permission/ui/television/AllAppPermissionsFragment.java
index 2fb9a510..d4910128 100644
--- a/src/com/android/packageinstaller/permission/ui/AllAppPermissionsFragment.java
+++ b/src/com/android/packageinstaller/permission/ui/television/AllAppPermissionsFragment.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.packageinstaller.permission.ui;
+package com.android.packageinstaller.permission.ui.television;
import android.app.ActionBar;
import android.app.AlertDialog;
diff --git a/src/com/android/packageinstaller/permission/ui/AppPermissionsFragment.java b/src/com/android/packageinstaller/permission/ui/television/AppPermissionsFragment.java
index 6396c61e..42a2661c 100644
--- a/src/com/android/packageinstaller/permission/ui/AppPermissionsFragment.java
+++ b/src/com/android/packageinstaller/permission/ui/television/AppPermissionsFragment.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.packageinstaller.permission.ui;
+package com.android.packageinstaller.permission.ui.television;
import android.annotation.Nullable;
import android.app.ActionBar;
@@ -50,6 +50,7 @@ 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.ui.OverlayTouchActivity;
import com.android.packageinstaller.permission.utils.LocationUtils;
import com.android.packageinstaller.permission.utils.SafetyNetLogger;
import com.android.packageinstaller.permission.utils.Utils;
diff --git a/src/com/android/packageinstaller/permission/ui/GrantPermissionsTvViewHandler.java b/src/com/android/packageinstaller/permission/ui/television/GrantPermissionsViewHandlerImpl.java
index 0e979ab6..a2538821 100644
--- a/src/com/android/packageinstaller/permission/ui/GrantPermissionsTvViewHandler.java
+++ b/src/com/android/packageinstaller/permission/ui/television/GrantPermissionsViewHandlerImpl.java
@@ -1,4 +1,4 @@
-package com.android.packageinstaller.permission.ui;
+package com.android.packageinstaller.permission.ui.television;
import android.content.Context;
import android.graphics.PixelFormat;
@@ -15,11 +15,12 @@ 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.
*/
-final class GrantPermissionsTvViewHandler implements GrantPermissionsViewHandler, OnClickListener {
+public final class GrantPermissionsViewHandlerImpl implements GrantPermissionsViewHandler, OnClickListener {
private static final String ARG_GROUP_NAME = "ARG_GROUP_NAME";
@@ -37,12 +38,12 @@ final class GrantPermissionsTvViewHandler implements GrantPermissionsViewHandler
private Button mSoftDenyButton;
private Button mHardDenyButton;
- GrantPermissionsTvViewHandler(Context context) {
+ public GrantPermissionsViewHandlerImpl(Context context) {
mContext = context;
}
@Override
- public GrantPermissionsTvViewHandler setResultListener(ResultListener listener) {
+ public GrantPermissionsViewHandlerImpl setResultListener(ResultListener listener) {
mResultListener = listener;
return this;
}
diff --git a/src/com/android/packageinstaller/permission/ui/ManagePermissionsFragment.java b/src/com/android/packageinstaller/permission/ui/television/ManagePermissionsFragment.java
index e5e06e09..47301f48 100644
--- a/src/com/android/packageinstaller/permission/ui/ManagePermissionsFragment.java
+++ b/src/com/android/packageinstaller/permission/ui/television/ManagePermissionsFragment.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.packageinstaller.permission.ui;
+package com.android.packageinstaller.permission.ui.television;
import android.annotation.Nullable;
import android.app.ActionBar;
@@ -202,7 +202,7 @@ public final class ManagePermissionsFragment extends PermissionsFrameFragment
Preference extraScreenPreference = new Preference(context);
extraScreenPreference.setKey(EXTRA_PREFS_KEY);
extraScreenPreference.setIcon(Utils.applyTint(context,
- com.android.internal.R.drawable.ic_more_items,
+ R.drawable.ic_more_items,
android.R.attr.colorControlNormal));
extraScreenPreference.setTitle(R.string.additional_permissions);
extraScreenPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
diff --git a/src/com/android/packageinstaller/permission/ui/PermissionAppsFragment.java b/src/com/android/packageinstaller/permission/ui/television/PermissionAppsFragment.java
index 8dacd037..e41e05fb 100644
--- a/src/com/android/packageinstaller/permission/ui/PermissionAppsFragment.java
+++ b/src/com/android/packageinstaller/permission/ui/television/PermissionAppsFragment.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.packageinstaller.permission.ui;
+package com.android.packageinstaller.permission.ui.television;
import android.app.ActionBar;
import android.app.AlertDialog;
@@ -44,6 +44,7 @@ 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.OverlayTouchActivity;
import com.android.packageinstaller.permission.utils.LocationUtils;
import com.android.packageinstaller.permission.utils.SafetyNetLogger;
import com.android.packageinstaller.permission.utils.Utils;
diff --git a/src/com/android/packageinstaller/permission/ui/PermissionsFrameFragment.java b/src/com/android/packageinstaller/permission/ui/television/PermissionsFrameFragment.java
index 40058f6d..bc0e8457 100644
--- a/src/com/android/packageinstaller/permission/ui/PermissionsFrameFragment.java
+++ b/src/com/android/packageinstaller/permission/ui/television/PermissionsFrameFragment.java
@@ -1,4 +1,20 @@
-package com.android.packageinstaller.permission.ui;
+/*
+ * 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.annotation.Nullable;
import android.os.Bundle;
diff --git a/src/com/android/packageinstaller/permission/ui/television/SettingsWithHeader.java b/src/com/android/packageinstaller/permission/ui/television/SettingsWithHeader.java
new file mode 100644
index 00000000..c7f5cda3
--- /dev/null
+++ b/src/com/android/packageinstaller/permission/ui/television/SettingsWithHeader.java
@@ -0,0 +1,85 @@
+/*
+ * 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.R;
+import com.android.packageinstaller.permission.utils.Utils;
+
+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 (!Utils.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/src/com/android/packageinstaller/permission/utils/LocationUtils.java b/src/com/android/packageinstaller/permission/utils/LocationUtils.java
index 512fcf44..0296ae80 100644
--- a/src/com/android/packageinstaller/permission/utils/LocationUtils.java
+++ b/src/com/android/packageinstaller/permission/utils/LocationUtils.java
@@ -36,23 +36,9 @@ public class LocationUtils {
public static final String LOCATION_PERMISSION = Manifest.permission_group.LOCATION;
- public static ArrayList<String> getLocationProviders() {
- ArrayList<String> providers = new ArrayList<>();
- Resources res = Resources.getSystem();
- providers.add(res.getString(
- com.android.internal.R.string.config_networkLocationProviderPackageName));
-
- for (String provider :
- res.getStringArray(com.android.internal.R.array.config_locationProviderPackageNames)) {
- providers.add(provider);
- }
-
- return providers;
- }
-
public static void showLocationDialog(final Context context, CharSequence label) {
new AlertDialog.Builder(context)
- .setIcon(com.android.internal.R.drawable.ic_dialog_alert_material)
+ .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)
@@ -83,5 +69,4 @@ public class LocationUtils {
return false;
}
}
-
}