service 是组件之一,可以理解class, 运行在某个进程中
App中的不同组件可以运行在不同的进程里,也可以运行在相同的进程。
zygote孵化而来的进程的代码执行入口点是ActivityThread.main()方法。main()方法初始化运行环境,最后创建一个looper并进入looper消息处理循环。main()方法所在的线程是进程的主线程,也称为UI线程。当启动的service没有通过android:process属性指定运行在一个新的进程中时,这个service也是运行在UI线程中的。那么这种情况下的service作用就大大折扣了,因为一旦这里执行耗时操作,后果可想而知。
Service生命周期
官网介绍
第一次 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/
网友评论