Commit 9478120a authored by Anthony Hugh's avatar Anthony Hugh
Browse files

Implement base version of GrantPermissions dialog

With the Emerald release, we need to support the new
permission APIs.  This changelist adds a dialog
for the Activity.requestPermissions() API so that
users can request permissions.

This check in is a functional version, but not polished.
will need to be a follow up CL to add the correct
animations and update the UI to the appropriate redlines.

The implementation for the confirmation dialog is modeled
after the one in the clockwork libs/Views folder.  There
are some tweaks to match the designed behavior of the
permission dialog.  When there's more time in the future,
we should try to condense this to one implementation.

This is a resubmit without the wearable-support lib.
I will figure out how to get that referenced in the next
UI pass.

BUG: 23118402
Change-Id: Ib2fb94b356aa965b999b3e12726fda86928a963e
parent 24938647
......@@ -14,7 +14,7 @@ LOCAL_STATIC_JAVA_LIBRARIES += \
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 \
......
res/drawable-watch-280dpi/ic_cc_cancel.png

14.4 KB

res/drawable-watch-280dpi/ic_cc_checkmark.png

14.5 KB

res/drawable-watch-hdpi/ic_cc_cancel.png

678 Bytes

res/drawable-watch-hdpi/ic_cc_checkmark.png

760 Bytes

res/drawable-watch-mdpi/ic_cc_cancel.png

535 Bytes

res/drawable-watch-mdpi/ic_cc_checkmark.png

612 Bytes

res/drawable-watch-xhdpi/ic_cc_cancel.png

312 Bytes

res/drawable-watch-xhdpi/ic_cc_checkmark.png

421 Bytes

<?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>
<?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>
<?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>
<?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>
<?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">
<FrameLayout
android:id="@+id/horizontal_button_bar"
android:layout_width="match_parent"
android:layout_height="72dp">
<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"
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"
android:background="@drawable/confirm_button"/>
</FrameLayout>
<FrameLayout
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>
</FrameLayout>
</FrameLayout>
</LinearLayout>
</ScrollView>
</FrameLayout>
\ No newline at end of file
<?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>
<!-- Copied from wearable support -->
<color name="circular_button_disabled">#757575</color>
</resources>
<?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>
<?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>
<?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>
<!-- Copied from WearableSupport lib -->
<style name="TextAppearance.WearDiag" parent="android:TextAppearance.Medium">
<item name="android:textColor">#FFFFFF</item>
<item name="android:textSize">16sp</item>
</style>
<style name="TextAppearance.WearDiag.Button">
<item name="android:textSize">16sp</item>
</style>
<style name="Widget.WearDiag.Button" parent="@android:style/Widget.DeviceDefault.Button">
<item name="android:fontFamily">sans-serif-condensed-light</item>
<item name="android:gravity">center_vertical|left</item>
<item name="android:textAppearance">@style/TextAppearance.WearDiag.Button</item>
<item name="android:background">@android:color/transparent</item>
<item name="android:minLines">1</item>
<item name="android:maxLines">3</item>
<item name="android:ellipsize">marquee</item>
<item name="android:layout_height">60dp</item>
<item name="android:layout_width">match_parent</item>
<item name="android:drawablePadding">12dp</item>
</style>
</resources>
......@@ -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);
}
......@@ -368,6 +370,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;
......
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);
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment