• 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.settings.utils;
18 
19 import android.app.ActivityManager;
20 import android.content.BroadcastReceiver;
21 import android.content.ComponentName;
22 import android.content.ContentResolver;
23 import android.content.Context;
24 import android.content.Intent;
25 import android.content.IntentFilter;
26 import android.content.pm.PackageManager;
27 import android.content.pm.ResolveInfo;
28 import android.content.pm.ServiceInfo;
29 import android.database.ContentObserver;
30 import android.net.Uri;
31 import android.os.Handler;
32 import android.provider.Settings;
33 import android.text.TextUtils;
34 import android.util.Slog;
35 
36 import com.android.settings.utils.ManagedServiceSettings.Config;
37 
38 import java.util.ArrayList;
39 import java.util.Arrays;
40 import java.util.HashSet;
41 import java.util.List;
42 
43 public class ServiceListing {
44     private final ContentResolver mContentResolver;
45     private final Context mContext;
46     private final Config mConfig;
47     private final HashSet<ComponentName> mEnabledServices = new HashSet<ComponentName>();
48     private final List<ServiceInfo> mServices = new ArrayList<ServiceInfo>();
49     private final List<Callback> mCallbacks = new ArrayList<Callback>();
50 
51     private boolean mListening;
52 
ServiceListing(Context context, Config config)53     public ServiceListing(Context context, Config config) {
54         mContext = context;
55         mConfig = config;
56         mContentResolver = context.getContentResolver();
57     }
58 
addCallback(Callback callback)59     public void addCallback(Callback callback) {
60         mCallbacks.add(callback);
61     }
62 
removeCallback(Callback callback)63     public void removeCallback(Callback callback) {
64         mCallbacks.remove(callback);
65     }
66 
setListening(boolean listening)67     public void setListening(boolean listening) {
68         if (mListening == listening) return;
69         mListening = listening;
70         if (mListening) {
71             // listen for package changes
72             IntentFilter filter = new IntentFilter();
73             filter.addAction(Intent.ACTION_PACKAGE_ADDED);
74             filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
75             filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
76             filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
77             filter.addDataScheme("package");
78             mContext.registerReceiver(mPackageReceiver, filter);
79             mContentResolver.registerContentObserver(Settings.Secure.getUriFor(mConfig.setting),
80                     false, mSettingsObserver);
81         } else {
82             mContext.unregisterReceiver(mPackageReceiver);
83             mContentResolver.unregisterContentObserver(mSettingsObserver);
84         }
85     }
86 
getEnabledServicesCount(Config config, Context context)87     public static int getEnabledServicesCount(Config config, Context context) {
88         final String flat = Settings.Secure.getString(context.getContentResolver(), config.setting);
89         if (flat == null || "".equals(flat)) return 0;
90         final String[] components = flat.split(":");
91         return components.length;
92     }
93 
getServicesCount(Config c, PackageManager pm)94     public static int getServicesCount(Config c, PackageManager pm) {
95         return getServices(c, null, pm);
96     }
97 
getServices(Config c, List<ServiceInfo> list, PackageManager pm)98     protected static int getServices(Config c, List<ServiceInfo> list, PackageManager pm) {
99         int services = 0;
100         if (list != null) {
101             list.clear();
102         }
103         final int user = ActivityManager.getCurrentUser();
104 
105         List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser(
106                 new Intent(c.intentAction),
107                 PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
108                 user);
109 
110         for (int i = 0, count = installedServices.size(); i < count; i++) {
111             ResolveInfo resolveInfo = installedServices.get(i);
112             ServiceInfo info = resolveInfo.serviceInfo;
113 
114             if (!c.permission.equals(info.permission)) {
115                 Slog.w(c.tag, "Skipping " + c.noun + " service "
116                         + info.packageName + "/" + info.name
117                         + ": it does not require the permission "
118                         + c.permission);
119                 continue;
120             }
121             if (list != null) {
122                 list.add(info);
123             }
124             services++;
125         }
126         return services;
127     }
128 
saveEnabledServices()129     private void saveEnabledServices() {
130         StringBuilder sb = null;
131         for (ComponentName cn : mEnabledServices) {
132             if (sb == null) {
133                 sb = new StringBuilder();
134             } else {
135                 sb.append(':');
136             }
137             sb.append(cn.flattenToString());
138         }
139         Settings.Secure.putString(mContentResolver, mConfig.setting,
140                 sb != null ? sb.toString() : "");
141     }
142 
loadEnabledServices()143     private void loadEnabledServices() {
144         mEnabledServices.clear();
145         final String flat = Settings.Secure.getString(mContentResolver, mConfig.setting);
146         if (flat != null && !"".equals(flat)) {
147             final String[] names = flat.split(":");
148             for (int i = 0; i < names.length; i++) {
149                 final ComponentName cn = ComponentName.unflattenFromString(names[i]);
150                 if (cn != null) {
151                     mEnabledServices.add(cn);
152                 }
153             }
154         }
155     }
156 
reload()157     public List<ServiceInfo> reload() {
158         loadEnabledServices();
159         getServices(mConfig, mServices, mContext.getPackageManager());
160         for (Callback callback : mCallbacks) {
161             callback.onServicesReloaded(mServices);
162         }
163         return mServices;
164     }
165 
isEnabled(ComponentName cn)166     public boolean isEnabled(ComponentName cn) {
167         return mEnabledServices.contains(cn);
168     }
169 
setEnabled(ComponentName cn, boolean enabled)170     public void setEnabled(ComponentName cn, boolean enabled) {
171         if (enabled) {
172             mEnabledServices.add(cn);
173         } else {
174             mEnabledServices.remove(cn);
175         }
176         saveEnabledServices();
177     }
178 
179     private final ContentObserver mSettingsObserver = new ContentObserver(new Handler()) {
180         @Override
181         public void onChange(boolean selfChange, Uri uri) {
182             reload();
183         }
184     };
185 
186     private final BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
187         @Override
188         public void onReceive(Context context, Intent intent) {
189             reload();
190         }
191     };
192 
193     public interface Callback {
onServicesReloaded(List<ServiceInfo> services)194         void onServicesReloaded(List<ServiceInfo> services);
195     }
196 }
197