• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 
17 package com.android.packageinstaller.permission.ui.wear;
18 
19 import android.Manifest;
20 import android.app.Activity;
21 import android.app.Fragment;
22 import android.content.Intent;
23 import android.content.pm.PackageInfo;
24 import android.content.pm.PackageManager;
25 import android.os.Bundle;
26 import android.support.wearable.view.WearableListView;
27 import android.util.Log;
28 import android.view.LayoutInflater;
29 import android.view.View;
30 import android.view.ViewGroup;
31 import android.widget.Toast;
32 
33 import com.android.packageinstaller.R;
34 import com.android.packageinstaller.permission.model.AppPermissionGroup;
35 import com.android.packageinstaller.permission.model.AppPermissions;
36 import com.android.packageinstaller.permission.ui.wear.settings.PermissionsSettingsAdapter;
37 import com.android.packageinstaller.permission.ui.wear.settings.SettingsAdapter;
38 import com.android.packageinstaller.permission.utils.LocationUtils;
39 import com.android.packageinstaller.permission.utils.SafetyNetLogger;
40 import com.android.packageinstaller.permission.utils.Utils;
41 
42 import java.util.ArrayList;
43 import java.util.List;
44 
45 public final class AppPermissionsFragmentWear extends TitledSettingsFragment {
46 
47     private static final String LOG_TAG = "ManagePermsFragment";
48 
49     private static final int WARNING_CONFIRMATION_REQUEST = 252;
50     private List<AppPermissionGroup> mToggledGroups;
51     private AppPermissions mAppPermissions;
52     private PermissionsSettingsAdapter mAdapter;
53 
54     private boolean mHasConfirmedRevoke;
55 
newInstance(String packageName)56     public static AppPermissionsFragmentWear newInstance(String packageName) {
57         return setPackageName(new AppPermissionsFragmentWear(), packageName);
58     }
59 
setPackageName(T fragment, String packageName)60     private static <T extends Fragment> T setPackageName(T fragment, String packageName) {
61         Bundle arguments = new Bundle();
62         arguments.putString(Intent.EXTRA_PACKAGE_NAME, packageName);
63         fragment.setArguments(arguments);
64         return fragment;
65     }
66 
67     @Override
onCreate(Bundle savedInstanceState)68     public void onCreate(Bundle savedInstanceState) {
69         super.onCreate(savedInstanceState);
70 
71         String packageName = getArguments().getString(Intent.EXTRA_PACKAGE_NAME);
72         Activity activity = getActivity();
73         PackageManager pm = activity.getPackageManager();
74         PackageInfo packageInfo;
75 
76         try {
77             packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
78         } catch (PackageManager.NameNotFoundException e) {
79             Log.i(LOG_TAG, "No package:" + activity.getCallingPackage(), e);
80             packageInfo = null;
81         }
82 
83         if (packageInfo == null) {
84             Toast.makeText(activity, R.string.app_not_found_dlg_title, Toast.LENGTH_LONG).show();
85             activity.finish();
86             return;
87         }
88 
89         mAppPermissions = new AppPermissions(activity, packageInfo, null, true, new Runnable() {
90             @Override
91             public void run() {
92                 getActivity().finish();
93             }
94         });
95 
96         mAdapter = new PermissionsSettingsAdapter(getContext());
97 
98         initializePermissionGroupList();
99     }
100 
101     @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)102     public View onCreateView(LayoutInflater inflater, ViewGroup container,
103             Bundle savedInstanceState) {
104         return inflater.inflate(R.layout.settings, container, false);
105     }
106 
107     @Override
onResume()108     public void onResume() {
109         super.onResume();
110         mAppPermissions.refresh();
111 
112         // Also refresh the UI
113         final int count = mAdapter.getItemCount();
114         for (int i = 0; i < count; ++i) {
115             updatePermissionGroupSetting(i);
116         }
117     }
118 
119     @Override
onViewCreated(View view, Bundle savedInstanceState)120     public void onViewCreated(View view, Bundle savedInstanceState) {
121         super.onViewCreated(view, savedInstanceState);
122         if (mAppPermissions != null) {
123             initializeLayout(mAdapter);
124             mHeader.setText(R.string.app_permissions);
125             mDetails.setText(R.string.no_permissions);
126             if (mAdapter.getItemCount() == 0) {
127                 mDetails.setVisibility(View.VISIBLE);
128                 mWheel.setVisibility(View.GONE);
129             } else {
130                 mDetails.setVisibility(View.GONE);
131                 mWheel.setVisibility(View.VISIBLE);
132             }
133         }
134     }
135 
initializePermissionGroupList()136     private void initializePermissionGroupList() {
137         final String packageName = mAppPermissions.getPackageInfo().packageName;
138         List<AppPermissionGroup> groups = mAppPermissions.getPermissionGroups();
139         List<SettingsAdapter.Setting<AppPermissionGroup>> nonSystemGroups = new ArrayList<>();
140 
141         final int count = groups.size();
142         for (int i = 0; i < count; ++i) {
143             final AppPermissionGroup group = groups.get(i);
144             if (!Utils.shouldShowPermission(group, packageName)) {
145                 continue;
146             }
147 
148             boolean isPlatform = group.getDeclaringPackage().equals(Utils.OS_PKG);
149 
150             SettingsAdapter.Setting<AppPermissionGroup> setting =
151                     new SettingsAdapter.Setting<AppPermissionGroup>(
152                             group.getLabel(),
153                             getPermissionGroupIcon(group),
154                             i);
155             setting.data = group;
156 
157             // The UI shows System settings first, then non-system settings
158             if (isPlatform) {
159                 mAdapter.addSetting(setting);
160             } else {
161                 nonSystemGroups.add(setting);
162             }
163         }
164 
165         // Now add the non-system settings to the end of the list
166         final int nonSystemCount = nonSystemGroups.size();
167         for (int i = 0; i < nonSystemCount; ++i) {
168             final SettingsAdapter.Setting<AppPermissionGroup> setting = nonSystemGroups.get(i);
169             mAdapter.addSetting(setting);
170         }
171     }
172 
173     @Override
onPause()174     public void onPause() {
175         super.onPause();
176         logAndClearToggledGroups();
177     }
178 
179     @Override
onClick(WearableListView.ViewHolder view)180     public void onClick(WearableListView.ViewHolder view) {
181         final int index = view.getPosition();
182         SettingsAdapter.Setting<AppPermissionGroup> setting = mAdapter.get(index);
183         final AppPermissionGroup group = setting.data;
184 
185         if (group == null) {
186             Log.e(LOG_TAG, "Error: AppPermissionGroup is null");
187             return;
188         }
189 
190         // The way WearableListView is designed, there is no way to avoid this click handler
191         // Since the policy is fixed, ignore the click as the user is not able to change the state
192         // of this permission group
193         if (group.isPolicyFixed()) {
194             return;
195         }
196 
197         addToggledGroup(group);
198 
199         if (LocationUtils.isLocationGroupAndProvider(group.getName(), group.getApp().packageName)) {
200             LocationUtils.showLocationDialog(getContext(), mAppPermissions.getAppLabel());
201             return;
202         }
203 
204         if (!group.areRuntimePermissionsGranted()) {
205             group.grantRuntimePermissions(false);
206         } else {
207             final boolean grantedByDefault = group.hasGrantedByDefaultPermission();
208             if (grantedByDefault || (!group.hasRuntimePermission() && !mHasConfirmedRevoke)) {
209                 Intent intent = new Intent(getActivity(), WarningConfirmationActivity.class);
210                 intent.putExtra(WarningConfirmationActivity.EXTRA_WARNING_MESSAGE,
211                         getString(grantedByDefault ?
212                                 R.string.system_warning : R.string.old_sdk_deny_warning));
213                 intent.putExtra(WarningConfirmationActivity.EXTRA_INDEX, index);
214                 startActivityForResult(intent, WARNING_CONFIRMATION_REQUEST);
215             } else {
216                 group.revokeRuntimePermissions(false);
217             }
218         }
219 
220         updatePermissionGroupSetting(index);
221     }
222 
223     @Override
onActivityResult(int requestCode, int resultCode, Intent data)224     public void onActivityResult(int requestCode, int resultCode, Intent data) {
225         if (requestCode == WARNING_CONFIRMATION_REQUEST) {
226             if (resultCode == Activity.RESULT_OK) {
227                 int index = data.getIntExtra(WarningConfirmationActivity.EXTRA_INDEX, -1);
228                 if (index == -1) {
229                     Log.e(LOG_TAG, "Warning confirmation request came back with no index.");
230                     return;
231                 }
232 
233                 SettingsAdapter.Setting<AppPermissionGroup> setting = mAdapter.get(index);
234                 final AppPermissionGroup group = setting.data;
235                 group.revokeRuntimePermissions(false);
236                 if (!group.hasGrantedByDefaultPermission()) {
237                     mHasConfirmedRevoke = true;
238                 }
239 
240                 updatePermissionGroupSetting(index);
241             }
242         } else {
243             super.onActivityResult(requestCode, resultCode, data);
244         }
245     }
246 
updatePermissionGroupSetting(int index)247     private void updatePermissionGroupSetting(int index) {
248         SettingsAdapter.Setting<AppPermissionGroup> setting = mAdapter.get(index);
249         AppPermissionGroup group = setting.data;
250         mAdapter.updateSetting(
251                 index,
252                 group.getLabel(),
253                 getPermissionGroupIcon(group),
254                 group);
255     }
256 
addToggledGroup(AppPermissionGroup group)257     private void addToggledGroup(AppPermissionGroup group) {
258         if (mToggledGroups == null) {
259             mToggledGroups = new ArrayList<>();
260         }
261         // Double toggle is back to initial state.
262         if (mToggledGroups.contains(group)) {
263             mToggledGroups.remove(group);
264         } else {
265             mToggledGroups.add(group);
266         }
267     }
268 
logAndClearToggledGroups()269     private void logAndClearToggledGroups() {
270         if (mToggledGroups != null) {
271             String packageName = mAppPermissions.getPackageInfo().packageName;
272             SafetyNetLogger.logPermissionsToggled(packageName, mToggledGroups);
273             mToggledGroups = null;
274         }
275     }
276 
getPermissionGroupIcon(AppPermissionGroup group)277     private int getPermissionGroupIcon(AppPermissionGroup group) {
278         String groupName = group.getName();
279         boolean isEnabled = group.areRuntimePermissionsGranted();
280         int resId;
281 
282         switch (groupName) {
283             case Manifest.permission_group.CALENDAR:
284                 resId = isEnabled ? R.drawable.ic_permission_calendar
285                         : R.drawable.ic_permission_calendardisable;
286                 break;
287             case Manifest.permission_group.CAMERA:
288                 resId = isEnabled ? R.drawable.ic_permission_camera
289                         : R.drawable.ic_permission_cameradisable;
290                 break;
291             case Manifest.permission_group.CONTACTS:
292                 resId = isEnabled ? R.drawable.ic_permission_contact
293                         : R.drawable.ic_permission_contactdisable;
294                 break;
295             case Manifest.permission_group.LOCATION:
296                 resId = isEnabled ? R.drawable.ic_permission_location
297                         : R.drawable.ic_permission_locationdisable;
298                 break;
299             case Manifest.permission_group.MICROPHONE:
300                 resId = isEnabled ? R.drawable.ic_permission_mic
301                         : R.drawable.ic_permission_micdisable;
302                 break;
303             case Manifest.permission_group.PHONE:
304                 resId = isEnabled ? R.drawable.ic_permission_call
305                         : R.drawable.ic_permission_calldisable;
306                 break;
307             case Manifest.permission_group.SENSORS:
308                 resId = isEnabled ? R.drawable.ic_permission_sensor
309                         : R.drawable.ic_permission_sensordisable;
310                 break;
311             case Manifest.permission_group.SMS:
312                 resId = isEnabled ? R.drawable.ic_permission_sms
313                         : R.drawable.ic_permission_smsdisable;
314                 break;
315             case Manifest.permission_group.STORAGE:
316                 resId = isEnabled ? R.drawable.ic_permission_storage
317                         : R.drawable.ic_permission_storagedisable;
318                 break;
319             default:
320                 resId = isEnabled ? R.drawable.ic_permission_shield
321                         : R.drawable.ic_permission_shielddisable;
322         }
323 
324         return resId;
325     }
326 }
327