service1-App中service与AMS 交互

2020-09-03  本文已影响0人  xuefeng_apple

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

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;

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

上一篇下一篇

猜你喜欢

热点阅读