Android service: startService的代码实现

1. startService是IActivityManager AIDL 接口的一部分

frameworks/base/core/java/android/app/IActivityManager.aidl
ComponentName startService(in IApplicationThread caller, in Intent service,
 in String resolvedType, 
 boolean requireForeground, 

 in String callingPackage, int userId);

2. Client端调用AM提供的service: startService

ActivityManager.java提供了获得AM 接口的方法

frameworks/base/core/java/android/app/ActivityManager.java

public class ActivityManager {
    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };

}

frameworks/base/core/java/android/app/ContextImpl.java
    public ComponentName startService(Intent service) {/*用户使用的接口*/
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, false, mUser);
    }

    private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
        try {
            validateServiceIntent(service);
            service.prepareToLeaveProcess(this);
            ComponentName cn = ActivityManager.getService().startService(/*RPC服务侧*/
                mMainThread.getApplicationThread(), service, 
service.resolveTypeIfNeeded(getContentResolver()), 
requireForeground,getOpPackageName(), user.getIdentifier());
            return cn;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

3. startService服务侧实现

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback{
    mServices = new ActiveServices(this);
    @Override
    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, boolean requireForeground, String callingPackage, int userId)
            throws TransactionTooLargeException {

   synchronized(this) {
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            ComponentName res;
            try {
                res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid,
                        requireForeground, callingPackage, userId);
            } 
            return res;
        }
    }
}

ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
            throws TransactionTooLargeException {
        ServiceLookupResult res = retrieveServiceLocked(service, resolvedType, callingPackage,
                    callingPid, callingUid, userId, true, callerFg, false);

        ServiceRecord r = res.record;
        r.lastActivity = SystemClock.uptimeMillis();
        r.startRequested = true;
        r.delayedStop = false;
        r.fgRequired = fgRequired;
        r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                service, neededGrants, callingUid));

        final ServiceMap smap = getServiceMapLocked(r.userId);

        ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
        return cmp;
}

ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
            boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
return r.name
}

private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
        if (!isolated) {
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
            if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
                        + " app=" + app);
            app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
            realStartServiceLocked(r, app, execInFg);
            return null;
}else{
mAm.startProcessLocked(procName, r.appInfo, true, intentFlags, ..);
}
        

}

3.1 以创建新进程为例isolated: startProcessLocked

如果service不在新的进程中运行,则调用 realStartServiceLocked,包含在创建新进程的流程中
3.1.1 new process

final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
            boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
            boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
            //String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
            String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler,
            String callerPackage) {
       ProcessRecord app;
        startProcessLocked( app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
        return (app.pid != 0) ? app : null;
}

private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
            // Start the process.  It will either succeed and return a result containing
            // the PID of the new process, or else throw a RuntimeException.
            boolean isActivityProcess = (entryPoint == null);
            if (entryPoint == null) entryPoint = "android.app.ActivityThread";
            startResult = Process.start(entryPoint,
                        app.processName, uid, uid, gids, debugFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, invokeWith, entryPointArgs);
}

public static final ProcessStartResult start(final String processClass,
                                  final String niceName,
                                  int uid, int gid, int[] gids,
                                  int debugFlags, int mountExternal,
                                  int targetSdkVersion,
                                  String seInfo,
                                  String abi,
                                  String instructionSet,
                                  String appDataDir,
                                  String invokeWith,
                                  String[] zygoteArgs) {
        return zygoteProcess.start(processClass, niceName, uid, gid, gids,
                    debugFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, zygoteArgs);

}

扫描二维码关注公众号,回复: 2118100 查看本文章

这里调用Process.start函数创建了一个新的进程,指定新的进程执行android.app.ActivityThread类

frameworks/base/core/java/android/app/ActivityThread.java

public final class ActivityThread {
......
public static final void main(String[] args) {
......
Looper.prepareMainLooper();
......
ActivityThread thread = new ActivityThread();
thread.attach(false);
......
Looper.loop();
......
thread.detach();
......
}

}

 注意,执行到这里的时候,已经是在上一步创建的新进程里面了,即这里的进程是用来启动服务的,原来的主进程已经完成了它的命令,返回了.

3.1.2 在新process中创建service
attach(){

        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
            final IActivityManager mgr = ActivityManager.getService();
            try {
                mgr.attachApplication(mAppThread);
            } 
    }

@Override

public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
    int callingPid = Binder.getCallingPid();
    final long origId = Binder.clearCallingIdentity();
    attachApplicationLocked(thread, callingPid);
    Binder.restoreCallingIdentity(origId);
   }
}

private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {

          mServices.attachApplicationLocked(app, processName);

}

boolean attachApplicationLocked(ProcessRecord proc, String processName) {
realStartServiceLocked(sr, proc, sr.createdFromFg);

}

class ActiveServices
{
......
private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app)  {
......
r.app = app;
......
try {
......
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
......

 
}

通过ApplicationThread客户端接口调用scheduleCreateService

frameworks/base/core/java/android/app/IApplicationThread.aidl

/**
 * System private API for communicating with the application.  This is given to
 * the activity manager by an application  when it starts up, for the activity
 * manager to tell the application about things it needs to do.
 *
 * {@hide}
 */
oneway interface IApplicationThread {
    void scheduleCreateService(IBinder token, in ServiceInfo info,
            in CompatibilityInfo compatInfo, int processState);

}

ApplicationThread服务端实现

frameworks/base/core/java/android/app/ActivityThread.java

public final void scheduleCreateService(IBinder token,
        ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
    updateProcessState(processState, false);
    CreateServiceData s = new CreateServiceData();
    s.token = token;
    s.info = info;
    s.compatInfo = compatInfo;
    sendMessage(H.CREATE_SERVICE, s);
}

public void handleMessage(Message msg) {
    switch (msg.what) {
        case CREATE_SERVICE:
            handleCreateService((CreateServiceData)msg.obj);

            break;

}

private void handleCreateService(CreateServiceData data) {
LoadedApk packageInfo = getPackageInfoNoCheck(data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
   java.lang.ClassLoader cl = packageInfo.getClassLoader();
   service = (Service) cl.loadClass(data.info.name).newInstance();
}

try {
   ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
   context.setOuterContext(service);

   Application app = packageInfo.makeApplication(false, mInstrumentation);
   service.attach(context, this, data.info.name, data.token, app, ActivityManager.getService());
   service.onCreate();
   mServices.put(data.token, service);
}
}

猜你喜欢

转载自blog.csdn.net/u011279649/article/details/80937637