Home | History | Annotate | Download | only in wear
      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 
     56     public static AppPermissionsFragmentWear newInstance(String packageName) {
     57         return setPackageName(new AppPermissionsFragmentWear(), packageName);
     58     }
     59 
     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
     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
    102     public View onCreateView(LayoutInflater inflater, ViewGroup container,
    103             Bundle savedInstanceState) {
    104         return inflater.inflate(R.layout.settings, container, false);
    105     }
    106 
    107     @Override
    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
    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 
    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
    174     public void onPause() {
    175         super.onPause();
    176         logAndClearToggledGroups();
    177     }
    178 
    179     @Override
    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
    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 
    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 
    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 
    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 
    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