Android - context.stopService

Android's stopSevice's documentation suggests that the entire operation of stopping a service is synchronous and that the caller could use the result (boolean) to determine if the requested service was stopped or not. However, in my case, the requested service's onDestroy() wasn't invoked immediately, especially that it was hosted in its own process space. Turns out that the framework's callback to the requested service is actually one way

  mRemote.transact(SCHEDULE_STOP_SERVICE_TRANSACTION, data, null,
                          IBinder.FLAG_ONEWAY);

and the callback isn't handled immediately in the binder thread, instead if posted to the main thread which ends up invoking onDestroy() on the service.

 And as far is the caller is concerned, a result is returned even before the requested service receives the callback.

int stopServiceLocked(IApplicationThread caller, Intent service,
            String resolvedType, int userId) {
        ...
        ...
        ...
        ServiceLookupResult r = retrieveServiceLocked(service, resolvedType,
                Binder.getCallingPid(), Binder.getCallingUid(), userId, false, false);
        if (r != null) {
            if (r.record != null) {
                final long origId = Binder.clearCallingIdentity();
                try {
                    stopServiceLocked(r.record);
                } finally {
                    Binder.restoreCallingIdentity(origId);
                }
                return 1;
            }
            return -1;
        }

        return 0;
    }


No comments: