• 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"); you may not use this file
5  * except in compliance with the License. You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the
10  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11  * KIND, either express or implied. See the License for the specific language governing
12  * permissions and limitations under the License.
13  */
14 
15 package com.android.settings.fuelgauge;
16 
17 import android.app.AppOpsManager;
18 import android.content.Context;
19 import android.content.pm.ApplicationInfo;
20 import android.content.pm.PackageManager;
21 import android.os.Build;
22 import android.support.annotation.VisibleForTesting;
23 import android.support.v14.preference.SwitchPreference;
24 import android.support.v7.preference.Preference;
25 import android.util.Log;
26 
27 import com.android.settings.R;
28 import com.android.settings.core.PreferenceController;
29 
30 /**
31  * Controller to control whether an app can run in the background
32  */
33 public class BackgroundActivityPreferenceController extends PreferenceController implements
34         Preference.OnPreferenceChangeListener {
35 
36     private static final String TAG = "BgActivityPrefContr";
37     private static final String KEY_BACKGROUND_ACTIVITY = "background_activity";
38 
39     private final PackageManager mPackageManager;
40     private final AppOpsManager mAppOpsManager;
41     private final String[] mPackages;
42     private final int mUid;
43 
44     private String mTargetPackage;
45 
BackgroundActivityPreferenceController(Context context, int uid)46     public BackgroundActivityPreferenceController(Context context, int uid) {
47         super(context);
48         mPackageManager = context.getPackageManager();
49         mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
50         mUid = uid;
51         mPackages = mPackageManager.getPackagesForUid(mUid);
52     }
53 
54     @Override
updateState(Preference preference)55     public void updateState(Preference preference) {
56         final int mode = mAppOpsManager
57                 .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, mUid, mTargetPackage);
58         if (mode == AppOpsManager.MODE_ERRORED) {
59             preference.setEnabled(false);
60         } else {
61             final boolean checked = mode != AppOpsManager.MODE_IGNORED;
62             ((SwitchPreference) preference).setChecked(checked);
63         }
64 
65         updateSummary(preference);
66     }
67 
68     @Override
isAvailable()69     public boolean isAvailable() {
70         if (mPackages == null) {
71             return false;
72         }
73         for (final String packageName : mPackages) {
74             if (isLegacyApp(packageName)) {
75                 mTargetPackage = packageName;
76                 return true;
77             }
78         }
79 
80         return false;
81     }
82 
83     @Override
getPreferenceKey()84     public String getPreferenceKey() {
85         return KEY_BACKGROUND_ACTIVITY;
86     }
87 
88     @Override
onPreferenceChange(Preference preference, Object newValue)89     public boolean onPreferenceChange(Preference preference, Object newValue) {
90         boolean switchOn = (Boolean) newValue;
91         mAppOpsManager.setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, mUid, mTargetPackage,
92                 switchOn ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED);
93 
94         updateSummary(preference);
95         return true;
96     }
97 
98     @VisibleForTesting
getTargetPackage()99     String getTargetPackage() {
100         return mTargetPackage;
101     }
102 
103     @VisibleForTesting
isLegacyApp(final String packageName)104     boolean isLegacyApp(final String packageName) {
105         try {
106             ApplicationInfo info = mPackageManager.getApplicationInfo(packageName,
107                     PackageManager.GET_META_DATA);
108 
109             return info.targetSdkVersion < Build.VERSION_CODES.O;
110         } catch (PackageManager.NameNotFoundException e) {
111             Log.e(TAG, "Cannot find package: " + packageName, e);
112         }
113 
114         return false;
115     }
116 
117     @VisibleForTesting
updateSummary(Preference preference)118     void updateSummary(Preference preference) {
119         final int mode = mAppOpsManager
120                 .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, mUid, mTargetPackage);
121 
122         if (mode == AppOpsManager.MODE_ERRORED) {
123             preference.setSummary(R.string.background_activity_summary_disabled);
124         } else {
125             final boolean checked = mode != AppOpsManager.MODE_IGNORED;
126             preference.setSummary(checked ? R.string.background_activity_summary_on
127                     : R.string.background_activity_summary_off);
128         }
129     }
130 }
131