• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.android.packageinstaller.permission.ui;
2 
3 import static com.android.packageinstaller.permission.ui.GrantPermissionsActivity.LABEL_DENY_AND_DONT_ASK_AGAIN_BUTTON;
4 
5 import android.app.AlertDialog;
6 import android.app.Dialog;
7 import android.content.Context;
8 import android.content.DialogInterface;
9 import android.content.res.TypedArray;
10 import android.graphics.PixelFormat;
11 import android.graphics.drawable.Drawable;
12 import android.graphics.drawable.Icon;
13 import android.os.Bundle;
14 import android.text.SpannableStringBuilder;
15 import android.text.Spanned;
16 import android.text.TextUtils;
17 import android.text.style.TextAppearanceSpan;
18 import android.util.Log;
19 import android.view.View;
20 import android.view.WindowManager;
21 import android.widget.Space;
22 
23 import androidx.wear.ble.view.AcceptDenyDialog;
24 import androidx.wear.ble.view.WearableDialogHelper;
25 
26 import com.android.permissioncontroller.R;
27 
28 /**
29  * Watch-specific view handler for the grant permissions activity.
30  */
31 final class GrantPermissionsWatchViewHandler implements GrantPermissionsViewHandler,
32         DialogInterface.OnClickListener {
33     private static final String TAG = "GrantPermsWatchViewH";
34 
35     private static final String WATCH_HANDLER_BUNDLE = "watch_handler_bundle";
36     private static final String DIALOG_BUNDLE = "dialog_bundle";
37     private static final String GROUP_NAME = "group_name";
38     private static final String SHOW_DO_NOT_ASK = "show_do_not_ask";
39     private static final String ICON = "icon";
40     private static final String MESSAGE = "message";
41     private static final String CURRENT_PAGE_TEXT = "current_page_text";
42 
43     private final Context mContext;
44 
45     private ResultListener mResultListener;
46 
47     private Dialog mDialog;
48 
49     private String mGroupName;
50     private boolean mShowDoNotAsk;
51 
52     private CharSequence mMessage;
53     private String mCurrentPageText;
54     private Icon mIcon;
55 
GrantPermissionsWatchViewHandler(Context context)56     GrantPermissionsWatchViewHandler(Context context) {
57         mContext = context;
58     }
59 
60     @Override
setResultListener(ResultListener listener)61     public GrantPermissionsWatchViewHandler setResultListener(ResultListener listener) {
62         mResultListener = listener;
63         return this;
64     }
65 
66     @Override
createView()67     public View createView() {
68         return new Space(mContext);
69     }
70 
71     @Override
updateWindowAttributes(WindowManager.LayoutParams outLayoutParams)72     public void updateWindowAttributes(WindowManager.LayoutParams outLayoutParams) {
73         outLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
74         outLayoutParams.height = WindowManager.LayoutParams.MATCH_PARENT;
75         outLayoutParams.format = PixelFormat.OPAQUE;
76         outLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
77         outLayoutParams.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
78     }
79 
80     @Override
updateUi(String groupName, int groupCount, int groupIndex, Icon icon, CharSequence message, CharSequence detailMessage, CharSequence[] buttonLabels)81     public void updateUi(String groupName, int groupCount, int groupIndex, Icon icon,
82             CharSequence message, CharSequence detailMessage,
83             CharSequence[] buttonLabels) {
84         // TODO: Handle detailMessage
85 
86         boolean showDoNotAsk = buttonLabels[LABEL_DENY_AND_DONT_ASK_AGAIN_BUTTON] != null;
87 
88         if (Log.isLoggable(TAG, Log.DEBUG)) {
89             Log.d(TAG, "updateUi() - groupName: " + groupName
90                             + ", groupCount: " + groupCount
91                             + ", groupIndex: " + groupIndex
92                             + ", icon: " + icon
93                             + ", message: " + message
94                             + ", showDoNotAsk: " + showDoNotAsk);
95         }
96 
97         mGroupName = groupName;
98         mShowDoNotAsk = showDoNotAsk;
99         mMessage = message;
100         mIcon = icon;
101         mCurrentPageText = groupCount > 1
102                 ? mContext.getString(R.string.current_permission_template,
103                         groupIndex + 1, groupCount)
104                 : null;
105         showDialog(null);
106     }
107 
showDialog(Bundle savedInstanceState)108     private void showDialog(Bundle savedInstanceState) {
109         TypedArray a = mContext.obtainStyledAttributes(
110                 new int[] { android.R.attr.textColorPrimary });
111         int color = a.getColor(0, mContext.getColor(android.R.color.white));
112         a.recycle();
113         Drawable drawable = mIcon == null ? null : mIcon.setTint(color).loadDrawable(mContext);
114 
115         SpannableStringBuilder ssb = new SpannableStringBuilder();
116         if (!TextUtils.isEmpty(mCurrentPageText)) {
117             ssb.append(mCurrentPageText, new TextAppearanceSpan(mContext, R.style.BreadcrumbText),
118                     Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
119             ssb.append('\n');
120         }
121         if (!TextUtils.isEmpty(mMessage)) {
122             ssb.append(mMessage, new TextAppearanceSpan(mContext, R.style.TitleText),
123                     Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
124         }
125 
126         if (mDialog != null) {
127             mDialog.dismiss();
128             mDialog = null;
129         }
130 
131         if (mShowDoNotAsk) {
132             AlertDialog alertDialog = new WearableDialogHelper.DialogBuilder(mContext)
133                     .setPositiveIcon(R.drawable.confirm_button)
134                     .setNeutralIcon(R.drawable.cancel_button)
135                     .setNegativeIcon(R.drawable.deny_button)
136                     .setTitle(ssb)
137                     .setIcon(drawable)
138                     .setPositiveButton(R.string.grant_dialog_button_allow, this)
139                     .setNeutralButton(R.string.grant_dialog_button_deny, this)
140                     .setNegativeButton(R.string.grant_dialog_button_deny_dont_ask_again, this)
141                     .show();
142             alertDialog.getButton(DialogInterface.BUTTON_POSITIVE)
143                     .setId(R.id.permission_allow_button);
144             alertDialog.getButton(DialogInterface.BUTTON_NEUTRAL)
145                     .setId(R.id.permission_deny_button);
146             alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE)
147                     .setId(R.id.permission_deny_dont_ask_again_button);
148 
149             mDialog = alertDialog;
150         } else {
151             AcceptDenyDialog acceptDenyDialog = new AcceptDenyDialog(mContext);
152             acceptDenyDialog.setTitle(ssb);
153             acceptDenyDialog.setIcon(drawable);
154             acceptDenyDialog.setPositiveButton(this);
155             acceptDenyDialog.setNegativeButton(this);
156             acceptDenyDialog.show();
157             acceptDenyDialog.getButton(DialogInterface.BUTTON_POSITIVE)
158                     .setId(R.id.permission_allow_button);
159             acceptDenyDialog.getButton(DialogInterface.BUTTON_NEGATIVE)
160                     .setId(R.id.permission_deny_button);
161 
162             mDialog = acceptDenyDialog;
163         }
164         mDialog.setCancelable(false);
165 
166         if (savedInstanceState != null) {
167             mDialog.onRestoreInstanceState(savedInstanceState);
168         }
169     }
170 
171     @Override
saveInstanceState(Bundle outState)172     public void saveInstanceState(Bundle outState) {
173         Bundle b = new Bundle();
174         b.putByte(SHOW_DO_NOT_ASK, (byte) (mShowDoNotAsk ? 1 : 0));
175         b.putString(GROUP_NAME, mGroupName);
176         b.putBundle(DIALOG_BUNDLE, mDialog.onSaveInstanceState());
177 
178         outState.putBundle(WATCH_HANDLER_BUNDLE, b);
179     }
180 
181     @Override
loadInstanceState(Bundle savedInstanceState)182     public void loadInstanceState(Bundle savedInstanceState) {
183         Bundle b = savedInstanceState.getBundle(WATCH_HANDLER_BUNDLE);
184         mShowDoNotAsk = b.getByte(SHOW_DO_NOT_ASK) == 1;
185         mGroupName = b.getString(GROUP_NAME);
186         showDialog(b.getBundle(DIALOG_BUNDLE));
187     }
188 
189     @Override
onBackPressed()190     public void onBackPressed() {
191         notifyListener(DENIED);
192     }
193 
194     @Override
onClick(DialogInterface dialog, int which)195     public void onClick(DialogInterface dialog, int which) {
196         switch (which) {
197             case DialogInterface.BUTTON_POSITIVE:
198                 notifyListener(GRANTED_ALWAYS);
199                 break;
200             case DialogInterface.BUTTON_NEUTRAL:
201                 notifyListener(DENIED);
202                 break;
203             case DialogInterface.BUTTON_NEGATIVE:
204                 /* In AlertDialog, the negative button is also a don't ask again button. */
205                 if (dialog instanceof AlertDialog) {
206                     notifyListener(DENIED_DO_NOT_ASK_AGAIN);
207                 } else {
208                     notifyListener(DENIED);
209                 }
210                 break;
211         }
212     }
213 
notifyListener(@esult int result)214     private void notifyListener(@Result int result) {
215         if (mResultListener != null) {
216             mResultListener.onPermissionGrantResult(mGroupName, result);
217         }
218     }
219 }
220