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.compat.annotation.UnsupportedAppUsage; 21 import android.util.ArrayMap; 22 import android.util.Log; 23 24 import com.android.internal.annotations.GuardedBy; 25 import com.android.internal.os.BinderInternal; 26 import com.android.internal.util.StatLogger; 27 28 import java.util.Map; 29 30 /** @hide */ 31 public final class ServiceManager { 32 private static final String TAG = "ServiceManager"; 33 private static final Object sLock = new Object(); 34 35 @UnsupportedAppUsage 36 private static IServiceManager sServiceManager; 37 38 /** 39 * Cache for the "well known" services, such as WM and AM. 40 */ 41 @UnsupportedAppUsage 42 private static Map<String, IBinder> sCache = new ArrayMap<String, IBinder>(); 43 44 /** 45 * We do the "slow log" at most once every this interval. 46 */ 47 private static final int SLOW_LOG_INTERVAL_MS = 5000; 48 49 /** 50 * We do the "stats log" at most once every this interval. 51 */ 52 private static final int STATS_LOG_INTERVAL_MS = 5000; 53 54 /** 55 * Threshold in uS for a "slow" call, used on core UIDs. We use a more relax value to 56 * avoid logspam. 57 */ 58 private static final long GET_SERVICE_SLOW_THRESHOLD_US_CORE = 59 SystemProperties.getInt("debug.servicemanager.slow_call_core_ms", 10) * 1000; 60 61 /** 62 * Threshold in uS for a "slow" call, used on non-core UIDs. We use a more relax value to 63 * avoid logspam. 64 */ 65 private static final long GET_SERVICE_SLOW_THRESHOLD_US_NON_CORE = 66 SystemProperties.getInt("debug.servicemanager.slow_call_ms", 50) * 1000; 67 68 /** 69 * We log stats logging ever this many getService() calls. 70 */ 71 private static final int GET_SERVICE_LOG_EVERY_CALLS_CORE = 72 SystemProperties.getInt("debug.servicemanager.log_calls_core", 100); 73 74 /** 75 * We log stats logging ever this many getService() calls. 76 */ 77 private static final int GET_SERVICE_LOG_EVERY_CALLS_NON_CORE = 78 SystemProperties.getInt("debug.servicemanager.log_calls", 200); 79 80 @GuardedBy("sLock") 81 private static int sGetServiceAccumulatedUs; 82 83 @GuardedBy("sLock") 84 private static int sGetServiceAccumulatedCallCount; 85 86 @GuardedBy("sLock") 87 private static long sLastStatsLogUptime; 88 89 @GuardedBy("sLock") 90 private static long sLastSlowLogUptime; 91 92 @GuardedBy("sLock") 93 private static long sLastSlowLogActualTime; 94 95 interface Stats { 96 int GET_SERVICE = 0; 97 98 int COUNT = GET_SERVICE + 1; 99 } 100 101 public static final StatLogger sStatLogger = new StatLogger(new String[] { 102 "getService()", 103 }); 104 105 @UnsupportedAppUsage ServiceManager()106 public ServiceManager() { 107 } 108 109 @UnsupportedAppUsage getIServiceManager()110 private static IServiceManager getIServiceManager() { 111 if (sServiceManager != null) { 112 return sServiceManager; 113 } 114 115 // Find the service manager 116 sServiceManager = ServiceManagerNative 117 .asInterface(Binder.allowBlocking(BinderInternal.getContextObject())); 118 return sServiceManager; 119 } 120 121 /** 122 * Returns a reference to a service with the given name. 123 * 124 * @param name the name of the service to get 125 * @return a reference to the service, or <code>null</code> if the service doesn't exist 126 */ 127 @UnsupportedAppUsage getService(String name)128 public static IBinder getService(String name) { 129 try { 130 IBinder service = sCache.get(name); 131 if (service != null) { 132 return service; 133 } else { 134 return Binder.allowBlocking(rawGetService(name)); 135 } 136 } catch (RemoteException e) { 137 Log.e(TAG, "error in getService", e); 138 } 139 return null; 140 } 141 142 /** 143 * Returns a reference to a service with the given name, or throws 144 * {@link ServiceNotFoundException} if none is found. 145 * 146 * @hide 147 */ getServiceOrThrow(String name)148 public static IBinder getServiceOrThrow(String name) throws ServiceNotFoundException { 149 final IBinder binder = getService(name); 150 if (binder != null) { 151 return binder; 152 } else { 153 throw new ServiceNotFoundException(name); 154 } 155 } 156 157 /** 158 * Place a new @a service called @a name into the service 159 * manager. 160 * 161 * @param name the name of the new service 162 * @param service the service object 163 */ 164 @UnsupportedAppUsage addService(String name, IBinder service)165 public static void addService(String name, IBinder service) { 166 addService(name, service, false, IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT); 167 } 168 169 /** 170 * Place a new @a service called @a name into the service 171 * manager. 172 * 173 * @param name the name of the new service 174 * @param service the service object 175 * @param allowIsolated set to true to allow isolated sandboxed processes 176 * to access this service 177 */ 178 @UnsupportedAppUsage addService(String name, IBinder service, boolean allowIsolated)179 public static void addService(String name, IBinder service, boolean allowIsolated) { 180 addService(name, service, allowIsolated, 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 * @param dumpPriority supported dump priority levels as a bitmask 191 * to access this service 192 */ 193 @UnsupportedAppUsage addService(String name, IBinder service, boolean allowIsolated, int dumpPriority)194 public static void addService(String name, IBinder service, boolean allowIsolated, 195 int dumpPriority) { 196 try { 197 getIServiceManager().addService(name, service, allowIsolated, dumpPriority); 198 } catch (RemoteException e) { 199 Log.e(TAG, "error in addService", e); 200 } 201 } 202 203 /** 204 * Retrieve an existing service called @a name from the 205 * service manager. Non-blocking. 206 */ 207 @UnsupportedAppUsage checkService(String name)208 public static IBinder checkService(String name) { 209 try { 210 IBinder service = sCache.get(name); 211 if (service != null) { 212 return service; 213 } else { 214 return Binder.allowBlocking(getIServiceManager().checkService(name)); 215 } 216 } catch (RemoteException e) { 217 Log.e(TAG, "error in checkService", e); 218 return null; 219 } 220 } 221 222 /** 223 * Returns whether the specified service is declared. 224 * 225 * @return true if the service is declared somewhere (eg. VINTF manifest) and 226 * waitForService should always be able to return the service. 227 */ isDeclared(@onNull String name)228 public static boolean isDeclared(@NonNull String name) { 229 try { 230 return getIServiceManager().isDeclared(name); 231 } catch (RemoteException e) { 232 Log.e(TAG, "error in isDeclared", e); 233 return false; 234 } 235 } 236 237 /** 238 * Returns the specified service from the service manager. 239 * 240 * If the service is not running, servicemanager will attempt to start it, and this function 241 * will wait for it to be ready. 242 * 243 * @return {@code null} only if there are permission problems or fatal errors. 244 */ waitForService(@onNull String name)245 public static native IBinder waitForService(@NonNull String name); 246 247 /** 248 * Returns the specified service from the service manager, if declared. 249 * 250 * If the service is not running, servicemanager will attempt to start it, and this function 251 * will wait for it to be ready. 252 * 253 * @return {@code null} if the service is not declared in the manifest, or if there are 254 * permission problems, or if there are fatal errors. 255 */ waitForDeclaredService(@onNull String name)256 public static IBinder waitForDeclaredService(@NonNull String name) { 257 return isDeclared(name) ? waitForService(name) : null; 258 } 259 260 /** 261 * Return a list of all currently running services. 262 * @return an array of all currently running services, or <code>null</code> in 263 * case of an exception 264 */ 265 @UnsupportedAppUsage listServices()266 public static String[] listServices() { 267 try { 268 return getIServiceManager().listServices(IServiceManager.DUMP_FLAG_PRIORITY_ALL); 269 } catch (RemoteException e) { 270 Log.e(TAG, "error in listServices", e); 271 return null; 272 } 273 } 274 275 /** 276 * This is only intended to be called when the process is first being brought 277 * up and bound by the activity manager. There is only one thread in the process 278 * at that time, so no locking is done. 279 * 280 * @param cache the cache of service references 281 * @hide 282 */ initServiceCache(Map<String, IBinder> cache)283 public static void initServiceCache(Map<String, IBinder> cache) { 284 if (sCache.size() != 0) { 285 throw new IllegalStateException("setServiceCache may only be called once"); 286 } 287 sCache.putAll(cache); 288 } 289 290 /** 291 * Exception thrown when no service published for given name. This might be 292 * thrown early during boot before certain services have published 293 * themselves. 294 * 295 * @hide 296 */ 297 public static class ServiceNotFoundException extends Exception { ServiceNotFoundException(String name)298 public ServiceNotFoundException(String name) { 299 super("No service published for: " + name); 300 } 301 } 302 rawGetService(String name)303 private static IBinder rawGetService(String name) throws RemoteException { 304 final long start = sStatLogger.getTime(); 305 306 final IBinder binder = getIServiceManager().getService(name); 307 308 final int time = (int) sStatLogger.logDurationStat(Stats.GET_SERVICE, start); 309 310 final int myUid = Process.myUid(); 311 final boolean isCore = UserHandle.isCore(myUid); 312 313 final long slowThreshold = isCore 314 ? GET_SERVICE_SLOW_THRESHOLD_US_CORE 315 : GET_SERVICE_SLOW_THRESHOLD_US_NON_CORE; 316 317 synchronized (sLock) { 318 sGetServiceAccumulatedUs += time; 319 sGetServiceAccumulatedCallCount++; 320 321 final long nowUptime = SystemClock.uptimeMillis(); 322 323 // Was a slow call? 324 if (time >= slowThreshold) { 325 // We do a slow log: 326 // - At most once in every SLOW_LOG_INTERVAL_MS 327 // - OR it was slower than the previously logged slow call. 328 if ((nowUptime > (sLastSlowLogUptime + SLOW_LOG_INTERVAL_MS)) 329 || (sLastSlowLogActualTime < time)) { 330 EventLogTags.writeServiceManagerSlow(time / 1000, name); 331 332 sLastSlowLogUptime = nowUptime; 333 sLastSlowLogActualTime = time; 334 } 335 } 336 337 // Every GET_SERVICE_LOG_EVERY_CALLS calls, log the total time spent in getService(). 338 339 final int logInterval = isCore 340 ? GET_SERVICE_LOG_EVERY_CALLS_CORE 341 : GET_SERVICE_LOG_EVERY_CALLS_NON_CORE; 342 343 if ((sGetServiceAccumulatedCallCount >= logInterval) 344 && (nowUptime >= (sLastStatsLogUptime + STATS_LOG_INTERVAL_MS))) { 345 346 EventLogTags.writeServiceManagerStats( 347 sGetServiceAccumulatedCallCount, // Total # of getService() calls. 348 sGetServiceAccumulatedUs / 1000, // Total time spent in getService() calls. 349 (int) (nowUptime - sLastStatsLogUptime)); // Uptime duration since last log. 350 sGetServiceAccumulatedCallCount = 0; 351 sGetServiceAccumulatedUs = 0; 352 sLastStatsLogUptime = nowUptime; 353 } 354 } 355 return binder; 356 } 357 } 358