1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.os; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.annotation.SystemApi; 22 import android.compat.annotation.UnsupportedAppUsage; 23 import android.util.ArrayMap; 24 import android.util.Log; 25 26 import com.android.internal.annotations.GuardedBy; 27 import com.android.internal.os.BinderInternal; 28 import com.android.internal.util.StatLogger; 29 30 import java.util.Map; 31 32 /** 33 * Manage binder services as registered with the binder context manager. These services must be 34 * declared statically on an Android device (SELinux access_vector service_manager, w/ service 35 * names in service_contexts files), and they do not follow the activity lifecycle. When 36 * building applications, android.app.Service should be preferred. 37 * 38 * @hide 39 **/ 40 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 41 public final class ServiceManager { 42 private static final String TAG = "ServiceManager"; 43 private static final Object sLock = new Object(); 44 45 @UnsupportedAppUsage 46 private static IServiceManager sServiceManager; 47 48 /** 49 * Cache for the "well known" services, such as WM and AM. 50 */ 51 @UnsupportedAppUsage 52 private static Map<String, IBinder> sCache = new ArrayMap<String, IBinder>(); 53 54 /** 55 * We do the "slow log" at most once every this interval. 56 */ 57 private static final int SLOW_LOG_INTERVAL_MS = 5000; 58 59 /** 60 * We do the "stats log" at most once every this interval. 61 */ 62 private static final int STATS_LOG_INTERVAL_MS = 5000; 63 64 /** 65 * Threshold in uS for a "slow" call, used on core UIDs. We use a more relax value to 66 * avoid logspam. 67 */ 68 private static final long GET_SERVICE_SLOW_THRESHOLD_US_CORE = 69 SystemProperties.getInt("debug.servicemanager.slow_call_core_ms", 10) * 1000; 70 71 /** 72 * Threshold in uS for a "slow" call, used on non-core UIDs. We use a more relax value to 73 * avoid logspam. 74 */ 75 private static final long GET_SERVICE_SLOW_THRESHOLD_US_NON_CORE = 76 SystemProperties.getInt("debug.servicemanager.slow_call_ms", 50) * 1000; 77 78 /** 79 * We log stats logging ever this many getService() calls. 80 */ 81 private static final int GET_SERVICE_LOG_EVERY_CALLS_CORE = 82 SystemProperties.getInt("debug.servicemanager.log_calls_core", 100); 83 84 /** 85 * We log stats logging ever this many getService() calls. 86 */ 87 private static final int GET_SERVICE_LOG_EVERY_CALLS_NON_CORE = 88 SystemProperties.getInt("debug.servicemanager.log_calls", 200); 89 90 @GuardedBy("sLock") 91 private static int sGetServiceAccumulatedUs; 92 93 @GuardedBy("sLock") 94 private static int sGetServiceAccumulatedCallCount; 95 96 @GuardedBy("sLock") 97 private static long sLastStatsLogUptime; 98 99 @GuardedBy("sLock") 100 private static long sLastSlowLogUptime; 101 102 @GuardedBy("sLock") 103 private static long sLastSlowLogActualTime; 104 105 interface Stats { 106 int GET_SERVICE = 0; 107 108 int COUNT = GET_SERVICE + 1; 109 } 110 111 /** @hide */ 112 public static final StatLogger sStatLogger = new StatLogger(new String[] { 113 "getService()", 114 }); 115 116 /** @hide */ 117 @UnsupportedAppUsage ServiceManager()118 public ServiceManager() { 119 } 120 121 @UnsupportedAppUsage getIServiceManager()122 private static IServiceManager getIServiceManager() { 123 if (sServiceManager != null) { 124 return sServiceManager; 125 } 126 127 // Find the service manager 128 sServiceManager = ServiceManagerNative 129 .asInterface(Binder.allowBlocking(BinderInternal.getContextObject())); 130 return sServiceManager; 131 } 132 133 /** 134 * Returns a reference to a service with the given name. 135 * 136 * @param name the name of the service to get 137 * @return a reference to the service, or <code>null</code> if the service doesn't exist 138 * @hide 139 */ 140 @UnsupportedAppUsage getService(String name)141 public static IBinder getService(String name) { 142 try { 143 IBinder service = sCache.get(name); 144 if (service != null) { 145 return service; 146 } else { 147 return Binder.allowBlocking(rawGetService(name)); 148 } 149 } catch (RemoteException e) { 150 Log.e(TAG, "error in getService", e); 151 } 152 return null; 153 } 154 155 /** 156 * Returns a reference to a service with the given name, or throws 157 * {@link ServiceNotFoundException} if none is found. 158 * 159 * @hide 160 */ getServiceOrThrow(String name)161 public static IBinder getServiceOrThrow(String name) throws ServiceNotFoundException { 162 final IBinder binder = getService(name); 163 if (binder != null) { 164 return binder; 165 } else { 166 throw new ServiceNotFoundException(name); 167 } 168 } 169 170 /** 171 * Place a new @a service called @a name into the service 172 * manager. 173 * 174 * @param name the name of the new service 175 * @param service the service object 176 * @hide 177 */ 178 @UnsupportedAppUsage addService(String name, IBinder service)179 public static void addService(String name, IBinder service) { 180 addService(name, service, false, IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT); 181 } 182 183 /** 184 * Place a new @a service called @a name into the service 185 * manager. 186 * 187 * @param name the name of the new service 188 * @param service the service object 189 * @param allowIsolated set to true to allow isolated sandboxed processes 190 * to access this service 191 * @hide 192 */ 193 @UnsupportedAppUsage addService(String name, IBinder service, boolean allowIsolated)194 public static void addService(String name, IBinder service, boolean allowIsolated) { 195 addService(name, service, allowIsolated, IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT); 196 } 197 198 /** 199 * Place a new @a service called @a name into the service 200 * manager. 201 * 202 * @param name the name of the new service 203 * @param service the service object 204 * @param allowIsolated set to true to allow isolated sandboxed processes 205 * @param dumpPriority supported dump priority levels as a bitmask 206 * to access this service 207 * @hide 208 */ 209 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) addService(String name, IBinder service, boolean allowIsolated, int dumpPriority)210 public static void addService(String name, IBinder service, boolean allowIsolated, 211 int dumpPriority) { 212 try { 213 getIServiceManager().addService(name, service, allowIsolated, dumpPriority); 214 } catch (RemoteException e) { 215 Log.e(TAG, "error in addService", e); 216 } 217 } 218 219 /** 220 * Retrieve an existing service called @a name from the 221 * service manager. Non-blocking. 222 * @hide 223 */ 224 @UnsupportedAppUsage checkService(String name)225 public static IBinder checkService(String name) { 226 try { 227 IBinder service = sCache.get(name); 228 if (service != null) { 229 return service; 230 } else { 231 return Binder.allowBlocking(getIServiceManager().checkService(name)); 232 } 233 } catch (RemoteException e) { 234 Log.e(TAG, "error in checkService", e); 235 return null; 236 } 237 } 238 239 /** 240 * Returns whether the specified service is declared. 241 * 242 * @return true if the service is declared somewhere (eg. VINTF manifest) and 243 * waitForService should always be able to return the service. 244 */ isDeclared(@onNull String name)245 public static boolean isDeclared(@NonNull String name) { 246 try { 247 return getIServiceManager().isDeclared(name); 248 } catch (RemoteException e) { 249 Log.e(TAG, "error in isDeclared", e); 250 return false; 251 } 252 } 253 254 /** 255 * Returns an array of all declared instances for a particular interface. 256 * 257 * For instance, if 'android.foo.IFoo/foo' is declared (e.g. in VINTF 258 * manifest), and 'android.foo.IFoo' is passed here, then ["foo"] would be 259 * returned. 260 * 261 * @hide 262 */ 263 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 264 @NonNull getDeclaredInstances(@onNull String iface)265 public static String[] getDeclaredInstances(@NonNull String iface) { 266 try { 267 return getIServiceManager().getDeclaredInstances(iface); 268 } catch (RemoteException e) { 269 Log.e(TAG, "error in getDeclaredInstances", e); 270 throw e.rethrowFromSystemServer(); 271 } 272 } 273 274 /** 275 * Returns the specified service from the service manager. 276 * 277 * If the service is not running, servicemanager will attempt to start it, and this function 278 * will wait for it to be ready. 279 * 280 * @return {@code null} only if there are permission problems or fatal errors. 281 * @hide 282 */ waitForService(@onNull String name)283 public static IBinder waitForService(@NonNull String name) { 284 return Binder.allowBlocking(waitForServiceNative(name)); 285 } 286 waitForServiceNative(@onNull String name)287 private static native IBinder waitForServiceNative(@NonNull String name); 288 289 /** 290 * Returns the specified service from the service manager, if declared. 291 * 292 * If the service is not running, servicemanager will attempt to start it, and this function 293 * will wait for it to be ready. 294 * 295 * @throws SecurityException if the process does not have the permissions to check 296 * isDeclared() for the service. 297 * @return {@code null} if the service is not declared in the manifest, or if there 298 * are fatal errors. 299 * @hide 300 */ 301 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) waitForDeclaredService(@onNull String name)302 @Nullable public static IBinder waitForDeclaredService(@NonNull String name) { 303 return isDeclared(name) ? waitForService(name) : null; 304 } 305 306 /** 307 * Register callback for service registration notifications. 308 * 309 * @throws RemoteException for underlying error. 310 * @hide 311 */ registerForNotifications( @onNull String name, @NonNull IServiceCallback callback)312 public static void registerForNotifications( 313 @NonNull String name, @NonNull IServiceCallback callback) throws RemoteException { 314 getIServiceManager().registerForNotifications(name, callback); 315 } 316 317 /** 318 * Return a list of all currently running services. 319 * @return an array of all currently running services, or <code>null</code> in 320 * case of an exception 321 * @hide 322 */ 323 @UnsupportedAppUsage listServices()324 public static String[] listServices() { 325 try { 326 return getIServiceManager().listServices(IServiceManager.DUMP_FLAG_PRIORITY_ALL); 327 } catch (RemoteException e) { 328 Log.e(TAG, "error in listServices", e); 329 return null; 330 } 331 } 332 333 /** 334 * Get service debug info. 335 * @return an array of information for each service (like listServices, but with PIDs) 336 * @hide 337 */ getServiceDebugInfo()338 public static ServiceDebugInfo[] getServiceDebugInfo() { 339 try { 340 return getIServiceManager().getServiceDebugInfo(); 341 } catch (RemoteException e) { 342 Log.e(TAG, "error in getServiceDebugInfo", e); 343 return null; 344 } 345 } 346 347 /** 348 * This is only intended to be called when the process is first being brought 349 * up and bound by the activity manager. There is only one thread in the process 350 * at that time, so no locking is done. 351 * 352 * @param cache the cache of service references 353 * @hide 354 */ initServiceCache(Map<String, IBinder> cache)355 public static void initServiceCache(Map<String, IBinder> cache) { 356 if (sCache.size() != 0) { 357 throw new IllegalStateException("setServiceCache may only be called once"); 358 } 359 sCache.putAll(cache); 360 } 361 362 /** 363 * Exception thrown when no service published for given name. This might be 364 * thrown early during boot before certain services have published 365 * themselves. 366 * 367 * @hide 368 */ 369 public static class ServiceNotFoundException extends Exception { ServiceNotFoundException(String name)370 public ServiceNotFoundException(String name) { 371 super("No service published for: " + name); 372 } 373 } 374 rawGetService(String name)375 private static IBinder rawGetService(String name) throws RemoteException { 376 final long start = sStatLogger.getTime(); 377 378 final IBinder binder = getIServiceManager().getService(name); 379 380 final int time = (int) sStatLogger.logDurationStat(Stats.GET_SERVICE, start); 381 382 final int myUid = Process.myUid(); 383 final boolean isCore = UserHandle.isCore(myUid); 384 385 final long slowThreshold = isCore 386 ? GET_SERVICE_SLOW_THRESHOLD_US_CORE 387 : GET_SERVICE_SLOW_THRESHOLD_US_NON_CORE; 388 389 synchronized (sLock) { 390 sGetServiceAccumulatedUs += time; 391 sGetServiceAccumulatedCallCount++; 392 393 final long nowUptime = SystemClock.uptimeMillis(); 394 395 // Was a slow call? 396 if (time >= slowThreshold) { 397 // We do a slow log: 398 // - At most once in every SLOW_LOG_INTERVAL_MS 399 // - OR it was slower than the previously logged slow call. 400 if ((nowUptime > (sLastSlowLogUptime + SLOW_LOG_INTERVAL_MS)) 401 || (sLastSlowLogActualTime < time)) { 402 EventLogTags.writeServiceManagerSlow(time / 1000, name); 403 404 sLastSlowLogUptime = nowUptime; 405 sLastSlowLogActualTime = time; 406 } 407 } 408 409 // Every GET_SERVICE_LOG_EVERY_CALLS calls, log the total time spent in getService(). 410 411 final int logInterval = isCore 412 ? GET_SERVICE_LOG_EVERY_CALLS_CORE 413 : GET_SERVICE_LOG_EVERY_CALLS_NON_CORE; 414 415 if ((sGetServiceAccumulatedCallCount >= logInterval) 416 && (nowUptime >= (sLastStatsLogUptime + STATS_LOG_INTERVAL_MS))) { 417 418 EventLogTags.writeServiceManagerStats( 419 sGetServiceAccumulatedCallCount, // Total # of getService() calls. 420 sGetServiceAccumulatedUs / 1000, // Total time spent in getService() calls. 421 (int) (nowUptime - sLastStatsLogUptime)); // Uptime duration since last log. 422 sGetServiceAccumulatedCallCount = 0; 423 sGetServiceAccumulatedUs = 0; 424 sLastStatsLogUptime = nowUptime; 425 } 426 } 427 return binder; 428 } 429 } 430