• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.settings.applications.appinfo;
18 
19 import android.app.Activity;
20 import android.content.ActivityNotFoundException;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.pm.PackageManager;
24 import android.content.res.Resources;
25 import android.icu.text.ListFormatter;
26 import android.util.Log;
27 
28 import androidx.annotation.VisibleForTesting;
29 import androidx.preference.Preference;
30 
31 import com.android.settings.R;
32 import com.android.settingslib.applications.PermissionsSummaryHelper;
33 import com.android.settingslib.core.lifecycle.LifecycleObserver;
34 import com.android.settingslib.core.lifecycle.events.OnStart;
35 import com.android.settingslib.core.lifecycle.events.OnStop;
36 
37 import java.util.ArrayList;
38 import java.util.List;
39 import java.util.Random;
40 
41 /**
42  * A PreferenceController handling the logic for permissions of apps.
43  */
44 public class AppPermissionPreferenceController extends AppInfoPreferenceControllerBase implements
45         LifecycleObserver, OnStart, OnStop {
46 
47     private static final String TAG = "PermissionPrefControl";
48     private static final String EXTRA_HIDE_INFO_BUTTON = "hideInfoButton";
49     private static final long INVALID_SESSION_ID = 0;
50 
51     private final PackageManager mPackageManager;
52 
53     private String mPackageName;
54 
55     @VisibleForTesting
56     final PermissionsSummaryHelper.PermissionsResultCallback mPermissionCallback
57             = new PermissionsSummaryHelper.PermissionsResultCallback() {
58         @Override
59         public void onPermissionSummaryResult(int standardGrantedPermissionCount,
60                 int requestedPermissionCount, int additionalGrantedPermissionCount,
61                 List<CharSequence> grantedGroupLabels) {
62             final Resources res = mContext.getResources();
63             CharSequence summary;
64 
65             if (requestedPermissionCount == 0) {
66                 summary = res.getString(
67                         R.string.runtime_permissions_summary_no_permissions_requested);
68                 mPreference.setEnabled(false);
69             } else {
70                 final ArrayList<CharSequence> list = new ArrayList<>(grantedGroupLabels);
71                 if (additionalGrantedPermissionCount > 0) {
72                     // N additional permissions.
73                     list.add(res.getQuantityString(
74                             R.plurals.runtime_permissions_additional_count,
75                             additionalGrantedPermissionCount, additionalGrantedPermissionCount));
76                 }
77                 if (list.size() == 0) {
78                     summary = res.getString(
79                             R.string.runtime_permissions_summary_no_permissions_granted);
80                 } else {
81                     summary = ListFormatter.getInstance().format(list);
82                 }
83                 mPreference.setEnabled(true);
84             }
85             mPreference.setSummary(summary);
86         }
87     };
88 
89     private final PackageManager.OnPermissionsChangedListener mOnPermissionsChangedListener =
90             uid -> updateState(mPreference);
91 
AppPermissionPreferenceController(Context context, String key)92     public AppPermissionPreferenceController(Context context, String key) {
93         super(context, key);
94         mPackageManager = context.getPackageManager();
95     }
96 
97     @Override
onStart()98     public void onStart() {
99         mPackageManager.addOnPermissionsChangeListener(mOnPermissionsChangedListener);
100     }
101 
102     @Override
onStop()103     public void onStop() {
104         mPackageManager.removeOnPermissionsChangeListener(mOnPermissionsChangedListener);
105     }
106 
107     @Override
updateState(Preference preference)108     public void updateState(Preference preference) {
109         PermissionsSummaryHelper.getPermissionSummary(mContext, mPackageName, mPermissionCallback);
110     }
111 
112     @Override
handlePreferenceTreeClick(Preference preference)113     public boolean handlePreferenceTreeClick(Preference preference) {
114         if (getPreferenceKey().equals(preference.getKey())) {
115             startManagePermissionsActivity();
116             return true;
117         }
118         return false;
119     }
120 
setPackageName(String packageName)121     public void setPackageName(String packageName) {
122         mPackageName = packageName;
123     }
124 
startManagePermissionsActivity()125     private void startManagePermissionsActivity() {
126         // start new activity to manage app permissions
127         final Intent permIntent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS);
128         permIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, mParent.getAppEntry().info.packageName);
129         permIntent.putExtra(EXTRA_HIDE_INFO_BUTTON, true);
130         Activity activity = mParent.getActivity();
131         Intent intent = activity != null ? activity.getIntent() : null;
132         if (intent != null) {
133             String action = intent.getAction();
134             long sessionId = intent.getLongExtra(
135                     Intent.ACTION_AUTO_REVOKE_PERMISSIONS, INVALID_SESSION_ID);
136             if ((action != null && action.equals(Intent.ACTION_AUTO_REVOKE_PERMISSIONS))
137                     || sessionId != INVALID_SESSION_ID) {
138                 // If intent is Auto revoke, and we don't already have a session ID, make one
139                 while (sessionId == INVALID_SESSION_ID) {
140                     sessionId = new Random().nextLong();
141                 }
142                 permIntent.putExtra(Intent.ACTION_AUTO_REVOKE_PERMISSIONS, sessionId);
143             }
144         }
145         try {
146             if (activity != null) {
147                 activity.startActivityForResult(permIntent, mParent.SUB_INFO_FRAGMENT);
148             }
149         } catch (ActivityNotFoundException e) {
150             Log.w(TAG, "No app can handle android.intent.action.MANAGE_APP_PERMISSIONS");
151         }
152     }
153 }
154