blob: 2ff036be4b4b8dba653d6498df142157d6fe5796 [file] [log] [blame]
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001/*
2 * Copyright (C) 2012 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
17package com.android.server;
18
Jeff Sharkey58482c552016-02-08 17:49:17 -070019import android.annotation.Nullable;
Victoria Lease03cdd3d2013-02-01 15:15:54 -080020import android.content.BroadcastReceiver;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070021import android.content.ComponentName;
22import android.content.Context;
23import android.content.Intent;
Victoria Lease03cdd3d2013-02-01 15:15:54 -080024import android.content.IntentFilter;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070025import android.content.ServiceConnection;
26import android.content.pm.PackageInfo;
27import android.content.pm.PackageManager;
28import android.content.pm.PackageManager.NameNotFoundException;
29import android.content.pm.ResolveInfo;
30import android.content.pm.Signature;
Zhentao Sunc5fc9982013-04-17 17:47:53 -070031import android.content.res.Resources;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070032import android.os.Handler;
33import android.os.IBinder;
Victoria Leaseb711d572012-10-02 13:14:11 -070034import android.os.UserHandle;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070035import android.util.Log;
Jeff Sharkey58482c552016-02-08 17:49:17 -070036import android.util.Slog;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070037
Jeff Sharkey58482c552016-02-08 17:49:17 -070038import com.android.internal.annotations.GuardedBy;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070039import com.android.internal.content.PackageMonitor;
40
41import java.util.ArrayList;
42import java.util.Arrays;
43import java.util.HashSet;
44import java.util.List;
Jeff Sharkey58482c552016-02-08 17:49:17 -070045import java.util.Objects;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070046
47/**
48 * Find the best Service, and bind to it.
49 * Handles run-time package changes.
50 */
51public class ServiceWatcher implements ServiceConnection {
52 private static final boolean D = false;
Jeff Hamiltonfbadb692012-10-05 14:21:58 -050053 public static final String EXTRA_SERVICE_VERSION = "serviceVersion";
Victoria Lease03cdd3d2013-02-01 15:15:54 -080054 public static final String EXTRA_SERVICE_IS_MULTIUSER = "serviceIsMultiuser";
Nick Pelly6fa9ad42012-07-16 12:18:23 -070055
56 private final String mTag;
57 private final Context mContext;
58 private final PackageManager mPm;
59 private final List<HashSet<Signature>> mSignatureSets;
60 private final String mAction;
Zhentao Sunc5fc9982013-04-17 17:47:53 -070061
62 /**
63 * If mServicePackageName is not null, only this package will be searched for the service that
64 * implements mAction. When null, all packages in the system that matches one of the signature
65 * in mSignatureSets are searched.
66 */
67 private final String mServicePackageName;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070068 private final Runnable mNewServiceWork;
69 private final Handler mHandler;
70
Jeff Sharkey58482c552016-02-08 17:49:17 -070071 private final Object mLock = new Object();
Nick Pelly6fa9ad42012-07-16 12:18:23 -070072
Jeff Sharkey58482c552016-02-08 17:49:17 -070073 @GuardedBy("mLock")
74 private int mCurrentUserId = UserHandle.USER_SYSTEM;
75
76 @GuardedBy("mLock")
77 private IBinder mBoundService;
78 @GuardedBy("mLock")
79 private ComponentName mBoundComponent;
80 @GuardedBy("mLock")
81 private String mBoundPackageName;
82 @GuardedBy("mLock")
83 private int mBoundVersion = Integer.MIN_VALUE;
84 @GuardedBy("mLock")
85 private int mBoundUserId = UserHandle.USER_NULL;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070086
Jeff Hamiltonfbadb692012-10-05 14:21:58 -050087 public static ArrayList<HashSet<Signature>> getSignatureSets(Context context,
88 List<String> initialPackageNames) {
89 PackageManager pm = context.getPackageManager();
90 ArrayList<HashSet<Signature>> sigSets = new ArrayList<HashSet<Signature>>();
91 for (int i = 0, size = initialPackageNames.size(); i < size; i++) {
92 String pkg = initialPackageNames.get(i);
93 try {
94 HashSet<Signature> set = new HashSet<Signature>();
Jeff Sharkeyc7bacab2016-02-09 15:56:11 -070095 Signature[] sigs = pm.getPackageInfo(pkg, PackageManager.MATCH_SYSTEM_ONLY
96 | PackageManager.GET_SIGNATURES).signatures;
Jeff Hamiltonfbadb692012-10-05 14:21:58 -050097 set.addAll(Arrays.asList(sigs));
98 sigSets.add(set);
99 } catch (NameNotFoundException e) {
100 Log.w("ServiceWatcher", pkg + " not found");
101 }
102 }
103 return sigSets;
104 }
105
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700106 public ServiceWatcher(Context context, String logTag, String action,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700107 int overlaySwitchResId, int defaultServicePackageNameResId,
108 int initialPackageNamesResId, Runnable newServiceWork,
109 Handler handler) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700110 mContext = context;
111 mTag = logTag;
112 mAction = action;
113 mPm = mContext.getPackageManager();
114 mNewServiceWork = newServiceWork;
115 mHandler = handler;
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700116 Resources resources = context.getResources();
117
118 // Whether to enable service overlay.
119 boolean enableOverlay = resources.getBoolean(overlaySwitchResId);
Jeff Sharkey58482c552016-02-08 17:49:17 -0700120 ArrayList<String> initialPackageNames = new ArrayList<String>();
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700121 if (enableOverlay) {
122 // A list of package names used to create the signatures.
123 String[] pkgs = resources.getStringArray(initialPackageNamesResId);
124 if (pkgs != null) initialPackageNames.addAll(Arrays.asList(pkgs));
125 mServicePackageName = null;
126 if (D) Log.d(mTag, "Overlay enabled, packages=" + Arrays.toString(pkgs));
127 } else {
128 // The default package name that is searched for service implementation when overlay is
129 // disabled.
130 String servicePackageName = resources.getString(defaultServicePackageNameResId);
131 if (servicePackageName != null) initialPackageNames.add(servicePackageName);
132 mServicePackageName = servicePackageName;
133 if (D) Log.d(mTag, "Overlay disabled, default package=" + servicePackageName);
134 }
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500135 mSignatureSets = getSignatureSets(context, initialPackageNames);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700136 }
137
Jeff Sharkey58482c552016-02-08 17:49:17 -0700138 /**
139 * Start this watcher, including binding to the current best match and
140 * re-binding to any better matches down the road.
141 * <p>
142 * Note that if there are no matching encryption-aware services, we may not
143 * bind to a real service until after the current user is unlocked.
Jeff Sharkey05ed25c2016-09-20 17:20:17 -0600144 *
145 * @returns {@code true} if a potential service implementation was found.
Jeff Sharkey58482c552016-02-08 17:49:17 -0700146 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700147 public boolean start() {
Jeff Sharkey05ed25c2016-09-20 17:20:17 -0600148 if (isServiceMissing()) return false;
149
Victoria Leaseb711d572012-10-02 13:14:11 -0700150 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700151 bindBestPackageLocked(mServicePackageName, false);
Victoria Leaseb711d572012-10-02 13:14:11 -0700152 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700153
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800154 // listen for user change
155 IntentFilter intentFilter = new IntentFilter();
156 intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
Jeff Sharkey58482c552016-02-08 17:49:17 -0700157 intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800158 mContext.registerReceiverAsUser(new BroadcastReceiver() {
159 @Override
160 public void onReceive(Context context, Intent intent) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700161 final String action = intent.getAction();
162 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
163 UserHandle.USER_NULL);
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800164 if (Intent.ACTION_USER_SWITCHED.equals(action)) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700165 switchUser(userId);
166 } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
167 unlockUser(userId);
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800168 }
169 }
170 }, UserHandle.ALL, intentFilter, null, mHandler);
171
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700172 // listen for relevant package changes if service overlay is enabled.
173 if (mServicePackageName == null) {
174 mPackageMonitor.register(mContext, null, UserHandle.ALL, true);
175 }
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800176
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700177 return true;
178 }
179
180 /**
Jeff Sharkey05ed25c2016-09-20 17:20:17 -0600181 * Check if any instance of this service is present on the device,
182 * regardless of it being encryption-aware or not.
183 */
184 private boolean isServiceMissing() {
185 final Intent intent = new Intent(mAction);
186 final int flags = PackageManager.MATCH_DIRECT_BOOT_AWARE
187 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
188 return mPm.queryIntentServicesAsUser(intent, flags, mCurrentUserId).isEmpty();
189 }
190
191 /**
Jeff Sharkey58482c552016-02-08 17:49:17 -0700192 * Searches and binds to the best package, or do nothing if the best package
193 * is already bound, unless force rebinding is requested.
194 *
195 * @param justCheckThisPackage Only consider this package, or consider all
196 * packages if it is {@code null}.
197 * @param forceRebind Force a rebinding to the best package if it's already
198 * bound.
Jeff Sharkey05ed25c2016-09-20 17:20:17 -0600199 * @returns {@code true} if a valid package was found to bind to.
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700200 */
Jeff Sharkey58482c552016-02-08 17:49:17 -0700201 private boolean bindBestPackageLocked(String justCheckThisPackage, boolean forceRebind) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700202 Intent intent = new Intent(mAction);
203 if (justCheckThisPackage != null) {
204 intent.setPackage(justCheckThisPackage);
205 }
Jeff Sharkey58482c552016-02-08 17:49:17 -0700206 final List<ResolveInfo> rInfos = mPm.queryIntentServicesAsUser(intent,
207 PackageManager.GET_META_DATA | PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
208 mCurrentUserId);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700209 int bestVersion = Integer.MIN_VALUE;
Jeff Sharkey58482c552016-02-08 17:49:17 -0700210 ComponentName bestComponent = null;
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800211 boolean bestIsMultiuser = false;
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700212 if (rInfos != null) {
213 for (ResolveInfo rInfo : rInfos) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700214 final ComponentName component = rInfo.serviceInfo.getComponentName();
215 final String packageName = component.getPackageName();
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700216
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700217 // check signature
218 try {
219 PackageInfo pInfo;
Jeff Sharkey58482c552016-02-08 17:49:17 -0700220 pInfo = mPm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES
221 | PackageManager.MATCH_DEBUG_TRIAGED_MISSING);
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700222 if (!isSignatureMatch(pInfo.signatures)) {
223 Log.w(mTag, packageName + " resolves service " + mAction
224 + ", but has wrong signature, ignoring");
225 continue;
226 }
227 } catch (NameNotFoundException e) {
228 Log.wtf(mTag, e);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700229 continue;
230 }
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700231
232 // check metadata
233 int version = Integer.MIN_VALUE;
234 boolean isMultiuser = false;
235 if (rInfo.serviceInfo.metaData != null) {
236 version = rInfo.serviceInfo.metaData.getInt(
237 EXTRA_SERVICE_VERSION, Integer.MIN_VALUE);
238 isMultiuser = rInfo.serviceInfo.metaData.getBoolean(EXTRA_SERVICE_IS_MULTIUSER);
239 }
240
Jeff Sharkey58482c552016-02-08 17:49:17 -0700241 if (version > bestVersion) {
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700242 bestVersion = version;
Jeff Sharkey58482c552016-02-08 17:49:17 -0700243 bestComponent = component;
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700244 bestIsMultiuser = isMultiuser;
245 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700246 }
247
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700248 if (D) {
249 Log.d(mTag, String.format("bindBestPackage for %s : %s found %d, %s", mAction,
250 (justCheckThisPackage == null ? ""
251 : "(" + justCheckThisPackage + ") "), rInfos.size(),
Jeff Sharkey58482c552016-02-08 17:49:17 -0700252 (bestComponent == null ? "no new best component"
253 : "new best component: " + bestComponent)));
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700254 }
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700255 } else {
256 if (D) Log.d(mTag, "Unable to query intent services for action: " + mAction);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700257 }
Jeff Sharkey58482c552016-02-08 17:49:17 -0700258
259 if (bestComponent == null) {
260 Slog.w(mTag, "Odd, no component found for service " + mAction);
261 unbindLocked();
262 return false;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700263 }
Jeff Sharkey58482c552016-02-08 17:49:17 -0700264
265 final int userId = bestIsMultiuser ? UserHandle.USER_SYSTEM : mCurrentUserId;
266 final boolean alreadyBound = Objects.equals(bestComponent, mBoundComponent)
267 && bestVersion == mBoundVersion && userId == mBoundUserId;
268 if (forceRebind || !alreadyBound) {
269 unbindLocked();
270 bindToPackageLocked(bestComponent, bestVersion, userId);
271 }
272 return true;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700273 }
274
Victoria Leaseb711d572012-10-02 13:14:11 -0700275 private void unbindLocked() {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700276 ComponentName component;
277 component = mBoundComponent;
278 mBoundComponent = null;
279 mBoundPackageName = null;
280 mBoundVersion = Integer.MIN_VALUE;
281 mBoundUserId = UserHandle.USER_NULL;
282 if (component != null) {
283 if (D) Log.d(mTag, "unbinding " + component);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700284 mContext.unbindService(this);
285 }
286 }
287
Jeff Sharkey58482c552016-02-08 17:49:17 -0700288 private void bindToPackageLocked(ComponentName component, int version, int userId) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700289 Intent intent = new Intent(mAction);
Jeff Sharkey58482c552016-02-08 17:49:17 -0700290 intent.setComponent(component);
291 mBoundComponent = component;
292 mBoundPackageName = component.getPackageName();
293 mBoundVersion = version;
294 mBoundUserId = userId;
295 if (D) Log.d(mTag, "binding " + component + " (v" + version + ") (u" + userId + ")");
296 mContext.bindServiceAsUser(intent, this,
297 Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE,
298 new UserHandle(userId));
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700299 }
300
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500301 public static boolean isSignatureMatch(Signature[] signatures,
302 List<HashSet<Signature>> sigSets) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700303 if (signatures == null) return false;
304
305 // build hashset of input to test against
306 HashSet<Signature> inputSet = new HashSet<Signature>();
307 for (Signature s : signatures) {
308 inputSet.add(s);
309 }
310
311 // test input against each of the signature sets
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500312 for (HashSet<Signature> referenceSet : sigSets) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700313 if (referenceSet.equals(inputSet)) {
314 return true;
315 }
316 }
317 return false;
318 }
319
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500320 private boolean isSignatureMatch(Signature[] signatures) {
321 return isSignatureMatch(signatures, mSignatureSets);
322 }
323
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700324 private final PackageMonitor mPackageMonitor = new PackageMonitor() {
325 /**
326 * Called when package has been reinstalled
327 */
328 @Override
329 public void onPackageUpdateFinished(String packageName, int uid) {
Victoria Leaseb711d572012-10-02 13:14:11 -0700330 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700331 final boolean forceRebind = Objects.equals(packageName, mBoundPackageName);
332 bindBestPackageLocked(null, forceRebind);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700333 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700334 }
335
336 @Override
337 public void onPackageAdded(String packageName, int uid) {
Victoria Leaseb711d572012-10-02 13:14:11 -0700338 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700339 final boolean forceRebind = Objects.equals(packageName, mBoundPackageName);
340 bindBestPackageLocked(null, forceRebind);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700341 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700342 }
343
344 @Override
345 public void onPackageRemoved(String packageName, int uid) {
Victoria Leaseb711d572012-10-02 13:14:11 -0700346 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700347 final boolean forceRebind = Objects.equals(packageName, mBoundPackageName);
348 bindBestPackageLocked(null, forceRebind);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700349 }
350 }
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700351
352 @Override
353 public boolean onPackageChanged(String packageName, int uid, String[] components) {
354 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700355 final boolean forceRebind = Objects.equals(packageName, mBoundPackageName);
356 bindBestPackageLocked(null, forceRebind);
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700357 }
358 return super.onPackageChanged(packageName, uid, components);
359 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700360 };
361
362 @Override
Jeff Sharkey58482c552016-02-08 17:49:17 -0700363 public void onServiceConnected(ComponentName component, IBinder binder) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700364 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700365 if (component.equals(mBoundComponent)) {
366 if (D) Log.d(mTag, component + " connected");
367 mBoundService = binder;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700368 if (mHandler !=null && mNewServiceWork != null) {
369 mHandler.post(mNewServiceWork);
370 }
371 } else {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700372 Log.w(mTag, "unexpected onServiceConnected: " + component);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700373 }
374 }
375 }
376
377 @Override
Jeff Sharkey58482c552016-02-08 17:49:17 -0700378 public void onServiceDisconnected(ComponentName component) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700379 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700380 if (D) Log.d(mTag, component + " disconnected");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700381
Jeff Sharkey58482c552016-02-08 17:49:17 -0700382 if (component.equals(mBoundComponent)) {
383 mBoundService = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700384 }
385 }
386 }
387
Jeff Sharkey58482c552016-02-08 17:49:17 -0700388 public @Nullable String getBestPackageName() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700389 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700390 return mBoundPackageName;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700391 }
392 }
393
394 public int getBestVersion() {
395 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700396 return mBoundVersion;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700397 }
398 }
399
Jeff Sharkey58482c552016-02-08 17:49:17 -0700400 public @Nullable IBinder getBinder() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700401 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700402 return mBoundService;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700403 }
404 }
Victoria Leaseb711d572012-10-02 13:14:11 -0700405
Jeff Sharkey58482c552016-02-08 17:49:17 -0700406 public void switchUser(int userId) {
Victoria Leaseb711d572012-10-02 13:14:11 -0700407 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700408 mCurrentUserId = userId;
409 bindBestPackageLocked(mServicePackageName, false);
410 }
411 }
412
413 public void unlockUser(int userId) {
414 synchronized (mLock) {
415 if (userId == mCurrentUserId) {
416 bindBestPackageLocked(mServicePackageName, false);
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800417 }
Victoria Leaseb711d572012-10-02 13:14:11 -0700418 }
419 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700420}