当前位置:网站首页>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
边栏推荐
- 一小时构建示例场景 声网发布灵隼物联网云平台
- What if the win11 policy service is disabled? Solution to disabling win11 policy service
- MBA-day19 如果p则q矛盾关系p 且非q
- 数据链路层
- Several policies of Shenzhen Futian District to support investment attraction in 2022
- CorelDRAW最新24.1.0.360版本更新介绍讲解
- Common knowledge of ECS security settings
- JVM (4) Bytecode Technology + Runtime Optimization
- With these four security testing tools, software security testing can be said so easy!
- Snowflake ID, distributed unique ID
猜你喜欢
![[USB flash disk test] in order to transfer the data at the bottom of the pressure box, I bought a 2T USB flash disk, and the test result is only 47g~](/img/c3/e0637385d35943f1914477bb9f2b54.png)
[USB flash disk test] in order to transfer the data at the bottom of the pressure box, I bought a 2T USB flash disk, and the test result is only 47g~

The concept and properties of mba-day26 number

Flume配置4——自定義Source+Sink

罗清启:高端家电已成红海?卡萨帝率先破局

Regular expression series of mobile phone numbers

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

Flutter calls Baidu map app to realize location search and route planning

Sophomore majoring in software engineering, the previous learning situation is not very good. How to plan the follow-up development route

Lock4j -- distributed lock Middleware -- customize the logic of lock acquisition failure

Kdd 2022 | prise en compte de l'alignement et de l'uniformité des représentations dans le Filtrage collaboratif
随机推荐
罗清启:高端家电已成红海?卡萨帝率先破局
Deficiencies and optimization schemes in Dao
The era of data security solutions
What about frequent network disconnection of win11 system? Solution to win11 network instability
[observation] softcom power liutianwen: embrace change and "follow the trend" to become an "enabler" of China's digital economy
2022年理财利率都降了,那该如何选择理财产品?
How to use filters in jfinal to monitor Druid for SQL execution?
画虎国手孟祥顺数字藏品限量发售,随赠虎年茅台
Freemaker template framework generates images
云服务器的安全设置常识
1404萬!四川省人社廳關系型數據庫及中間件軟件系統昇級采購招標!
Where is the win11 installation permission set? Win11 installation permission setting method
JVM(2) 垃圾回收
Dynamics crm: among locally deployed servers, sandbox, unzip, VSS, asynchronous and monitor services
How important is it to make a silver K-line chart?
【Try to Hack】vulnhub narak
第二章(物理层)
剑指 Offer 59 - II. 队列的最大值
MSYQL, redis, mongodb visual monitoring tool grafana
Sword finger offer 59 - I. maximum value of sliding window