blob: 1585c916dac3a13a42928f858b73f4ea2890d348 [file] [log] [blame]
/*
* 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.permissioncontroller.permission.ui.wear;
import static com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.DENY_AND_DONT_ASK_AGAIN_BUTTON;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.TypedArray;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.TextAppearanceSpan;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Space;
import androidx.wear.ble.view.AcceptDenyDialog;
import androidx.wear.ble.view.WearableDialogHelper;
import com.android.permissioncontroller.R;
import com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler;
/**
* Watch-specific view handler for the grant permissions activity.
*/
public final class GrantPermissionsWearViewHandler implements GrantPermissionsViewHandler,
DialogInterface.OnClickListener {
private static final String TAG = "GrantPermsWatchViewH";
private static final String WATCH_HANDLER_BUNDLE = "watch_handler_bundle";
private static final String DIALOG_BUNDLE = "dialog_bundle";
private static final String GROUP_NAME = "group_name";
private static final String SHOW_DO_NOT_ASK = "show_do_not_ask";
private static final String ICON = "icon";
private static final String MESSAGE = "message";
private static final String CURRENT_PAGE_TEXT = "current_page_text";
private final Context mContext;
private ResultListener mResultListener;
private Dialog mDialog;
private String mGroupName;
private boolean mShowDoNotAsk;
private CharSequence mMessage;
private String mCurrentPageText;
private Icon mIcon;
public GrantPermissionsWearViewHandler(Context context) {
mContext = context;
}
@Override
public GrantPermissionsWearViewHandler setResultListener(ResultListener listener) {
mResultListener = listener;
return this;
}
@Override
public View createView() {
return new Space(mContext);
}
@Override
public void updateWindowAttributes(WindowManager.LayoutParams outLayoutParams) {
outLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
outLayoutParams.height = WindowManager.LayoutParams.MATCH_PARENT;
outLayoutParams.format = PixelFormat.OPAQUE;
outLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
outLayoutParams.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
}
@Override
public void updateUi(String groupName, int groupCount, int groupIndex, Icon icon,
CharSequence message, CharSequence detailMessage, boolean[] buttonVisibilities) {
// TODO: Handle detailMessage
boolean showDoNotAsk = buttonVisibilities[DENY_AND_DONT_ASK_AGAIN_BUTTON];
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "updateUi() - groupName: " + groupName
+ ", groupCount: " + groupCount
+ ", groupIndex: " + groupIndex
+ ", icon: " + icon
+ ", message: " + message
+ ", showDoNotAsk: " + showDoNotAsk);
}
mGroupName = groupName;
mShowDoNotAsk = showDoNotAsk;
mMessage = message;
mIcon = icon;
mCurrentPageText = groupCount > 1
? mContext.getString(R.string.current_permission_template,
groupIndex + 1, groupCount)
: null;
showDialog(null);
}
private void showDialog(Bundle savedInstanceState) {
TypedArray a = mContext.obtainStyledAttributes(
new int[] { android.R.attr.textColorPrimary });
int color = a.getColor(0, mContext.getColor(android.R.color.white));
a.recycle();
Drawable drawable = mIcon == null ? null : mIcon.setTint(color).loadDrawable(mContext);
SpannableStringBuilder ssb = new SpannableStringBuilder();
if (!TextUtils.isEmpty(mCurrentPageText)) {
ssb.append(mCurrentPageText, new TextAppearanceSpan(mContext, R.style.BreadcrumbText),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.append('\n');
}
if (!TextUtils.isEmpty(mMessage)) {
ssb.append(mMessage, new TextAppearanceSpan(mContext, R.style.TitleText),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
if (mDialog != null) {
mDialog.dismiss();
mDialog = null;
}
if (mShowDoNotAsk) {
AlertDialog alertDialog = new WearableDialogHelper.DialogBuilder(mContext)
.setPositiveIcon(R.drawable.confirm_button)
.setNeutralIcon(R.drawable.cancel_button)
.setNegativeIcon(R.drawable.deny_button)
.setTitle(ssb)
.setIcon(drawable)
.setPositiveButton(R.string.grant_dialog_button_allow, this)
.setNeutralButton(R.string.grant_dialog_button_deny, this)
.setNegativeButton(R.string.grant_dialog_button_deny_dont_ask_again, this)
.show();
alertDialog.getButton(DialogInterface.BUTTON_POSITIVE)
.setId(R.id.permission_allow_button);
alertDialog.getButton(DialogInterface.BUTTON_NEUTRAL)
.setId(R.id.permission_deny_button);
alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE)
.setId(R.id.permission_deny_dont_ask_again_button);
mDialog = alertDialog;
} else {
AcceptDenyDialog acceptDenyDialog = new AcceptDenyDialog(mContext);
acceptDenyDialog.setTitle(ssb);
acceptDenyDialog.setIcon(drawable);
acceptDenyDialog.setPositiveButton(this);
acceptDenyDialog.setNegativeButton(this);
acceptDenyDialog.show();
acceptDenyDialog.getButton(DialogInterface.BUTTON_POSITIVE)
.setId(R.id.permission_allow_button);
acceptDenyDialog.getButton(DialogInterface.BUTTON_NEGATIVE)
.setId(R.id.permission_deny_button);
mDialog = acceptDenyDialog;
}
mDialog.setCancelable(false);
if (savedInstanceState != null) {
mDialog.onRestoreInstanceState(savedInstanceState);
}
}
@Override
public void saveInstanceState(Bundle outState) {
Bundle b = new Bundle();
b.putByte(SHOW_DO_NOT_ASK, (byte) (mShowDoNotAsk ? 1 : 0));
b.putString(GROUP_NAME, mGroupName);
b.putBundle(DIALOG_BUNDLE, mDialog.onSaveInstanceState());
outState.putBundle(WATCH_HANDLER_BUNDLE, b);
}
@Override
public void loadInstanceState(Bundle savedInstanceState) {
Bundle b = savedInstanceState.getBundle(WATCH_HANDLER_BUNDLE);
mShowDoNotAsk = b.getByte(SHOW_DO_NOT_ASK) == 1;
mGroupName = b.getString(GROUP_NAME);
showDialog(b.getBundle(DIALOG_BUNDLE));
}
@Override
public void onBackPressed() {
notifyListener(DENIED);
}
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
notifyListener(GRANTED_ALWAYS);
break;
case DialogInterface.BUTTON_NEUTRAL:
notifyListener(DENIED);
break;
case DialogInterface.BUTTON_NEGATIVE:
/* In AlertDialog, the negative button is also a don't ask again button. */
if (dialog instanceof AlertDialog) {
notifyListener(DENIED_DO_NOT_ASK_AGAIN);
} else {
notifyListener(DENIED);
}
break;
}
}
private void notifyListener(@Result int result) {
if (mResultListener != null) {
mResultListener.onPermissionGrantResult(mGroupName, result);
}
}
}