mServices.startServiceLocked ->
try {
// Before going further -- if this app is not allowed to run in the
// background, then at this point we aren't going to let it period.
final int allowed = mAm.checkAllowBackgroundLocked(
r.appInfo.uid, r.packageName, callingPid, true);
if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
Slog.w(TAG, "Background start not allowed: service "
+ service + " to " + r.name.flattenToShortString()
+ " from pid=" + callingPid + " uid=" + callingUid
+ " pkg=" + callingPackage);
return null;
}
} finally {
Binder.restoreCallingIdentity(token);
}
检查是否允许后台启动,后台不在白名单中的APP将禁止启动后台服务,前台服务必须启动一个通知出来,即给5S的延时,调用startForeground,否则报异常。
如果后台服务过多,会将service延时启动。
如果所属的进程尚未启动先启动进程,然后把service 加入pengdingservice列表中。
bind service 与 start service 区别:
bindService-> bindserviceLocked ,
ConnectionRecord c = new ConnectionRecord(b, activity,
connection, flags, clientLabel, clientIntent);
IBinder binder = connection.asBinder();
ConnectionRecord 会把app端的IServiceConnection asBinder 放入到 ConnectionRecord列表中。当connect 上service时,回调onServiceConnected 接口。
因此 如果只是做一些耗时操作,直接start service
如果需要与service进行交互 使用bind service
后台service 超时时间60S,超过60s后 其优先级将会降低(updateOomAdjLocked),被认为是闲置状态,会被stop掉。
前台service 20S 对用户有感知的.
匿名binder:写入binder接口参数: parcel.writeStrongBinder (listener.asBinder)
读出: readStrongBinder
binder 属性加上 FLAG_ONEWAY 无需要等待客户端返回,
一般binder最大传输数据限制1M。
关于进程的管理:
在activityThread创建出来进行attach的时候:
final ApplicationThread mAppThread = new ApplicationThread(); 系统进程访问应用的接口,负责与AMS通讯 并告知ActivityThread,ActivityThread 负责完成ActivityThread 生命周期的调度。
try {//向AMS发送binder调用。传递ApplicationThread。
mgr.attachApplication(mAppThread);//进入AMS的attachApplication
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
//没有Application 创建
mInitialApplication = context.mPackageInfo.makeApplication(true, null);
mInitialApplication.onCreate();//Application 的 onCreate 回调
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();//调用了同进程中的attachApplicationLocked的接口前,clearCallingIdentity()方法会清除APP process的UID和PID,
//重置为AMS的UID和PID。否则接下来的attachApplicationLocked 将会无权限调用
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
//此时仍然处在APP process远程调用attachApplication 方法的过程中,此时需要restore APP process的UID和PID。
Binder.restoreCallingIdentity(origId);
}
}
每个应用程序,在AMS中对应唯一的一个ProcessRecord对象,而在应用端,对应唯一的一个ActivityThread和ApplicationThread对象。*/
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// 该进程中第一个驻留的app(apk)
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
// 该进程中可以驻留多个app(apk)例如 一些系统APP 配置在同一个process: system
final ArrayMap<String, ProcessStats.ProcessStateHolder> pkgList = new ArrayMap<>();
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)
UidRecord uidRecord; // overall state of process's uid.
初始化一个ProcessRecord描述进程信息。
app.makeActive(thread, mProcessStats);
app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;
app.curSchedGroup = app.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.forcingToImportant = null;
updateProcessForegroundLocked(app, false, false);
app.hasShownUi = false;
app.debugging = false;
app.cached = false;
app.killedByAm = false;
app.killed = false;
IApplicationThread thread 参数传递
//调取到ActivityThread.bindApplication
thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
null, null, null, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(getGlobalConfiguration()), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, isAutofillCompatEnabled);
sendMessage(H.BIND_APPLICATION, data);//-->handleBindApplication
-》 //创建Application对象,这是根据AndroidManifest.xml配置文件中的Application标签的信息来创建的
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
try {
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
这个attachApplicationLocked怎么调的?
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
final String processName = app.processName;
boolean didSomething = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (!isFocusedStack(stack)) {
continue;
}
ActivityRecord hr = stack.topRunningActivityLocked();
if (hr != null) {
if (hr.app == null && app.uid == hr.info.applicationInfo.uid
&& processName.equals(hr.processName)) {
try {
if (realStartActivityLocked(hr, app, true, true)) {
didSomething = true;
}
} catch (RemoteException e) {
Slog.w(TAG, "Exception in new application when starting activity "
+ hr.intent.getComponent().flattenToShortString(), e);
throw e;
}
}
}
}
}
if (!didSomething) {
ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
return didSomething;