• 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.tv.settings.device.apps;
18 
19 import android.app.ActivityManager;
20 import android.content.Context;
21 import android.content.pm.PackageInfo;
22 import android.content.pm.PackageManager;
23 import android.content.pm.ResolveInfo;
24 import android.content.pm.Signature;
25 import android.os.Bundle;
26 import android.support.annotation.NonNull;
27 import android.support.v17.leanback.widget.GuidanceStylist;
28 import android.util.Log;
29 
30 import com.android.settingslib.applications.ApplicationsState;
31 import com.android.tv.settings.R;
32 
33 import java.util.ArrayList;
34 import java.util.HashSet;
35 import java.util.List;
36 
37 public class EnableDisablePreference extends AppActionPreference {
38     private static final String TAG = "EnableDisablePreference";
39 
40     private static Signature sSystemSignature;
41 
42     private final PackageManager mPackageManager;
43 
EnableDisablePreference(Context context, ApplicationsState.AppEntry entry)44     public EnableDisablePreference(Context context,
45             ApplicationsState.AppEntry entry) {
46         super(context, entry);
47         mPackageManager = context.getPackageManager();
48         refresh();
49     }
50 
refresh()51     public void refresh() {
52         if (!UninstallPreference.canUninstall(mEntry) && canDisable()) {
53             setVisible(true);
54             if (mEntry.info.enabled) {
55                 setTitle(R.string.device_apps_app_management_disable);
56                 ConfirmationFragment.prepareArgs(getExtras(), mEntry.info.packageName, false);
57             } else {
58                 setTitle(R.string.device_apps_app_management_enable);
59                 ConfirmationFragment.prepareArgs(getExtras(), mEntry.info.packageName, true);
60             }
61         } else {
62             setVisible(false);
63         }
64     }
65 
canDisable()66     private boolean canDisable() {
67         final HashSet<String> homePackages = getHomePackages();
68         PackageInfo packageInfo;
69         try {
70             packageInfo = mPackageManager.getPackageInfo(mEntry.info.packageName,
71                     PackageManager.GET_DISABLED_COMPONENTS |
72                             PackageManager.GET_UNINSTALLED_PACKAGES |
73                             PackageManager.GET_SIGNATURES);
74         } catch (PackageManager.NameNotFoundException e) {
75             return false;
76         }
77         return !(homePackages.contains(mEntry.info.packageName) ||
78                 isSystemPackage(mPackageManager, packageInfo));
79     }
80 
getHomePackages()81     private HashSet<String> getHomePackages() {
82         HashSet<String> homePackages = new HashSet<>();
83         // Get list of "home" apps and trace through any meta-data references
84         List<ResolveInfo> homeActivities = new ArrayList<>();
85         mPackageManager.getHomeActivities(homeActivities);
86         for (ResolveInfo ri : homeActivities) {
87             final String activityPkg = ri.activityInfo.packageName;
88             homePackages.add(activityPkg);
89             // Also make sure to include anything proxying for the home app
90             final Bundle metadata = ri.activityInfo.metaData;
91             if (metadata != null) {
92                 final String metaPkg = metadata.getString(ActivityManager.META_HOME_ALTERNATE);
93                 if (signaturesMatch(mPackageManager, metaPkg, activityPkg)) {
94                     homePackages.add(metaPkg);
95                 }
96             }
97         }
98         return homePackages;
99     }
100 
signaturesMatch(PackageManager pm, String pkg1, String pkg2)101     private static boolean signaturesMatch(PackageManager pm, String pkg1, String pkg2) {
102         if (pkg1 != null && pkg2 != null) {
103             try {
104                 final int match = pm.checkSignatures(pkg1, pkg2);
105                 if (match >= PackageManager.SIGNATURE_MATCH) {
106                     return true;
107                 }
108             } catch (Exception e) {
109                 // e.g. named alternate package not found during lookup;
110                 // this is an expected case sometimes
111             }
112         }
113         return false;
114     }
115 
116     /**
117      * Determine whether a package is a "system package", in which case certain things (like
118      * disabling notifications or disabling the package altogether) should be disallowed.
119      */
isSystemPackage(PackageManager pm, PackageInfo pkg)120     private static boolean isSystemPackage(PackageManager pm, PackageInfo pkg) {
121         if (sSystemSignature == null) {
122             try {
123                 final PackageInfo sys = pm.getPackageInfo("android", PackageManager.GET_SIGNATURES);
124                 sSystemSignature = getFirstSignature(sys);
125             } catch (PackageManager.NameNotFoundException e) {
126                 Log.e(TAG, "Could not look up system signature", e);
127             }
128         }
129         return sSystemSignature != null && sSystemSignature.equals(getFirstSignature(pkg));
130     }
131 
getFirstSignature(PackageInfo pkg)132     private static Signature getFirstSignature(PackageInfo pkg) {
133         if (pkg != null && pkg.signatures != null && pkg.signatures.length > 0) {
134             return pkg.signatures[0];
135         }
136         return null;
137     }
138 
139     @Override
getFragment()140     public String getFragment() {
141         return ConfirmationFragment.class.getName();
142     }
143 
144     public static class ConfirmationFragment extends AppActionPreference.ConfirmationFragment {
145         private static final String ARG_PACKAGE_NAME = "packageName";
146         private static final String ARG_ENABLE = "enable";
147 
prepareArgs(@onNull Bundle args, String packageName, boolean enable)148         private static void prepareArgs(@NonNull Bundle args, String packageName, boolean enable) {
149             args.putString(ARG_PACKAGE_NAME, packageName);
150             args.putBoolean(ARG_ENABLE, enable);
151         }
152 
153         @NonNull
154         @Override
onCreateGuidance(Bundle savedInstanceState)155         public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) {
156             final AppManagementFragment fragment = (AppManagementFragment) getTargetFragment();
157             final Boolean enable = getArguments().getBoolean(ARG_ENABLE);
158             return new GuidanceStylist.Guidance(
159                     getString(enable ? R.string.device_apps_app_management_enable :
160                             R.string.device_apps_app_management_disable),
161                     getString(enable ? R.string.device_apps_app_management_enable_desc :
162                             R.string.device_apps_app_management_disable_desc),
163                     fragment.getAppName(),
164                     fragment.getAppIcon());
165         }
166 
167         @Override
onOk()168         public void onOk() {
169             getActivity().getPackageManager().setApplicationEnabledSetting(
170                     getArguments().getString(ARG_PACKAGE_NAME),
171                     getArguments().getBoolean(ARG_ENABLE) ?
172                             PackageManager.COMPONENT_ENABLED_STATE_DEFAULT :
173                             PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER,
174                     0);
175         }
176     }
177 }
178