Home | History | Annotate | Download | only in utils
      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 
     53     public ServiceListing(Context context, Config config) {
     54         mContext = context;
     55         mConfig = config;
     56         mContentResolver = context.getContentResolver();
     57     }
     58 
     59     public void addCallback(Callback callback) {
     60         mCallbacks.add(callback);
     61     }
     62 
     63     public void removeCallback(Callback callback) {
     64         mCallbacks.remove(callback);
     65     }
     66 
     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 
     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 
     94     public static int getServicesCount(Config c, PackageManager pm) {
     95         return getServices(c, null, pm);
     96     }
     97 
     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 
    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 
    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 
    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 
    166     public boolean isEnabled(ComponentName cn) {
    167         return mEnabledServices.contains(cn);
    168     }
    169 
    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 {
    194         void onServicesReloaded(List<ServiceInfo> services);
    195     }
    196 }
    197