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 the list of declared instances for an interface. 256 * 257 * @return true if the service is declared somewhere (eg. VINTF manifest) and 258 * waitForService should always be able to return the service. 259 * @hide 260 */ getDeclaredInstances(@onNull String iface)261 public static String[] getDeclaredInstances(@NonNull String iface) { 262 try { 263 return getIServiceManager().getDeclaredInstances(iface); 264 } catch (RemoteException e) { 265 Log.e(TAG, "error in getDeclaredInstances", e); 266 return null; 267 } 268 } 269 270 /** 271 * Returns the specified service from the service manager. 272 * 273 * If the service is not running, servicemanager will attempt to start it, and this function 274 * will wait for it to be ready. 275 * 276 * @return {@code null} only if there are permission problems or fatal errors. 277 * @hide 278 */ waitForService(@onNull String name)279 public static IBinder waitForService(@NonNull String name) { 280 return Binder.allowBlocking(waitForServiceNative(name)); 281 } 282 waitForServiceNative(@onNull String name)283 private static native IBinder waitForServiceNative(@NonNull String name); 284 285 /** 286 * Returns the specified service from the service manager, if declared. 287 * 288 * If the service is not running, servicemanager will attempt to start it, and this function 289 * will wait for it to be ready. 290 * 291 * @return {@code null} if the service is not declared in the manifest, or if there are 292 * permission problems, or if there are fatal errors. 293 * @hide 294 */ 295 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) waitForDeclaredService(@onNull String name)296 @Nullable public static IBinder waitForDeclaredService(@NonNull String name) { 297 return isDeclared(name) ? waitForService(name) : null; 298 } 299 300 /** 301 * Register callback for service registration notifications. 302 * 303 * @throws RemoteException for underlying error. 304 * @hide 305 */ registerForNotifications( @onNull String name, @NonNull IServiceCallback callback)306 public static void registerForNotifications( 307 @NonNull String name, @NonNull IServiceCallback callback) throws RemoteException { 308 getIServiceManager().registerForNotifications(name, callback); 309 } 310 311 /** 312 * Return a list of all currently running services. 313 * @return an array of all currently running services, or <code>null</code> in 314 * case of an exception 315 * @hide 316 */ 317 @UnsupportedAppUsage listServices()318 public static String[] listServices() { 319 try { 320 return getIServiceManager().listServices(IServiceManager.DUMP_FLAG_PRIORITY_ALL); 321 } catch (RemoteException e) { 322 Log.e(TAG, "error in listServices", e); 323 return null; 324 } 325 } 326 327 /** 328 * Get service debug info. 329 * @return an array of information for each service (like listServices, but with PIDs) 330 * @hide 331 */ getServiceDebugInfo()332 public static ServiceDebugInfo[] getServiceDebugInfo() { 333 try { 334 return getIServiceManager().getServiceDebugInfo(); 335 } catch (RemoteException e) { 336 Log.e(TAG, "error in getServiceDebugInfo", e); 337 return null; 338 } 339 } 340 341 /** 342 * This is only intended to be called when the process is first being brought 343 * up and bound by the activity manager. There is only one thread in the process 344 * at that time, so no locking is done. 345 * 346 * @param cache the cache of service references 347 * @hide 348 */ initServiceCache(Map<String, IBinder> cache)349 public static void initServiceCache(Map<String, IBinder> cache) { 350 if (sCache.size() != 0) { 351 throw new IllegalStateException("setServiceCache may only be called once"); 352 } 353 sCache.putAll(cache); 354 } 355 356 /** 357 * Exception thrown when no service published for given name. This might be 358 * thrown early during boot before certain services have published 359 * themselves. 360 * 361 * @hide 362 */ 363 public static class ServiceNotFoundException extends Exception { ServiceNotFoundException(String name)364 public ServiceNotFoundException(String name) { 365 super("No service published for: " + name); 366 } 367 } 368 rawGetService(String name)369 private static IBinder rawGetService(String name) throws RemoteException { 370 final long start = sStatLogger.getTime(); 371 372 final IBinder binder = getIServiceManager().getService(name); 373 374 final int time = (int) sStatLogger.logDurationStat(Stats.GET_SERVICE, start); 375 376 final int myUid = Process.myUid(); 377 final boolean isCore = UserHandle.isCore(myUid); 378 379 final long slowThreshold = isCore 380 ? GET_SERVICE_SLOW_THRESHOLD_US_CORE 381 : GET_SERVICE_SLOW_THRESHOLD_US_NON_CORE; 382 383 synchronized (sLock) { 384 sGetServiceAccumulatedUs += time; 385 sGetServiceAccumulatedCallCount++; 386 387 final long nowUptime = SystemClock.uptimeMillis(); 388 389 // Was a slow call? 390 if (time >= slowThreshold) { 391 // We do a slow log: 392 // - At most once in every SLOW_LOG_INTERVAL_MS 393 // - OR it was slower than the previously logged slow call. 394 if ((nowUptime > (sLastSlowLogUptime + SLOW_LOG_INTERVAL_MS)) 395 || (sLastSlowLogActualTime < time)) { 396 EventLogTags.writeServiceManagerSlow(time / 1000, name); 397 398 sLastSlowLogUptime = nowUptime; 399 sLastSlowLogActualTime = time; 400 } 401 } 402 403 // Every GET_SERVICE_LOG_EVERY_CALLS calls, log the total time spent in getService(). 404 405 final int logInterval = isCore 406 ? GET_SERVICE_LOG_EVERY_CALLS_CORE 407 : GET_SERVICE_LOG_EVERY_CALLS_NON_CORE; 408 409 if ((sGetServiceAccumulatedCallCount >= logInterval) 410 && (nowUptime >= (sLastStatsLogUptime + STATS_LOG_INTERVAL_MS))) { 411 412 EventLogTags.writeServiceManagerStats( 413 sGetServiceAccumulatedCallCount, // Total # of getService() calls. 414 sGetServiceAccumulatedUs / 1000, // Total time spent in getService() calls. 415 (int) (nowUptime - sLastStatsLogUptime)); // Uptime duration since last log. 416 sGetServiceAccumulatedCallCount = 0; 417 sGetServiceAccumulatedUs = 0; 418 sLastStatsLogUptime = nowUptime; 419 } 420 } 421 return binder; 422 } 423 } 424