当前位置:网站首页>Startservice() procedure
Startservice() procedure
2022-06-29 19:55:00 【Full stack programmer webmaster】
client Terminal startService()
We are Application perhaps Activity Call inside bindService() When , It's actually calling theta Context Abstract methods in :
public abstract ComponentName startService(Intent service);
Copy code The real thing is now ContextImpl in :
@Override
public ComponentName startService(Intent service) {
// When system When the process calls this method, it outputs warn Information ,system Process setup call startServiceAsUser Method
warnIfCallingFromSystemProcess();
return startServiceCommon(service, mUser);
}
Copy code and startServiceCommon() The method is as follows :
private ComponentName startServiceCommon(Intent service, UserHandle user) {
try {
// test service, When service If it's empty throw abnormal
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
// call ActivityManagerNative class
ComponentName cn = ActivityManagerNative.getDefault().startService(
mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
getContentResolver()), getOpPackageName(), user.getIdentifier());
if (cn != null) {
if (cn.getPackageName().equals("!")) {
throw new SecurityException(
"Not allowed to start service " + service
+ " without permission " + cn.getClassName());
} else if (cn.getPackageName().equals("!!")) {
throw new SecurityException(
"Unable to start service " + service
+ ": " + cn.getClassName());
}
}
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
Copy code This method mainly calls AMS.startService(), Some of the parameters , And then through IPC Call to AMS Of startService() Method .
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, String callingPackage, int userId)
throws TransactionTooLargeException {
// When the caller is an isolated process , Throw an exception .
enforceNotIsolatedCaller("startService");
// 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");
}
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
"startService: " + service + " type=" + resolvedType);
synchronized(this) {
final int callingPid = Binder.getCallingPid();// caller pid
final int callingUid = Binder.getCallingUid();// caller uid
final long origId = Binder.clearCallingIdentity();
// This time mServices by ActiveServices object
ComponentName res = mServices.startServiceLocked(
caller,//IApplicationThread type
service,//Intent type , Contains the service Information
resolvedType,//String type
callingPid,
callingUid,
callingPackage,//String type , The method is called package
userId// User id
);
Binder.restoreCallingIdentity(origId);
return res;
}
}
Copy code mServices yes ActiveServices object , Its bindServiceLocked() The method is as follows :
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, String callingPackage, final int userId)
throws TransactionTooLargeException {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service
+ " type=" + resolvedType + " args=" + service.getExtras());
final boolean callerFg;
if (caller != null) {
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
if (callerApp == null) {
throw new SecurityException(
"Unable to find app for caller " + caller
+ " (pid=" + Binder.getCallingPid()
+ ") when starting service " + service);
}
callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
} else {
callerFg = true;
}
// Retrieve service information
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg, false);
if (res == null) {
return null;
}
if (res.record == null) {
return new ComponentName("!", res.permission != null
? res.permission : "private to package");
}
ServiceRecord r = res.record;
// Check if there is a to start the service user
if (!mAm.mUserController.exists(r.userId)) {
Slog.w(TAG, "Trying to start service with non-existent user! " + r.userId);
return null;
}
if (!r.startRequested) {
final long token = Binder.clearCallingIdentity();
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); } } NeededUriGrants neededGrants = mAm.checkGrantUriPermissionFromIntentLocked( callingUid, r.packageName, service, service.getFlags(), null, r.userId); // If permissions need a review before any of the app components can run, // we do not start the service and launch a review activity if the calling app // is in the foreground passing it a pending intent to start the service when // review is completed. if (Build.PERMISSIONS_REVIEW_REQUIRED) { if (!requestStartTargetPermissionsReviewIfNeededLocked(r, callingPackage, callingUid, service, callerFg, userId)) { return null; } } if (unscheduleServiceRestartLocked(r, callingUid, false)) { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "START SERVICE WHILE RESTART PENDING: " + r); } r.lastActivity = SystemClock.uptimeMillis(); r.startRequested = true; r.delayedStop = false; r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(), service, neededGrants)); final ServiceMap smap = getServiceMap(r.userId); boolean addToStarting = false; // For the scheduling of non foreground processes if (!callerFg && r.app == null && mAm.mUserController.hasStartedUserState(r.userId)) { ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false); if (proc == null || proc.curProcState > ActivityManager.PROCESS_STATE_RECEIVER) { // If this is not coming from a foreground caller, then we may want // to delay the start if there are already other background services // that are starting. This is to avoid process start spam when lots // of applications are all handling things like connectivity broadcasts. // We only do this for cached processes, because otherwise an application // can have assumptions about calling startService() for a service to run // in its own process, and for that process to not be killed before the // service is started. This is especially the case for receivers, which // may start a service in onReceive() to do some additional work and have // initialized some global state as part of that. if (DEBUG_DELAYED_SERVICE) Slog.v(TAG_SERVICE, "Potential start delay of " + r + " in " + proc); if (r.delayed) {// Delayed start scheduled // This service is already scheduled for a delayed start; just leave // it still waiting. if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Continuing to delay: " + r); return r.name; } if (smap.mStartingBackground.size() >= mMaxStartingBackground) { // Something else is starting, delay! Slog.i(TAG_SERVICE, "Delaying start of: " + r); // When exceeding The maximum number of services that can be subsequently started at the same time , Then add the service to the delayed start queue . smap.mDelayedStartList.add(r); r.delayed = true; return r.name; } if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Not delaying: " + r); addToStarting = true; } else if (proc.curProcState >= ActivityManager.PROCESS_STATE_SERVICE) { // We slightly loosen when we will enqueue this new service as a background // starting service we are waiting for, to also include processes that are // currently running other services or receivers. // Add a new service to the background startup queue , The queue also contains other currently running services perhaps receivers The process of addToStarting = true; if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Not delaying, but counting as bg: " + r); } else if (DEBUG_DELAYED_STARTS) { StringBuilder sb = new StringBuilder(128); sb.append("Not potential delay (state=").append(proc.curProcState) .append(' ').append(proc.adjType); String reason = proc.makeAdjReason(); if (reason != null) { sb.append(' '); sb.append(reason); } sb.append("): "); sb.append(r.toString()); Slog.v(TAG_SERVICE, sb.toString()); } } else if (DEBUG_DELAYED_STARTS) { // When the initiator process is not equal to Process.THREAD_GROUP_BG_NONINTERACTIVE, Or the initiator is empty , be callerFg= true; // otherwise ,callerFg= false; if (callerFg) { Slog.v(TAG_SERVICE, "Not potential delay (callerFg=" + callerFg + " uid=" + callingUid + " pid=" + callingPid + "): " + r); } else if (r.app != null) { Slog.v(TAG_SERVICE, "Not potential delay (cur app=" + r.app + "): " + r); } else { Slog.v(TAG_SERVICE, "Not potential delay (user " + r.userId + " not started): " + r); } } return startServiceInnerLocked(smap, service, r, callerFg, addToStarting); } Copy code The method mainly includes :
- call retrieveServiceLocked() Method to get ServiceLookupResult This query result , This method will first try to fetch from the cache ServiceRecord object , If not, new ServiceRecord And stored in the cache , Last returned ServiceLookupResult yes ServiceRecord The wrapper class ;
- call unscheduleServiceRestartLocked(), That is, if you want to start Service In the restart list , Then take it from AMS Of mHandler Remove the rebooted Callback;
- call startServiceInnerLocked() Will start Service, This process may also be accompanied by startup Service In the process ( If the process does not start );
startServiceInnerLocked() as follows :
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
ServiceState stracker = r.getTracker();
if (stracker != null) {
stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
}
r.callStart = false;
synchronized (r.stats.getBatteryStats()) {
r.stats.startRunningLocked();// Used for power consumption statistics , Start the running state
}
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
if (error != null) {
return new ComponentName("!!", error);
}
if (r.startRequested && addToStarting) {
boolean first = smap.mStartingBackground.size() == 0;
smap.mStartingBackground.add(r);
r.startingBgTimeout = SystemClock.uptimeMillis() + BG_START_TIMEOUT;
if (DEBUG_DELAYED_SERVICE) {
RuntimeException here = new RuntimeException("here");
here.fillInStackTrace();
Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r, here);
} else if (DEBUG_DELAYED_STARTS) {
Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r);
}
if (first) {
smap.rescheduleDelayedStarts();
}
} else if (callerFg) {
smap.ensureNotStartingBackground(r);
}
return r.name;
}
Copy code service End process startup and service start-up
You can refer to bindService().
start-up service
service The process has been started
If you need to start service Has been launched
public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,
int flags ,Intent args) {
ServiceArgsData s = new ServiceArgsData();
s.token = token;
s.taskRemoved = taskRemoved;
s.startId = startId;
s.flags = flags;
s.args = args;
sendMessage(H.SERVICE_ARGS, s);
}
Copy code stay Handler In the processing :
private void handleServiceArgs(ServiceArgsData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
if (data.args != null) {
data.args.setExtrasClassLoader(s.getClassLoader());
data.args.prepareToEnterProcess();
}
int res;
if (!data.taskRemoved) {
res = s.onStartCommand(data.args, data.flags, data.startId);
} else {
s.onTaskRemoved(data.args);
res = Service.START_TASK_REMOVED_COMPLETE;
}
QueuedWork.waitToFinish();
try {
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
ensureJitEnabled();
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
throw new RuntimeException(
"Unable to start service " + s
+ " with " + data.args + ": " + e.toString(), e);
}
}
}
}
Copy code Here we call service Of onStartCommand() Method .
If you need to start service Not yet. It has been started
First create service
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);
// send out delay news
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()) {
r.stats.startLaunchedLocked();
}
mAm.notifyPackageUse(r.serviceInfo.packageName,
PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
// Service entry onCreate()
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);
// Apply death treatment
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) {
app.services.remove(r);
r.app = null;
}
// Retry.
// Try restarting the service
if (!inDestroying) {
scheduleServiceRestartLocked(r, false);
}
}
}
if (r.whitelistManager) {
app.whitelistManager = true;
}
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 Get into onStartCommand()
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); // Out of Service } } } Copy code The main method is to do , establish service And call onCreate() Method , Binding services , call service Of onStartCommand() Method .
service The process has not started yet
private final String bringUpServiceLocked(ServiceRecord r,
int intentFlags, boolean execInFg, boolean whileRestarting) {
...
// The first two cases are omitted , Has analyzed
if (app == null) {
// This process has not been loaded , Create a new process , Then start service
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);
// start-up service, I'll analyze it later
bringDownServiceLocked(r);
return msg;
}
if (isolated) {
r.isolatedProc = app;
}
}
// Save this ServiceRecord
if (!mPendingServices.contains(r)) {
mPendingServices.add(r);
}
....
return null;
}
Copy code It is judged above that if the process needs to be created, it is through calling mAm.startProcessLocked Generated process ,mAm Namely AMS, Let's see startProcessLocked Method :
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
long startTime = SystemClock.elapsedRealtime();
.....
try {
.....
// Notice if entryPoint be equal to null Words , Will be assigned android.app.ActivityThread
boolean isActivityProcess = (entryPoint == null);
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
checkTime(startTime, "startProcess: asking zygote to start proc");
// Start the process
Process.ProcessStartResult startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
app.info.dataDir, entryPointArgs);
checkTime(startTime, "startProcess: returned from zygote!");
....
} catch (RuntimeException e) {
.....
}
}
Copy code It specifies ActivityThread After this class of , After the process is created, it will call ActivityThread Of main Method . The process will call back during startup
boolean attachApplicationLocked(ProcessRecord proc, String processName)
throws RemoteException {
boolean didSomething = false;
// Collect any services that are waiting for this process to come up.
// start-up mPendingServices In line , Wait for the service to start in this process
if (mPendingServices.size() > 0) {
ServiceRecord sr = null;
try {
for (int i=0; i<mPendingServices.size(); i++) {
sr = mPendingServices.get(i);
if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
|| !processName.equals(sr.processName))) {
continue;
}
mPendingServices.remove(i);
i--;
// Add the package information of the current service to proc
proc.addPackage(sr.appInfo.packageName, sr.appInfo.versionCode,
mAm.mProcessStats);
// Start the service , About to enter the service life cycle
realStartServiceLocked(sr, proc, sr.createdFromFg);
didSomething = true;
if (!isServiceNeeded(sr, false, false)) {
// We were waiting for this service to start, but it is actually no
// longer needed. This could happen because bringDownServiceIfNeeded
// won't bring down a service that is pending... so now the pending // is done, so let's drop it.
bringDownServiceLocked(sr);
}
}
} catch (RemoteException e) {
Slog.w(TAG, "Exception in new application when starting service "
+ sr.shortName, e);
throw e;
}
}
// Also, if there are any services that are waiting to restart and
// would run in this process, now is a good time to start them. It would
// be weird to bring up the process but arbitrarily not let the services
// run at this point just because their restart time hasn't come up. // For services that are waiting to be restarted and need to run in the process , Now is a good time to start them if (mRestartingServices.size() > 0) { ServiceRecord sr; for (int i=0; i<mRestartingServices.size(); i++) { sr = mRestartingServices.get(i); if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid || !processName.equals(sr.processName))) { continue; } mAm.mHandler.removeCallbacks(sr.restarter); mAm.mHandler.post(sr.restarter); } } return didSomething; } Copy code Back here is service Has not started , however service The process already exists .
establish service
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 yes LoadedApk The object is APK The representation of a file in memory .
//Apk Information about the document , Such as Apk File code and resources ,
// Even in the code Activity,Service The information of the four components can be obtained through this object .
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
// load service class
java.lang.ClassLoader cl = packageInfo.getClassLoader();
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 {
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
// Judge Application Whether to create , Not created Application object ,
// But when the process is created above, it is already created , So it's going to go straight back to
Application app = packageInfo.makeApplication(false, mInstrumentation);
// initialization service
service.attach(context, this, data.info.name, data.token, app,
ActivityManagerNative.getDefault());
// call service Of onCreate Method
service.onCreate();
// Storage service Information about
mServices.put(data.token, service);
try {
// notice AMS Created
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (RemoteException e) {
// nothing to do.
}
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to create service " + data.info.name
+ ": " + e.toString(), e);
}
}
}
Copy code Publisher : Full stack programmer stack length , Reprint please indicate the source :https://javaforall.cn/101620.html Link to the original text :https://javaforall.cn
边栏推荐
- How is the combination of convolution and transformer optimal?
- WPS和Excele
- Flume配置4——自定义Source+Sink
- Regular expression series of mobile phone numbers
- 创作者基金会 6 月份亮点
- Connaissance générale des paramètres de sécurité du serveur Cloud
- One hour to build a sample scenario sound network to release lingfalcon Internet of things cloud platform
- 一个mysql里有3306端口下,一个mysql有20多个数据库,怎么一键备份20多个数据库,做系统备份,防止数据误删除?
- Physical verification LVS process and Technology (Part I)
- Dynamics crm: among locally deployed servers, sandbox, unzip, VSS, asynchronous and monitor services
猜你喜欢

How is the combination of convolution and transformer optimal?

One hour to build a sample scenario sound network to release lingfalcon Internet of things cloud platform

Understanding of software test logic coverage

文件包含漏洞

MySQL remote connection

一个mysql里有3306端口下,一个mysql有20多个数据库,怎么一键备份20多个数据库,做系统备份,防止数据误删除?

How to install and use computer SSD hard disk

Etcd database source code analysis - put process of server

【网络方向实训】-企业园区网络设计-【Had Done】

Deficiencies and optimization schemes in Dao
随机推荐
社区访谈丨一个IT新人眼中的JumpServer开源堡垒机
How to use filters in jfinal to monitor Druid for SQL execution?
With these four security testing tools, software security testing can be said so easy!
As the "only" privacy computing provider, insight technology is the "first" to settle in the Yangtze River Delta data element circulation service platform
shell bash脚本注意:单行末尾转义符 \ 后千万不能有其他无关字符(多行命令)
Deficiencies and optimization schemes in Dao
Exploration and practice of NLP problem modeling scheme
Flume理论
MBA-day26 数的概念与性质
Linux Installation mysql8
@Sneakythlows annotation
Freemaker template framework generates images
[network orientation training] - Enterprise Park Network Design - [had done]
freemarker模板框架生成图片
Canonical engineers are trying to solve the performance problem of Firefox snap
Inception 新结构 | 究竟卷积与Transformer如何结合才是最优的?
KDD 2022 | 协同过滤中考虑表征对齐和均匀性
做白银k线图有多重要?
Shell bash script note: there must be no other irrelevant characters after the escape character \ at the end of a single line (multi line command)
云服务器的安全设置常识