[컴][안드로이드] startService 와 bindService 의 종료 순간


A service can be both started and have connections bound to it. In such a case, the system will keep the service running as long as either it is started or there are one or more connections to it with the Context.BIND_AUTO_CREATE flag. Once neither of these situations hold, the service's onDestroy() method is called and the service is effectively terminated. All cleanup (stopping threads, unregistering receivers) should be complete upon returning from onDestroy().



flow

android.content.ContextWrapper.stopService()
> android.app.ContextImpl.stopService()
> android.app.ContextImpl.stopServiceAsUser()
> android.app.ActivityManagerProxy.stopService()



// android.content.ContextWrapper
public boolean stopService(Intent name) {
    return mBase.stopService(name);
}

// android.app.ContextImpl    
public boolean stopService(Intent service) {
    warnIfCallingFromSystemProcess();
    return stopServiceAsUser(service, mUser);
}

// android.app.ContextImpl
public boolean stopServiceAsUser(Intent service, UserHandle user) {
    try {
        service.setAllowFds(false);
        int res = ActivityManagerNative.getDefault().stopService(
            mMainThread.getApplicationThread(), service,
            service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
        if (res < 0) {
            throw new SecurityException(
                    "Not allowed to stop service " + service);
        }
        return res != 0;
    } catch (RemoteException e) {
        return false;
    }
}

// android.app.ActivityManagerProxy
public int stopService(IApplicationThread caller, Intent service,
        String resolvedType, int userId) throws RemoteException
{
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IActivityManager.descriptor);
    data.writeStrongBinder(caller != null ? caller.asBinder() : null);
    service.writeToParcel(data, 0);
    data.writeString(resolvedType);
    data.writeInt(userId);
    mRemote.transact(STOP_SERVICE_TRANSACTION, data, reply, 0);
    reply.readException();
    int res = reply.readInt();
    reply.recycle();
    data.recycle();
    return res;
}



// android.app.ActivityThread
public void handleMessage(Message msg) {
    if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
    switch (msg.what) {
         case STOP_SERVICE:
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStop");
            handleStopService((IBinder)msg.obj);
            maybeSnapshot();
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            break;
        ...
    }
}

// android.app.ActivityThread
private void handleStopService(IBinder token) {
    Service s = mServices.remove(token);
    if (s != null) {
        try {
            if (localLOGV) Slog.v(TAG, "Destroying service " + s);
            s.onDestroy();
            Context context = s.getBaseContext();
            if (context instanceof ContextImpl) {
                final String who = s.getClassName();
                ((ContextImpl) context).scheduleFinalCleanup(who, "Service");
            }
            QueuedWork.waitToFinish();
            try {
                ActivityManagerNative.getDefault().serviceDoneExecuting(
                        token, 0, 0, 0);
            } catch (RemoteException e) {
                // nothing to do.
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(s, e)) {
                throw new RuntimeException(
                        "Unable to stop service " + s
                        + ": " + e.toString(), e);
            }
        }
    }
    //Slog.i(TAG, "Running services: " + mServices);
}


http://developer.android.com/guide/components/services.html#Lifecycle

댓글 없음:

댓글 쓰기