Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f6f9f2d0 authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Add more control over a service's start state.

One of the problems I have been noticing is background services
sitting around running and using resources.  Some times this is
due to the app developer doing this when they shouldn't, but there
are also a number of issues with the current Service interaction
model that make it very difficult (or impossible) to avoid
getting services stuck in the started state.  This is a
change/enhancement to the Service API to try to address this.

The main change is that Service.onStart() has been deprecated,
replaced with a new Service.onStartCommand() that allows the
service to better control how the system should manage it.  The
key part here is a new result code returned by the function, telling
the system what it should do with the service afterwards:

- START_STICKY is basically the same as the previous behavior,
  where we usually leave the service running.  The only difference
  is that it if it gets restarted because its process is killed,
  onStartCommand() will be called on the new service with a null
  Intent instead of not being called at all.

- START_NOT_STICKY says that, upon returning to the system, if
  its process is killed with no remaining start commands to
  deliver, then the service will be stopped instead of restarted.
  This makes a lot more sense for services that are intended to
  only run while executing commands sent to them.

- START_REDELIVER_INTENT is like START_NOT_STICKY, except if
  the service's process is killed before it calls stopSelf()
  for a given intent, that intent will be re-delivered to it
  until it completes (unless after 4 or more tries it still
  can't complete, at which point we give up).

Change-Id: I978f5ca420d70023d1b5e7f97de639d09381f8ad
parent 2e951b55
Loading
Loading
Loading
Loading
+118 −0
Original line number Diff line number Diff line
@@ -21568,6 +21568,19 @@
<parameter name="intent" type="android.content.Intent">
</parameter>
</method>
<method name="setIntentRedelivery"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="enabled" type="boolean">
</parameter>
</method>
</class>
<class name="KeyguardManager"
 extends="java.lang.Object"
@@ -23767,11 +23780,28 @@
 synchronized="false"
 static="false"
 final="false"
 deprecated="deprecated"
 visibility="public"
>
<parameter name="intent" type="android.content.Intent">
</parameter>
<parameter name="startId" type="int">
</parameter>
</method>
<method name="onStartCommand"
 return="int"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="intent" type="android.content.Intent">
</parameter>
<parameter name="flags" type="int">
</parameter>
<parameter name="startId" type="int">
</parameter>
</method>
@@ -23866,6 +23896,83 @@
<parameter name="startId" type="int">
</parameter>
</method>
<field name="START_CONTINUATION_MASK"
 type="int"
 transient="false"
 volatile="false"
 value="15"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="START_FLAG_REDELIVERY"
 type="int"
 transient="false"
 volatile="false"
 value="1"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="START_FLAG_RETRY"
 type="int"
 transient="false"
 volatile="false"
 value="2"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="START_NOT_STICKY"
 type="int"
 transient="false"
 volatile="false"
 value="2"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="START_REDELIVER_INTENT"
 type="int"
 transient="false"
 volatile="false"
 value="3"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="START_STICKY"
 type="int"
 transient="false"
 volatile="false"
 value="1"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="START_STICKY_COMPATIBILITY"
 type="int"
 transient="false"
 volatile="false"
 value="0"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
</class>
<class name="TabActivity"
 extends="android.app.ActivityGroup"
@@ -95009,6 +95116,17 @@
 visibility="public"
>
</field>
<field name="ECLAIR"
 type="int"
 transient="false"
 volatile="false"
 value="10000"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
</class>
<class name="Bundle"
 extends="java.lang.Object"
+9 −2
Original line number Diff line number Diff line
@@ -608,7 +608,10 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
        case SERVICE_DONE_EXECUTING_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            IBinder token = data.readStrongBinder();
            serviceDoneExecuting(token);
            int type = data.readInt();
            int startId = data.readInt();
            int res = data.readInt();
            serviceDoneExecuting(token, type, startId, res);
            reply.writeNoException();
            return true;
        }
@@ -1746,11 +1749,15 @@ class ActivityManagerProxy implements IActivityManager
        reply.recycle();
    }

    public void serviceDoneExecuting(IBinder token) throws RemoteException {
    public void serviceDoneExecuting(IBinder token, int type, int startId,
            int res) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(token);
        data.writeInt(type);
        data.writeInt(startId);
        data.writeInt(res);
        mRemote.transact(SERVICE_DONE_EXECUTING_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
        reply.readException();
        data.recycle();
+12 −7
Original line number Diff line number Diff line
@@ -1215,6 +1215,7 @@ public final class ActivityThread {
    private static final class ServiceArgsData {
        IBinder token;
        int startId;
        int flags;
        Intent args;
        public String toString() {
            return "ServiceArgsData{token=" + token + " startId=" + startId
@@ -1417,10 +1418,11 @@ public final class ActivityThread {
        }

        public final void scheduleServiceArgs(IBinder token, int startId,
            Intent args) {
            int flags ,Intent args) {
            ServiceArgsData s = new ServiceArgsData();
            s.token = token;
            s.startId = startId;
            s.flags = flags;
            s.args = args;

            queueOrSendMessage(H.SERVICE_ARGS, s);
@@ -2684,7 +2686,8 @@ public final class ActivityThread {
            service.onCreate();
            mServices.put(data.token, service);
            try {
                ActivityManagerNative.getDefault().serviceDoneExecuting(data.token);
                ActivityManagerNative.getDefault().serviceDoneExecuting(
                        data.token, 0, 0, 0);
            } catch (RemoteException e) {
                // nothing to do.
            }
@@ -2710,7 +2713,7 @@ public final class ActivityThread {
                    } else {
                        s.onRebind(data.intent);
                        ActivityManagerNative.getDefault().serviceDoneExecuting(
                                data.token);
                                data.token, 0, 0, 0);
                    }
                } catch (RemoteException ex) {
                }
@@ -2736,7 +2739,7 @@ public final class ActivityThread {
                                data.token, data.intent, doRebind);
                    } else {
                        ActivityManagerNative.getDefault().serviceDoneExecuting(
                                data.token);
                                data.token, 0, 0, 0);
                    }
                } catch (RemoteException ex) {
                }
@@ -2773,9 +2776,10 @@ public final class ActivityThread {
                if (data.args != null) {
                    data.args.setExtrasClassLoader(s.getClassLoader());
                }
                s.onStart(data.args, data.startId);
                int res = s.onStartCommand(data.args, data.flags, data.startId);
                try {
                    ActivityManagerNative.getDefault().serviceDoneExecuting(data.token);
                    ActivityManagerNative.getDefault().serviceDoneExecuting(
                            data.token, 1, data.startId, res);
                } catch (RemoteException e) {
                    // nothing to do.
                }
@@ -2801,7 +2805,8 @@ public final class ActivityThread {
                    ((ApplicationContext) context).scheduleFinalCleanup(who, "Service");
                }
                try {
                    ActivityManagerNative.getDefault().serviceDoneExecuting(token);
                    ActivityManagerNative.getDefault().serviceDoneExecuting(
                            token, 0, 0, 0);
                } catch (RemoteException e) {
                    // nothing to do.
                }
+16 −4
Original line number Diff line number Diff line
@@ -206,8 +206,14 @@ public abstract class ApplicationThreadNative extends Binder
            data.enforceInterface(IApplicationThread.descriptor);
            IBinder token = data.readStrongBinder();
            int startId = data.readInt();
            Intent args = Intent.CREATOR.createFromParcel(data);
            scheduleServiceArgs(token, startId, args);
            int fl = data.readInt();
            Intent args;
            if (data.readInt() != 0) {
                args = Intent.CREATOR.createFromParcel(data);
            } else {
                args = null;
            }
            scheduleServiceArgs(token, startId, fl, args);
            return true;
        }

@@ -573,12 +579,18 @@ class ApplicationThreadProxy implements IApplicationThread {
    }

    public final void scheduleServiceArgs(IBinder token, int startId,
	    Intent args) throws RemoteException {
	    int flags, Intent args) throws RemoteException {
        Parcel data = Parcel.obtain();
        data.writeInterfaceToken(IApplicationThread.descriptor);
        data.writeStrongBinder(token);
        data.writeInt(startId);
        data.writeInt(flags);
        if (args != null) {
            data.writeInt(1);
            args.writeToParcel(data, 0);
        } else {
            data.writeInt(0);
        }
        mRemote.transact(SCHEDULE_SERVICE_ARGS_TRANSACTION, data, null,
                IBinder.FLAG_ONEWAY);
        data.recycle();
+2 −1
Original line number Diff line number Diff line
@@ -149,7 +149,8 @@ public interface IActivityManager extends IInterface {
    public void unbindFinished(IBinder token, Intent service,
            boolean doRebind) throws RemoteException;
    /* oneway */
    public void serviceDoneExecuting(IBinder token) throws RemoteException;
    public void serviceDoneExecuting(IBinder token, int type, int startId,
            int res) throws RemoteException;
    public IBinder peekService(Intent service, String resolvedType) throws RemoteException;
    
    public boolean bindBackupAgent(ApplicationInfo appInfo, int backupRestoreMode)
Loading