IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android中的Service#bindService流程分析 -> 正文阅读

[移动开发]Android中的Service#bindService流程分析

Android中的Service#bindService流程分析

一、概述

环境:android7.1.2

android里面可以通过bindService来启动一个Service,然后和这个Service进行绑定,我们现在来分析下这个流程

这个流程涉及两个进程间的通信,用的是binder

设计的类主要包括:ContextImpl、IActivityManager、ActivityManagerNative、ActivityThread、IApplicationThread、ApplicationThreadNaitve、ActivityManagerService、ActiveService

ContextImpl:这个是Context这个抽象类的实现类,Context是android的上下文,里面可以获取资源还有服务

IActivityManager:这个类是一个接口,定义了一些和AMS(ActivityManagerService)通信的接口,这些接口主要是调用AMS的一些方法接口

ActivityManagerNative:这个是IActivityManager的实现类,继承自Binder,说明这个类是负责binder通信的

,这个类实际上负责app进程和AMS之间Binder通信的实现,他们的读写都是在这里完成的,ActivityManagerProxy是这个类的内部类实现了IActivityManager接口,构造方法中传入一个远程(AMS)的binder,负责实际的App进程端发送消息任务

高版本的android比如android10 这个类已经去掉了,统一使用了aidl来自动生成的,这个类变成了IActivityManager.Stub,还有ApplicationThreadNaitve也是这样 都去掉了,改用aidl来实现

ActivityManagerService:这个是整个android系统的核心服务,负责四大组件的管理和调度状态的存储,比如activity,service的启动和关闭,生命周期的维护等,非常重要

ActivityThread:如果AMS远程服务端端的服务总管,那么ActivityThread就是客户端的调度总管,负责客户端的activity,server的调度任务,和AMS保持密切的联系,和AMS的联系是通过ActivityManagerNative和ApplicationThreadNaitve来实现通信的,ActivityManagerNative负责发消息,ActivityThread内部的ApplicationThread类负责接受AMS的消息,ApplicationThread继承自ApplicationThreadNaitve

IApplicationThread:这个是app进程和AMS进程通信的接口,这些接口主要是AMS调用ActivityThread的一些方法接口

ApplicationThreadNaitve:这个是IApplicationThread的实现类,ApplicationThreadNaitve是继承自Binder的,可以实现Binder通信,ApplicationThreadNaitve主要做了两件事,1:接受AMS发的消息,在onTransact做的处理,2、ApplicationThreadNaitve#ApplicationThreadProxy的代理类是AMS中向ActivitThread发送消息的实际调用的地方,给AMS提供了发送消息到客户端提供了方法实现,说白了ApplicationThreadProxy是AMS发送消息的代理

ActiveService:这个是AMS服务内部的处理Service事务的工具类,很多的工作AMS没有实际的去做,都交给了ActiveService,ActiveService持有了AMS的引用

大致了解了上面这些类后,我们分析流程的时候心里就有个底,知道这个类的作用了,到了哪一步,废话不多少,我们开始走流程吧。

二、流程分析

1、Context#bindService

Context:
public abstract class Context {
/*
xxxxxxx
代码省略
xxxxxxx
*/
public abstract boolean bindService(@RequiresPermission Intent service,
            @NonNull ServiceConnection conn, @BindServiceFlags int flags);
 /*
xxxxxxx
代码省略
xxxxxxx
*/
}

我们看到Context其实是个抽象类的,bindService方法没有实现,Context的实现类是ContextImpl

我们看下这几个参数:

Intent service:这个是要启动的那个服务,是一个目的,在android5.0之后,google建议使用隐式调用,就是要设置ComponentName、PackageName来调用

ServiceConnection:这个是binder的连接和断开连接的回调

flags:这个是连接的flag,是一中连接的操作选项,一般都是BIND_AUTO_CREATE,服务没有开启要自动创建服务

2、ContextImpl#bindService

@Override
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        warnIfCallingFromSystemProcess();
        return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
                Process.myUserHandle());
    }
    
    mMainThread.getHandler:这个是主线程的Handler
    Process.myUserHandle() :这个要获取UserHandle 最终从这里获取程序的uid,
    这里多说下:
    uid是每个程序安装之后,系统给默认分配的一个id,用户id
    pid:是进程id,每个程序只有一个uid,但是每个程序可以有1个或者多个pid,因为每个程序可以有多个进程
    
    

继续调用bindServiceCommon

private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
            handler, UserHandle user) {
        //这个IServiceConnection 其实是几个binder,是对ServiceConnection的转化,最后要通过
        //binder传入到AMS。然后被回调的,
        IServiceConnection sd;
        if (conn == null) {
            throw new IllegalArgumentException("connection is null");
        }
        //这个mPackageInfo是LoadedApk,当前这个已经安装了的apk的描述,里面有关于安装的位置,cloassload,各种资源等,关于apk的信息
        if (mPackageInfo != null) {
        //这里主要是做了ServiceConnection 转这个IServiceConnection,注册了转这个IServiceConnection回调,IServiceConnection回调会触发ServiceConnection,传递个app,
        //还有关于解绑回调的处理,就不往里深究了
            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
        } else {
        //如果这个是null,说明app都不存在,信息没有,抛出异常
            throw new RuntimeException("Not supported in system context");
        }
        //这个就是android5.0之后Intent需要设置ComponentName 还有package启动服务的校验
        validateServiceIntent(service);
        try {
        //获取当前activity的token,这个token主要是鉴别作用,AMS要知道是哪个activity发起的,然后做处理,相当于这个token是activity的身份证
            IBinder token = getActivityToken();
            if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
                    && mPackageInfo.getApplicationInfo().targetSdkVersion
                    < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                flags |= BIND_WAIVE_PRIORITY;
            }
            //Intent 在离开这个进程的时候做一些处理
            service.prepareToLeaveProcess(this);
            //进程间通信,到AMS中的bindService,然后返回结果
            int res = ActivityManagerNative.getDefault().bindService(
                mMainThread.getApplicationThread(), getActivityToken(), service,
                service.resolveTypeIfNeeded(getContentResolver()),
                sd, flags, getOpPackageName(), user.getIdentifier());
            if (res < 0) {
            	//小于0 bind失败
                throw new SecurityException(
                        "Not allowed to bind to service " + service);
            }
            return res != 0;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

3、ActivityManagerNative#getDefault().bindService

ActivityManagerNative:

static public IActivityManager getDefault() {
        return gDefault.get();
    }
    
============================================
//gDefault,这个是一个单例模式获取的
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
        	//关键:从ServiceManager中获取AMS服务的Binder,这个过程也是进程间通信
        	//这个是向serviceManager 发消息 GET_SERVICE,获取AMS的服务
        	//因为系统启动的时候所有的服务到会注册到serviceManager中被管理起来
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            //连接到下面的asInterface
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };
     
     
============================================
   
//最终获取到的是ActivityManagerProxy的实列
 static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }

        return new ActivityManagerProxy(obj);
    }

4、ActivityManagerProxy#bindService

 public int bindService(IApplicationThread caller, IBinder token,
            Intent service, String resolvedType, IServiceConnection connection,
            int flags,  String callingPackage, int userId) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        //发送了binder验证字符串,这里是“activitymanager”
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeStrongBinder(token);
        service.writeToParcel(data, 0);
        data.writeString(resolvedType);
        data.writeStrongBinder(connection.asBinder());
        data.writeInt(flags);
        data.writeString(callingPackage);
        data.writeInt(userId);
        mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);
        reply.readException();
        int res = reply.readInt();
        data.recycle();
        reply.recycle();
        return res;
    }

我们可以看到这里是真正的发消息的地方,向AMS发消息,发送了一个操作命令BIND_SERVICE_TRANSACTION

1、binder的发消息写数据的时候是有顺序的,写和读要类型顺序一致才可以

2、这里写入数据后,直接读取返回值 int res = reply.readInt();,这里binder通信是同步的返回,当然Binder也可以异步

那么我们继续看AMS如何接受这个消息的

5、ActivityManagerService

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rudu1Woq-1637946523711)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211126153048675.png)]

我们可以看到ActivityManagerService是继承自ActivityManagerNative的 说明AMS的接受消息是在AMN中完成的,这样说来ActivityManagerNative发送和接受的代码都在这个类里面,只不过ActivityManagerNative是两个副本在不同的进程中执行的

继续看AMN接收消息的部分

6、ActivityManagerNative#onTransact

@Override
//这里是AMS接收消息的地方
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
            //代码省略
            **************
            //按照客户端发的消息顺序依次读取
            case BIND_SERVICE_TRANSACTION: {
            //验证binder的描述符,之前传的是"activitymanager"如果这个验证不成功就抛异常了
            data.enforceInterface(IActivityManager.descriptor);
            //这个是binder是客户端那边的binder,说白了是ActivityThread#ApplicationThread
            //ApplicationThread 是一个binder
            IBinder b = data.readStrongBinder();
            //这个其实是ApplicationThreadNative里的内部代理类,ApplicationThreadProxy
            //以后AMS要向客户端发消息就是通过ApplicationThreadProxy来实际操作发送的
            IApplicationThread app = ApplicationThreadNative.asInterface(b);
            //这个是activity里面的token,鉴别之用
            IBinder token = data.readStrongBinder();
            //获取要启动的service的Intent
            Intent service = Intent.CREATOR.createFromParcel(data);
            String resolvedType = data.readString();
            //这个是那个回调Binder,
            b = data.readStrongBinder();
            int fl = data.readInt();
            String callingPackage = data.readString();
            //获取uid
            int userId = data.readInt();
            //转成IServiceConnection
            IServiceConnection conn = IServiceConnection.Stub.asInterface(b);
            //这里是关键函数了,调用了AMS的bindService
            int res = bindService(app, token, service, resolvedType, conn, fl,
                    callingPackage, userId);
            reply.writeNoException();
            reply.writeInt(res);
            return true;
        }
        
            **************
            
}

7、ActivityManagerService#bindService

public int bindService(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, IServiceConnection connection, int flags, String callingPackage,
            int userId) throws TransactionTooLargeException {
        enforceNotIsolatedCaller("bindService");

        // Refuse possible leaked file descriptors
        if (service != null && service.hasFileDescriptors() == true) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }

        if (callingPackage == null) {
            throw new IllegalArgumentException("callingPackage cannot be null");
        }

        synchronized(this) {
        //调用了ActiveService 来做处理,并将参数传入进去
            return mServices.bindServiceLocked(caller, token, service,
                    resolvedType, connection, flags, callingPackage, userId);
        }
    }

8、ActiveService#bindServiceLocked

 //这个方法比较长 我做了简略写法,写关键函数
 int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, final IServiceConnection connection, int flags,
            String callingPackage, final int userId) throws TransactionTooLargeException {
      final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
        if (callerApp == null) {
        //当前进程==null就直接抛异常了
            throw new SecurityException(
                    "Unable to find app for caller " + caller
                    + " (pid=" + Binder.getCallingPid()
                    + ") when binding service " + service);
        }

        ActivityRecord activity = null;
        if (token != null) {
        //如果这个activity没有在栈中就直接返回了,启动不了service
            activity = ActivityRecord.isInStackLocked(token);
            if (activity == null) {
                Slog.w(TAG, "Binding with unknown activity: " + token);
                return 0;
            }
        }  
        
        //这里要通过Intent 去查看这个Service,把查询的结果返回到ServiceLookupResult中
        //里面做了很多的验证工作,比如果这个service不存在就抛异常,
        //还有保存这些信息到缓存中
        //比如这个service的intent的componentName是null的会设置进去
        //ServiceLookupResult 里面有ServiceRecord对象,记录者关于Service的信息,这里持有一些外部信息比如ams
        //总结来说:这里就是查询这个启动的这个服务是否合法,是否完成,是否可以启动,如果可以就设置信息,组装成最终结果ServiceLookupResult返回,如果有问题里面就抛异常或者返回null
    ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(),
                    Binder.getCallingUid(), userId, true, callerFg, isBindExternal);       //如果null 就不启动,返回0 启动失败了
             if (res == null) {
            return 0;
        }
            
           
           
           
----------分割线(1)--------------
           
boolean permissionsReviewRequired = false;

        // If permissions need a review before any of the app components can run,
        // we schedule binding to the service but do not start its process, then
        // we launch a review activity to which is passed a callback to invoke
        // when done to start the bound service's process to completing the binding.
        if (mAm.mPermissionReviewRequired || Build.PERMISSIONS_REVIEW_REQUIRED) {
            if (mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired(
                    s.packageName, s.userId)) {

                permissionsReviewRequired = true;

                // Show a permission review UI only for binding from a foreground app
                if (!callerFg) {
                    Slog.w(TAG, "u" + s.userId + " Binding to a service in package"
                            + s.packageName + " requires a permissions review");
                    return 0;
                }

                final ServiceRecord serviceRecord = s;
                final Intent serviceIntent = service;

                RemoteCallback callback = new RemoteCallback(
                        new RemoteCallback.OnResultListener() {
                    @Override
                    public void onResult(Bundle result) {
                        synchronized(mAm) {
                            final long identity = Binder.clearCallingIdentity();
                            try {
                                if (!mPendingServices.contains(serviceRecord)) {
                                    return;
                                }
                                // If there is still a pending record, then the service
                                // binding request is still valid, so hook them up. We
                                // proceed only if the caller cleared the review requirement
                                // otherwise we unbind because the user didn't approve.
                                if (!mAm.getPackageManagerInternalLocked()
                                        .isPermissionsReviewRequired(
                                                serviceRecord.packageName,
                                                serviceRecord.userId)) {
                                    try {
                                        bringUpServiceLocked(serviceRecord,
                                                serviceIntent.getFlags(),
                                                callerFg, false, false);
                                    } catch (RemoteException e) {
                                        /* ignore - local call */
                                    }
                                } else {
                                    unbindServiceLocked(connection);
                                }
                            } finally {
                                Binder.restoreCallingIdentity(identity);
                            }
                        }
                    }
                });

                final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                        | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
                intent.putExtra(Intent.EXTRA_PACKAGE_NAME, s.packageName);
                intent.putExtra(Intent.EXTRA_REMOTE_CALLBACK, callback);

                if (DEBUG_PERMISSIONS_REVIEW) {
                    Slog.i(TAG, "u" + s.userId + " Launching permission review for package "
                            + s.packageName);
                }

                mAm.mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        mAm.mContext.startActivityAsUser(intent, new UserHandle(userId));
                    }
                });
            }
        }
        
        
        
 ----------分割线(1)--------------
 上面分割线(1)里要做的就是对这个服务启动的权限申请,启动的服务是否满足应该有的权限,发个Intent,然后弹出UI动态申请权限,如果用户统一了,就在RemoteCallback 里面继续执行bringUpServiceLocked 唤醒服务的核心函数
 
 如果上面的权限满足,就不走上面的流程
 
 /*
 *
 *
 代码省略了
 *
 *
 */
 //如果含有BIND_AUTO_CREATE的flag
 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
                s.lastActivity = SystemClock.uptimeMillis();
                //唤醒Service 这个是核心方法
                if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
                        permissionsReviewRequired) != null) {
                    return 0;
                }
            }      
           
}

if (s.app != null && b.intent.received) {
                // Service is already running, so we can immediately
                // publish the connection.
                try {
                
                //如果启动service成功了,就回调那个connect回调函数,回调函数通过binder 传入到app那边,然后回调app的那边的connect回调接口onServiceConnected方法
                    c.conn.connected(s.name, b.intent.binder);
                } catch (Exception e) {
                    Slog.w(TAG, "Failure sending service " + s.shortName
                            + " to connection " + c.conn.asBinder()
                            + " (in " + c.binding.client.processName + ")", e);
                }

                // If this is the first app connected back to this binding,
                // and the service had previously asked to be told when
                // rebound, then do so.
                if (b.intent.apps.size() == 1 && b.intent.doRebind) {
                    requestServiceBindingLocked(s, b.intent, callerFg, true);
                }
            } else if (!b.intent.requested) {
                requestServiceBindingLocked(s, b.intent, callerFg, false);
            }




9、ActiveService#bringUpServiceLocked

  private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
        //Slog.i(TAG, "Bring up service:");
        //r.dump("  ");
		
        if (r.app != null && r.app.thread != null) {
        //如果这个service已经启动了就执行Service的onStartCommand方法
        //这些都是最终通过binder通信到ActivityThread中执行的
            sendServiceArgsLocked(r, execInFg, false);
            return null;
        }

        if (!whileRestarting && r.restartDelay > 0) {
        //如果当前这个服务正在等待被重启中,这个状态下,什么都不做
            // If waiting for a restart, then do nothing.
            return null;
        }

        if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bringing up " + r + " " + r.intent);

        // We are now bringing the service up, so no longer in the
        // restarting state.
        //重启服务的列表重构移除这个服务,ServiceRecord
        if (mRestartingServices.remove(r)) {
            r.resetRestartCounter();
            clearRestartingIfNeededLocked(r);
        }

        // Make sure this service is no longer considered delayed, we are starting it now.
        if (r.delayed) {
            if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (bring up): " + r);
            getServiceMap(r.userId).mDelayedStartList.remove(r);
            r.delayed = false;
        }

        // Make sure that the user who owns this service is started.  If not,
        // we don't want to allow it to run.
        //启动这个服务之前 先确保这个服务所在的程序已经启动了
        //这个就是要求我们启动某个服务之前 先把程序拉起来才可以
        //应为uid是程序的唯一id,mAm.mUserController保存了启动程序的id
        if (!mAm.mUserController.hasStartedUserState(r.userId)) {
            String msg = "Unable to launch app "
                    + r.appInfo.packageName + "/"
                    + r.appInfo.uid + " for service "
                    + r.intent.getIntent() + ": user " + r.userId + " is stopped";
            Slog.w(TAG, msg);
            //解绑服务,
            bringDownServiceLocked(r);
            return msg;
        }

        // Service is now being launched, its package can't be stopped.
        try {
        //这个服务要启动起来了,这个app不能关闭,当前给这个app的状态就是不会被杀的状态
            AppGlobals.getPackageManager().setPackageStoppedState(
                    r.packageName, false, r.userId);
        } catch (RemoteException e) {
        } catch (IllegalArgumentException e) {
            Slog.w(TAG, "Failed trying to unstop package "
                    + r.packageName + ": " + e);
        }

        final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
        final String procName = r.processName;
        ProcessRecord app;

		//这个标志意思是service会运行在一个特殊的进程中
		//我们现在只考虑 运行在自己的app线程中情况
        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);
            if (app != null && app.thread != null) {
                try {
                //添加信息
                    app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
                    //核心函数,启动了服务,我们继续往下看
                    realStartServiceLocked(r, app, execInFg);
                    return null;
                } catch (TransactionTooLargeException e) {
                    throw e;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when starting service " + r.shortName, e);
                }

                // If a dead object exception was thrown -- fall through to
                // restart the application.
            }
        } else {
            // If this service runs in an isolated process, then each time
            // we call startProcessLocked() we will get a new isolated
            // process, starting another process if we are currently waiting
            // for a previous process to come up.  To deal with this, we store
            // in the service any current isolated process it is running in or
            // waiting to have come up.
            app = r.isolatedProc;
        }

        // Not running -- get it started, and enqueue this service record
        // to be executed when the app comes up.
       
        if (app == null && !permissionsReviewRequired) {
         //如果是隔离进程中启动服务的话,就先等待,然后开启一个新的进程,等那个新的进程启动了 在启动这个服务
            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    "service", r.name, false, isolated, false)) == null) {
                    //新的进程启动不了 就报错,然后关闭这个服务,这个服务以后有可能还会被唤醒
                String msg = "Unable to launch app "
                        + r.appInfo.packageName + "/"
                        + r.appInfo.uid + " for service "
                        + r.intent.getIntent() + ": process is bad";
                Slog.w(TAG, msg);
                bringDownServiceLocked(r);
                return msg;
            }
            if (isolated) {
                r.isolatedProc = app;
            }
        }

        if (!mPendingServices.contains(r)) {
        //将这个服务添加到 PendingServices中,达到某个条件后 然乎启动
        //比如onstartcommand 的返回值 flag模式,会重启启动服务
            mPendingServices.add(r);
        }

        if (r.delayedStop) {
            // Oh and hey we've already been asked to stop!
            r.delayedStop = false;
            if (r.startRequested) {
                if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
                        "Applying delayed stop (in bring up): " + r);
                stopServiceLocked(r);
            }
        }

        return null;
    }

9、ActiveService#realStartServiceLocked

 private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        if (app.thread == null) {
            throw new RemoteException();
        }
        if (DEBUG_MU)
            Slog.v(TAG_MU, "realStartServiceLocked, ServiceRecord.uid = " + r.appInfo.uid
                    + ", ProcessRecord.uid = " + app.uid);
        r.app = app;
        r.restartTime = r.lastActivity = SystemClock.uptimeMillis();

        final boolean newService = app.services.add(r);
        //发送一个延迟启动服务的消息
        bumpServiceExecutingLocked(r, execInFg, "create");
        mAm.updateLruProcessLocked(app, false, null);
        mAm.updateOomAdjLocked();

        boolean created = false;
        try {
            if (LOG_SERVICE_START_STOP) {
                String nameTerm;
                int lastPeriod = r.shortName.lastIndexOf('.');
                nameTerm = lastPeriod >= 0 ? r.shortName.substring(lastPeriod) : r.shortName;
                EventLogTags.writeAmCreateService(
                        r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid);
            }
            synchronized (r.stats.getBatteryStats()) {
            //开启耗电统计服务,BatteryStatsImpl 这个是实现类
                r.stats.startLaunchedLocked();
            }
            mAm.notifyPackageUse(r.serviceInfo.packageName,
                                 PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
            app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
            //binder通信,通知ActivityThread 创建Service 然后启动
            //这里我们跳转到ActivityThread的创建方法
            //但是这个消息的发送是通过ApplicationThreadProxy发送消息的,里面的binder是ActivityThread中ApplicationThread这个binder
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
            r.postNotification();
            created = true;
        } catch (DeadObjectException e) {
            Slog.w(TAG, "Application dead when creating service " + r);
            mAm.appDiedLocked(app);
            throw e;
        } finally {
            if (!created) {
                // Keep the executeNesting count accurate.
                final boolean inDestroying = mDestroyingServices.contains(r);
                serviceDoneExecutingLocked(r, inDestroying, inDestroying);

                // Cleanup.
                if (newService) {
                //如果是新启动的Service 先清除ServiceRecord
                    app.services.remove(r);
                    r.app = null;
                }

                // Retry.
                if (!inDestroying) {
                		//如果没有创建 就尝试重新启动服务
                    scheduleServiceRestartLocked(r, false);
                }
            }
        }

        if (r.whitelistManager) {
            app.whitelistManager = true;
        }
	    //这个是要等待service 启动了runing了 才去bind 最终会回调Service的onBind方法
		//这些都是通过binder通信 通知activityThread 执行的
        requestServiceBindingsLocked(r, execInFg);

        updateServiceClientActivitiesLocked(app, null, true);

        // If the service is in the started state, and there are no
        // pending arguments, then fake up one so its onStartCommand() will
        // be called.
        if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
            r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                    null, null));
        }
		//这个最终会回调Service的onstartCommand方法,这些都是通过binder通信 通知activityThread 执行的
        sendServiceArgsLocked(r, execInFg, true);

        if (r.delayed) {
            if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (new proc): " + r);
            getServiceMap(r.userId).mDelayedStartList.remove(r);
            r.delayed = false;
        }

        if (r.delayedStop) {
            // Oh and hey we've already been asked to stop!
            r.delayedStop = false;
            if (r.startRequested) {
                if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
                        "Applying delayed stop (from start): " + r);
                stopServiceLocked(r);
            }
        }
    }

10、ApplicationThreadNative#scheduleCreateService

public abstract class ApplicationThreadNative extends Binder
        implements IApplicationThread {
       
        public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
        {
         *******
        *******
        *******
        *******
case SCHEDULE_CREATE_SERVICE_TRANSACTION: {
            data.enforceInterface(IApplicationThread.descriptor);
            IBinder token = data.readStrongBinder();
            ServiceInfo info = ServiceInfo.CREATOR.createFromParcel(data);
            CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data);
            int processState = data.readInt();
            //这个方法会调用到ActivityThread#ApplicationThread中的scheduleCreateService方法
            //
            scheduleCreateService(token, info, compatInfo, processState);
            return true;
        }
        ******
        *******
        *******
        *******
        }
}

11、ApplicationThread#scheduleCreateService

//下面这个方法是ApplicationThread中的方法,重写了ApplicationThreadNative 对应的方法而得到的
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;
			//向ActivityThread里面的Handler发送个消息,然后处理
			
            sendMessage(H.CREATE_SERVICE, s);
        }

12、ActivityThread#handleMessage

                    handleReceiver((ReceiverData)msg.obj);
                    maybeSnapshot();
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                    //这个就是要create service里面
                case CREATE_SERVICE:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
                    //这个是创建service的核心方法,在ActivityThread实现的
                    handleCreateService((CreateServiceData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                case BIND_SERVICE:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
                    handleBindService((BindServiceData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;

13、ActivityThread#handleCreateService

private void handleCreateService(CreateServiceData data) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();

        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
        try {
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            //可以清楚的看到Service是通过类名反射创建成功的,
            service = (Service) cl.loadClass(data.info.name).newInstance();
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to instantiate service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }

        try {
            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
			//创建ContextImpl 设置给Service
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);
			//创建Application 设置给Service
            Application app = packageInfo.makeApplication(false, mInstrumentation);
            //执行service的attach 设置各种信息操作
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManagerNative.getDefault());
            //执行service的onCreate方法        
            service.onCreate();
            mServices.put(data.token, service);
            try {
            //发送service已经启动的消息给AMS 相当于发个成功启动的回执消息
                ActivityManagerNative.getDefault().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to create service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }
    }

这个Service的onStrartCommand 还有在onBind 已经在前面的方法中的代码注释里写了,大家可以仔细看下

那么这个Service已经启动起来了,那我们继续看下Service的destory走的流程

14、Service#stopSelf

public final void stopSelf() {
        stopSelf(-1);
    }

    /**
     * Old version of {@link #stopSelfResult} that doesn't return a result.
     *  
     * @see #stopSelfResult
     */
    public final void stopSelf(int startId) {
    	//上面这个startid就是onStartCommad传进来的id,这个和stopself的startid是对应的,
  
        if (mActivityManager == null) {
            return;
        }
        try {
        //这个mActivityManager 是哪里来的呢?
        //还记得在ActivityThread创建Service的时候吗,执行了attach操作,最后一个参数是					//ActivityManagerNative.getDefault(),这个最终获取的是ActivityManagerProxy的实例,			//binder传入的是从ServiceManager获取的远程AMS的binder,从而可以和AMS通信
            mActivityManager.stopServiceToken(
                    new ComponentName(this, mClassName), mToken, startId);
        } catch (RemoteException ex) {
        }
    }

stopServiceToken

这个binder的通信过程和之前启动Service过程一样,我就直接跳到AMS的stopService代码里看下

15、ActivityManagerService#stopServiceToken

AMS{
......
@Override
    public boolean stopServiceToken(ComponentName className, IBinder token,
            int startId) {
        synchronized(this) {
        //和之前的一样 还是要去ActiveService里操作
            return mServices.stopServiceTokenLocked(className, token, startId);
        }
    }

......
}

16、ActiveService#stopServiceTokenLocked

 boolean stopServiceTokenLocked(ComponentName className, IBinder token,
            int startId) {
        if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "stopServiceToken: " + className
                + " " + token + " startId=" + startId);
        ServiceRecord r = findServiceLocked(className, token, UserHandle.getCallingUserId());
        if (r != null) {
            if (startId >= 0) {
                // Asked to only stop if done with all work.  Note that
                // to avoid leaks, we will take this as dropping all
                // start items up to and including this one.
                ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
                if (si != null) {
                    while (r.deliveredStarts.size() > 0) {
                        ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
                        cur.removeUriPermissionsLocked();
                        if (cur == si) {
                            break;
                        }
                    }
                }

                if (r.getLastStartId() != startId) {
                    return false;
                }

                if (r.deliveredStarts.size() > 0) {
                    Slog.w(TAG, "stopServiceToken startId " + startId
                            + " is last, but have " + r.deliveredStarts.size()
                            + " remaining args");
                }
            }

            synchronized (r.stats.getBatteryStats()) {
            //关闭耗电统计服务
                r.stats.stopRunningLocked();
            }
            r.startRequested = false;
            if (r.tracker != null) {
                r.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(),
                        SystemClock.uptimeMillis());
            }
            r.callStart = false;
            //清空Binder远程调用端的pid 和uid 用本线程的pid 和uid代替,并返回一个tokenid
            //这个tokenid 可以后面恢复使用的
            final long origId = Binder.clearCallingIdentity();
            //关闭远程端的Service
            bringDownServiceIfNeededLocked(r, false, false);
            //回复远程调用端的pid和uid
            Binder.restoreCallingIdentity(origId);
            return true;
        }
        return false;
    }

17、ActiveService#bringDownServiceIfNeededLocked

    private final void bringDownServiceIfNeededLocked(ServiceRecord r, boolean knowConn,
            boolean hasConn) {
        //Slog.i(TAG, "Bring down service:");
        //r.dump("  ");
		//还有明确的条件 指明这个服务需要运行吗
		//如果没有就继续走下去
        if (isServiceNeeded(r, knowConn, hasConn)) {
            return;
        }

        // Are we in the process of launching?
        //我们这个服务在launcher的进程中吗?如果是的话就不关闭
        if (mPendingServices.contains(r)) {
            return;
        }
		//关闭服务
        bringDownServiceLocked(r);
    }

18、ActiveService#bringDownServiceLocked

 private final void bringDownServiceLocked(ServiceRecord r) {
        //Slog.i(TAG, "Bring down service:");
        //r.dump("  ");

        // Report to all of the connections that the service is no longer
        // available.
        //告诉其他的和这个服务连接的客户端,这个服务不可以用了,连接要端了
        for (int conni=r.connections.size()-1; conni>=0; conni--) {
            ArrayList<ConnectionRecord> c = r.connections.valueAt(conni);
            for (int i=0; i<c.size(); i++) {
                ConnectionRecord cr = c.get(i);
                // There is still a connection to the service that is
                // being brought down.  Mark it as dead.
                cr.serviceDead = true;
                try {
                //这里binder传入的是null,所以 最终会回调 app端的disConnect的接口
                //这里要说下,一个服务是可以和多个Client连接的,绑定的
                    cr.conn.connected(r.name, null);
                } catch (Exception e) {
                    Slog.w(TAG, "Failure disconnecting service " + r.name +
                          " to connection " + c.get(i).conn.asBinder() +
                          " (in " + c.get(i).binding.client.processName + ")", e);
                }
            }
        }

        // Tell the service that it has been unbound.
        //下面是回调远程端的Service的onUnbind 方法
        if (r.app != null && r.app.thread != null) {
            for (int i=r.bindings.size()-1; i>=0; i--) {
                IntentBindRecord ibr = r.bindings.valueAt(i);
                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bringing down binding " + ibr
                        + ": hasBound=" + ibr.hasBound);
                if (ibr.hasBound) {
                    try {
                        bumpServiceExecutingLocked(r, false, "bring down unbind");
                        mAm.updateOomAdjLocked(r.app);
                        ibr.hasBound = false;
                        //最终会回调Service端的onUnbind 方法
                        //这个过程也 binder通信 到ActivityThread 我就不分析了
                        r.app.thread.scheduleUnbindService(r,
                                ibr.intent.getIntent());
                    } catch (Exception e) {
                        Slog.w(TAG, "Exception when unbinding service "
                                + r.shortName, e);
                        serviceProcessGoneLocked(r);
                    }
                }
            }
        }

        if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bringing down " + r + " " + r.intent);
        r.destroyTime = SystemClock.uptimeMillis();
        if (LOG_SERVICE_START_STOP) {
            EventLogTags.writeAmDestroyService(
                    r.userId, System.identityHashCode(r), (r.app != null) ? r.app.pid : -1);
        }

        final ServiceMap smap = getServiceMap(r.userId);
        smap.mServicesByName.remove(r.name);
        smap.mServicesByIntent.remove(r.intent);
        r.totalRestartCount = 0;
        //移除重新启动service的列表中的这个服务,因为这个是自己关闭的,所以不能重启服务了
        unscheduleServiceRestartLocked(r, 0, true);

        // Also make sure it is not on the pending list.
        
        //还要把mPendingServices中移除这个Service,将来也不会启动了
        for (int i=mPendingServices.size()-1; i>=0; i--) {
            if (mPendingServices.get(i) == r) {
                mPendingServices.remove(i);
                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Removed pending: " + r);
            }
        }

        cancelForegroudNotificationLocked(r);
        r.isForeground = false;
        r.foregroundId = 0;
        r.foregroundNoti = null;

        // Clear start entries.
        r.clearDeliveredStartsLocked();
        r.pendingStarts.clear();

        if (r.app != null) {
            synchronized (r.stats.getBatteryStats()) {
            //关闭电池电量统计服务
                r.stats.stopLaunchedLocked();
            }
            r.app.services.remove(r);
            if (r.whitelistManager) {
                updateWhitelistManagerLocked(r.app);
            }
            if (r.app.thread != null) {
                updateServiceForegroundLocked(r.app, false);
                try {
                    bumpServiceExecutingLocked(r, false, "destroy");
                    mDestroyingServices.add(r);
                    r.destroying = true;
                    mAm.updateOomAdjLocked(r.app);
                    //经过上面的把这个服务从当前的AMS中的信息中去除调,保证以后也不会自动重启服务了
                    
                    //核心代码 调用了客户端的ActivityThread  停止服务
                    r.app.thread.scheduleStopService(r);
                } catch (Exception e) {
                    Slog.w(TAG, "Exception when destroying service "
                            + r.shortName, e);
                    serviceProcessGoneLocked(r);
                }
            } else {
                if (DEBUG_SERVICE) Slog.v(
                    TAG_SERVICE, "Removed service that has no process: " + r);
            }
        } else {
            if (DEBUG_SERVICE) Slog.v(
                TAG_SERVICE, "Removed service that is not running: " + r);
        }

        if (r.bindings.size() > 0) {
            r.bindings.clear();
        }

        if (r.restarter instanceof ServiceRestarter) {
           ((ServiceRestarter)r.restarter).setService(null);
        }

        int memFactor = mAm.mProcessStats.getMemFactorLocked();
        long now = SystemClock.uptimeMillis();
        if (r.tracker != null) {
            r.tracker.setStarted(false, memFactor, now);
            r.tracker.setBound(false, memFactor, now);
            if (r.executeNesting == 0) {
                r.tracker.clearCurrentOwner(r, false);
                r.tracker = null;
            }
        }

        smap.ensureNotStartingBackground(r);
    }

前面说到了核心代码 r.app.thread.scheduleStopService?;

这个也是进程间通信,中间过程不说了,直接到ActivityThread中的代码来说

19、ActivityThread#handleStopService

    private void handleStopService(IBinder token) {
    //把当前的服务列表中移除这个服务
    
        Service s = mServices.remove(token);
        if (s != null) {
            try {
                if (localLOGV) Slog.v(TAG, "Destroying service " + s);
                //执行这个service的onDestory方法
                s.onDestroy();
                Context context = s.getBaseContext();
                if (context instanceof ContextImpl) {
                    final String who = s.getClassName();
                    //执行Service中的Context 清除工作
                    //比如反注册广播等
                    ((ContextImpl) context).scheduleFinalCleanup(who, "Service");
                }
				//等待里面的异步线程runable执行完,才继续
                QueuedWork.waitToFinish();

                try {
                //向AMS发送 关闭这个服务成功了的回执,然后在AMS也要对这个服务的信息做清理工作
                    ActivityManagerNative.getDefault().serviceDoneExecuting(
                            token, SERVICE_DONE_EXECUTING_STOP, 0, 0);
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            } catch (Exception e) {
                if (!mInstrumentation.onException(s, e)) {
                    throw new RuntimeException(
                            "Unable to stop service " + s
                            + ": " + e.toString(), e);
                }
                Slog.i(TAG, "handleStopService: exception for " + token, e);
            }
        } else {
            Slog.i(TAG, "handleStopService: token=" + token + " not found.");
        }
        //Slog.i(TAG, "Running services: " + mServices);
    }

我们来说下Service开始和停止的本质是什么,

启动了这个Service后,这个Service 执行了生命周期的方法,然后这个服务的信息就记录到AMS中了,以后系统发的消息,都会按照条件发送到Service中,比如广播等,这个Service是活着的,可以和外界通信

如果这个服务停止了,就把这个服务在AMS上注册的信息还有资源删除掉,这个服务无法和外界交互了,这个服务所持有的Context 都清理了,这个Service就无法正常工作了

好了到此为止吧,整个Service的启动还有结束就分析完了,由于技术有限,如有错误,期待评论中讨论~~~。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-11-28 11:24:56  更:2021-11-28 11:27:08 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 6:08:22-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码