美文网首页
service1-App中service与AMS 交互

service1-App中service与AMS 交互

作者: xuefeng_apple | 来源:发表于2020-09-03 11:52 被阅读0次

    service 是组件之一,可以理解class, 运行在某个进程中
    App中的不同组件可以运行在不同的进程里,也可以运行在相同的进程。

    zygote孵化而来的进程的代码执行入口点是ActivityThread.main()方法。main()方法初始化运行环境,最后创建一个looper并进入looper消息处理循环。main()方法所在的线程是进程的主线程,也称为UI线程。当启动的service没有通过android:process属性指定运行在一个新的进程中时,这个service也是运行在UI线程中的。那么这种情况下的service作用就大大折扣了,因为一旦这里执行耗时操作,后果可想而知。

    Service生命周期
    官网介绍

    图片.png
    第一次 startService 会触发 onCreate 和 onStartCommand,以后在服务运行过程中,每次 startService 都只会触发 onStartCommand。而且不论 startService 多少次,stopService 一次就会停止服务。

    第一次 bindService 会触发 onCreate 和 onBind,以后在服务运行过程中,每次 bindService 都不会触发任何回调。这里要注意的是 bindService 多少次,就要有对应多少次的 unbindService, 最后的一次unbindService执行完后,就会停止当前服务。

    service在AMS中的代表
    组件的生命周期方法都是AMS负责管理的,service当然也不例外了。一个运行着的service在AMS中的代表是ServiceRecord
    frameworks/base/services/core/java/com/android/server/am/ServiceRecord.java
    ServiceRecord:

    final class ServiceRecord extends Binder {
        private static final String TAG = TAG_WITH_CLASS_NAME ? "ServiceRecord" : TAG_AM;
        final ActivityManagerService ams; 
        final ServiceInfo serviceInfo;
                                // all information about the service.
        final ApplicationInfo appInfo;
                                // information about service's app.
    
        final ArrayMap<Intent.FilterComparison, IntentBindRecord> bindings
                = new ArrayMap<Intent.FilterComparison, IntentBindRecord>();
                                // All active bindings to the service.
        final ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections
                = new ArrayMap<IBinder, ArrayList<ConnectionRecord>>();
                                // IBinder -> ConnectionRecord of all bound clients
    
        ProcessRecord app;      // where this service is running or null.
        boolean isForeground;   // is service currently in foreground mode?
    
    }
    

    serviceInfo和appInfo都是从PMS中获取的,PMS又是在该apk安装的时候通过解析AndroidManifest.xml中的service和applictaion标签获取的,并将信息存储到serviceInfo和appInfo

    bindings:
    bind service时需要用到intent。 AMS为每类bind 该service的Intent分配了一个IntentBindRecord类型对象,并存储在ServiceRecord.bindings

    connections:
    AMS为每次bind的连接分配一个ConnectionRecor类型对象d,并存储在ServiceRecord.connections

    另外ServiceRecord继承自Binder,说明在AMS中,负责管理service的ServiceRecord节点本身就是个binder实体。
    frameworks/base/services/core/java/com/android/server/am/ConnectionRecord.java
    ConnectionRecord:

    final class ConnectionRecord {
        final AppBindRecord binding;    // The application/service binding.
        final ActivityRecord activity;  // If non-null, the owning activity.
        final IServiceConnection conn;  // The client connection. ----》ServiceConnection.onServiceConnected()
        final int flags;                // Binding options.
        final int clientLabel;          // String resource labeling this client.
        final PendingIntent clientIntent; // How to launch the client.
        String stringName;              // Caching of toString.
        boolean serviceDead;            // Well is it?
        ........ 
    }
    

    IServiceConnection对象conn。这是app进程中的一个代理binder对象,通过这个对象AMS最终可以调用ServiceConnection.onServiceConnected().

    frameworks/base/services/core/java/com/android/server/am/ProcessRecord.java
    ProcessRecord是一个运行的进程在AMS中的代表,与service相关的重要成员

    final class ProcessRecord {
        private static final String TAG = TAG_WITH_CLASS_NAME ? "ProcessRecord" : TAG_AM;
        private final BatteryStatsImpl mBatteryStats; // where to collect runtime statistics
        final ApplicationInfo info; // all about the first app in the process
        final boolean isolated;     // true if this is a special isolated process
        final int uid;              // uid of process; may be different from 'info' if isolated
        final int userId;           // user of process.
        final String processName;   // name of the process
        // List of packages running in the process
        final ArrayMap<String, ProcessStats.ProcessStateHolder> pkgList = new ArrayMap<>();
        UidRecord uidRecord;        // overall state of process's uid.
        ArraySet<String> pkgDeps;   // additional packages we have a dependency on
    
        ////-----》thread 对应AMS 中
        IApplicationThread thread;  // the actual proc...  may be null only if
                                    // 'persistent' is true (in which case we
                                    // are in the process of launching the app)
    
        // all activities running in the process-----》activities 
        final ArrayList<ActivityRecord> activities = new ArrayList<>();
    
        // all ServiceRecord running in this process------》 services 
        final ArraySet<ServiceRecord> services = new ArraySet<>();
    
        // services that are currently executing code (need to remain foreground).
        final ArraySet<ServiceRecord> executingServices = new ArraySet<>();
    
        // All ConnectionRecord this process holds
        final ArraySet<ConnectionRecord> connections = new ArraySet<>();
        // all IIntentReceivers that are registered from this process.
        final ArraySet<ReceiverList> receivers = new ArraySet<>();
        // class (String) -> ContentProviderRecord
        final ArrayMap<String, ContentProviderRecord> pubProviders = new ArrayMap<>();
        // All ContentProviderRecord process is using
        final ArrayList<ContentProviderConnection> conProviders = new ArrayList<>();
    }
    

    其中IApplicationThread类型的对象thread就是app进程中的ActivityThread.mAppThread这个binder在AMS中的代理。通过这个代理binder对象,AMS就可以间接跨进程调用app进程中的ActivityThread中的相关方法来创建一个service对象,并执行其生命周期方法了。

    ProcessRecord中的services是这个进程中的运行着的service的集合。
    connections是bind这个进程中的service时,分配的所有ConnectionRecord集合。

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

    /**
     * This manages the execution of the main thread in an
     * application process, scheduling and executing activities,
     * broadcasts, and other operations on it as the activity
     * manager requests.
     *
     * {@hide}
     */
    public final class ActivityThread {
        /** @hide */
        public static final String TAG = "ActivityThread";
        private static final android.graphics.Bitmap.Config THUMBNAIL_FORMAT = Bitmap.Config.RGB_565;
        static final boolean localLOGV = false;
        static final boolean DEBUG_MESSAGES = false;
        public static final long INVALID_PROC_STATE_SEQ = -1;
        private final Object mNetworkPolicyLock = new Object();
    
        static volatile IPackageManager sPackageManager;
        final ApplicationThread mAppThread = new ApplicationThread();----->这里对应AMS 中的thread
        final Looper mLooper = Looper.myLooper();
        final H mH = new H();
    
        private int mLastSessionId;
        final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();  --->这个AMS ServiceRecord 经过传递最后保存在 Service mToken中
    }
    

    service在app进程的代表
    frameworks/base/core/java/android/app/Service.java
    Service :

    public abstract class Service extends ContextWrapper implements ComponentCallbacks2 {
       private static final String TAG = "Service";
       
       // set by the thread after the constructor and before onCreate(Bundle icicle) is called.
       private ActivityThread mThread = null;
       private String mClassName = null;
       private IBinder mToken = null;
       private Application mApplication = null;
       private IActivityManager mActivityManager = null;   ---》 AMS 代理
       private boolean mStartCompatibility = false;
    }
    

    service紧紧是一个Context而已,运行某个进程中就可以

    注释中也说的很清楚了,在这个service被创建之后,有thread,也就是ActivityThread来设置这些属性成员,之后在执行service的第一个声明周期方法:onCreate.

    mThread就是service所在进程的ActivityThread对象。

    mToken就是这个service在AMS中的代表ServiceRecord的一个代理对象。

    mActivityManager是AMS在当前进程的代理对象。

    当service创建之后,它和AMS的关系如下:


    图片.png
    • service所在的进程是一个普通的app进程,是由zygote孵化的,这样的进程中有一个唯一的ActivityThread对象;

    • app进程在AMS中用ProcessRecord对象来表示;

    • ActivityThread.mAppThread是一个ApplicationThread类型的binder实体对象,在app进程启动后,会在ActivityThread.main()方法中传递给AMS,在AMS进程中这个binder的代理binder保存在ProcessRecord.thread中,这样的AMS可以通过这个代理binder跨进程调用某个app进程中的方法;

    • ActivityThread同样保存了AMS的代理binder,这样app进程也可以跨进程请求AMS中的方法。

    ActivityThread.mServices:

    final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();
    

    ServiceRecord 继承了binder,上面的ArrayMap中的key (IBinder)是一个运行在该进程中的service在AMS中的代表ServiceRecord这个实体的代理。
    当AMS请求app进程运行一个service时,会将这个代理binder传递到app进程,然后作为key保存mservice中。value就是运行在这个进程中的service。
    这个代理binder还会在Service对象创建之后,在service.attach中以参数的形式传入service,并作保存在service.mToken中 。private IBinder mToken=binder=ServiceRecord;

    • AMS中代表一个运行着的Service的ServiceRecord对象中保存了其所在的ProcessRecord。

    REF:
    https://developer.android.com/guide/components/services
    https://androidforums.com/threads/apps-restarting-themselves-after-force-stop.352806/

    相关文章

      网友评论

          本文标题:service1-App中service与AMS 交互

          本文链接:https://www.haomeiwen.com/subject/ejvnsktx.html