summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk8
-rw-r--r--res/drawable-watch-280dpi/ic_cc_cancel.pngbin0 -> 14774 bytes
-rw-r--r--res/drawable-watch-280dpi/ic_cc_checkmark.pngbin0 -> 14840 bytes
-rw-r--r--res/drawable-watch-hdpi/ic_cc_cancel.pngbin0 -> 678 bytes
-rw-r--r--res/drawable-watch-hdpi/ic_cc_checkmark.pngbin0 -> 760 bytes
-rw-r--r--res/drawable-watch-mdpi/ic_cc_cancel.pngbin0 -> 535 bytes
-rw-r--r--res/drawable-watch-mdpi/ic_cc_checkmark.pngbin0 -> 612 bytes
-rw-r--r--res/drawable-watch-xhdpi/ic_cc_cancel.pngbin0 -> 312 bytes
-rw-r--r--res/drawable-watch-xhdpi/ic_cc_checkmark.pngbin0 -> 421 bytes
-rw-r--r--res/drawable-watch/action_negative_bg.xml21
-rw-r--r--res/drawable-watch/action_positive_bg.xml21
-rw-r--r--res/drawable-watch/cancel_button.xml7
-rw-r--r--res/drawable-watch/confirm_button.xml7
-rw-r--r--res/layout-watch/grant_permissions.xml126
-rw-r--r--res/values-watch/colors.xml26
-rw-r--r--res/values-watch/dimens.xml28
-rw-r--r--res/values-watch/strings.xml29
-rw-r--r--res/values-watch/themes.xml46
-rw-r--r--src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java7
-rw-r--r--src/com/android/packageinstaller/permission/ui/GrantPermissionsWatchViewHandler.java159
-rw-r--r--src/com/android/packageinstaller/permission/ui/PermissionConfirmationViewHandler.java149
21 files changed, 630 insertions, 4 deletions
diff --git a/Android.mk b/Android.mk
index 5a53086e..9a7fcc42 100644
--- a/Android.mk
+++ b/Android.mk
@@ -9,12 +9,11 @@ LOCAL_SRC_FILES := \
LOCAL_STATIC_JAVA_LIBRARIES += \
android-support-v4 \
- android-support-v7-recyclerview \
android-support-v7-preference \
android-support-v7-appcompat \
android-support-v14-preference \
android-support-v17-preference-leanback \
- android-support-v17-leanback
+ android-support-v17-leanback \
LOCAL_RESOURCE_DIR := \
frameworks/support/v17/leanback/res \
@@ -22,11 +21,10 @@ LOCAL_RESOURCE_DIR := \
frameworks/support/v14/preference/res \
frameworks/support/v17/preference-leanback/res \
frameworks/support/v7/appcompat/res \
- frameworks/support/v7/recyclerview/res \
$(LOCAL_PATH)/res
LOCAL_AAPT_FLAGS := --auto-add-overlay \
- --extra-packages android.support.v17.leanback:android.support.v7.preference:android.support.v14.preference:android.support.v17.preference:android.support.v7.appcompat:android.support.v7.recyclerview
+ --extra-packages android.support.v17.leanback:android.support.v7.preference:android.support.v14.preference:android.support.v17.preference:android.support.v7.appcompat
LOCAL_PACKAGE_NAME := PackageInstaller
LOCAL_CERTIFICATE := platform
@@ -35,4 +33,6 @@ LOCAL_PRIVILEGED_MODULE := true
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
+include vendor/unbundled_google/libs/wearable/wearable-support.mk
+
include $(BUILD_PACKAGE)
diff --git a/res/drawable-watch-280dpi/ic_cc_cancel.png b/res/drawable-watch-280dpi/ic_cc_cancel.png
new file mode 100644
index 00000000..249b8697
--- /dev/null
+++ b/res/drawable-watch-280dpi/ic_cc_cancel.png
Binary files differ
diff --git a/res/drawable-watch-280dpi/ic_cc_checkmark.png b/res/drawable-watch-280dpi/ic_cc_checkmark.png
new file mode 100644
index 00000000..94db9ab0
--- /dev/null
+++ b/res/drawable-watch-280dpi/ic_cc_checkmark.png
Binary files differ
diff --git a/res/drawable-watch-hdpi/ic_cc_cancel.png b/res/drawable-watch-hdpi/ic_cc_cancel.png
new file mode 100644
index 00000000..a57893e1
--- /dev/null
+++ b/res/drawable-watch-hdpi/ic_cc_cancel.png
Binary files differ
diff --git a/res/drawable-watch-hdpi/ic_cc_checkmark.png b/res/drawable-watch-hdpi/ic_cc_checkmark.png
new file mode 100644
index 00000000..29f9ecd9
--- /dev/null
+++ b/res/drawable-watch-hdpi/ic_cc_checkmark.png
Binary files differ
diff --git a/res/drawable-watch-mdpi/ic_cc_cancel.png b/res/drawable-watch-mdpi/ic_cc_cancel.png
new file mode 100644
index 00000000..87fc65ab
--- /dev/null
+++ b/res/drawable-watch-mdpi/ic_cc_cancel.png
Binary files differ
diff --git a/res/drawable-watch-mdpi/ic_cc_checkmark.png b/res/drawable-watch-mdpi/ic_cc_checkmark.png
new file mode 100644
index 00000000..0989daa6
--- /dev/null
+++ b/res/drawable-watch-mdpi/ic_cc_checkmark.png
Binary files differ
diff --git a/res/drawable-watch-xhdpi/ic_cc_cancel.png b/res/drawable-watch-xhdpi/ic_cc_cancel.png
new file mode 100644
index 00000000..fec6ecb8
--- /dev/null
+++ b/res/drawable-watch-xhdpi/ic_cc_cancel.png
Binary files differ
diff --git a/res/drawable-watch-xhdpi/ic_cc_checkmark.png b/res/drawable-watch-xhdpi/ic_cc_checkmark.png
new file mode 100644
index 00000000..f98cc1ec
--- /dev/null
+++ b/res/drawable-watch-xhdpi/ic_cc_checkmark.png
Binary files differ
diff --git a/res/drawable-watch/action_negative_bg.xml b/res/drawable-watch/action_negative_bg.xml
new file mode 100644
index 00000000..f1c33b54
--- /dev/null
+++ b/res/drawable-watch/action_negative_bg.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false">
+ <shape android:shape="oval">
+ <solid android:color="@color/circular_button_disabled"/>
+ <size android:width="40dp" android:height="40dp" />
+ </shape>
+ </item>
+ <item android:state_pressed="true">
+ <shape android:shape="oval">
+ <solid android:color="#757575"/>
+ <size android:width="40dp" android:height="40dp" />
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="oval">
+ <solid android:color="#BDBDBD"/>
+ <size android:width="40dp" android:height="40dp" />
+ </shape>
+ </item>
+</selector>
diff --git a/res/drawable-watch/action_positive_bg.xml b/res/drawable-watch/action_positive_bg.xml
new file mode 100644
index 00000000..bc3e88ba
--- /dev/null
+++ b/res/drawable-watch/action_positive_bg.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false">
+ <shape android:shape="oval">
+ <solid android:color="@color/circular_button_disabled"/>
+ <size android:width="40dp" android:height="40dp" />
+ </shape>
+ </item>
+ <item android:state_pressed="true">
+ <shape android:shape="oval">
+ <solid android:color="#009688"/>
+ <size android:width="40dp" android:height="40dp" />
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="oval">
+ <solid android:color="#00BFA5"/>
+ <size android:width="40dp" android:height="40dp" />
+ </shape>
+ </item>
+</selector>
diff --git a/res/drawable-watch/cancel_button.xml b/res/drawable-watch/cancel_button.xml
new file mode 100644
index 00000000..5b16f549
--- /dev/null
+++ b/res/drawable-watch/cancel_button.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item android:drawable="@drawable/action_negative_bg" />
+ <item>
+ <bitmap android:src="@drawable/ic_cc_cancel" android:gravity="center" />
+ </item>
+</layer-list>
diff --git a/res/drawable-watch/confirm_button.xml b/res/drawable-watch/confirm_button.xml
new file mode 100644
index 00000000..6a895ec6
--- /dev/null
+++ b/res/drawable-watch/confirm_button.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item android:drawable="@drawable/action_positive_bg" />
+ <item>
+ <bitmap android:src="@drawable/ic_cc_checkmark" android:gravity="center" />
+ </item>
+</layer-list>
diff --git a/res/layout-watch/grant_permissions.xml b/res/layout-watch/grant_permissions.xml
new file mode 100644
index 00000000..80ed5b92
--- /dev/null
+++ b/res/layout-watch/grant_permissions.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/confirmation"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ >
+
+ <ScrollView
+ android:id="@+id/scrolling_container"
+ android:overScrollMode="never"
+ android:scrollbars="none"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:id="@+id/content"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:id="@+id/current_page_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_marginBottom="@dimen/grant_permissions_app_breadcrumb_margin_bottom"
+ android:textAppearance="@style/GrantPermissions.BreadcrumbText" />
+
+ <ImageView
+ android:id="@+id/icon"
+ android:layout_width="@dimen/grant_permissions_app_icon_size"
+ android:layout_height="@dimen/grant_permissions_app_icon_size"
+ android:tint="@color/grant_permissions_app_color"
+ android:layout_gravity="center"
+ android:layout_marginTop="@dimen/grant_permissions_app_icon_margin_top"/>
+
+ <TextView
+ android:id="@+id/message"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:textSize="20sp"
+ android:gravity="center"
+ android:fontFamily="sans-serif-condensed-light"
+ android:textAppearance="@style/GrantPermissions.TitleText"/>
+
+ <!-- TODO: Change this to use a ViewStub instead of show/hiding the two layouts -->
+ <FrameLayout android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/button_bar_container"
+ android:layout_gravity="bottom"
+ android:background="#FF606060">
+ <android.support.wearable.view.WearableFrameLayout
+ android:id="@+id/horizontal_button_bar"
+ android:layout_width="match_parent"
+ android:layout_height="72dp"
+ app:layout_heightRound="96dp">
+ <Button
+ android:id="@+id/horizontal_deny_button"
+ android:layout_width="54dp"
+ android:layout_height="54dp"
+ android:layout_gravity="top|left"
+ android:layout_marginLeft="16dp"
+ android:layout_marginTop="9dp"
+ app:layout_marginLeftRound="36dp"
+ app:layout_marginTopRound="12dp"
+ android:background="@drawable/cancel_button"/>
+
+ <Button
+ android:id="@+id/horizontal_allow_button"
+ android:layout_width="54dp"
+ android:layout_height="54dp"
+ android:layout_gravity="top|right"
+ android:layout_marginRight="16dp"
+ android:layout_marginTop="9dp"
+ app:layout_marginRightRound="36dp"
+ app:layout_marginTopRound="12dp"
+ android:background="@drawable/confirm_button"/>
+ </android.support.wearable.view.WearableFrameLayout>
+
+ <android.support.wearable.view.WearableFrameLayout
+ android:id="@+id/vertical_button_bar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:visibility="gone">
+ <LinearLayout
+ android:id="@+id/buttonPanel"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ <Button
+ android:id="@+id/vertical_allow_button"
+ style="@style/Widget.WearDiag.Button"/>
+
+ <Button
+ android:id="@+id/vertical_deny_button"
+ style="@style/Widget.WearDiag.Button"/>
+
+ <Button
+ android:id="@+id/vertical_deny_do_not_ask_again_button"
+ style="@style/Widget.WearDiag.Button"/>
+ </LinearLayout>
+ </android.support.wearable.view.WearableFrameLayout>
+ </FrameLayout>
+ </LinearLayout>
+ </ScrollView>
+</FrameLayout> \ No newline at end of file
diff --git a/res/values-watch/colors.xml b/res/values-watch/colors.xml
new file mode 100644
index 00000000..614e8f14
--- /dev/null
+++ b/res/values-watch/colors.xml
@@ -0,0 +1,26 @@
+<?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>
+ <color name="grant_permissions_app_color">@color/grant_permissions_white_text_alpha_100</color>
+ <color name="grant_permissions_progress_color">@color/grant_permissions_white_text_alpha_100</color>
+ <color name="grant_permissions_title_color">@color/grant_permissions_white_text_alpha_70</color>
+
+ <color name="grant_permissions_white_text_alpha_100">@color/off_white</color>
+ <color name="grant_permissions_white_text_alpha_70">#b2eeeeee</color>
+
+ <color name="off_white">#ffeeeeee</color>
+</resources>
diff --git a/res/values-watch/dimens.xml b/res/values-watch/dimens.xml
new file mode 100644
index 00000000..29a65fdc
--- /dev/null
+++ b/res/values-watch/dimens.xml
@@ -0,0 +1,28 @@
+<?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>
+ <dimen name="grant_permissions_app_icon_size">32dp</dimen>
+ <dimen name="grant_permissions_app_icon_margin_top">8dp</dimen>
+
+ <dimen name="grant_permissions_app_breadcrumb_margin_bottom">3dp</dimen>
+
+ <dimen name="action_dialog_z">16dp</dimen>
+
+ <!-- Confirmation Dialog -->
+ <dimen name="conf_diag_floating_height">16dp</dimen>
+
+</resources>
diff --git a/res/values-watch/strings.xml b/res/values-watch/strings.xml
new file mode 100644
index 00000000..3ec72e5e
--- /dev/null
+++ b/res/values-watch/strings.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.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Title for the dialog button to deny a permission grant and never ask the user again. -->
+ <string name="grant_dialog_button_deny_dont_ask_again">Deny and don\'t ask again</string>
+
+ <!-- Template for the current permission from the total number of permissions. -->
+ <string name="current_permission_template">
+ <xliff:g id="current_permission_index" example="1">%1$s</xliff:g>
+ <xliff:g id="permission_count" example="2">%2$s</xliff:g>
+ </string>
+
+ <!-- Preference row title for showing system apps. -->
+ <string name="preference_show_system_apps">Show system apps</string>
+</resources>
diff --git a/res/values-watch/themes.xml b/res/values-watch/themes.xml
new file mode 100644
index 00000000..fd49185f
--- /dev/null
+++ b/res/values-watch/themes.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<resources>
+ <style name="Settings" parent="Theme.Leanback">
+ <item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Permissions</item>
+ </style>
+
+ <style name="GrantPermissions" parent="Theme.Leanback">
+ <item name="android:windowIsFloating">true</item>
+ <item name="android:windowAnimationStyle">@style/Animation.Snackbar</item>
+ <item name="android:windowElevation">@dimen/action_dialog_z</item>
+ </style>
+
+ <style name="GrantPermissions.BreadcrumbText">
+ <item name="android:fontFamily">sans-serif-condensed</item>
+ <item name="android:textSize">14sp</item>
+ <item name="android:textColor">@color/grant_permissions_progress_color</item>
+ </style>
+
+ <style name="GrantPermissions.TitleText">
+ <item name="android:fontFamily">sans-serif-light</item>
+ <item name="android:textSize">18sp</item>
+ <item name="android:textColor">@color/grant_permissions_title_color</item>
+ <item name="android:lineSpacingMultiplier">1.221</item>
+ </style>
+
+ <style name="Animation.Snackbar" parent="@android:style/Animation">
+ <item name="android:windowEnterAnimation">@anim/snackbar_enter</item>
+ <item name="android:windowExitAnimation">@anim/snackbar_exit</item>
+ </style>
+</resources>
diff --git a/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java b/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java
index c451dd50..c55267e0 100644
--- a/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java
+++ b/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java
@@ -73,6 +73,8 @@ public class GrantPermissionsActivity extends OverlayTouchActivity
if (Utils.isTelevision(this)) {
mViewHandler = new GrantPermissionsTvViewHandler(this).setResultListener(this);
+ } else if (isWatch()) {
+ mViewHandler = new GrantPermissionsWatchViewHandler(this).setResultListener(this);
} else {
mViewHandler = new GrantPermissionsDefaultViewHandler(this).setResultListener(this);
}
@@ -357,6 +359,11 @@ public class GrantPermissionsActivity extends OverlayTouchActivity
SafetyNetLogger.logPermissionsRequested(mAppPermissions.getPackageInfo(), groups);
}
+ private boolean isWatch() {
+ PackageManager pm = getPackageManager();
+ return pm.hasSystemFeature(pm.FEATURE_WATCH);
+ }
+
private static final class GroupState {
static final int STATE_UNKNOWN = 0;
static final int STATE_ALLOWED = 1;
diff --git a/src/com/android/packageinstaller/permission/ui/GrantPermissionsWatchViewHandler.java b/src/com/android/packageinstaller/permission/ui/GrantPermissionsWatchViewHandler.java
new file mode 100644
index 00000000..ac573c43
--- /dev/null
+++ b/src/com/android/packageinstaller/permission/ui/GrantPermissionsWatchViewHandler.java
@@ -0,0 +1,159 @@
+package com.android.packageinstaller.permission.ui;
+
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.Icon;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.view.WindowManager;
+
+import com.android.packageinstaller.R;
+
+/**
+ * Watch-specific view handler for the grant permissions activity.
+ */
+final class GrantPermissionsWatchViewHandler extends PermissionConfirmationViewHandler
+ implements GrantPermissionsViewHandler {
+ private static final String TAG = "GrantPermissionsViewH";
+
+ private static final String ARG_GROUP_NAME = "ARG_GROUP_NAME";
+
+ private final Context mContext;
+
+ private ResultListener mResultListener;
+
+ private String mGroupName;
+ private boolean mShowDoNotAsk;
+
+ private CharSequence mMessage;
+ private String mCurrentPageText;
+ private Icon mIcon;
+
+ GrantPermissionsWatchViewHandler(Context context) {
+ super(context);
+ mContext = context;
+ }
+
+ @Override
+ public GrantPermissionsWatchViewHandler setResultListener(ResultListener listener) {
+ mResultListener = listener;
+ return this;
+ }
+
+ @Override
+ public View createView() {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "createView()");
+ }
+
+ mShowDoNotAsk = false;
+
+ return super.createView();
+ }
+
+ @Override
+ public void updateWindowAttributes(WindowManager.LayoutParams outLayoutParams) {
+ outLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
+ outLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
+ outLayoutParams.format = PixelFormat.OPAQUE;
+ outLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
+ outLayoutParams.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
+ }
+
+ @Override
+ public void updateUi(String groupName, int groupCount, int groupIndex, Icon icon,
+ CharSequence message, boolean showDoNotAsk) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "updateUi() - groupName: " + groupName
+ + ", groupCount: " + groupCount
+ + ", groupIndex: " + groupIndex
+ + ", icon: " + icon
+ + ", message: " + message
+ + ", showDoNotAsk: " + showDoNotAsk);
+ }
+
+ mGroupName = groupName;
+ mShowDoNotAsk = showDoNotAsk;
+ mMessage = message;
+ mIcon = icon;
+ mCurrentPageText = (groupCount > 1 ?
+ mContext.getString(R.string.current_permission_template, groupIndex + 1, groupCount)
+ : null);
+
+ invalidate();
+ }
+
+ @Override
+ public void saveInstanceState(Bundle outState) {
+ outState.putString(ARG_GROUP_NAME, mGroupName);
+ }
+
+ @Override
+ public void loadInstanceState(Bundle savedInstanceState) {
+ mGroupName = savedInstanceState.getString(ARG_GROUP_NAME);
+ }
+
+ @Override
+ public void onBackPressed() {
+ if (mResultListener != null) {
+ mResultListener.onPermissionGrantResult(mGroupName, false, false);
+ }
+ }
+
+ @Override // PermissionConfirmationViewHandler
+ public void onAllow() {
+ onClick(true /* granted */, false /* doNotAskAgain */);
+ }
+
+ @Override // PermissionConfirmationViewHandler
+ public void onDeny() {
+ onClick(false /* granted */, false /* doNotAskAgain */);
+ }
+
+ @Override // PermissionConfirmationViewHandler
+ public void onDenyDoNotAskAgain() {
+ onClick(false /* granted */, true /* doNotAskAgain */);
+ }
+
+ @Override // PermissionConfirmationViewHandler
+ public CharSequence getCurrentPageText() {
+ return mCurrentPageText;
+ }
+
+ @Override // PermissionConfirmationViewHandler
+ public Icon getPermissionIcon() {
+ return mIcon;
+ }
+
+ @Override // PermissionConfirmationViewHandler
+ public CharSequence getMessage() {
+ return mMessage;
+ }
+
+ @Override // PermissionConfirmationViewHandler
+ public int getButtonBarMode() {
+ return mShowDoNotAsk ? MODE_VERTICAL_BUTTONS : MODE_HORIZONTAL_BUTTONS;
+ }
+
+ @Override // PermissionConfirmationViewHandler
+ public CharSequence getVerticalAllowText() {
+ return mContext.getString(R.string.grant_dialog_button_allow);
+ }
+
+ @Override // PermissionConfirmationViewHandler
+ public CharSequence getVerticalDenyText() {
+ return mContext.getString(R.string.grant_dialog_button_deny);
+ }
+
+ @Override // PermissionConfirmationViewHandler
+ public CharSequence getVerticalDenyDoNotAskAgainText() {
+ return mContext.getString(R.string.grant_dialog_button_deny_dont_ask_again);
+ }
+
+ private void onClick(boolean granted, boolean doNotAskAgain) {
+ if (mResultListener != null) {
+ mResultListener.onPermissionGrantResult(mGroupName, granted, doNotAskAgain);
+ }
+ }
+}
diff --git a/src/com/android/packageinstaller/permission/ui/PermissionConfirmationViewHandler.java b/src/com/android/packageinstaller/permission/ui/PermissionConfirmationViewHandler.java
new file mode 100644
index 00000000..63ed0a45
--- /dev/null
+++ b/src/com/android/packageinstaller/permission/ui/PermissionConfirmationViewHandler.java
@@ -0,0 +1,149 @@
+package com.android.packageinstaller.permission.ui;
+
+import android.content.Context;
+import android.graphics.drawable.Icon;
+import android.os.Handler;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.ScrollView;
+import android.widget.TextView;
+
+import com.android.packageinstaller.R;
+
+public abstract class PermissionConfirmationViewHandler implements
+ View.OnClickListener {
+ public static final int MODE_HORIZONTAL_BUTTONS = 0;
+ public static final int MODE_VERTICAL_BUTTONS = 1;
+
+ private View mRoot;
+ private TextView mCurrentPageText;
+ private ImageView mIcon;
+ private TextView mMessage;
+ private ScrollView mScrollingContainer;
+ private ViewGroup mContent;
+ private ViewGroup mHorizontalButtonBar;
+ private ViewGroup mVerticalButtonBar;
+ private Button mVerticalAllow;
+ private Button mVerticalDeny;
+ private Button mVerticalDenyDoNotAskAgain;
+ private View mButtonBarContainer;
+
+ private Context mContext;
+
+ // TODO: Move these into a builder
+ public abstract void onAllow();
+ public abstract void onDeny();
+ public abstract void onDenyDoNotAskAgain();
+ public abstract CharSequence getVerticalAllowText();
+ public abstract CharSequence getVerticalDenyText();
+ public abstract CharSequence getVerticalDenyDoNotAskAgainText();
+ public abstract CharSequence getCurrentPageText();
+ public abstract Icon getPermissionIcon();
+ public abstract CharSequence getMessage();
+
+ public PermissionConfirmationViewHandler(Context context) {
+ mContext = context;
+ }
+
+ public View createView() {
+ mRoot = LayoutInflater.from(mContext).inflate(R.layout.grant_permissions, null);
+
+ mMessage = (TextView) mRoot.findViewById(R.id.message);
+ mCurrentPageText = (TextView) mRoot.findViewById(R.id.current_page_text);
+ mIcon = (ImageView) mRoot.findViewById(R.id.icon);
+ mButtonBarContainer = mRoot.findViewById(R.id.button_bar_container);
+ mContent = (ViewGroup) mRoot.findViewById(R.id.content);
+ mScrollingContainer = (ScrollView) mRoot.findViewById(R.id.scrolling_container);
+ mHorizontalButtonBar = (ViewGroup) mRoot.findViewById(R.id.horizontal_button_bar);
+ mVerticalButtonBar = (ViewGroup) mRoot.findViewById(R.id.vertical_button_bar);
+
+ Button horizontalAllow = (Button) mRoot.findViewById(R.id.horizontal_allow_button);
+ Button horizontalDeny = (Button) mRoot.findViewById(R.id.horizontal_deny_button);
+ horizontalAllow.setOnClickListener(this);
+ horizontalDeny.setOnClickListener(this);
+
+ mVerticalAllow = (Button) mRoot.findViewById(R.id.vertical_allow_button);
+ mVerticalDeny = (Button) mRoot.findViewById(R.id.vertical_deny_button);
+ mVerticalDenyDoNotAskAgain =
+ (Button) mRoot.findViewById(R.id.vertical_deny_do_not_ask_again_button);
+ mVerticalAllow.setOnClickListener(this);
+ mVerticalDeny.setOnClickListener(this);
+ mVerticalDenyDoNotAskAgain.setOnClickListener(this);
+
+ return mRoot;
+ }
+
+ /**
+ * Child class should override this for other modes. Call invalidate() to update the UI to the
+ * new button mode.
+ * @return The current mode the layout should use for the buttons
+ */
+ public int getButtonBarMode() {
+ return MODE_HORIZONTAL_BUTTONS;
+ }
+
+ public void invalidate() {
+ CharSequence currentPageText = getCurrentPageText();
+ if (!TextUtils.isEmpty(currentPageText)) {
+ mCurrentPageText.setText(currentPageText);
+ mCurrentPageText.setVisibility(View.VISIBLE);
+ } else {
+ mCurrentPageText.setVisibility(View.INVISIBLE);
+ }
+
+ Icon icon = getPermissionIcon();
+ if (icon != null) {
+ mIcon.setImageIcon(icon);
+ mIcon.setVisibility(View.VISIBLE);
+ } else {
+ mIcon.setVisibility(View.INVISIBLE);
+ }
+
+ mMessage.setText(getMessage());
+
+ switch (getButtonBarMode()) {
+ case MODE_HORIZONTAL_BUTTONS:
+ mHorizontalButtonBar.setVisibility(View.VISIBLE);
+ mVerticalButtonBar.setVisibility(View.GONE);
+ break;
+ case MODE_VERTICAL_BUTTONS:
+ mHorizontalButtonBar.setVisibility(View.GONE);
+ mVerticalButtonBar.setVisibility(View.VISIBLE);
+ mVerticalAllow.setText(getVerticalAllowText());
+ mVerticalDeny.setText(getVerticalDenyText());
+ mVerticalDenyDoNotAskAgain.setText(getVerticalDenyDoNotAskAgainText());
+
+ mVerticalAllow.setCompoundDrawablesWithIntrinsicBounds(
+ mContext.getDrawable(R.drawable.confirm_button), null, null, null);
+ mVerticalDeny.setCompoundDrawablesWithIntrinsicBounds(
+ mContext.getDrawable(R.drawable.cancel_button), null, null, null);
+ mVerticalDenyDoNotAskAgain.setCompoundDrawablesWithIntrinsicBounds(
+ mContext.getDrawable(R.drawable.cancel_button), null, null, null);
+ break;
+ }
+
+ mScrollingContainer.scrollTo(0, 0);
+ }
+
+ @Override
+ public void onClick(View v) {
+ int id = v.getId();
+ switch (id) {
+ case R.id.horizontal_allow_button:
+ case R.id.vertical_allow_button:
+ onAllow();
+ break;
+ case R.id.horizontal_deny_button:
+ case R.id.vertical_deny_button:
+ onDeny();
+ break;
+ case R.id.vertical_deny_do_not_ask_again_button:
+ onDenyDoNotAskAgain();
+ break;
+ }
+ }
+}