blob: f4238f21f47c2b0977d3fb4fcd7654e3624df2b3 [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
Lifu Tang66f761c2017-11-13 15:51:54 -080019import android.annotation.NonNull;
Jeff Sharkey58482c552016-02-08 17:49:17 -070020import android.annotation.Nullable;
Victoria Lease03cdd3d2013-02-01 15:15:54 -080021import android.content.BroadcastReceiver;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070022import android.content.ComponentName;
23import android.content.Context;
24import android.content.Intent;
Victoria Lease03cdd3d2013-02-01 15:15:54 -080025import android.content.IntentFilter;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070026import android.content.ServiceConnection;
27import android.content.pm.PackageInfo;
28import android.content.pm.PackageManager;
29import android.content.pm.PackageManager.NameNotFoundException;
30import android.content.pm.ResolveInfo;
31import android.content.pm.Signature;
Zhentao Sunc5fc9982013-04-17 17:47:53 -070032import android.content.res.Resources;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070033import android.os.Handler;
34import android.os.IBinder;
Victoria Leaseb711d572012-10-02 13:14:11 -070035import android.os.UserHandle;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070036import android.util.Log;
Jeff Sharkey58482c552016-02-08 17:49:17 -070037import android.util.Slog;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070038
Jeff Sharkey58482c552016-02-08 17:49:17 -070039import com.android.internal.annotations.GuardedBy;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070040import com.android.internal.content.PackageMonitor;
41
42import java.util.ArrayList;
43import java.util.Arrays;
44import java.util.HashSet;
45import java.util.List;
Jeff Sharkey58482c552016-02-08 17:49:17 -070046import java.util.Objects;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070047
48/**
49 * Find the best Service, and bind to it.
50 * Handles run-time package changes.
51 */
52public class ServiceWatcher implements ServiceConnection {
53 private static final boolean D = false;
Jeff Hamiltonfbadb692012-10-05 14:21:58 -050054 public static final String EXTRA_SERVICE_VERSION = "serviceVersion";
Victoria Lease03cdd3d2013-02-01 15:15:54 -080055 public static final String EXTRA_SERVICE_IS_MULTIUSER = "serviceIsMultiuser";
Nick Pelly6fa9ad42012-07-16 12:18:23 -070056
57 private final String mTag;
58 private final Context mContext;
59 private final PackageManager mPm;
60 private final List<HashSet<Signature>> mSignatureSets;
61 private final String mAction;
Zhentao Sunc5fc9982013-04-17 17:47:53 -070062
63 /**
64 * If mServicePackageName is not null, only this package will be searched for the service that
65 * implements mAction. When null, all packages in the system that matches one of the signature
66 * in mSignatureSets are searched.
67 */
68 private final String mServicePackageName;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070069 private final Runnable mNewServiceWork;
70 private final Handler mHandler;
71
Jeff Sharkey58482c552016-02-08 17:49:17 -070072 private final Object mLock = new Object();
Nick Pelly6fa9ad42012-07-16 12:18:23 -070073
Jeff Sharkey58482c552016-02-08 17:49:17 -070074 @GuardedBy("mLock")
75 private int mCurrentUserId = UserHandle.USER_SYSTEM;
76
77 @GuardedBy("mLock")
78 private IBinder mBoundService;
79 @GuardedBy("mLock")
80 private ComponentName mBoundComponent;
81 @GuardedBy("mLock")
82 private String mBoundPackageName;
83 @GuardedBy("mLock")
84 private int mBoundVersion = Integer.MIN_VALUE;
85 @GuardedBy("mLock")
86 private int mBoundUserId = UserHandle.USER_NULL;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070087
Jeff Hamiltonfbadb692012-10-05 14:21:58 -050088 public static ArrayList<HashSet<Signature>> getSignatureSets(Context context,
89 List<String> initialPackageNames) {
90 PackageManager pm = context.getPackageManager();
91 ArrayList<HashSet<Signature>> sigSets = new ArrayList<HashSet<Signature>>();
92 for (int i = 0, size = initialPackageNames.size(); i < size; i++) {
93 String pkg = initialPackageNames.get(i);
94 try {
95 HashSet<Signature> set = new HashSet<Signature>();
Jeff Sharkeyc7bacab2016-02-09 15:56:11 -070096 Signature[] sigs = pm.getPackageInfo(pkg, PackageManager.MATCH_SYSTEM_ONLY
97 | PackageManager.GET_SIGNATURES).signatures;
Jeff Hamiltonfbadb692012-10-05 14:21:58 -050098 set.addAll(Arrays.asList(sigs));
99 sigSets.add(set);
100 } catch (NameNotFoundException e) {
101 Log.w("ServiceWatcher", pkg + " not found");
102 }
103 }
104 return sigSets;
105 }
106
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700107 public ServiceWatcher(Context context, String logTag, String action,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700108 int overlaySwitchResId, int defaultServicePackageNameResId,
109 int initialPackageNamesResId, Runnable newServiceWork,
110 Handler handler) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700111 mContext = context;
112 mTag = logTag;
113 mAction = action;
114 mPm = mContext.getPackageManager();
115 mNewServiceWork = newServiceWork;
116 mHandler = handler;
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700117 Resources resources = context.getResources();
118
119 // Whether to enable service overlay.
120 boolean enableOverlay = resources.getBoolean(overlaySwitchResId);
Jeff Sharkey58482c552016-02-08 17:49:17 -0700121 ArrayList<String> initialPackageNames = new ArrayList<String>();
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700122 if (enableOverlay) {
123 // A list of package names used to create the signatures.
124 String[] pkgs = resources.getStringArray(initialPackageNamesResId);
125 if (pkgs != null) initialPackageNames.addAll(Arrays.asList(pkgs));
126 mServicePackageName = null;
127 if (D) Log.d(mTag, "Overlay enabled, packages=" + Arrays.toString(pkgs));
128 } else {
129 // The default package name that is searched for service implementation when overlay is
130 // disabled.
131 String servicePackageName = resources.getString(defaultServicePackageNameResId);
132 if (servicePackageName != null) initialPackageNames.add(servicePackageName);
133 mServicePackageName = servicePackageName;
134 if (D) Log.d(mTag, "Overlay disabled, default package=" + servicePackageName);
135 }
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500136 mSignatureSets = getSignatureSets(context, initialPackageNames);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700137 }
138
Jeff Sharkey58482c552016-02-08 17:49:17 -0700139 /**
140 * Start this watcher, including binding to the current best match and
141 * re-binding to any better matches down the road.
142 * <p>
143 * Note that if there are no matching encryption-aware services, we may not
144 * bind to a real service until after the current user is unlocked.
Jeff Sharkey05ed25c2016-09-20 17:20:17 -0600145 *
146 * @returns {@code true} if a potential service implementation was found.
Jeff Sharkey58482c552016-02-08 17:49:17 -0700147 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700148 public boolean start() {
Jeff Sharkey05ed25c2016-09-20 17:20:17 -0600149 if (isServiceMissing()) return false;
150
Victoria Leaseb711d572012-10-02 13:14:11 -0700151 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700152 bindBestPackageLocked(mServicePackageName, false);
Victoria Leaseb711d572012-10-02 13:14:11 -0700153 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700154
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800155 // listen for user change
156 IntentFilter intentFilter = new IntentFilter();
157 intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
Jeff Sharkey58482c552016-02-08 17:49:17 -0700158 intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800159 mContext.registerReceiverAsUser(new BroadcastReceiver() {
160 @Override
161 public void onReceive(Context context, Intent intent) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700162 final String action = intent.getAction();
163 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
164 UserHandle.USER_NULL);
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800165 if (Intent.ACTION_USER_SWITCHED.equals(action)) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700166 switchUser(userId);
167 } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
168 unlockUser(userId);
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800169 }
170 }
171 }, UserHandle.ALL, intentFilter, null, mHandler);
172
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700173 // listen for relevant package changes if service overlay is enabled.
174 if (mServicePackageName == null) {
175 mPackageMonitor.register(mContext, null, UserHandle.ALL, true);
176 }
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800177
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700178 return true;
179 }
180
181 /**
Jeff Sharkey05ed25c2016-09-20 17:20:17 -0600182 * Check if any instance of this service is present on the device,
183 * regardless of it being encryption-aware or not.
184 */
185 private boolean isServiceMissing() {
186 final Intent intent = new Intent(mAction);
187 final int flags = PackageManager.MATCH_DIRECT_BOOT_AWARE
188 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
189 return mPm.queryIntentServicesAsUser(intent, flags, mCurrentUserId).isEmpty();
190 }
191
192 /**
Jeff Sharkey58482c552016-02-08 17:49:17 -0700193 * Searches and binds to the best package, or do nothing if the best package
194 * is already bound, unless force rebinding is requested.
195 *
196 * @param justCheckThisPackage Only consider this package, or consider all
197 * packages if it is {@code null}.
198 * @param forceRebind Force a rebinding to the best package if it's already
199 * bound.
Jeff Sharkey05ed25c2016-09-20 17:20:17 -0600200 * @returns {@code true} if a valid package was found to bind to.
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700201 */
Jeff Sharkey58482c552016-02-08 17:49:17 -0700202 private boolean bindBestPackageLocked(String justCheckThisPackage, boolean forceRebind) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700203 Intent intent = new Intent(mAction);
204 if (justCheckThisPackage != null) {
205 intent.setPackage(justCheckThisPackage);
206 }
Jeff Sharkey58482c552016-02-08 17:49:17 -0700207 final List<ResolveInfo> rInfos = mPm.queryIntentServicesAsUser(intent,
208 PackageManager.GET_META_DATA | PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
209 mCurrentUserId);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700210 int bestVersion = Integer.MIN_VALUE;
Jeff Sharkey58482c552016-02-08 17:49:17 -0700211 ComponentName bestComponent = null;
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800212 boolean bestIsMultiuser = false;
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700213 if (rInfos != null) {
214 for (ResolveInfo rInfo : rInfos) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700215 final ComponentName component = rInfo.serviceInfo.getComponentName();
216 final String packageName = component.getPackageName();
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700217
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700218 // check signature
219 try {
220 PackageInfo pInfo;
Jeff Sharkey58482c552016-02-08 17:49:17 -0700221 pInfo = mPm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES
222 | PackageManager.MATCH_DEBUG_TRIAGED_MISSING);
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700223 if (!isSignatureMatch(pInfo.signatures)) {
224 Log.w(mTag, packageName + " resolves service " + mAction
225 + ", but has wrong signature, ignoring");
226 continue;
227 }
228 } catch (NameNotFoundException e) {
229 Log.wtf(mTag, e);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700230 continue;
231 }
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700232
233 // check metadata
234 int version = Integer.MIN_VALUE;
235 boolean isMultiuser = false;
236 if (rInfo.serviceInfo.metaData != null) {
237 version = rInfo.serviceInfo.metaData.getInt(
238 EXTRA_SERVICE_VERSION, Integer.MIN_VALUE);
239 isMultiuser = rInfo.serviceInfo.metaData.getBoolean(EXTRA_SERVICE_IS_MULTIUSER);
240 }
241
Jeff Sharkey58482c552016-02-08 17:49:17 -0700242 if (version > bestVersion) {
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700243 bestVersion = version;
Jeff Sharkey58482c552016-02-08 17:49:17 -0700244 bestComponent = component;
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700245 bestIsMultiuser = isMultiuser;
246 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700247 }
248
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700249 if (D) {
250 Log.d(mTag, String.format("bindBestPackage for %s : %s found %d, %s", mAction,
251 (justCheckThisPackage == null ? ""
252 : "(" + justCheckThisPackage + ") "), rInfos.size(),
Jeff Sharkey58482c552016-02-08 17:49:17 -0700253 (bestComponent == null ? "no new best component"
254 : "new best component: " + bestComponent)));
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700255 }
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700256 } else {
257 if (D) Log.d(mTag, "Unable to query intent services for action: " + mAction);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700258 }
Jeff Sharkey58482c552016-02-08 17:49:17 -0700259
260 if (bestComponent == null) {
261 Slog.w(mTag, "Odd, no component found for service " + mAction);
262 unbindLocked();
263 return false;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700264 }
Jeff Sharkey58482c552016-02-08 17:49:17 -0700265
266 final int userId = bestIsMultiuser ? UserHandle.USER_SYSTEM : mCurrentUserId;
267 final boolean alreadyBound = Objects.equals(bestComponent, mBoundComponent)
268 && bestVersion == mBoundVersion && userId == mBoundUserId;
269 if (forceRebind || !alreadyBound) {
270 unbindLocked();
271 bindToPackageLocked(bestComponent, bestVersion, userId);
272 }
273 return true;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700274 }
275
Victoria Leaseb711d572012-10-02 13:14:11 -0700276 private void unbindLocked() {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700277 ComponentName component;
278 component = mBoundComponent;
279 mBoundComponent = null;
280 mBoundPackageName = null;
281 mBoundVersion = Integer.MIN_VALUE;
282 mBoundUserId = UserHandle.USER_NULL;
283 if (component != null) {
284 if (D) Log.d(mTag, "unbinding " + component);
Lifu Tangeb298df2017-11-22 12:13:12 -0800285 mBoundService = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700286 mContext.unbindService(this);
287 }
288 }
289
Jeff Sharkey58482c552016-02-08 17:49:17 -0700290 private void bindToPackageLocked(ComponentName component, int version, int userId) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700291 Intent intent = new Intent(mAction);
Jeff Sharkey58482c552016-02-08 17:49:17 -0700292 intent.setComponent(component);
293 mBoundComponent = component;
294 mBoundPackageName = component.getPackageName();
295 mBoundVersion = version;
296 mBoundUserId = userId;
297 if (D) Log.d(mTag, "binding " + component + " (v" + version + ") (u" + userId + ")");
298 mContext.bindServiceAsUser(intent, this,
299 Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE,
300 new UserHandle(userId));
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700301 }
302
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500303 public static boolean isSignatureMatch(Signature[] signatures,
304 List<HashSet<Signature>> sigSets) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700305 if (signatures == null) return false;
306
307 // build hashset of input to test against
308 HashSet<Signature> inputSet = new HashSet<Signature>();
309 for (Signature s : signatures) {
310 inputSet.add(s);
311 }
312
313 // test input against each of the signature sets
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500314 for (HashSet<Signature> referenceSet : sigSets) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700315 if (referenceSet.equals(inputSet)) {
316 return true;
317 }
318 }
319 return false;
320 }
321
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500322 private boolean isSignatureMatch(Signature[] signatures) {
323 return isSignatureMatch(signatures, mSignatureSets);
324 }
325
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700326 private final PackageMonitor mPackageMonitor = new PackageMonitor() {
327 /**
328 * Called when package has been reinstalled
329 */
330 @Override
331 public void onPackageUpdateFinished(String packageName, int uid) {
Victoria Leaseb711d572012-10-02 13:14:11 -0700332 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700333 final boolean forceRebind = Objects.equals(packageName, mBoundPackageName);
334 bindBestPackageLocked(null, forceRebind);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700335 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700336 }
337
338 @Override
339 public void onPackageAdded(String packageName, int uid) {
Victoria Leaseb711d572012-10-02 13:14:11 -0700340 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700341 final boolean forceRebind = Objects.equals(packageName, mBoundPackageName);
342 bindBestPackageLocked(null, forceRebind);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700343 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700344 }
345
346 @Override
347 public void onPackageRemoved(String packageName, int uid) {
Victoria Leaseb711d572012-10-02 13:14:11 -0700348 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700349 final boolean forceRebind = Objects.equals(packageName, mBoundPackageName);
350 bindBestPackageLocked(null, forceRebind);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700351 }
352 }
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700353
354 @Override
355 public boolean onPackageChanged(String packageName, int uid, String[] components) {
356 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700357 final boolean forceRebind = Objects.equals(packageName, mBoundPackageName);
358 bindBestPackageLocked(null, forceRebind);
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700359 }
360 return super.onPackageChanged(packageName, uid, components);
361 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700362 };
363
364 @Override
Jeff Sharkey58482c552016-02-08 17:49:17 -0700365 public void onServiceConnected(ComponentName component, IBinder binder) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700366 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700367 if (component.equals(mBoundComponent)) {
368 if (D) Log.d(mTag, component + " connected");
369 mBoundService = binder;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700370 if (mHandler !=null && mNewServiceWork != null) {
371 mHandler.post(mNewServiceWork);
372 }
373 } else {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700374 Log.w(mTag, "unexpected onServiceConnected: " + component);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700375 }
376 }
377 }
378
379 @Override
Jeff Sharkey58482c552016-02-08 17:49:17 -0700380 public void onServiceDisconnected(ComponentName component) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700381 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700382 if (D) Log.d(mTag, component + " disconnected");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700383
Jeff Sharkey58482c552016-02-08 17:49:17 -0700384 if (component.equals(mBoundComponent)) {
385 mBoundService = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700386 }
387 }
388 }
389
Jeff Sharkey58482c552016-02-08 17:49:17 -0700390 public @Nullable String getBestPackageName() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700391 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700392 return mBoundPackageName;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700393 }
394 }
395
396 public int getBestVersion() {
397 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700398 return mBoundVersion;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700399 }
400 }
401
Lifu Tang66f761c2017-11-13 15:51:54 -0800402 /**
403 * The runner that runs on the binder retrieved from {@link ServiceWatcher}.
404 */
405 public interface BinderRunner {
406 /**
407 * Runs on the retrieved binder.
408 * @param binder the binder retrieved from the {@link ServiceWatcher}.
409 */
410 public void run(@NonNull IBinder binder);
411 }
412
413 /**
414 * Retrieves the binder from {@link ServiceWatcher} and runs it.
415 * @return whether a valid service exists.
416 */
417 public boolean runOnBinder(@NonNull BinderRunner runner) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700418 synchronized (mLock) {
Lifu Tang66f761c2017-11-13 15:51:54 -0800419 if (mBoundService == null) {
420 return false;
421 } else {
422 runner.run(mBoundService);
423 return true;
424 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700425 }
426 }
Victoria Leaseb711d572012-10-02 13:14:11 -0700427
Jeff Sharkey58482c552016-02-08 17:49:17 -0700428 public void switchUser(int userId) {
Victoria Leaseb711d572012-10-02 13:14:11 -0700429 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700430 mCurrentUserId = userId;
431 bindBestPackageLocked(mServicePackageName, false);
432 }
433 }
434
435 public void unlockUser(int userId) {
436 synchronized (mLock) {
437 if (userId == mCurrentUserId) {
438 bindBestPackageLocked(mServicePackageName, false);
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800439 }
Victoria Leaseb711d572012-10-02 13:14:11 -0700440 }
441 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700442}