DO NOT MERGE - Run the task manager service at startup
Also moves most of it into android.app.task rather than android.content. (Cherrypick from master) Change-Id: Ic07a664bf54bc3e40aa0b892946edba4bf37262a
This commit is contained in:
@@ -78,6 +78,7 @@ LOCAL_SRC_FILES += \
|
||||
core/java/android/app/IServiceConnection.aidl \
|
||||
core/java/android/app/IStopUserCallback.aidl \
|
||||
core/java/android/app/task/ITaskCallback.aidl \
|
||||
core/java/android/app/task/ITaskManager.aidl \
|
||||
core/java/android/app/task/ITaskService.aidl \
|
||||
core/java/android/app/IThumbnailRetriever.aidl \
|
||||
core/java/android/app/ITransientNotification.aidl \
|
||||
|
||||
101
api/current.txt
101
api/current.txt
@@ -5298,6 +5298,57 @@ package android.app.maintenance {
|
||||
|
||||
package android.app.task {
|
||||
|
||||
public class Task implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public int getBackoffPolicy();
|
||||
method public android.os.Bundle getExtras();
|
||||
method public long getInitialBackoffMillis();
|
||||
method public long getIntervalMillis();
|
||||
method public long getMaxExecutionDelayMillis();
|
||||
method public long getMinLatencyMillis();
|
||||
method public int getNetworkCapabilities();
|
||||
method public android.content.ComponentName getService();
|
||||
method public int getTaskId();
|
||||
method public boolean isPeriodic();
|
||||
method public boolean isRequireCharging();
|
||||
method public boolean isRequireDeviceIdle();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator CREATOR;
|
||||
}
|
||||
|
||||
public static abstract interface Task.BackoffPolicy {
|
||||
field public static final int EXPONENTIAL = 1; // 0x1
|
||||
field public static final int LINEAR = 0; // 0x0
|
||||
}
|
||||
|
||||
public final class Task.Builder {
|
||||
ctor public Task.Builder(int, android.content.ComponentName);
|
||||
method public android.app.task.Task build();
|
||||
method public android.app.task.Task.Builder setBackoffCriteria(long, int);
|
||||
method public android.app.task.Task.Builder setExtras(android.os.Bundle);
|
||||
method public android.app.task.Task.Builder setMinimumLatency(long);
|
||||
method public android.app.task.Task.Builder setOverrideDeadline(long);
|
||||
method public android.app.task.Task.Builder setPeriodic(long);
|
||||
method public android.app.task.Task.Builder setRequiredNetworkCapabilities(int);
|
||||
method public android.app.task.Task.Builder setRequiresCharging(boolean);
|
||||
method public android.app.task.Task.Builder setRequiresDeviceIdle(boolean);
|
||||
}
|
||||
|
||||
public static abstract interface Task.NetworkType {
|
||||
field public static final int ANY = 0; // 0x0
|
||||
field public static final int UNMETERED = 1; // 0x1
|
||||
}
|
||||
|
||||
public abstract class TaskManager {
|
||||
ctor public TaskManager();
|
||||
method public abstract void cancel(int);
|
||||
method public abstract void cancelAll();
|
||||
method public abstract java.util.List<android.app.task.Task> getAllPendingTasks();
|
||||
method public abstract int schedule(android.app.task.Task);
|
||||
field public static final int RESULT_INVALID_PARAMETERS = -1; // 0xffffffff
|
||||
field public static final int RESULT_OVER_QUOTA = -2; // 0xfffffffe
|
||||
}
|
||||
|
||||
public class TaskParams implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public android.os.Bundle getExtras();
|
||||
@@ -6995,6 +7046,7 @@ package android.content {
|
||||
field public static final java.lang.String SEARCH_SERVICE = "search";
|
||||
field public static final java.lang.String SENSOR_SERVICE = "sensor";
|
||||
field public static final java.lang.String STORAGE_SERVICE = "storage";
|
||||
field public static final java.lang.String TASK_SERVICE = "task";
|
||||
field public static final java.lang.String TELEPHONY_SERVICE = "phone";
|
||||
field public static final java.lang.String TEXT_SERVICES_MANAGER_SERVICE = "textservices";
|
||||
field public static final java.lang.String TV_INPUT_SERVICE = "tv_input";
|
||||
@@ -7933,55 +7985,6 @@ package android.content {
|
||||
method public abstract void onStatusChanged(int);
|
||||
}
|
||||
|
||||
public class Task implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public int getBackoffPolicy();
|
||||
method public android.os.Bundle getExtras();
|
||||
method public long getInitialBackoffMillis();
|
||||
method public long getIntervalMillis();
|
||||
method public long getMaxExecutionDelayMillis();
|
||||
method public long getMinLatencyMillis();
|
||||
method public int getNetworkCapabilities();
|
||||
method public android.content.ComponentName getService();
|
||||
method public int getTaskId();
|
||||
method public boolean isPeriodic();
|
||||
method public boolean isRequireCharging();
|
||||
method public boolean isRequireDeviceIdle();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator CREATOR;
|
||||
}
|
||||
|
||||
public static abstract interface Task.BackoffPolicy {
|
||||
field public static final int EXPONENTIAL = 1; // 0x1
|
||||
field public static final int LINEAR = 0; // 0x0
|
||||
}
|
||||
|
||||
public final class Task.Builder {
|
||||
ctor public Task.Builder(int, android.content.ComponentName);
|
||||
method public android.content.Task build();
|
||||
method public android.content.Task.Builder setBackoffCriteria(long, int);
|
||||
method public android.content.Task.Builder setExtras(android.os.Bundle);
|
||||
method public android.content.Task.Builder setMinimumLatency(long);
|
||||
method public android.content.Task.Builder setOverrideDeadline(long);
|
||||
method public android.content.Task.Builder setPeriodic(long);
|
||||
method public android.content.Task.Builder setRequiredNetworkCapabilities(int);
|
||||
method public android.content.Task.Builder setRequiresCharging(boolean);
|
||||
method public android.content.Task.Builder setRequiresDeviceIdle(boolean);
|
||||
}
|
||||
|
||||
public static abstract interface Task.NetworkType {
|
||||
field public static final int ANY = 0; // 0x0
|
||||
field public static final int UNMETERED = 1; // 0x1
|
||||
}
|
||||
|
||||
public abstract class TaskManager {
|
||||
ctor public TaskManager();
|
||||
method public abstract void cancel(int);
|
||||
method public abstract void cancelAll();
|
||||
method public abstract java.util.List<android.content.Task> getAllPendingTasks();
|
||||
method public abstract int schedule(android.content.Task);
|
||||
}
|
||||
|
||||
public class UriMatcher {
|
||||
ctor public UriMatcher(int);
|
||||
method public void addURI(java.lang.String, java.lang.String, int);
|
||||
|
||||
@@ -133,10 +133,12 @@ import android.view.textservice.TextServicesManager;
|
||||
import android.accounts.AccountManager;
|
||||
import android.accounts.IAccountManager;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.app.task.ITaskManager;
|
||||
import android.app.trust.TrustManager;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.app.IAppOpsService;
|
||||
import com.android.internal.appwidget.IAppWidgetService.Stub;
|
||||
import com.android.internal.os.IDropBoxManagerService;
|
||||
|
||||
import java.io.File;
|
||||
@@ -693,6 +695,12 @@ class ContextImpl extends Context {
|
||||
public Object createService(ContextImpl ctx) {
|
||||
return new UsageStatsManager(ctx.getOuterContext());
|
||||
}});
|
||||
|
||||
registerService(TASK_SERVICE, new ServiceFetcher() {
|
||||
public Object createService(ContextImpl ctx) {
|
||||
IBinder b = ServiceManager.getService(TASK_SERVICE);
|
||||
return new TaskManagerImpl(ITaskManager.Stub.asInterface(b));
|
||||
}});
|
||||
}
|
||||
|
||||
static ContextImpl getImpl(Context context) {
|
||||
|
||||
62
core/java/android/app/TaskManagerImpl.java
Normal file
62
core/java/android/app/TaskManagerImpl.java
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// in android.app so ContextImpl has package access
|
||||
package android.app;
|
||||
|
||||
import android.app.task.ITaskManager;
|
||||
import android.app.task.Task;
|
||||
import android.app.task.TaskManager;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Concrete implementation of the TaskManager interface
|
||||
* @hide
|
||||
*/
|
||||
public class TaskManagerImpl extends TaskManager {
|
||||
ITaskManager mBinder;
|
||||
|
||||
/* package */ TaskManagerImpl(ITaskManager binder) {
|
||||
mBinder = binder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int schedule(Task task) {
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel(int taskId) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelAll() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Task> getAllPendingTasks() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
30
core/java/android/app/task/ITaskManager.aidl
Normal file
30
core/java/android/app/task/ITaskManager.aidl
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.app.task;
|
||||
|
||||
import android.app.task.Task;
|
||||
|
||||
/**
|
||||
* IPC interface that supports the app-facing {@link #TaskManager} api.
|
||||
* {@hide}
|
||||
*/
|
||||
interface ITaskManager {
|
||||
int schedule(in Task task);
|
||||
void cancel(int taskId);
|
||||
void cancelAll();
|
||||
List<Task> getAllPendingTasks();
|
||||
}
|
||||
20
core/java/android/app/task/Task.aidl
Normal file
20
core/java/android/app/task/Task.aidl
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.app.task;
|
||||
|
||||
parcelable Task;
|
||||
|
||||
@@ -14,15 +14,15 @@
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package android.content;
|
||||
package android.app.task;
|
||||
|
||||
import android.app.task.TaskService;
|
||||
import android.content.ComponentName;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* Container of data passed to the {@link android.content.TaskManager} fully encapsulating the
|
||||
* Container of data passed to the {@link android.app.task.TaskManager} fully encapsulating the
|
||||
* parameters required to schedule work against the calling application. These are constructed
|
||||
* using the {@link Task.Builder}.
|
||||
*/
|
||||
@@ -92,7 +92,7 @@ public class Task implements Parcelable {
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link android.content.Task.NetworkType} for a description of this value.
|
||||
* See {@link android.app.task.Task.NetworkType} for a description of this value.
|
||||
*/
|
||||
public int getNetworkCapabilities() {
|
||||
return networkCapabilities;
|
||||
@@ -139,7 +139,7 @@ public class Task implements Parcelable {
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link android.content.Task.BackoffPolicy} for an explanation of the values this field
|
||||
* See {@link android.app.task.Task.BackoffPolicy} for an explanation of the values this field
|
||||
* can take. This defaults to exponential.
|
||||
*/
|
||||
public int getBackoffPolicy() {
|
||||
@@ -255,7 +255,7 @@ public class Task implements Parcelable {
|
||||
|
||||
/**
|
||||
* Set some description of the kind of network capabilities you would like to have. This
|
||||
* will be a parameter defined in {@link android.content.Task.NetworkType}.
|
||||
* will be a parameter defined in {@link android.app.task.Task.NetworkType}.
|
||||
* Not calling this function means the network is not necessary.
|
||||
* Bear in mind that calling this function defines network as a strict requirement for your
|
||||
* task if the network requested is not available your task will never run. See
|
||||
@@ -314,7 +314,7 @@ public class Task implements Parcelable {
|
||||
* Specify that this task should be delayed by the provided amount of time.
|
||||
* Because it doesn't make sense setting this property on a periodic task, doing so will
|
||||
* throw an {@link java.lang.IllegalArgumentException} when
|
||||
* {@link android.content.Task.Builder#build()} is called.
|
||||
* {@link android.app.task.Task.Builder#build()} is called.
|
||||
* @param minLatencyMillis Milliseconds before which this task will not be considered for
|
||||
* execution.
|
||||
*/
|
||||
@@ -328,7 +328,7 @@ public class Task implements Parcelable {
|
||||
* deadline even if other requirements are not met. Because it doesn't make sense setting
|
||||
* this property on a periodic task, doing so will throw an
|
||||
* {@link java.lang.IllegalArgumentException} when
|
||||
* {@link android.content.Task.Builder#build()} is called.
|
||||
* {@link android.app.task.Task.Builder#build()} is called.
|
||||
*/
|
||||
public Builder setOverrideDeadline(long maxExecutionDelayMillis) {
|
||||
mMaxExecutionDelayMillis = maxExecutionDelayMillis;
|
||||
@@ -14,14 +14,19 @@
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package android.content;
|
||||
package android.app.task;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
/**
|
||||
* Class for scheduling various types of tasks with the scheduling framework on the device.
|
||||
*
|
||||
* Get an instance of this class through {@link Context#getSystemService(String)}.
|
||||
* <p>You do not
|
||||
* instantiate this class directly; instead, retrieve it through
|
||||
* {@link android.content.Context#getSystemService
|
||||
* Context.getSystemService(Context.TASK_SERVICE)}.
|
||||
*/
|
||||
public abstract class TaskManager {
|
||||
/*
|
||||
@@ -29,18 +34,20 @@ public abstract class TaskManager {
|
||||
* if the run-time for your task is too short, or perhaps the system can't resolve the
|
||||
* requisite {@link TaskService} in your package.
|
||||
*/
|
||||
static final int RESULT_INVALID_PARAMETERS = -1;
|
||||
public static final int RESULT_INVALID_PARAMETERS = -1;
|
||||
|
||||
/**
|
||||
* Returned from {@link #schedule(Task)} if this application has made too many requests for
|
||||
* work over too short a time.
|
||||
*/
|
||||
// TODO: Determine if this is necessary.
|
||||
static final int RESULT_OVER_QUOTA = -2;
|
||||
public static final int RESULT_OVER_QUOTA = -2;
|
||||
|
||||
/*
|
||||
* @param task The task you wish scheduled. See {@link Task#TaskBuilder} for more detail on
|
||||
* the sorts of tasks you can schedule.
|
||||
* @return If >0, this int corresponds to the taskId of the successfully scheduled task.
|
||||
/**
|
||||
* @param task The task you wish scheduled. See
|
||||
* {@link android.app.task.Task.Builder Task.Builder} for more detail on the sorts of tasks
|
||||
* you can schedule.
|
||||
* @return If >0, this int returns the taskId of the successfully scheduled task.
|
||||
* Otherwise you have to compare the return value to the error codes defined in this class.
|
||||
*/
|
||||
public abstract int schedule(Task task);
|
||||
@@ -47,7 +47,7 @@ public class TaskParams implements Parcelable {
|
||||
|
||||
/**
|
||||
* @return The extras you passed in when constructing this task with
|
||||
* {@link android.content.Task.Builder#setExtras(android.os.Bundle)}. This will
|
||||
* {@link android.app.task.Task.Builder#setExtras(android.os.Bundle)}. This will
|
||||
* never be null. If you did not set any extras this will be an empty bundle.
|
||||
*/
|
||||
public Bundle getExtras() {
|
||||
|
||||
@@ -28,7 +28,7 @@ import android.util.Log;
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
|
||||
/**
|
||||
* <p>Entry point for the callback from the {@link android.content.TaskManager}.</p>
|
||||
* <p>Entry point for the callback from the {@link android.app.task.TaskManager}.</p>
|
||||
* <p>This is the base class that handles asynchronous requests that were previously scheduled. You
|
||||
* are responsible for overriding {@link TaskService#onStartTask(TaskParams)}, which is where
|
||||
* you will implement your task logic.</p>
|
||||
@@ -215,9 +215,9 @@ public abstract class TaskService extends Service {
|
||||
*
|
||||
* <p>This will happen if the requirements specified at schedule time are no longer met. For
|
||||
* example you may have requested WiFi with
|
||||
* {@link android.content.Task.Builder#setRequiredNetworkCapabilities(int)}, yet while your
|
||||
* {@link android.app.task.Task.Builder#setRequiredNetworkCapabilities(int)}, yet while your
|
||||
* task was executing the user toggled WiFi. Another example is if you had specified
|
||||
* {@link android.content.Task.Builder#setRequiresDeviceIdle(boolean)}, and the phone left its
|
||||
* {@link android.app.task.Task.Builder#setRequiresDeviceIdle(boolean)}, and the phone left its
|
||||
* idle maintenance window. You are solely responsible for the behaviour of your application
|
||||
* upon receipt of this message; your app will likely start to misbehave if you ignore it. One
|
||||
* immediate repercussion is that the system will cease holding a wakelock for you.</p>
|
||||
@@ -237,7 +237,7 @@ public abstract class TaskService extends Service {
|
||||
* You can specify post-execution behaviour to the scheduler here with
|
||||
* <code>needsReschedule </code>. This will apply a back-off timer to your task based on
|
||||
* the default, or what was set with
|
||||
* {@link android.content.Task.Builder#setBackoffCriteria(long, int)}. The original
|
||||
* {@link android.app.task.Task.Builder#setBackoffCriteria(long, int)}. The original
|
||||
* requirements are always honoured even for a backed-off task. Note that a task running in
|
||||
* idle mode will not be backed-off. Instead what will happen is the task will be re-added
|
||||
* to the queue and re-executed within a future idle maintenance window.
|
||||
|
||||
@@ -2023,6 +2023,7 @@ public abstract class Context {
|
||||
PRINT_SERVICE,
|
||||
MEDIA_SESSION_SERVICE,
|
||||
BATTERY_SERVICE,
|
||||
TASK_SERVICE,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface ServiceName {}
|
||||
@@ -2079,6 +2080,8 @@ public abstract class Context {
|
||||
* <dd> A {@link android.app.DownloadManager} for requesting HTTP downloads
|
||||
* <dt> {@link #BATTERY_SERVICE} ("batterymanager")
|
||||
* <dd> A {@link android.os.BatteryManager} for managing battery state
|
||||
* <dt> {@link #TASK_SERVICE} ("taskmanager")
|
||||
* <dd> A {@link android.app.task.TaskManager} for managing scheduled tasks
|
||||
* </dl>
|
||||
*
|
||||
* <p>Note: System services obtained via this API may be closely associated with
|
||||
@@ -2134,6 +2137,8 @@ public abstract class Context {
|
||||
* @see android.app.DownloadManager
|
||||
* @see #BATTERY_SERVICE
|
||||
* @see android.os.BatteryManager
|
||||
* @see #TASK_SERVICE
|
||||
* @see android.app.task.TaskManager
|
||||
*/
|
||||
public abstract Object getSystemService(@ServiceName @NonNull String name);
|
||||
|
||||
@@ -2727,6 +2732,15 @@ public abstract class Context {
|
||||
*/
|
||||
public static final String USAGE_STATS_SERVICE = "usagestats";
|
||||
|
||||
/**
|
||||
* Use with {@link #getSystemService} to retrieve a {@link
|
||||
* android.app.task.TaskManager} instance for managing occasional
|
||||
* background tasks.
|
||||
* @see #getSystemService
|
||||
* @see android.app.task.TaskManager
|
||||
*/
|
||||
public static final String TASK_SERVICE = "task";
|
||||
|
||||
/**
|
||||
* Determine whether the given permission is allowed for a particular
|
||||
* process and user ID running in the system.
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -93,21 +104,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>
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
* -
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
@@ -94,6 +94,13 @@ public class TaskStore {
|
||||
return new SparseArray<TaskStatus>();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of tasks in the store
|
||||
*/
|
||||
public int size() {
|
||||
return mTasks.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The live array of TaskStatus objects.
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
Reference in New Issue
Block a user