ManagedServices.java revision 3b98b3f1f85aff0c84ebef4dd497c146d1b4d248
19df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown/** 29df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * Copyright (c) 2014, The Android Open Source Project 39df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * 49df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 59df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * you may not use this file except in compliance with the License. 69df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * You may obtain a copy of the License at 79df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * 89df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * http://www.apache.org/licenses/LICENSE-2.0 99df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * 109df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * Unless required by applicable law or agreed to in writing, software 119df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 129df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * See the License for the specific language governing permissions and 149df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * limitations under the License. 159df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown */ 169df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown 179df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownpackage com.android.server.notification; 189df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown 199df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport android.app.ActivityManager; 209df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport android.app.PendingIntent; 219df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport android.content.ComponentName; 22a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brownimport android.content.ContentResolver; 23af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport android.content.Context; 24ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.content.Intent; 25af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport android.content.ServiceConnection; 26af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport android.content.pm.ApplicationInfo; 27ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.content.pm.PackageManager; 28ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.content.pm.PackageManager.NameNotFoundException; 29a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brownimport android.content.pm.ResolveInfo; 30ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.content.pm.ServiceInfo; 31ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.content.pm.UserInfo; 329df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport android.database.ContentObserver; 339f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brownimport android.net.Uri; 34ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.os.Build; 35ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.os.Handler; 369df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport android.os.IBinder; 37af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport android.os.IInterface; 38af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport android.os.RemoteException; 399df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport android.os.UserHandle; 409df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport android.os.UserManager; 419df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport android.provider.Settings; 429df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport android.text.TextUtils; 439df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport android.util.ArraySet; 449df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport android.util.Slog; 459df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport android.util.SparseArray; 469df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown 479df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport java.io.PrintWriter; 489df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport java.util.ArrayList; 499df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport java.util.Arrays; 50af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport java.util.List; 51af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport java.util.Set; 52af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown 53af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown/** 54af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown * Manages the lifecycle of application-provided services bound by system server. 559df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * 569f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown * Services managed by this helper must have: 579df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * - An associated system settings value with a list of enabled component names. 589f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown * - A well-known action for services to use in their intent-filter. 59af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown * - A system permission for services to require in order to ensure system has exclusive binding. 60af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown * - A settings page for user configuration of enabled services, and associated intent action. 61af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown * - A remote interface definition (aidl) provided by the service used for communication. 62af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown */ 63af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownabstract public class ManagedServices { 64af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown protected final String TAG = getClass().getSimpleName(); 65af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown protected static final boolean DEBUG = true; 669df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown 679df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown private static final String ENABLED_SERVICES_SEPARATOR = ":"; 689df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown 699df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown private final Context mContext; 709df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown protected final Object mMutex; 719df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown private final UserProfiles mUserProfiles; 729df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown private final SettingsObserver mSettingsObserver; 739df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown private final Config mConfig; 749df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown 759df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown // contains connections to all connected services, including app services 769df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown // and system services 779df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown protected final ArrayList<ManagedServiceInfo> mServices = new ArrayList<ManagedServiceInfo>(); 789df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown // things that will be put into mServices as soon as they're ready 799df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown private final ArrayList<String> mServicesBinding = new ArrayList<String>(); 80d9fec5d317c09da6bcc7a54df4e0190a76d21eaeJeff Brown // lists the component names of all enabled (and therefore connected) 81d9fec5d317c09da6bcc7a54df4e0190a76d21eaeJeff Brown // app services for current profiles. 829df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown private ArraySet<ComponentName> mEnabledServicesForCurrentProfiles 839df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown = new ArraySet<ComponentName>(); 849df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown // Just the packages from mEnabledServicesForCurrentProfiles 859df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown private ArraySet<String> mEnabledServicesPackageNames = new ArraySet<String>(); 869df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown 879df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown public ManagedServices(Context context, Handler handler, Object mutex, 889df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown UserProfiles userProfiles) { 899df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown mContext = context; 909df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown mMutex = mutex; 919df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown mUserProfiles = userProfiles; 929df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown mConfig = getConfig(); 939df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown mSettingsObserver = new SettingsObserver(handler); 94d9fec5d317c09da6bcc7a54df4e0190a76d21eaeJeff Brown } 95d9fec5d317c09da6bcc7a54df4e0190a76d21eaeJeff Brown 96d9fec5d317c09da6bcc7a54df4e0190a76d21eaeJeff Brown abstract protected Config getConfig(); 979df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown 989df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown private String getCaption() { 999df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown return mConfig.caption; 1009df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown } 1019df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown 1022f0957607411b99810226ad38d59cf18718b86d0Jeff Brown abstract protected IInterface asInterface(IBinder binder); 1039df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown 1049df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown abstract protected void onServiceAdded(ManagedServiceInfo info); 1059df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown 1069df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown protected void onServiceRemovedLocked(ManagedServiceInfo removed) { } 1079df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown 1089df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown private ManagedServiceInfo newServiceInfo(IInterface service, 1092f0957607411b99810226ad38d59cf18718b86d0Jeff Brown ComponentName component, int userid, boolean isSystem, ServiceConnection connection, 1109df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown int targetSdkVersion) { 1119df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown return new ManagedServiceInfo(service, component, userid, isSystem, connection, 1129df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown targetSdkVersion); 1139df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown } 1149df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown 1159df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown public void onBootPhaseAppsCanStart() { 1169df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown mSettingsObserver.observe(); 1179df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown } 1189df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown 1199df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown public void dump(PrintWriter pw) { 1209df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown pw.println(" All " + getCaption() + "s (" + mEnabledServicesForCurrentProfiles.size() 1219df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown + ") enabled for current profiles:"); 1229df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown for (ComponentName cmpt : mEnabledServicesForCurrentProfiles) { 1239df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown pw.println(" " + cmpt); 1249df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown } 1259df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown 1269df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown pw.println(" Live " + getCaption() + "s (" + mServices.size() + "):"); 1279df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown for (ManagedServiceInfo info : mServices) { 1289df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown pw.println(" " + info.component 129ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown + " (user " + info.userid + "): " + info.service 130ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown + (info.isSystem?" SYSTEM":"")); 131ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 132ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 133ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown 134ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown public void onPackagesChanged(boolean queryReplace, String[] pkgList) { 135ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown if (DEBUG) Slog.d(TAG, "onPackagesChanged queryReplace=" + queryReplace 136ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown + " pkgList=" + (pkgList == null ? null : Arrays.asList(pkgList)) 137ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown + " mEnabledServicesPackageNames=" + mEnabledServicesPackageNames); 138ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown boolean anyServicesInvolved = false; 139ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown if (pkgList != null && (pkgList.length > 0)) { 140ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown for (String pkgName : pkgList) { 141ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown if (mEnabledServicesPackageNames.contains(pkgName)) { 142ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown anyServicesInvolved = true; 143ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 144ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 145ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 146ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown 147ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown if (anyServicesInvolved) { 148ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown // if we're not replacing a package, clean up orphaned bits 149ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown if (!queryReplace) { 150ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown disableNonexistentServices(); 151ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 152ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown // make sure we're still bound to any of our services who may have just upgraded 153ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown rebindServices(); 154ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 155ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 156ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown 157ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown public ManagedServiceInfo checkServiceTokenLocked(IInterface service) { 158ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown checkNotNull(service); 159ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown final IBinder token = service.asBinder(); 160ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown final int N = mServices.size(); 161ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown for (int i=0; i<N; i++) { 162ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown final ManagedServiceInfo info = mServices.get(i); 163ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown if (info.service.asBinder() == token) return info; 164ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 165ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown throw new SecurityException("Disallowed call from unknown " + getCaption() + ": " 166ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown + service); 167ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 168ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown 169ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown public void unregisterService(IInterface service, int userid) { 170ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown checkNotNull(service); 1719f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown // no need to check permissions; if your service binder is in the list, 1729f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown // that's proof that you had permission to add it in the first place 173ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown unregisterServiceImpl(service, userid); 174ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 1759f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown 1769f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown public void registerService(IInterface service, ComponentName component, int userid) { 1779f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown checkNotNull(service); 1789f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown registerServiceImpl(service, component, userid); 1799f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown } 1809f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown 1819f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown /** 1829f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown * Remove access for any services that no longer exist. 1839f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown */ 1849f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown private void disableNonexistentServices() { 1859f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown int[] userIds = mUserProfiles.getCurrentProfileIds(); 1869f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown final int N = userIds.length; 1879f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown for (int i = 0 ; i < N; ++i) { 1889f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown disableNonexistentServices(userIds[i]); 1899f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown } 1909df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown } 1919df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown 1929df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown private void disableNonexistentServices(int userId) { 193af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown String flatIn = Settings.Secure.getStringForUser( 194af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown mContext.getContentResolver(), 195af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown mConfig.secureSettingName, 196af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown userId); 197af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown if (!TextUtils.isEmpty(flatIn)) { 198af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown if (DEBUG) Slog.v(TAG, "flat before: " + flatIn); 199af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown PackageManager pm = mContext.getPackageManager(); 200af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser( 201af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown new Intent(mConfig.serviceInterface), 202af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown PackageManager.GET_SERVICES | PackageManager.GET_META_DATA, 203af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown userId); 204af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown if (DEBUG) Slog.v(TAG, mConfig.serviceInterface + " services: " + installedServices); 205af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown Set<ComponentName> installed = new ArraySet<ComponentName>(); 206af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown for (int i = 0, count = installedServices.size(); i < count; i++) { 207af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown ResolveInfo resolveInfo = installedServices.get(i); 208af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown ServiceInfo info = resolveInfo.serviceInfo; 209af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown 210af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown if (!mConfig.bindPermission.equals(info.permission)) { 211af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown Slog.w(TAG, "Skipping " + getCaption() + " service " 212af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown + info.packageName + "/" + info.name 213af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown + ": it does not require the permission " 214af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown + mConfig.bindPermission); 215af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown continue; 216af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 217af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown installed.add(new ComponentName(info.packageName, info.name)); 218af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 219af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown 220af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown String flatOut = ""; 221af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown if (!installed.isEmpty()) { 222af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown String[] enabled = flatIn.split(ENABLED_SERVICES_SEPARATOR); 223af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown ArrayList<String> remaining = new ArrayList<String>(enabled.length); 224af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown for (int i = 0; i < enabled.length; i++) { 225af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown ComponentName enabledComponent = ComponentName.unflattenFromString(enabled[i]); 226af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown if (installed.contains(enabledComponent)) { 227af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown remaining.add(enabled[i]); 228af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 229af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 230af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown flatOut = TextUtils.join(ENABLED_SERVICES_SEPARATOR, remaining); 231af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 232af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown if (DEBUG) Slog.v(TAG, "flat after: " + flatOut); 233af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown if (!flatIn.equals(flatOut)) { 234af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown Settings.Secure.putStringForUser(mContext.getContentResolver(), 235af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown mConfig.secureSettingName, 236af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown flatOut, userId); 237af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 238af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 239af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 240af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown 241af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown /** 242af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown * Called whenever packages change, the user switches, or the secure setting 243af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown * is altered. (For example in response to USER_SWITCHED in our broadcast receiver) 244af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown */ 245af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown private void rebindServices() { 246af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown if (DEBUG) Slog.d(TAG, "rebindServices"); 247af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown final int[] userIds = mUserProfiles.getCurrentProfileIds(); 248af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown final int nUserIds = userIds.length; 249af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown 250af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown final SparseArray<String> flat = new SparseArray<String>(); 251af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown 252af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown for (int i = 0; i < nUserIds; ++i) { 253af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown flat.put(userIds[i], Settings.Secure.getStringForUser( 254af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown mContext.getContentResolver(), 255af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown mConfig.secureSettingName, 256af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown userIds[i])); 257af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 258af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown 259af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown ManagedServiceInfo[] toRemove = new ManagedServiceInfo[mServices.size()]; 260af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown final SparseArray<ArrayList<ComponentName>> toAdd 261af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown = new SparseArray<ArrayList<ComponentName>>(); 262af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown 263af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown synchronized (mMutex) { 264af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown // unbind and remove all existing services 265af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown toRemove = mServices.toArray(toRemove); 266af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown 267af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown final ArraySet<ComponentName> newEnabled = new ArraySet<ComponentName>(); 268af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown final ArraySet<String> newPackages = new ArraySet<String>(); 269af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown 270af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown for (int i = 0; i < nUserIds; ++i) { 271af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown final ArrayList<ComponentName> add = new ArrayList<ComponentName>(); 272af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown toAdd.put(userIds[i], add); 273af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown 2749e6d4b035d4f012d23264d3d2bc946b1ca02dba1Jeff Brown // decode the list of components 2759e6d4b035d4f012d23264d3d2bc946b1ca02dba1Jeff Brown String toDecode = flat.get(userIds[i]); 276af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown if (toDecode != null) { 277af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown String[] components = toDecode.split(ENABLED_SERVICES_SEPARATOR); 278af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown for (int j = 0; j < components.length; j++) { 279af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown final ComponentName component 280af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown = ComponentName.unflattenFromString(components[j]); 281af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown if (component != null) { 282af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown newEnabled.add(component); 283af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown add.add(component); 284af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown newPackages.add(component.getPackageName()); 285af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 286af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 287af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown 288af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 289af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 290af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown mEnabledServicesForCurrentProfiles = newEnabled; 291af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown mEnabledServicesPackageNames = newPackages; 2929df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown } 2939df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown 2949df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown for (ManagedServiceInfo info : toRemove) { 2959df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown final ComponentName component = info.component; 2969df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown final int oldUser = info.userid; 2979df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown Slog.v(TAG, "disabling " + getCaption() + " for user " 2989df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown + oldUser + ": " + component); 2999df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown unregisterService(component, info.userid); 3009f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown } 3019df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown 3029df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown for (int i = 0; i < nUserIds; ++i) { 3039f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown final ArrayList<ComponentName> add = toAdd.get(userIds[i]); 3049f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown final int N = add.size(); 3059f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown for (int j = 0; j < N; j++) { 3069f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown final ComponentName component = add.get(j); 3079f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown Slog.v(TAG, "enabling " + getCaption() + " for user " + userIds[i] + ": " 3089f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown + component); 3099df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown registerService(component, userIds[i]); 3109df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown } 3119df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown } 3129df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown } 3139df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown 3149df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown /** 3159df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * Version of registerService that takes the name of a service component to bind to. 3169df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown */ 3179df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown private void registerService(final ComponentName name, final int userid) { 3189df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown if (DEBUG) Slog.v(TAG, "registerService: " + name + " u=" + userid); 3199df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown 3209df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown synchronized (mMutex) { 3219df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown final String servicesBindingTag = name.toString() + "/" + userid; 3229df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown if (mServicesBinding.contains(servicesBindingTag)) { 3239df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown // stop registering this thing already! we're working on it 3249df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown return; 3259df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown } 3269df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown mServicesBinding.add(servicesBindingTag); 3279f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown 3289f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown final int N = mServices.size(); 3299f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown for (int i=N-1; i>=0; i--) { 3309df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown final ManagedServiceInfo info = mServices.get(i); 3319df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown if (name.equals(info.component) 3329df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown && info.userid == userid) { 3339df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown // cut old connections 3349df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown if (DEBUG) Slog.v(TAG, " disconnecting old " + getCaption() + ": " 3359df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown + info.service); 3369df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown removeServiceLocked(i); 3379df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown if (info.connection != null) { 3389df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown mContext.unbindService(info.connection); 3399df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown } 3409df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown } 3419df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown } 3429df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown 3439f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown Intent intent = new Intent(mConfig.serviceInterface); 3449df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown intent.setComponent(name); 3459df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown 3469df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown intent.putExtra(Intent.EXTRA_CLIENT_LABEL, mConfig.clientLabel); 3479df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown 3489f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown final PendingIntent pendingIntent = PendingIntent.getActivity( 3499f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown mContext, 0, new Intent(mConfig.settingsAction), 0); 3509f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown intent.putExtra(Intent.EXTRA_CLIENT_INTENT, pendingIntent); 3519f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown 3529f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown ApplicationInfo appInfo = null; 3539f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown try { 3549df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown appInfo = mContext.getPackageManager().getApplicationInfo( 3559df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown name.getPackageName(), 0); 3569df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown } catch (NameNotFoundException e) { 3579df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown // Ignore if the package doesn't exist we won't be able to bind to the service. 3589df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown } 3599df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown final int targetSdkVersion = 3609df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown appInfo != null ? appInfo.targetSdkVersion : Build.VERSION_CODES.BASE; 3619df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown 3629df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown try { 3639df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown if (DEBUG) Slog.v(TAG, "binding: " + intent); 3649df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown if (!mContext.bindServiceAsUser(intent, 3659df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown new ServiceConnection() { 3669df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown IInterface mService; 3679df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown 3689df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown @Override 3699f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown public void onServiceConnected(ComponentName name, IBinder binder) { 3709df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown boolean added = false; 3719df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown ManagedServiceInfo info = null; 3729df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown synchronized (mMutex) { 3739df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown mServicesBinding.remove(servicesBindingTag); 3749df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown try { 3759df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown mService = asInterface(binder); 3769f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown info = newServiceInfo(mService, name, 3779f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown userid, false /*isSystem*/, this, targetSdkVersion); 3789f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown binder.linkToDeath(info, 0); 3799df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown added = mServices.add(info); 3809df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown } catch (RemoteException e) { 3819df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown // already dead 382ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 383ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 384ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown if (added) { 385ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown onServiceAdded(info); 386ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 387ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 388ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown 3899f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown @Override 390ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown public void onServiceDisconnected(ComponentName name) { 391ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown Slog.v(TAG, getCaption() + " connection lost: " + name); 392ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 393ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown }, 394ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown Context.BIND_AUTO_CREATE, 3959f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown new UserHandle(userid))) 396ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown { 397ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown mServicesBinding.remove(servicesBindingTag); 3989f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown Slog.w(TAG, "Unable to bind " + getCaption() + " service: " + intent); 399ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown return; 400ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 401ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } catch (SecurityException ex) { 402ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown Slog.e(TAG, "Unable to bind " + getCaption() + " service: " + intent, ex); 403ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown return; 404ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 405ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 406ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 407ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown 408ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown /** 409ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown * Remove a service for the given user by ComponentName 410ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown */ 4119f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown private void unregisterService(ComponentName name, int userid) { 412ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown synchronized (mMutex) { 413ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown final int N = mServices.size(); 414ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown for (int i=N-1; i>=0; i--) { 415ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown final ManagedServiceInfo info = mServices.get(i); 416ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown if (name.equals(info.component) 4179f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown && info.userid == userid) { 418ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown removeServiceLocked(i); 419ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown if (info.connection != null) { 420ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown try { 421ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown mContext.unbindService(info.connection); 4229f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown } catch (IllegalArgumentException ex) { 423ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown // something happened to the service: we think we have a connection 424ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown // but it's bogus. 425ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown Slog.e(TAG, getCaption() + " " + name + " could not be unbound: " + ex); 426ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 427ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 428ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 429ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 430ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 431ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 432ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown 433ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown /** 434ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown * Removes a service from the list but does not unbind 435ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown * 436ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown * @return the removed service. 437ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown */ 438ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown private ManagedServiceInfo removeServiceImpl(IInterface service, final int userid) { 439ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown if (DEBUG) Slog.d(TAG, "removeServiceImpl service=" + service + " u=" + userid); 440ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown ManagedServiceInfo serviceInfo = null; 441ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown synchronized (mMutex) { 442ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown final int N = mServices.size(); 4439f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown for (int i=N-1; i>=0; i--) { 444ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown final ManagedServiceInfo info = mServices.get(i); 445ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown if (info.service.asBinder() == service.asBinder() 446ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown && info.userid == userid) { 447ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown if (DEBUG) Slog.d(TAG, "Removing active service " + info.component); 448ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown serviceInfo = removeServiceLocked(i); 449ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 450ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 451ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 452ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown return serviceInfo; 453ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 454ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown 455ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown private ManagedServiceInfo removeServiceLocked(int i) { 456ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown final ManagedServiceInfo info = mServices.remove(i); 457ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown onServiceRemovedLocked(info); 458ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown return info; 459ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 460ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown 4619f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown private void checkNotNull(IInterface service) { 462ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown if (service == null) { 463ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown throw new IllegalArgumentException(getCaption() + " must not be null"); 4649f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown } 465ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 466ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown 467ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown private void registerServiceImpl(final IInterface service, 468ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown final ComponentName component, final int userid) { 469ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown synchronized (mMutex) { 470ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown try { 471ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown ManagedServiceInfo info = newServiceInfo(service, component, userid, 472ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown true /*isSystem*/, null, Build.VERSION_CODES.L); 473ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown service.asBinder().linkToDeath(info, 0); 474ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown mServices.add(info); 475ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } catch (RemoteException e) { 476ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown // already dead 477ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 478ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 479ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 480ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown 481ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown /** 482ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown * Removes a service from the list and unbinds. 483ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown */ 484ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown private void unregisterServiceImpl(IInterface service, int userid) { 485ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown ManagedServiceInfo info = removeServiceImpl(service, userid); 486ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown if (info != null && info.connection != null) { 487ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown mContext.unbindService(info.connection); 488ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 489ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 490ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown 491ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown private class SettingsObserver extends ContentObserver { 4929f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown private final Uri mSecureSettingsUri = Settings.Secure.getUriFor(mConfig.secureSettingName); 493ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown 494ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown private SettingsObserver(Handler handler) { 495ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown super(handler); 496ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown } 497ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown 498ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown private void observe() { 499ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown ContentResolver resolver = mContext.getContentResolver(); 500ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown resolver.registerContentObserver(mSecureSettingsUri, 501ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown false, this, UserHandle.USER_ALL); 502ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown update(null); 5039f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown } 504ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown 505ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown @Override 506ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown public void onChange(boolean selfChange, Uri uri) { 507ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown update(uri); 508af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 509af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown 510af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown private void update(Uri uri) { 511af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown if (uri == null || mSecureSettingsUri.equals(uri)) { 512af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown rebindServices(); 513af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 514af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 515af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 516af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown 517af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown public class ManagedServiceInfo implements IBinder.DeathRecipient { 518af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown public IInterface service; 519af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown public ComponentName component; 520af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown public int userid; 521af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown public boolean isSystem; 522af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown public ServiceConnection connection; 523af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown public int targetSdkVersion; 524af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown 525af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown public ManagedServiceInfo(IInterface service, ComponentName component, 526af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown int userid, boolean isSystem, ServiceConnection connection, int targetSdkVersion) { 527af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown this.service = service; 528af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown this.component = component; 529af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown this.userid = userid; 530af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown this.isSystem = isSystem; 531af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown this.connection = connection; 532af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown this.targetSdkVersion = targetSdkVersion; 533af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 534af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown 535af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown @Override 536af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown public String toString() { 537af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown return new StringBuilder("ManagedServiceInfo[") 538af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown .append("component=").append(component) 539af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown .append(",userid=").append(userid) 540af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown .append(",isSystem=").append(isSystem) 541af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown .append(",targetSdkVersion=").append(targetSdkVersion) 542af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown .append(",connection=").append(connection == null ? null : "<connection>") 543af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown .append(",service=").append(service) 544af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown .append(']').toString(); 545af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 546af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown 547af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown public boolean enabledAndUserMatches(int nid) { 548af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown if (!isEnabledForCurrentProfiles()) { 549af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown return false; 550af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 551af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown if (this.userid == UserHandle.USER_ALL) return true; 552af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown if (nid == UserHandle.USER_ALL || nid == this.userid) return true; 553af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown return supportsProfiles() && mUserProfiles.isCurrentProfile(nid); 554af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 555af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown 556af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown public boolean supportsProfiles() { 557af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown return targetSdkVersion >= Build.VERSION_CODES.L; 558af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 559af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown 560af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown @Override 561af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown public void binderDied() { 562af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown if (DEBUG) Slog.d(TAG, "binderDied"); 563af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown // Remove the service, but don't unbind from the service. The system will bring the 564af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown // service back up, and the onServiceConnected handler will readd the service with the 565af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown // new binding. If this isn't a bound service, and is just a registered 566af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown // service, just removing it from the list is all we need to do anyway. 567af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown removeServiceImpl(this.service, this.userid); 568af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 569af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown 570af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown /** convenience method for looking in mEnabledServicesForCurrentProfiles */ 571af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown public boolean isEnabledForCurrentProfiles() { 572af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown if (this.isSystem) return true; 573af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown if (this.connection == null) return false; 574af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown return mEnabledServicesForCurrentProfiles.contains(this.component); 575af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 576af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 577af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown 578af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown public static class UserProfiles { 579af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown // Profiles of the current user. 580af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown private final SparseArray<UserInfo> mCurrentProfiles = new SparseArray<UserInfo>(); 581af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown 582af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown public void updateCache(Context context) { 583af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE); 584af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown if (userManager != null) { 585af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown int currentUserId = ActivityManager.getCurrentUser(); 586af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown List<UserInfo> profiles = userManager.getProfiles(currentUserId); 587af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown synchronized (mCurrentProfiles) { 588af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown mCurrentProfiles.clear(); 589af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown for (UserInfo user : profiles) { 590af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown mCurrentProfiles.put(user.id, user); 591af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 592af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 593af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 594af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 595af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown 596af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown public int[] getCurrentProfileIds() { 597a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown synchronized (mCurrentProfiles) { 598a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown int[] users = new int[mCurrentProfiles.size()]; 599a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown final int N = mCurrentProfiles.size(); 600a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown for (int i = 0; i < N; ++i) { 601a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown users[i] = mCurrentProfiles.keyAt(i); 602a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown } 603a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown return users; 604a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown } 605a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown } 606af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown 607af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown public boolean isCurrentProfile(int userId) { 608af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown synchronized (mCurrentProfiles) { 609af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown return mCurrentProfiles.get(userId) != null; 610af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 611af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 612af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 613af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown 614af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown protected static class Config { 615af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown String caption; 616af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown String serviceInterface; 617af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown String secureSettingName; 618af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown String bindPermission; 619af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown String settingsAction; 620af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown int clientLabel; 621af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown } 622af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown} 623af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown