android start 서비스 프로세스 정리 노트
start Service는Context방법,Activity,Service는ContextWrapper를계승하고,ContextWrapper는Context를계승한다.BroadcastReceiver의onReceive방법중 하나의파라미터는Context유형이기 때문에Activity,Service,BroadcastReceiver에서start Service방법을 호출할 수 있다.Activity 등에서start Service를 호출할 때먼저 ContextWrapper의 startService 메서드가 호출됩니다.
public ComponentName startService(Intent service) {
return mBase.startService(service);
}
2、ContextImpl.startService
mBase는 ContextImpl의 실례로 이름에서도 볼 수 있고 ContextImpl도 Context의 하위 클래스이다. ContextWrapper의 이름에서도 볼 수 있다. 이것은 단지 Context의 포장 클래스일 뿐이고 함수 내부의 실현은 내부 ContextImpl 클래스의 실례 mBase를 호출하여 실제 요청을 완성하는 것으로 장식자 모드라고 부른다.
ContextImpl의 start Service는 start Service Asuser를 직접 호출하고 start Service Asuser에서Activity ManagerNative를 호출합니다.getDefault().startService,ActivityManagerNative.getDefault () 는 전형적인 Binder 통신을 위한 IACtivity Manager 대상을 되돌려줍니다.따라서 다음은Activity Manager Proxy의 start Service를 통해 Binder를 통해Activity Manager Service(Activity Manager Native에서 계승된)의 start Service 방법으로 호출됩니다.
public ComponentName startServiceAsUser(Intent service, UserHandle user) {
try {
service.setAllowFds(false);
ComponentName cn = ActivityManagerNative.getDefault().startService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
...
return cn;
} catch (RemoteException e) {
return null;
}
}
3、ActivityManagerService.startService 및 ActiveServices
Activity Manager 서비스의 start 서비스에서 먼저 Caller의 합법성(PID, UID)을 검사한 다음에Active Services의 start Service Locked 방법(구 버전에서는Activity Manager 서비스에서)을 호출하고 start Service Locked에서는retrieve Service Locked를 통해 start Service를 호출할 때 전송된 Intent 정보를 검색합니다.결과를 ServiceLookupResult에 저장합니다.record에서(ServiceRecord) Active Services의bringUp ServiceLocked 방법을 호출합니다.
bringUpServiceLocked에서ActivityManagerService를 호출하는 startProcessLocked는ProcessRecord 대상을 획득하여 mPendingServices 대기열에 추가합니다.start Service Locked,bring Up Service Locked는 모두Activity Manager 서비스에서 호출된 것이기 때문에Activity a Manager 서비스 프로세스에서 계속 실행되고Activity Manager 서비스를 다시 호출하는 방법은 IPC를 통과하지 않고 직접 호출하는 것이다.
Activity Manager 서비스에는 두 개의 재부팅 형식의 start Process Locked가 있습니다. 먼저 파라미터가 많은 곳에 들어가면 new Process Record Locked를 통해 하나의 Process Record 대상을 얻고 이 대상을 파라미터로 다른 형식의 start Process Locked를 호출합니다. 이 start Process Locked에서 Process를 호출합니다.start에서 새 프로세스를 만들고 Process로 돌아갑니다.ProcessStartResult 대상, 새 프로세스의 PID 및 획득한 ProcessRecord 대상을 mPidSelfLocked 목록에 넣습니다.
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
String hostingType, ComponentName hostingName, boolean allowWhileBooting, boolean isolated) {
...
app = newProcessRecordLocked(null, info, processName, isolated);
...
startProcessLocked(app, hostingType, hostingNameStr);
return (app.pid != 0) ? app : null;
}
private final void startProcessLocked(ProcessRecord app,
String hostingType, String hostingNameStr) {
...
Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, null, null);
...
synchronized (mPidsSelfLocked) {
this.mPidsSelfLocked.put(startResult.pid, app);
...
}
...
}
4、ActivityThread.main
Process.start에서 프로세스를 만들고 ActivityThread의main 함수를 호출했습니다.
public static void main(String[] args) {
...
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
...
Looper.loop();
...
}
5、ActivityManagerService.attachApplication
main에 ActivityThread 대상을 새로 만들고 attach 방법을 호출합니다. 매개 변수는 시스템 프로세스인지 여부를 표시합니다.이곳은 이미 새로운 진행 과정 안에 있다.attach에서 Activity ManagerNative가 호출되었습니다.getDefault().attachApplication(mAppThread).마찬가지로 Binder에서Activity Manager Proxy에서Activity Manager 서비스의attach Application 방법으로 attach Application에서attach Application Locked를 직접 호출합니다.
attach Application Locked에서 새 프로세스의 PID를 통해 3단계에서 mPid Self Locked 목록에 있는 Process Record 대상을 얻고Activey Services의attach Application Locked 방법을 호출합니다. 이 방법에서 프로세스 PID와 프로세스 이름을 통해 3단계에서 mPending Services에 넣은 서비스 Record 대상을 찾습니다.이 찾은 서비스 Record 대상과 전송된 Process Record 대상을 매개 변수로 RealStart 서비스 Locked를 호출합니다. 이 함수도Active 서비스에 있습니다.
private final boolean attachApplicationLocked(IApplicationThread thread, nt pid) {
ProcessRecord app;
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);
}
} else {
app = null;
}
...
mServices.attachApplicationLocked(app, processName);
...
}
boolean attachApplicationLocked(ProcessRecord proc, String processName) throws Exception {
boolean didSomething = false;
// Collect any services that are waiting for this process to come up.
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--;
realStartServiceLocked(sr, proc);
didSomething = true;
}
} catch (Exception e) {
Slog.w(TAG, "Exception in new application when starting service "
+ sr.shortName, e);
throw e;
}
}
...
}
6、ActiveServices.realStartServiceLocked
real Start Service Locked에서 전송된 Process Record 대상의 IApplication Thread 형식의 구성원 변수thread를 호출하여 schedule Create Service 방법을 호출합니다.Activity Manager Proxy와 같이 Application Thread Proxy의 schedule Create Service를 호출합니다.그리고 Binder를 통해 Application Thread의 schedule Create 서비스로 갑니다. (Application Thread는Activity Thread의 개인 내부 클래스입니다.)
7、ApplicationThread.scheduleCreate Service 및 ActivityThread.handleCreateService
Application Thread의 schedule Create 서비스에서 외부 클래스인Activity Thread의queue Or Send Message 방법을 호출하여 H의send Message(H는 Handler에서 계승됨)에 이어 H의handle Message에 틀림없이고handle Message에서CREATESERVICE의 switch case, 외부 클래스ActivityThread의handleCreate 서비스 방법을 호출합니다.
handleCreate 서비스는 JAVA의ClassLoader load를 통해 시작할 서비스의 클래스를 불러오고 newInstance를 통해 새 서비스의 예를 만듭니다. new Context Impl,make Application, 그리고 새 서비스의 실례attach를 불러옵니다. 그리고 익숙한 서비스의 onCreate 방법을 호출하여 서비스가 시작됩니다.
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 packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = (Service) cl.loadClass(data.info.name).newInstance();
} catch (Exception e) {
...
}
try {
if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
ContextImpl context = new ContextImpl();
context.init(packageInfo, null, this);
Application app = packageInfo.makeApplication(false, mInstrumentation);
context.setOuterContext(service);
service.attach(context, this, data.info.name, data.token, app,
ActivityManagerNative.getDefault());
// Service onCreate, Service onCreate
service.onCreate();
mServices.put(data.token, service);
try {
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, 0, 0, 0);
} catch (RemoteException e) {
// nothing to do.
}
} catch (Exception e) {
...
}
}
요약:
1. ContextImpl의 start Service를 호출하고 Binder를 통해Activity Manager Service에 들어가는 프로세스에서Activity Manager Service의 start Service 방법을 실행합니다.
2. startService 과정에서 새 프로세스를 만들고 새 프로세스에서 Looper를 만들며ActivityThread의attach 방법을 호출한 다음ActivityManagerService 프로세스에 들어갑니다.
3. 새 프로세스에서 시작할 서비스에 대한 정보를 얻고Activity Manager 서비스에서 ApplicationThreadProxy를 통해 서비스 프로세스에 들어가면 서비스 프로세스가 시작되고 우리가 익숙한 서비스의 onCreate 방법을 호출합니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.