• 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 package com.android.settings.applications;
17 
18 import android.app.AlertDialog;
19 import android.app.AppOpsManager;
20 import android.app.admin.DevicePolicyManager;
21 import android.content.ActivityNotFoundException;
22 import android.content.ComponentName;
23 import android.content.Context;
24 import android.content.Intent;
25 import android.content.pm.PackageManager;
26 import android.content.pm.ResolveInfo;
27 import android.os.Bundle;
28 import android.os.UserHandle;
29 import android.provider.Settings;
30 import android.support.v14.preference.SwitchPreference;
31 import android.support.v7.preference.Preference;
32 import android.support.v7.preference.Preference.OnPreferenceChangeListener;
33 import android.support.v7.preference.Preference.OnPreferenceClickListener;
34 import android.util.Log;
35 
36 import com.android.internal.annotations.VisibleForTesting;
37 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
38 import com.android.settings.R;
39 import com.android.settings.applications.AppStateUsageBridge.UsageState;
40 import com.android.settings.overlay.FeatureFactory;
41 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
42 
43 public class UsageAccessDetails extends AppInfoWithHeader implements OnPreferenceChangeListener,
44         OnPreferenceClickListener {
45 
46     private static final String KEY_APP_OPS_PREFERENCE_SCREEN = "app_ops_preference_screen";
47     private static final String KEY_APP_OPS_SETTINGS_SWITCH = "app_ops_settings_switch";
48     private static final String KEY_APP_OPS_SETTINGS_DESC = "app_ops_settings_description";
49 
50     // Use a bridge to get the usage stats but don't initialize it to connect with all state.
51     // TODO: Break out this functionality into its own class.
52     private AppStateUsageBridge mUsageBridge;
53     private AppOpsManager mAppOpsManager;
54     private SwitchPreference mSwitchPref;
55     private Preference mUsageDesc;
56     private Intent mSettingsIntent;
57     private UsageState mUsageState;
58     private DevicePolicyManager mDpm;
59 
60     @Override
onCreate(Bundle savedInstanceState)61     public void onCreate(Bundle savedInstanceState) {
62         super.onCreate(savedInstanceState);
63 
64         Context context = getActivity();
65         mUsageBridge = new AppStateUsageBridge(context, mState, null);
66         mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
67         mDpm = context.getSystemService(DevicePolicyManager.class);
68 
69         addPreferencesFromResource(R.xml.app_ops_permissions_details);
70         mSwitchPref = (SwitchPreference) findPreference(KEY_APP_OPS_SETTINGS_SWITCH);
71         mUsageDesc = findPreference(KEY_APP_OPS_SETTINGS_DESC);
72 
73         getPreferenceScreen().setTitle(R.string.usage_access);
74         mSwitchPref.setTitle(R.string.permit_usage_access);
75         mUsageDesc.setSummary(R.string.usage_access_description);
76 
77         mSwitchPref.setOnPreferenceChangeListener(this);
78 
79         mSettingsIntent = new Intent(Intent.ACTION_MAIN)
80                 .addCategory(Settings.INTENT_CATEGORY_USAGE_ACCESS_CONFIG)
81                 .setPackage(mPackageName);
82     }
83 
84     @Override
onPreferenceClick(Preference preference)85     public boolean onPreferenceClick(Preference preference) {
86         return false;
87     }
88 
89     @Override
onPreferenceChange(Preference preference, Object newValue)90     public boolean onPreferenceChange(Preference preference, Object newValue) {
91         if (preference == mSwitchPref) {
92             if (mUsageState != null && (Boolean) newValue != mUsageState.isPermissible()) {
93                 if (mUsageState.isPermissible() && mDpm.isProfileOwnerApp(mPackageName)) {
94                     new AlertDialog.Builder(getContext())
95                             .setIcon(com.android.internal.R.drawable.ic_dialog_alert_material)
96                             .setTitle(android.R.string.dialog_alert_title)
97                             .setMessage(R.string.work_profile_usage_access_warning)
98                             .setPositiveButton(R.string.okay, null)
99                             .show();
100                 }
101                 setHasAccess(!mUsageState.isPermissible());
102                 refreshUi();
103             }
104             return true;
105         }
106         return false;
107     }
108 
setHasAccess(boolean newState)109     private void setHasAccess(boolean newState) {
110         logSpecialPermissionChange(newState, mPackageName);
111         mAppOpsManager.setMode(AppOpsManager.OP_GET_USAGE_STATS, mPackageInfo.applicationInfo.uid,
112                 mPackageName, newState ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED);
113     }
114 
115     @VisibleForTesting
logSpecialPermissionChange(boolean newState, String packageName)116     void logSpecialPermissionChange(boolean newState, String packageName) {
117         int logCategory = newState ? MetricsEvent.APP_SPECIAL_PERMISSION_USAGE_VIEW_ALLOW
118                 : MetricsEvent.APP_SPECIAL_PERMISSION_USAGE_VIEW_DENY;
119         FeatureFactory.getFactory(getContext()).getMetricsFeatureProvider().action(getContext(),
120                 logCategory, packageName);
121     }
122 
123     @Override
refreshUi()124     protected boolean refreshUi() {
125         retrieveAppEntry();
126         if (mAppEntry == null) {
127             return false;
128         }
129         if (mPackageInfo == null) {
130             return false; // onCreate must have failed, make sure to exit
131         }
132         mUsageState = mUsageBridge.getUsageInfo(mPackageName,
133                 mPackageInfo.applicationInfo.uid);
134 
135         boolean hasAccess = mUsageState.isPermissible();
136         mSwitchPref.setChecked(hasAccess);
137         mSwitchPref.setEnabled(mUsageState.permissionDeclared);
138 
139         ResolveInfo resolveInfo = mPm.resolveActivityAsUser(mSettingsIntent,
140                 PackageManager.GET_META_DATA, mUserId);
141         if (resolveInfo != null) {
142             Bundle metaData = resolveInfo.activityInfo.metaData;
143             mSettingsIntent.setComponent(new ComponentName(resolveInfo.activityInfo.packageName,
144                     resolveInfo.activityInfo.name));
145             if (metaData != null
146                     && metaData.containsKey(Settings.METADATA_USAGE_ACCESS_REASON)) {
147                 mSwitchPref.setSummary(
148                         metaData.getString(Settings.METADATA_USAGE_ACCESS_REASON));
149             }
150         }
151 
152         return true;
153     }
154 
155     @Override
createDialog(int id, int errorCode)156     protected AlertDialog createDialog(int id, int errorCode) {
157         return null;
158     }
159 
160     @Override
getMetricsCategory()161     public int getMetricsCategory() {
162         return MetricsEvent.APPLICATIONS_USAGE_ACCESS_DETAIL;
163     }
164 
165 }
166