diff options
author | Christopher Tate <ctate@google.com> | 2014-05-28 19:03:02 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-05-28 19:03:03 +0000 |
commit | 560ce61c598d9912c4adbd9c602f1a870fb478f4 (patch) | |
tree | 736d2cab5df887591bb1fcfda6d08a2487fcfcef /services | |
parent | 63ded513513ab3d8fd1707a8ea59368dd2edcb20 (diff) | |
parent | fa380e982e41b0dcbbcf2201803abf26808016b5 (diff) | |
download | frameworks_base-560ce61c598d9912c4adbd9c602f1a870fb478f4.zip frameworks_base-560ce61c598d9912c4adbd9c602f1a870fb478f4.tar.gz frameworks_base-560ce61c598d9912c4adbd9c602f1a870fb478f4.tar.bz2 |
Merge "DO NOT MERGE - Run the task manager service at startup" into lmp-preview-dev
Diffstat (limited to 'services')
6 files changed, 188 insertions, 48 deletions
diff --git a/services/core/java/com/android/server/task/TaskManagerService.java b/services/core/java/com/android/server/task/TaskManagerService.java index 6d208ff..80030b4 100644 --- a/services/core/java/com/android/server/task/TaskManagerService.java +++ b/services/core/java/com/android/server/task/TaskManagerService.java @@ -16,12 +16,22 @@ package com.android.server.task; +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; + +import android.app.task.ITaskManager; +import android.app.task.Task; import android.content.Context; -import android.content.Task; +import android.content.pm.PackageManager; +import android.os.Binder; import android.os.Handler; import android.os.Looper; import android.os.Message; -import android.util.Log; +import android.os.RemoteException; +import android.os.UserHandle; +import android.util.Slog; import android.util.SparseArray; import com.android.server.task.controllers.TaskStatus; @@ -39,13 +49,6 @@ public class TaskManagerService extends com.android.server.SystemService /** Master list of tasks. */ private final TaskStore mTasks; - /** Check the pending queue and start any tasks. */ - static final int MSG_RUN_PENDING = 0; - /** Initiate the stop task flow. */ - static final int MSG_STOP_TASK = 1; - /** */ - static final int MSG_CHECK_TASKS = 2; - /** * Track Services that have currently active or pending tasks. The index is provided by * {@link TaskStatus#getServiceToken()} @@ -54,6 +57,14 @@ public class TaskManagerService extends com.android.server.SystemService new SparseArray<TaskServiceContext>(); private final TaskHandler mHandler; + private final TaskManagerStub mTaskManagerStub; + + /** Check the pending queue and start any tasks. */ + static final int MSG_RUN_PENDING = 0; + /** Initiate the stop task flow. */ + static final int MSG_STOP_TASK = 1; + /** */ + static final int MSG_CHECK_TASKS = 2; private class TaskHandler extends Handler { @@ -94,21 +105,6 @@ public class TaskManagerService extends com.android.server.SystemService } /** - * Entry point from client to schedule the provided task. - * This will add the task to the - * @param task Task object containing execution parameters - * @param userId The id of the user this task is for. - * @param uId The package identifier of the application this task is for. - * @param canPersistTask Whether or not the client has the appropriate permissions for persisting - * of this task. - * @return Result of this operation. See <code>TaskManager#RESULT_*</code> return codes. - */ - public int schedule(Task task, int userId, int uId, boolean canPersistTask) { - TaskStatus taskStatus = mTasks.addNewTaskForUser(task, userId, uId, canPersistTask); - return 0; - } - - /** * Initializes the system service. * <p> * Subclasses must define a single argument constructor that accepts the context @@ -121,11 +117,42 @@ public class TaskManagerService extends com.android.server.SystemService super(context); mTasks = new TaskStore(context); mHandler = new TaskHandler(context.getMainLooper()); + mTaskManagerStub = new TaskManagerStub(); } @Override public void onStart() { + publishBinderService(Context.TASK_SERVICE, mTaskManagerStub); + } + + /** + * Entry point from client to schedule the provided task. + * This will add the task to the + * @param task Task object containing execution parameters + * @param userId The id of the user this task is for. + * @param uId The package identifier of the application this task is for. + * @param canPersistTask Whether or not the client has the appropriate permissions for + * persisting of this task. + * @return Result of this operation. See <code>TaskManager#RESULT_*</code> return codes. + */ + public int schedule(Task task, int userId, int uId, boolean canPersistTask) { + TaskStatus taskStatus = mTasks.addNewTaskForUser(task, userId, uId, canPersistTask); + return 0; + } + public List<Task> getPendingTasks(int uid) { + ArrayList<Task> outList = new ArrayList<Task>(3); + synchronized (mTasks) { + final SparseArray<TaskStatus> tasks = mTasks.getTasks(); + final int N = tasks.size(); + for (int i = 0; i < N; i++) { + TaskStatus ts = tasks.get(i); + if (ts.getUid() == uid) { + outList.add(ts.getTask()); + } + } + } + return outList; } // StateChangedListener implementations. @@ -162,7 +189,7 @@ public class TaskManagerService extends com.android.server.SystemService public void onTaskCompleted(int serviceToken, int taskId, boolean needsReschedule) { final TaskServiceContext serviceContext = mActiveServices.get(serviceToken); if (serviceContext == null) { - Log.e(TAG, "Task completed for invalid service context; " + serviceToken); + Slog.e(TAG, "Task completed for invalid service context; " + serviceToken); return; } @@ -203,4 +230,98 @@ public class TaskManagerService extends com.android.server.SystemService private void postCheckTasksMessage() { mHandler.obtainMessage(MSG_CHECK_TASKS).sendToTarget(); } + + /** + * Binder stub trampoline implementation + */ + final class TaskManagerStub extends ITaskManager.Stub { + /** Cache determination of whether a given app can persist tasks + * key is uid of the calling app; value is undetermined/true/false + */ + private final SparseArray<Boolean> mPersistCache = new SparseArray<Boolean>(); + + // Determine whether the caller is allowed to persist tasks, with a small cache + // because the lookup is expensive enough that we'd like to avoid repeating it. + // This must be called from within the calling app's binder identity! + private boolean canCallerPersistTasks() { + final boolean canPersist; + final int callingUid = Binder.getCallingUid(); + synchronized (mPersistCache) { + Boolean cached = mPersistCache.get(callingUid); + if (cached) { + canPersist = cached.booleanValue(); + } else { + // Persisting tasks is tantamount to running at boot, so we permit + // it when the app has declared that it uses the RECEIVE_BOOT_COMPLETED + // permission + int result = getContext().checkCallingPermission( + android.Manifest.permission.RECEIVE_BOOT_COMPLETED); + canPersist = (result == PackageManager.PERMISSION_GRANTED); + mPersistCache.put(callingUid, canPersist); + } + } + return canPersist; + } + + // ITaskManager implementation + @Override + public int schedule(Task task) throws RemoteException { + final boolean canPersist = canCallerPersistTasks(); + final int uid = Binder.getCallingUid(); + final int userId = UserHandle.getCallingUserId(); + + long ident = Binder.clearCallingIdentity(); + try { + return TaskManagerService.this.schedule(task, userId, uid, canPersist); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override + public List<Task> getAllPendingTasks() throws RemoteException { + return null; + } + + @Override + public void cancelAll() throws RemoteException { + } + + @Override + public void cancel(int taskId) throws RemoteException { + } + + /** + * "dumpsys" infrastructure + */ + @Override + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); + + long identityToken = Binder.clearCallingIdentity(); + try { + TaskManagerService.this.dumpInternal(pw); + } finally { + Binder.restoreCallingIdentity(identityToken); + } + } + }; + + void dumpInternal(PrintWriter pw) { + synchronized (mTasks) { + pw.print("Registered tasks:"); + if (mTasks.size() > 0) { + SparseArray<TaskStatus> tasks = mTasks.getTasks(); + for (int i = 0; i < tasks.size(); i++) { + TaskStatus ts = tasks.get(i); + pw.println(); + ts.dump(pw, " "); + } + } else { + pw.println(); + pw.println("No tasks scheduled."); + } + } + pw.println(); + } } diff --git a/services/core/java/com/android/server/task/TaskServiceContext.java b/services/core/java/com/android/server/task/TaskServiceContext.java index b51cbb3..165445a 100644 --- a/services/core/java/com/android/server/task/TaskServiceContext.java +++ b/services/core/java/com/android/server/task/TaskServiceContext.java @@ -45,7 +45,7 @@ import java.util.concurrent.atomic.AtomicBoolean; * is reused to start concurrent tasks on the TaskService. Information here is unique * to the service. * Functionality provided by this class: - * - Managages wakelock for the service. + * - Manages wakelock for the service. * - Sends onStartTask() and onStopTask() messages to client app, and handles callbacks. * - */ diff --git a/services/core/java/com/android/server/task/TaskStore.java b/services/core/java/com/android/server/task/TaskStore.java index 3bfc8a5..81187c8 100644 --- a/services/core/java/com/android/server/task/TaskStore.java +++ b/services/core/java/com/android/server/task/TaskStore.java @@ -16,8 +16,8 @@ package com.android.server.task; +import android.app.task.Task; import android.content.Context; -import android.content.Task; import android.util.SparseArray; import com.android.server.task.controllers.TaskStatus; @@ -95,6 +95,13 @@ public class TaskStore { } /** + * @return the number of tasks in the store + */ + public int size() { + return mTasks.size(); + } + + /** * @return The live array of TaskStatus objects. */ public SparseArray<TaskStatus> getTasks() { diff --git a/services/core/java/com/android/server/task/controllers/ConnectivityController.java b/services/core/java/com/android/server/task/controllers/ConnectivityController.java index 6a4e1f3..a0038c5 100644 --- a/services/core/java/com/android/server/task/controllers/ConnectivityController.java +++ b/services/core/java/com/android/server/task/controllers/ConnectivityController.java @@ -70,13 +70,10 @@ public class ConnectivityController extends StateController { } /** - * @param userId Id of the user for whom we are updating the connectivity state. + * */ - private void updateTrackedTasks(int userId) { + private void updateTrackedTasks() { for (TaskStatus ts : mTrackedTasks) { - if (ts.userId != userId) { - continue; - } boolean prevIsConnected = ts.connectivityConstraintSatisfied.getAndSet(mConnectivity); boolean prevIsMetered = ts.meteredConstraintSatisfied.getAndSet(mMetered); if (prevIsConnected != mConnectivity || prevIsMetered != mMetered) { @@ -107,14 +104,13 @@ public class ConnectivityController extends StateController { final NetworkInfo activeNetwork = connManager.getActiveNetworkInfo(); // This broadcast gets sent a lot, only update if the active network has changed. if (activeNetwork.getType() == networkType) { - final int userid = context.getUserId(); mMetered = false; mConnectivity = !intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false); if (mConnectivity) { // No point making the call if we know there's no conn. mMetered = connManager.isActiveNetworkMetered(); } - updateTrackedTasks(userid); + updateTrackedTasks(); } } else { Log.w(TAG, "Unrecognised action in intent: " + action); diff --git a/services/core/java/com/android/server/task/controllers/TaskStatus.java b/services/core/java/com/android/server/task/controllers/TaskStatus.java index d96fedc..d270016 100644 --- a/services/core/java/com/android/server/task/controllers/TaskStatus.java +++ b/services/core/java/com/android/server/task/controllers/TaskStatus.java @@ -16,17 +16,19 @@ package com.android.server.task.controllers; +import android.app.task.Task; import android.content.ComponentName; -import android.content.Task; import android.content.pm.PackageParser; import android.os.Bundle; import android.os.SystemClock; +import android.os.UserHandle; +import java.io.PrintWriter; import java.util.concurrent.atomic.AtomicBoolean; /** * Uniquely identifies a task internally. - * Created from the public {@link android.content.Task} object when it lands on the scheduler. + * Created from the public {@link android.app.task.Task} object when it lands on the scheduler. * Contains current state of the requirements of the task, as well as a function to evaluate * whether it's ready to run. * This object is shared among the various controllers - hence why the different fields are atomic. @@ -36,10 +38,9 @@ import java.util.concurrent.atomic.AtomicBoolean; * @hide */ public class TaskStatus { + final Task task; final int taskId; - final int userId; final int uId; - final ComponentName component; final Bundle extras; final AtomicBoolean chargingConstraintSatisfied = new AtomicBoolean(); @@ -57,9 +58,9 @@ public class TaskStatus { private long earliestRunTimeElapsedMillis; private long latestRunTimeElapsedMillis; - /** Provide a unique handle to the service that this task will be run on. */ + /** Provide a handle to the service that this task will be run on. */ public int getServiceToken() { - return component.hashCode() + userId; + return uId; } /** Generate a TaskStatus object for a given task and uid. */ @@ -70,9 +71,8 @@ public class TaskStatus { /** Set up the state of a newly scheduled task. */ TaskStatus(Task task, int userId, int uId) { + this.task = task; this.taskId = task.getTaskId(); - this.userId = userId; - this.component = task.getService(); this.extras = task.getExtras(); this.uId = uId; @@ -100,16 +100,20 @@ public class TaskStatus { hasConnectivityConstraint = task.getNetworkCapabilities() == Task.NetworkType.ANY; } + public Task getTask() { + return task; + } + public int getTaskId() { return taskId; } public ComponentName getServiceComponent() { - return component; + return task.getService(); } public int getUserId() { - return userId; + return UserHandle.getUserId(uId); } public int getUid() { @@ -161,9 +165,9 @@ public class TaskStatus { @Override public int hashCode() { - int result = component.hashCode(); + int result = getServiceComponent().hashCode(); result = 31 * result + taskId; - result = 31 * result + userId; + result = 31 * result + uId; return result; } @@ -174,7 +178,14 @@ public class TaskStatus { TaskStatus that = (TaskStatus) o; return ((taskId == that.taskId) - && (userId == that.userId) - && (component.equals(that.component))); + && (uId == that.uId) + && (getServiceComponent().equals(that.getServiceComponent()))); + } + + // Dumpsys infrastructure + public void dump(PrintWriter pw, String prefix) { + pw.print(prefix); pw.print("Task "); pw.println(taskId); + pw.print(prefix); pw.print("uid="); pw.println(uId); + pw.print(prefix); pw.print("component="); pw.println(task.getService()); } } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index de46b16..bc34e0e 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -83,6 +83,7 @@ import com.android.server.power.ShutdownThread; import com.android.server.search.SearchManagerService; import com.android.server.statusbar.StatusBarManagerService; import com.android.server.storage.DeviceStorageMonitorService; +import com.android.server.task.TaskManagerService; import com.android.server.trust.TrustManagerService; import com.android.server.tv.TvInputManagerService; import com.android.server.twilight.TwilightService; @@ -132,6 +133,8 @@ public final class SystemServer { "com.android.server.hdmi.HdmiCecService"; private static final String ETHERNET_SERVICE_CLASS = "com.android.server.ethernet.EthernetService"; + private static final String TASK_SERVICE_CLASS = + "com.android.server.task.TaskManagerService"; private final int mFactoryTestMode; private Timer mProfilerSnapshotTimer; @@ -831,6 +834,8 @@ public final class SystemServer { mSystemServiceManager.startService(UiModeManagerService.class); + mSystemServiceManager.startService(TaskManagerService.class); + if (!disableNonCoreServices) { try { if (pm.hasSystemFeature(PackageManager.FEATURE_BACKUP)) { |