基于8.0源码解析:bindService 启动过程
2018-01-25 14:13
429 查看
基于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<ConnectionRecord> clist = s.connections.get(binder); 1407 if (clist == null) { 1408 clist = new ArrayList<ConnectionRecord>(); 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<ConnectionRecord>(); 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<ConnectionRecord>(); 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<ConnectionRecord> clist = r.connections.valueAt(conni); 1507 for (int i=0; i<clist.size(); i++) { 1508 ConnectionRecord c = clist.get(i); 1509 if (!filter.equals(c.binding.intent.intent)) { 1510 if (DEBUG_SERVICE) Slog.v( 1511 TAG_SERVICE, "Not publishing to: " + c); 1512 if (DEBUG_SERVICE) Slog.v( 1513 TAG_SERVICE, "Bound intent: " + c.binding.intent.intent); 1514 if (DEBUG_SERVICE) Slog.v( 1515 TAG_SERVICE, "Published intent: " + intent); 1516 continue; 1517 } 1518 if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Publishing to: " + c); 1519 try { 1520 c.conn.connected(r.name, service, false); 1521 } catch (Exception e) { 1522 Slog.w(TAG, "Failure sending service " + r.name + 1523 " to connection " + c.conn.asBinder() + 1524 " (in " + c.binding.client.processName + ")", e); 1525 } 1526 } 1527 } 1528 } 1529 1530 serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false); 1531 } 1532 } finally { 1533 Binder.restoreCallingIdentity(origId); 1534 } 1535 }
c.conn.connected(r.name,service,false);就是调用的Service的connected
相关文章推荐
- 基于8.0源码解析:startService 启动过程
- Android 8.0系统源码分析--startService启动过程源码分析
- Android源码解析四大组件系列(一)---Service的启动过程分析
- Android源码解析之新进程中启动自定义服务过程(startService)的原理分析
- Android笔记-service启动过程分析:bindService源码分析、startService和bindService区别
- Android源码解析之bindService过程分析
- 源码解析:Activity启动过程全解析
- 基于linux2.6.38.8内核启动过程完全解析[一]
- Spring源码解析-Web容器启动过程
- S5PV210之UBOOT-2011.06启动过程解析-基于u-boot for tiny210 ver3.1 (by liukun321咕唧咕唧)
- AngularJS进阶(三十九)基于项目实例解析ng启动加载过程
- PackageManagerService启动流程源码解析
- 源码解析--activity启动过程
- Android Activity的启动流程源码解析(8.0)
- docker 源码分析 一(基于1.8.2版本),docker daemon启动过程;
- Android中bindService()启动Service的过程分析
- AngularJS进阶(三十九)基于项目实战解析ng启动加载过程
- 从源码角度解析android APP启动过程中各类及其方法的调用
- Android ContentProvider启动流程源码解析(8.0)