blob: 42c836eab7d7b0324049cbb19d45babb7cc9b677 [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 */
Andreas Gampea36dc622018-02-05 17:19:22 -0800202 @GuardedBy("mLock")
Jeff Sharkey58482c552016-02-08 17:49:17 -0700203 private boolean bindBestPackageLocked(String justCheckThisPackage, boolean forceRebind) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700204 Intent intent = new Intent(mAction);
205 if (justCheckThisPackage != null) {
206 intent.setPackage(justCheckThisPackage);
207 }
Jeff Sharkey58482c552016-02-08 17:49:17 -0700208 final List<ResolveInfo> rInfos = mPm.queryIntentServicesAsUser(intent,
209 PackageManager.GET_META_DATA | PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
210 mCurrentUserId);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700211 int bestVersion = Integer.MIN_VALUE;
Jeff Sharkey58482c552016-02-08 17:49:17 -0700212 ComponentName bestComponent = null;
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800213 boolean bestIsMultiuser = false;
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700214 if (rInfos != null) {
215 for (ResolveInfo rInfo : rInfos) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700216 final ComponentName component = rInfo.serviceInfo.getComponentName();
217 final String packageName = component.getPackageName();
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700218
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700219 // check signature
220 try {
221 PackageInfo pInfo;
Jeff Sharkey58482c552016-02-08 17:49:17 -0700222 pInfo = mPm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES
223 | PackageManager.MATCH_DEBUG_TRIAGED_MISSING);
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700224 if (!isSignatureMatch(pInfo.signatures)) {
225 Log.w(mTag, packageName + " resolves service " + mAction
226 + ", but has wrong signature, ignoring");
227 continue;
228 }
229 } catch (NameNotFoundException e) {
230 Log.wtf(mTag, e);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700231 continue;
232 }
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700233
234 // check metadata
235 int version = Integer.MIN_VALUE;
236 boolean isMultiuser = false;
237 if (rInfo.serviceInfo.metaData != null) {
238 version = rInfo.serviceInfo.metaData.getInt(
239 EXTRA_SERVICE_VERSION, Integer.MIN_VALUE);
240 isMultiuser = rInfo.serviceInfo.metaData.getBoolean(EXTRA_SERVICE_IS_MULTIUSER);
241 }
242
Jeff Sharkey58482c552016-02-08 17:49:17 -0700243 if (version > bestVersion) {
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700244 bestVersion = version;
Jeff Sharkey58482c552016-02-08 17:49:17 -0700245 bestComponent = component;
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700246 bestIsMultiuser = isMultiuser;
247 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700248 }
249
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700250 if (D) {
251 Log.d(mTag, String.format("bindBestPackage for %s : %s found %d, %s", mAction,
252 (justCheckThisPackage == null ? ""
253 : "(" + justCheckThisPackage + ") "), rInfos.size(),
Jeff Sharkey58482c552016-02-08 17:49:17 -0700254 (bestComponent == null ? "no new best component"
255 : "new best component: " + bestComponent)));
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700256 }
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700257 } else {
258 if (D) Log.d(mTag, "Unable to query intent services for action: " + mAction);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700259 }
Jeff Sharkey58482c552016-02-08 17:49:17 -0700260
261 if (bestComponent == null) {
262 Slog.w(mTag, "Odd, no component found for service " + mAction);
263 unbindLocked();
264 return false;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700265 }
Jeff Sharkey58482c552016-02-08 17:49:17 -0700266
267 final int userId = bestIsMultiuser ? UserHandle.USER_SYSTEM : mCurrentUserId;
268 final boolean alreadyBound = Objects.equals(bestComponent, mBoundComponent)
269 && bestVersion == mBoundVersion && userId == mBoundUserId;
270 if (forceRebind || !alreadyBound) {
271 unbindLocked();
272 bindToPackageLocked(bestComponent, bestVersion, userId);
273 }
274 return true;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700275 }
276
Andreas Gampea36dc622018-02-05 17:19:22 -0800277 @GuardedBy("mLock")
Victoria Leaseb711d572012-10-02 13:14:11 -0700278 private void unbindLocked() {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700279 ComponentName component;
280 component = mBoundComponent;
281 mBoundComponent = null;
282 mBoundPackageName = null;
283 mBoundVersion = Integer.MIN_VALUE;
284 mBoundUserId = UserHandle.USER_NULL;
285 if (component != null) {
286 if (D) Log.d(mTag, "unbinding " + component);
Lifu Tangeb298df2017-11-22 12:13:12 -0800287 mBoundService = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700288 mContext.unbindService(this);
289 }
290 }
291
Andreas Gampea36dc622018-02-05 17:19:22 -0800292 @GuardedBy("mLock")
Jeff Sharkey58482c552016-02-08 17:49:17 -0700293 private void bindToPackageLocked(ComponentName component, int version, int userId) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700294 Intent intent = new Intent(mAction);
Jeff Sharkey58482c552016-02-08 17:49:17 -0700295 intent.setComponent(component);
296 mBoundComponent = component;
297 mBoundPackageName = component.getPackageName();
298 mBoundVersion = version;
299 mBoundUserId = userId;
300 if (D) Log.d(mTag, "binding " + component + " (v" + version + ") (u" + userId + ")");
301 mContext.bindServiceAsUser(intent, this,
302 Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE,
303 new UserHandle(userId));
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700304 }
305
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500306 public static boolean isSignatureMatch(Signature[] signatures,
307 List<HashSet<Signature>> sigSets) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700308 if (signatures == null) return false;
309
310 // build hashset of input to test against
311 HashSet<Signature> inputSet = new HashSet<Signature>();
312 for (Signature s : signatures) {
313 inputSet.add(s);
314 }
315
316 // test input against each of the signature sets
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500317 for (HashSet<Signature> referenceSet : sigSets) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700318 if (referenceSet.equals(inputSet)) {
319 return true;
320 }
321 }
322 return false;
323 }
324
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500325 private boolean isSignatureMatch(Signature[] signatures) {
326 return isSignatureMatch(signatures, mSignatureSets);
327 }
328
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700329 private final PackageMonitor mPackageMonitor = new PackageMonitor() {
330 /**
331 * Called when package has been reinstalled
332 */
333 @Override
334 public void onPackageUpdateFinished(String packageName, int uid) {
Victoria Leaseb711d572012-10-02 13:14:11 -0700335 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700336 final boolean forceRebind = Objects.equals(packageName, mBoundPackageName);
337 bindBestPackageLocked(null, forceRebind);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700338 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700339 }
340
341 @Override
342 public void onPackageAdded(String packageName, int uid) {
Victoria Leaseb711d572012-10-02 13:14:11 -0700343 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700344 final boolean forceRebind = Objects.equals(packageName, mBoundPackageName);
345 bindBestPackageLocked(null, forceRebind);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700346 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700347 }
348
349 @Override
350 public void onPackageRemoved(String packageName, int uid) {
Victoria Leaseb711d572012-10-02 13:14:11 -0700351 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700352 final boolean forceRebind = Objects.equals(packageName, mBoundPackageName);
353 bindBestPackageLocked(null, forceRebind);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700354 }
355 }
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700356
357 @Override
358 public boolean onPackageChanged(String packageName, int uid, String[] components) {
359 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700360 final boolean forceRebind = Objects.equals(packageName, mBoundPackageName);
361 bindBestPackageLocked(null, forceRebind);
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700362 }
363 return super.onPackageChanged(packageName, uid, components);
364 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700365 };
366
367 @Override
Jeff Sharkey58482c552016-02-08 17:49:17 -0700368 public void onServiceConnected(ComponentName component, IBinder binder) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700369 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700370 if (component.equals(mBoundComponent)) {
371 if (D) Log.d(mTag, component + " connected");
372 mBoundService = binder;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700373 if (mHandler !=null && mNewServiceWork != null) {
374 mHandler.post(mNewServiceWork);
375 }
376 } else {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700377 Log.w(mTag, "unexpected onServiceConnected: " + component);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700378 }
379 }
380 }
381
382 @Override
Jeff Sharkey58482c552016-02-08 17:49:17 -0700383 public void onServiceDisconnected(ComponentName component) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700384 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700385 if (D) Log.d(mTag, component + " disconnected");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700386
Jeff Sharkey58482c552016-02-08 17:49:17 -0700387 if (component.equals(mBoundComponent)) {
388 mBoundService = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700389 }
390 }
391 }
392
Jeff Sharkey58482c552016-02-08 17:49:17 -0700393 public @Nullable String getBestPackageName() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700394 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700395 return mBoundPackageName;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700396 }
397 }
398
399 public int getBestVersion() {
400 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700401 return mBoundVersion;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700402 }
403 }
404
Lifu Tang66f761c2017-11-13 15:51:54 -0800405 /**
406 * The runner that runs on the binder retrieved from {@link ServiceWatcher}.
407 */
408 public interface BinderRunner {
409 /**
410 * Runs on the retrieved binder.
411 * @param binder the binder retrieved from the {@link ServiceWatcher}.
412 */
413 public void run(@NonNull IBinder binder);
414 }
415
416 /**
417 * Retrieves the binder from {@link ServiceWatcher} and runs it.
418 * @return whether a valid service exists.
419 */
420 public boolean runOnBinder(@NonNull BinderRunner runner) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700421 synchronized (mLock) {
Lifu Tang66f761c2017-11-13 15:51:54 -0800422 if (mBoundService == null) {
423 return false;
424 } else {
425 runner.run(mBoundService);
426 return true;
427 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700428 }
429 }
Victoria Leaseb711d572012-10-02 13:14:11 -0700430
Jeff Sharkey58482c552016-02-08 17:49:17 -0700431 public void switchUser(int userId) {
Victoria Leaseb711d572012-10-02 13:14:11 -0700432 synchronized (mLock) {
Jeff Sharkey58482c552016-02-08 17:49:17 -0700433 mCurrentUserId = userId;
434 bindBestPackageLocked(mServicePackageName, false);
435 }
436 }
437
438 public void unlockUser(int userId) {
439 synchronized (mLock) {
440 if (userId == mCurrentUserId) {
441 bindBestPackageLocked(mServicePackageName, false);
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800442 }
Victoria Leaseb711d572012-10-02 13:14:11 -0700443 }
444 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700445}