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

Commit effacfa7 authored by Matthew Williams's avatar Matthew Williams
Browse files

Add OnNetworkActive to TaskManager and simplify locking.

Bug: 14993295
Hooks up a ConnectivityManager.NetworkActiveListener.
    
Previously was using 3 locks where 1 would suffice,
negligible to no performance issues b/c most of the previous locks
were nested.

Added OnNetworkActiveListener so that the ConnectivityController can kick of
tasks when it knows that the network is active.

Fixed some bugs that stopped timecontroller from executing tasks.

Requesting a retry will not add a deadline to that task. However backed-off
tasks are run as soon as they are ready, subject to their constraints.

Added receiver to listen for package removal and user removal, which will
delete any outstanding jobs for that uid.

Change-Id: I4c4523af558b927f19b8a215878fcc7198abb93f
parent 6fffd2b8
Loading
Loading
Loading
Loading
+17 −7
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ package android.app;
import android.app.task.ITaskManager;
import android.app.task.Task;
import android.app.task.TaskManager;
import android.os.RemoteException;

import java.util.List;

@@ -37,26 +38,35 @@ public class TaskManagerImpl extends TaskManager {

    @Override
    public int schedule(Task task) {
        // TODO Auto-generated method stub
        return 0;
        try {
            return mBinder.schedule(task);
        } catch (RemoteException e) {
            return TaskManager.RESULT_FAILURE;
        }
    }

    @Override
    public void cancel(int taskId) {
        // TODO Auto-generated method stub
        try {
            mBinder.cancel(taskId);
        } catch (RemoteException e) {}

    }

    @Override
    public void cancelAll() {
        // TODO Auto-generated method stub
        try {
            mBinder.cancelAll();
        } catch (RemoteException e) {}

    }

    @Override
    public List<Task> getAllPendingTasks() {
        // TODO Auto-generated method stub
        try {
            return mBinder.getAllPendingTasks();
        } catch (RemoteException e) {
            return null;
        }

    }
}
+8 −3
Original line number Diff line number Diff line
@@ -48,6 +48,11 @@ public class Task implements Parcelable {
     * @hide
     */
    public static final int DEFAULT_BACKOFF_POLICY = BackoffPolicy.EXPONENTIAL;
    /**
     * Maximum backoff we allow for a job, in milliseconds.
     * @hide
     */
    public static final long MAX_BACKOFF_DELAY_MILLIS = 24 * 60 * 60 * 1000;  // 24 hours.

    /**
     * Linear: retry_time(failure_time, t) = failure_time + initial_retry_delay * t, t >= 1
@@ -185,7 +190,7 @@ public class Task implements Parcelable {
    private Task(Parcel in) {
        taskId = in.readInt();
        extras = in.readPersistableBundle();
        service = ComponentName.readFromParcel(in);
        service = in.readParcelable(null);
        requireCharging = in.readInt() == 1;
        requireDeviceIdle = in.readInt() == 1;
        networkCapabilities = in.readInt();
@@ -201,7 +206,7 @@ public class Task implements Parcelable {

    private Task(Task.Builder b) {
        taskId = b.mTaskId;
        extras = new PersistableBundle(b.mExtras);
        extras = b.mExtras;
        service = b.mTaskService;
        requireCharging = b.mRequiresCharging;
        requireDeviceIdle = b.mRequiresDeviceIdle;
@@ -225,7 +230,7 @@ public class Task implements Parcelable {
    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(taskId);
        out.writePersistableBundle(extras);
        ComponentName.writeToParcel(service, out);
        out.writeParcelable(service, flags);
        out.writeInt(requireCharging ? 1 : 0);
        out.writeInt(requireDeviceIdle ? 1 : 0);
        out.writeInt(networkCapabilities);
+1 −1
Original line number Diff line number Diff line
@@ -35,5 +35,5 @@ public interface StateChangedListener {
     * it must be run immediately.
     * @param taskStatus The state of the task which is to be run immediately.
     */
    public void onTaskDeadlineExpired(TaskStatus taskStatus);
    public void onRunTaskNow(TaskStatus taskStatus);
}
+214 −131

File changed.

Preview size limit exceeded, changes collapsed.

+61 −43
Original line number Diff line number Diff line
@@ -31,11 +31,11 @@ import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.WorkSource;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -54,7 +54,7 @@ public class TaskServiceContext extends ITaskCallback.Stub implements ServiceCon
    private static final int defaultMaxActiveTasksPerService =
            ActivityManager.isLowRamDeviceStatic() ? 1 : 3;
    /** Amount of time a task is allowed to execute for before being considered timed-out. */
    private static final long EXECUTING_TIMESLICE_MILLIS = 5 * 60 * 1000;
    private static final long EXECUTING_TIMESLICE_MILLIS = 60 * 1000;
    /** Amount of time the TaskManager will wait for a response from an app for a message. */
    private static final long OP_TIMEOUT_MILLIS = 8 * 1000;
    /** String prefix for all wakelock names. */
@@ -100,10 +100,14 @@ public class TaskServiceContext extends ITaskCallback.Stub implements ServiceCon
    /** Binder to the client service. */
    ITaskService service;

    private final Object mAvailableLock = new Object();
    private final Object mLock = new Object();
    /** Whether this context is free. */
    @GuardedBy("mAvailableLock")
    @GuardedBy("mLock")
    private boolean mAvailable;
    /** Track start time. */
    private long mExecutionStartTimeElapsed;
    /** Track when job will timeout. */
    private long mTimeoutElapsed;

    TaskServiceContext(TaskManagerService service, Looper looper) {
        this(service.getContext(), service, looper);
@@ -114,32 +118,25 @@ public class TaskServiceContext extends ITaskCallback.Stub implements ServiceCon
        mContext = context;
        mCallbackHandler = new TaskServiceHandler(looper);
        mCompletedListener = completedListener;
        mAvailable = true;
    }

    /**
     * Give a task to this context for execution. Callers must first check {@link #isAvailable()}
     * to make sure this is a valid context.
     * @param ts The status of the task that we are going to run.
     * @return True if the task was accepted and is going to run.
     * @return True if the task is valid and is running. False if the task cannot be executed.
     */
    boolean executeRunnableTask(TaskStatus ts) {
        synchronized (mAvailableLock) {
        synchronized (mLock) {
            if (!mAvailable) {
                Slog.e(TAG, "Starting new runnable but context is unavailable > Error.");
                return false;
            }
            mAvailable = false;
        }

        final PowerManager pm =
                (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                TM_WAKELOCK_PREFIX + ts.getServiceComponent().getPackageName());
        mWakeLock.setWorkSource(new WorkSource(ts.getUid()));
        mWakeLock.setReferenceCounted(false);

            mRunningTask = ts;
            mParams = new TaskParams(ts.getTaskId(), ts.getExtras(), this);
            mExecutionStartTimeElapsed = SystemClock.elapsedRealtime();

            mVerb = VERB_BINDING;
            final Intent intent = new Intent().setComponent(ts.getServiceComponent());
@@ -150,11 +147,15 @@ public class TaskServiceContext extends ITaskCallback.Stub implements ServiceCon
                if (DEBUG) {
                    Slog.d(TAG, ts.getServiceComponent().getShortClassName() + " unavailable.");
                }
                mRunningTask = null;
                mParams = null;
                mExecutionStartTimeElapsed = 0L;
                return false;
            }

            mAvailable = false;
            return true;
        }
    }

    /** Used externally to query the running task. Will return null if there is no task running. */
    TaskStatus getRunningTask() {
@@ -170,11 +171,19 @@ public class TaskServiceContext extends ITaskCallback.Stub implements ServiceCon
     * @return Whether this context is available to handle incoming work.
     */
    boolean isAvailable() {
        synchronized (mAvailableLock) {
        synchronized (mLock) {
            return mAvailable;
        }
    }

    long getExecutionStartTimeElapsed() {
        return mExecutionStartTimeElapsed;
    }

    long getTimeoutElapsed() {
        return mTimeoutElapsed;
    }

    @Override
    public void taskFinished(int taskId, boolean reschedule) {
        if (!verifyCallingUid()) {
@@ -217,6 +226,12 @@ public class TaskServiceContext extends ITaskCallback.Stub implements ServiceCon
        this.service = ITaskService.Stub.asInterface(service);
        // Remove all timeouts.
        mCallbackHandler.removeMessages(MSG_TIMEOUT);
        final PowerManager pm =
                (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                TM_WAKELOCK_PREFIX + mRunningTask.getServiceComponent().getPackageName());
        mWakeLock.setWorkSource(new WorkSource(mRunningTask.getUid()));
        mWakeLock.setReferenceCounted(false);
        mWakeLock.acquire();
        mCallbackHandler.obtainMessage(MSG_SERVICE_BOUND).sendToTarget();
    }
@@ -263,7 +278,8 @@ public class TaskServiceContext extends ITaskCallback.Stub implements ServiceCon
                    break;
                case MSG_CALLBACK:
                    if (DEBUG) {
                        Slog.d(TAG, "MSG_CALLBACK of : " + mRunningTask);
                        Slog.d(TAG, "MSG_CALLBACK of : " + mRunningTask + " v:" +
                                VERB_STRINGS[mVerb]);
                    }
                    removeMessages(MSG_TIMEOUT);

@@ -288,6 +304,7 @@ public class TaskServiceContext extends ITaskCallback.Stub implements ServiceCon
                    break;
                case MSG_SHUTDOWN_EXECUTION:
                    closeAndCleanupTaskH(true /* needsReschedule */);
                    break;
                default:
                    Log.e(TAG, "Unrecognised message: " + message);
            }
@@ -423,7 +440,7 @@ public class TaskServiceContext extends ITaskCallback.Stub implements ServiceCon
                case VERB_EXECUTING:
                    // Not an error - client ran out of time.
                    Log.i(TAG, "Client timed out while executing (no taskFinished received)." +
                            " Reporting failure and asking for reschedule. "  +
                            " sending onStop. "  +
                            mRunningTask.getServiceComponent().getShortClassName() + "' tId: "
                            + taskId);
                    sendStopMessageH();
@@ -452,7 +469,7 @@ public class TaskServiceContext extends ITaskCallback.Stub implements ServiceCon
                service.stopTask(mParams);
            } catch (RemoteException e) {
                Log.e(TAG, "Error sending onStopTask to client.", e);
                closeAndCleanupTaskH(false);
                closeAndCleanupTaskH(false /* reschedule */);
            }
        }

@@ -464,6 +481,7 @@ public class TaskServiceContext extends ITaskCallback.Stub implements ServiceCon
         */
        private void closeAndCleanupTaskH(boolean reschedule) {
            removeMessages(MSG_TIMEOUT);
            synchronized (mLock) {
                mWakeLock.release();
                mContext.unbindService(TaskServiceContext.this);
                mCompletedListener.onTaskCompleted(mRunningTask, reschedule);
@@ -474,7 +492,6 @@ public class TaskServiceContext extends ITaskCallback.Stub implements ServiceCon
                mVerb = -1;
                mCancelled.set(false);
                service = null;
            synchronized (mAvailableLock) {
                mAvailable = true;
            }
        }
@@ -496,6 +513,7 @@ public class TaskServiceContext extends ITaskCallback.Stub implements ServiceCon
            }
            Message m = mCallbackHandler.obtainMessage(MSG_TIMEOUT);
            mCallbackHandler.sendMessageDelayed(m, timeoutMillis);
            mTimeoutElapsed = SystemClock.elapsedRealtime() + timeoutMillis;
        }
    }
}
Loading