基于8.0源码解析:bindService 启动过程
欢迎关注我的公众号:
调用bindService 后会到ContextWrapper中:
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
return mBase.bindService(service, conn, flags);
}
应为ContextWrapper是继承自context,而context的实现是contextImpl,
@Override
1538 public boolean bindService(Intent service, ServiceConnection conn,
1539 int flags) {
1540 warnIfCallingFromSystemProcess();
1541 return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
1542 Process.myUserHandle());
1543 }
这个方法又调用了bindServiceCommon,
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
1582 handler, UserHandle user) {
1583 // Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.
1584 IServiceConnection sd;
1585 if (conn == null) {
1586 throw new IllegalArgumentException("connection is null");
1587 }
1588 if (mPackageInfo != null) {
1589 sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
1590 } else {
1591 throw new RuntimeException("Not supported in system context");
1592 }
1593 validateServiceIntent(service);
1594 try {
1595 IBinder token = getActivityToken();
1596 if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
1597 && mPackageInfo.getApplicationInfo().targetSdkVersion
1598 < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
1599 flags |= BIND_WAIVE_PRIORITY;
1600 }
1601 service.prepareToLeaveProcess(this);
1602 int res = ActivityManager.getService().bindService(
1603 mMainThread.getApplicationThread(), getActivityToken(), service,
1604 service.resolveTypeIfNeeded(getContentResolver()),
1605 sd, flags, getOpPackageName(), user.getIdentifier());
1606 if (res < 0) {
1607 throw new SecurityException(
1608 "Not allowed to bind to service " + service);
1609 }
1610 return res != 0;
1611 } catch (RemoteException e) {
1612 throw e.rethrowFromSystemServer();
1613 }
1614 }
ActivityManager.getService().bindService会通过Binder机制调用到ActivityManagerService中:
public int bindService(IApplicationThread caller, IBinder token, Intent service,
18276 String resolvedType, IServiceConnection connection, int flags, String callingPackage,
18277 int userId) throws TransactionTooLargeException {
18278 enforceNotIsolatedCaller("bindService");
18279
18280 // Refuse possible leaked file descriptors
18281 if (service != null && service.hasFileDescriptors() == true) {
18282 throw new IllegalArgumentException("File descriptors passed in Intent");
18283 }
18284
18285 if (callingPackage == null) {
18286 throw new IllegalArgumentException("callingPackage cannot be null");
18287 }
18288
18289 synchronized(this) {
18290 return mServices.bindServiceLocked(caller, token, service,
18291 resolvedType, connection, flags, callingPackage, userId);
18292 }
18293 }
18294
mServices.bindServiceLocked会调用到ActiveServices中:
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
1229 String resolvedType, final IServiceConnection connection, int flags,
1230 String callingPackage, final int userId) throws TransactionTooLargeException {
1231 if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "bindService: " + service
1232 + " type=" + resolvedType + " conn=" + connection.asBinder()
1233 + " flags=0x" + Integer.toHexString(flags));
1234 final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
1235 if (callerApp == null) {
1236 throw new SecurityException(
1237 "Unable to find app for caller " + caller
1238 + " (pid=" + Binder.getCallingPid()
1239 + ") when binding service " + service);
1240 }
1241
1242 ActivityRecord activity = null;
1243 if (token != null) {
1244 activity = ActivityRecord.isInStackLocked(token);
1245 if (activity == null) {
1246 Slog.w(TAG, "Binding with unknown activity: " + token);
1247 return 0;
1248 }
1249 }
1250
1251 int clientLabel = 0;
1252 PendingIntent clientIntent = null;
1253 final boolean isCallerSystem = callerApp.info.uid == Process.SYSTEM_UID;
1254
1255 if (isCallerSystem) {
1256 // Hacky kind of thing -- allow system stuff to tell us
1257 // what they are, so we can report this elsewhere for
1258 // others to know why certain services are running.
1259 service.setDefusable(true);
1260 clientIntent = service.getParcelableExtra(Intent.EXTRA_CLIENT_INTENT);
1261 if (clientIntent != null) {
1262 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
1263 if (clientLabel != 0) {
1264 // There are no useful extras in the intent, trash them.
1265 // System code calling with this stuff just needs to know
1266 // this will happen.
1267 service = service.cloneFilter();
1268 }
1269 }
1270 }
1271
1272 if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
1273 mAm.enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
1274 "BIND_TREAT_LIKE_ACTIVITY");
1275 }
1276
1277 if ((flags & Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0 && !isCallerSystem) {
1278 throw new SecurityException(
1279 "Non-system caller " + caller + " (pid=" + Binder.getCallingPid()
1280 + ") set BIND_ALLOW_WHITELIST_MANAGEMENT when binding service " + service);
1281 }
1282
1283 final boolean callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
1284 final boolean isBindExternal = (flags & Context.BIND_EXTERNAL_SERVICE) != 0;
1285
1286 ServiceLookupResult res =
1287 retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(),
1288 Binder.getCallingUid(), userId, true, callerFg, isBindExternal);
1289 if (res == null) {
1290 return 0;
1291 }
1292 if (res.record == null) {
1293 return -1;
1294 }
1295 ServiceRecord s = res.record;
1296
1297 boolean permissionsReviewRequired = false;
1298
1299 // If permissions need a review before any of the app components can run,
1300 // we schedule binding to the service but do not start its process, then
1301 // we launch a review activity to which is passed a callback to invoke
1302 // when done to start the bound service's process to completing the binding.
1303 if (mAm.mPermissionReviewRequired) {
1304 if (mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired(
1305 s.packageName, s.userId)) {
1306
1307 permissionsReviewRequired = true;
1308
1309 // Show a permission review UI only for binding from a foreground app
1310 if (!callerFg) {
1311 Slog.w(TAG, "u" + s.userId + " Binding to a service in package"
1312 + s.packageName + " requires a permissions review");
1313 return 0;
1314 }
1315
1316 final ServiceRecord serviceRecord = s;
1317 final Intent serviceIntent = service;
1318
1319 RemoteCallback callback = new RemoteCallback(
1320 new RemoteCallback.OnResultListener() {
1321 @Override
1322 public void onResult(Bundle result) {
1323 synchronized(mAm) {
1324 final long identity = Binder.clearCallingIdentity();
1325 try {
1326 if (!mPendingServices.contains(serviceRecord)) {
1327 return;
1328 }
1329 // If there is still a pending record, then the service
1330 // binding request is still valid, so hook them up. We
1331 // proceed only if the caller cleared the review requirement
1332 // otherwise we unbind because the user didn't approve.
1333 if (!mAm.getPackageManagerInternalLocked()
1334 .isPermissionsReviewRequired(
1335 serviceRecord.packageName,
1336 serviceRecord.userId)) {
1337 try {
1338 bringUpServiceLocked(serviceRecord,
1339 serviceIntent.getFlags(),
1340 callerFg, false, false);
1341 } catch (RemoteException e) {
1342 /* ignore - local call */
1343 }
1344 } else {
1345 unbindServiceLocked(connection);
1346 }
1347 } finally {
1348 Binder.restoreCallingIdentity(identity);
1349 }
1350 }
1351 }
1352 });
1353
1354 final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
1355 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1356 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
1357 intent.putExtra(Intent.EXTRA_PACKAGE_NAME, s.packageName);
1358 intent.putExtra(Intent.EXTRA_REMOTE_CALLBACK, callback);
1359
1360 if (DEBUG_PERMISSIONS_REVIEW) {
1361 Slog.i(TAG, "u" + s.userId + " Launching permission review for package "
1362 + s.packageName);
1363 }
1364
1365 mAm.mHandler.post(new Runnable() {
1366 @Override
1367 public void run() {
1368 mAm.mContext.startActivityAsUser(intent, new UserHandle(userId));
1369 }
1370 });
1371 }
1372 }
1373
1374 final long origId = Binder.clearCallingIdentity();
1375
1376 try {
1377 if (unscheduleServiceRestartLocked(s, callerApp.info.uid, false)) {
1378 if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "BIND SERVICE WHILE RESTART PENDING: "
1379 + s);
1380 }
1381
1382 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
1383 s.lastActivity = SystemClock.uptimeMillis();
1384 if (!s.hasAutoCreateConnections()) {
1385 // This is the first binding, let the tracker know.
1386 ServiceState stracker = s.getTracker();
1387 if (stracker != null) {
1388 stracker.setBound(true, mAm.mProcessStats.getMemFactorLocked(),
1389 s.lastActivity);
1390 }
1391 }
1392 }
1393
1394 mAm.startAssociationLocked(callerApp.uid, callerApp.processName, callerApp.curProcState,
1395 s.appInfo.uid, s.name, s.processName);
1396 // Once the apps have become associated, if one of them is caller is ephemeral
1397 // the target app should now be able to see the calling app
1398 mAm.grantEphemeralAccessLocked(callerApp.userId, service,
1399 s.appInfo.uid, UserHandle.getAppId(callerApp.uid));
1400
1401 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
1402 ConnectionRecord c = new ConnectionRecord(b, activity,
1403 connection, flags, clientLabel, clientIntent);
1404
1405 IBinder binder = connection.asBinder();
1406 ArrayList clist = s.connections.get(binder);
1407 if (clist == null) {
1408 clist = new ArrayList();
1409 s.connections.put(binder, clist);
1410 }
1411 clist.add(c);
1412 b.connections.add(c);
1413 if (activity != null) {
1414 if (activity.connections == null) {
1415 activity.connections = new HashSet();
1416 }
1417 activity.connections.add(c);
1418 }
1419 b.client.connections.add(c);
1420 if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
1421 b.client.hasAboveClient = true;
1422 }
1423 if ((c.flags&Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) {
1424 s.whitelistManager = true;
1425 }
1426 if (s.app != null) {
1427 updateServiceClientActivitiesLocked(s.app, c, true);
1428 }
1429 clist = mServiceConnections.get(binder);
1430 if (clist == null) {
1431 clist = new ArrayList();
1432 mServiceConnections.put(binder, clist);
1433 }
1434 clist.add(c);
1435
1436 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
1437 s.lastActivity = SystemClock.uptimeMillis();
1438 if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
1439 permissionsReviewRequired) != null) {
1440 return 0;
1441 }
1442 }
1443
1444 if (s.app != null) {
1445 if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
1446 s.app.treatLikeActivity = true;
1447 }
1448 if (s.whitelistManager) {
1449 s.app.whitelistManager = true;
1450 }
1451 // This could have made the service more important.
1452 mAm.updateLruProcessLocked(s.app, s.app.hasClientActivities
1453 || s.app.treatLikeActivity, b.client);
1454 mAm.updateOomAdjLocked(s.app, true);
1455 }
1456
1457 if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bind " + s + " with " + b
1458 + ": received=" + b.intent.received
1459 + " apps=" + b.intent.apps.size()
1460 + " doRebind=" + b.intent.doRebind);
1461
1462 if (s.app != null && b.intent.received) {
1463 // Service is already running, so we can immediately
1464 // publish the connection.
1465 try {
1466 c.conn.connected(s.name, b.intent.binder, false);
1467 } catch (Exception e) {
1468 Slog.w(TAG, "Failure sending service " + s.shortName
1469 + " to connection " + c.conn.asBinder()
1470 + " (in " + c.binding.client.processName + ")", e);
1471 }
1472
1473 // If this is the first app connected back to this binding,
1474 // and the service had previously asked to be told when
1475 // rebound, then do so.
1476 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
1477 requestServiceBindingLocked(s, b.intent, callerFg, true);
1478 }
1479 } else if (!b.intent.requested) {
1480 requestServiceBindingLocked(s, b.intent, callerFg, false);
1481 }
1482
1483 getServiceMapLocked(s.userId).ensureNotStartingBackgroundLocked(s);
1484
1485 } finally {
1486 Binder.restoreCallingIdentity(origId);
1487 }
1488
1489 return 1;
1490 }
最后又调用了requestServiceBindingLocked:
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
1841 boolean execInFg, boolean rebind) throws TransactionTooLargeException {
1842 if (r.app == null || r.app.thread == null) {
1843 // If service is not currently running, can't yet bind.
1844 return false;
1845 }
1846 if (DEBUG_SERVICE) Slog.d(TAG_SERVICE, "requestBind " + i + ": requested=" + i.requested
1847 + " rebind=" + rebind);
1848 if ((!i.requested || rebind) && i.apps.size() > 0) {
1849 try {
1850 bumpServiceExecutingLocked(r, execInFg, "bind");
1851 r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
1852 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
1853 r.app.repProcState);
1854 if (!rebind) {
1855 i.requested = true;
1856 }
1857 i.hasBound = true;
1858 i.doRebind = false;
1859 } catch (TransactionTooLargeException e) {
1860 // Keep the executeNesting count accurate.
1861 if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r, e);
1862 final boolean inDestroying = mDestroyingServices.contains(r);
1863 serviceDoneExecutingLocked(r, inDestroying, inDestroying);
1864 throw e;
1865 } catch (RemoteException e) {
1866 if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r);
1867 // Keep the executeNesting count accurate.
1868 final boolean inDestroying = mDestroyingServices.contains(r);
1869 serviceDoneExecutingLocked(r, inDestroying, inDestroying);
1870 return false;
1871 }
1872 }
1873 return true;
1874 }
r.app.thread.scheduleBindService会调用到ActivityThread中:
public final void scheduleBindService(IBinder token, Intent intent,
853 boolean rebind, int processState) {
854 updateProcessState(processState, false);
855 BindServiceData s = new BindServiceData();
856 s.token = token;
857 s.intent = intent;
858 s.rebind = rebind;
859
860 if (DEBUG_SERVICE)
861 Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
862 + Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
863 sendMessage(H.BIND_SERVICE, s);
864 }
对应的H中:
case BIND_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
handleBindService((BindServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
handleBindService中
private void handleBindService(BindServiceData data) {
Service s = mServices.get(data.token);
if (DEBUG_SERVICE)
Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess();
try {
if (!data.rebind) {
IBinder binder = s.onBind(data.intent);
ActivityManagerNative.getDefault().publishService(
data.token, data.intent, binder);
} else {
s.onRebind(data.intent);
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
ensureJitEnabled();
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
throw new RuntimeException(
"Unable to bind to service " + s
+ " with " + data.intent + ": " + e.toString(), e);
}
}
}
}
ActivityManagerNative.getDefault().publishService(
data.token, data.intent, binder),于是又回到了ActivityManagerService中(Binder机制):
public void publishService(IBinder token, Intent intent, IBinder service) {
18302 // Refuse possible leaked file descriptors
18303 if (intent != null && intent.hasFileDescriptors() == true) {
18304 throw new IllegalArgumentException("File descriptors passed in Intent");
18305 }
18306
18307 synchronized(this) {
18308 if (!(token instanceof ServiceRecord)) {
18309 throw new IllegalArgumentException("Invalid service token");
18310 }
18311 mServices.publishServiceLocked((ServiceRecord)token, intent, service);
18312 }
18313 }
最后又调用到了mServices.publishServiceLocked,(ActiveServices.java)
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
1493 final long origId = Binder.clearCallingIdentity();
1494 try {
1495 if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "PUBLISHING " + r
1496 + " " + intent + ": " + service);
1497 if (r != null) {
1498 Intent.FilterComparison filter
1499 = new Intent.FilterComparison(intent);
1500 IntentBindRecord b = r.bindings.get(filter);
1501 if (b != null && !b.received) {
1502 b.binder = service;
1503 b.requested = true;
1504 b.received = true;
1505 for (int conni=r.connections.size()-1; conni>=0; conni--) {
1506 ArrayList clist = r.connections.valueAt(conni);
1507 for (int i=0; i
c.conn.connected(r.name,service,false);就是调用的Service的connected
[图片上传失败...(image-80c6b4-1516860823936)]