基于8.0源码解析:bindService 启动过程

基于8.0源码解析:bindService 启动过程

欢迎关注我的公众号:


基于8.0源码解析:bindService 启动过程_第1张图片
qrcode_for_gh_1d2b09f3edbf_258 (2).jpg

基于8.0源码解析:bindService 启动过程_第2张图片
bindService 启动过程.png

调用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)]

你可能感兴趣的:(基于8.0源码解析:bindService 启动过程)