am 4dbb0aab: am 581feb87: am 90ac517c: Create API for launching from recents
* commit '4dbb0aabb98986ed8105f85d6d46c6d4b2f78408': Create API for launching from recents
This commit is contained in:
@@ -284,6 +284,17 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
|
||||
return true;
|
||||
}
|
||||
|
||||
case START_ACTIVITY_FROM_RECENTS_TRANSACTION:
|
||||
{
|
||||
data.enforceInterface(IActivityManager.descriptor);
|
||||
int taskId = data.readInt();
|
||||
Bundle options = data.readInt() == 0 ? null : Bundle.CREATOR.createFromParcel(data);
|
||||
int result = startActivityFromRecents(taskId, options);
|
||||
reply.writeNoException();
|
||||
reply.writeInt(result);
|
||||
return true;
|
||||
}
|
||||
|
||||
case FINISH_ACTIVITY_TRANSACTION: {
|
||||
data.enforceInterface(IActivityManager.descriptor);
|
||||
IBinder token = data.readStrongBinder();
|
||||
@@ -2482,6 +2493,24 @@ class ActivityManagerProxy implements IActivityManager
|
||||
data.recycle();
|
||||
return result != 0;
|
||||
}
|
||||
public int startActivityFromRecents(int taskId, Bundle options) throws RemoteException {
|
||||
Parcel data = Parcel.obtain();
|
||||
Parcel reply = Parcel.obtain();
|
||||
data.writeInterfaceToken(IActivityManager.descriptor);
|
||||
data.writeInt(taskId);
|
||||
if (options == null) {
|
||||
data.writeInt(0);
|
||||
} else {
|
||||
data.writeInt(1);
|
||||
options.writeToParcel(data, 0);
|
||||
}
|
||||
mRemote.transact(START_ACTIVITY_FROM_RECENTS_TRANSACTION, data, reply, 0);
|
||||
reply.readException();
|
||||
int result = reply.readInt();
|
||||
reply.recycle();
|
||||
data.recycle();
|
||||
return result;
|
||||
}
|
||||
public boolean finishActivity(IBinder token, int resultCode, Intent resultData, boolean finishTask)
|
||||
throws RemoteException {
|
||||
Parcel data = Parcel.obtain();
|
||||
|
||||
@@ -86,6 +86,7 @@ public interface IActivityManager extends IInterface {
|
||||
ParcelFileDescriptor profileFd, Bundle options, int userId) throws RemoteException;
|
||||
public boolean startNextMatchingActivity(IBinder callingActivity,
|
||||
Intent intent, Bundle options) throws RemoteException;
|
||||
public int startActivityFromRecents(int taskId, Bundle options) throws RemoteException;
|
||||
public boolean finishActivity(IBinder token, int code, Intent data, boolean finishTask)
|
||||
throws RemoteException;
|
||||
public void finishSubActivity(IBinder token, String resultWho, int requestCode) throws RemoteException;
|
||||
@@ -756,4 +757,5 @@ public interface IActivityManager extends IInterface {
|
||||
int IS_BG_MEDIA_PLAYING_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+226;
|
||||
int MEDIA_RESOURCES_RELEASED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+227;
|
||||
int NOTIFY_LAUNCH_TASK_BEHIND_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+228;
|
||||
int START_ACTIVITY_FROM_RECENTS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 229;
|
||||
}
|
||||
|
||||
@@ -1364,6 +1364,14 @@
|
||||
android:label="@string/permlab_getTasks"
|
||||
android:description="@string/permdesc_getTasks" />
|
||||
|
||||
<!-- Allows an application to start a task from a ActivityManager#RecentTaskInfo.
|
||||
@hide -->
|
||||
<permission android:name="android.permission.START_TASKS_FROM_RECENTS"
|
||||
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
|
||||
android:protectionLevel="signature|system"
|
||||
android:label="@string/permlab_startTasksFromRecents"
|
||||
android:description="@string/permdesc_startTasksFromRecents" />
|
||||
|
||||
<!-- @SystemApi @hide Allows an application to call APIs that allow it to do interactions
|
||||
across the users on the device, using singleton services and
|
||||
user-targeted broadcasts. This permission is not available to
|
||||
|
||||
@@ -774,6 +774,12 @@
|
||||
about currently and recently running tasks. This may allow the app to
|
||||
discover information about which applications are used on the device.</string>
|
||||
|
||||
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
||||
<string name="permlab_startTasksFromRecents">start a task from recents</string>
|
||||
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
||||
<string name="permdesc_startTasksFromRecents">Allows the app to use an ActivityManager.RecentTaskInfo
|
||||
object to launch a defunct task that was returned from ActivityManager.getRecentTaskList().</string>
|
||||
|
||||
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=NONE] -->
|
||||
<string name="permlab_interactAcrossUsers">interact across users</string>
|
||||
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=NONE] -->
|
||||
|
||||
@@ -74,6 +74,7 @@
|
||||
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
|
||||
<uses-permission android:name="android.permission.GET_TOP_ACTIVITY_INFO" />
|
||||
<uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" />
|
||||
<uses-permission android:name="android.permission.START_TASKS_FROM_RECENTS" />
|
||||
|
||||
<!-- WindowManager -->
|
||||
<uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" />
|
||||
|
||||
@@ -467,4 +467,13 @@ public class SystemServicesProxy {
|
||||
public Bitmap takeAppScreenshot() {
|
||||
return takeScreenshot();
|
||||
}
|
||||
|
||||
public void startActivityFromRecents(int taskId, ActivityOptions options) {
|
||||
if (mIam != null) {
|
||||
try {
|
||||
mIam.startActivityFromRecents(taskId, options == null ? null : options.toBundle());
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.net.Uri;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -452,8 +451,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
|
||||
public void run() {
|
||||
if (task.isActive) {
|
||||
// Bring an active task to the foreground
|
||||
RecentsTaskLoader.getInstance().getSystemServicesProxy()
|
||||
.moveTaskToFront(task.key.id, launchOpts);
|
||||
ssp.moveTaskToFront(task.key.id, launchOpts);
|
||||
} else {
|
||||
// Launch the activity anew with the desired animation
|
||||
Intent i = new Intent(task.key.baseIntent);
|
||||
@@ -463,15 +461,9 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
}
|
||||
try {
|
||||
UserHandle taskUser = new UserHandle(task.userId);
|
||||
if (launchOpts != null) {
|
||||
getContext().startActivityAsUser(i, launchOpts.toBundle(), taskUser);
|
||||
|
||||
} else {
|
||||
getContext().startActivityAsUser(i, taskUser);
|
||||
if (lockToTask) {
|
||||
ssp.lockCurrentTask();
|
||||
}
|
||||
ssp.startActivityFromRecents(task.key.id, launchOpts);
|
||||
if (launchOpts == null && lockToTask) {
|
||||
ssp.lockCurrentTask();
|
||||
}
|
||||
} catch (ActivityNotFoundException anfe) {
|
||||
Console.logError(getContext(), "Could not start Activity");
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.server.am;
|
||||
|
||||
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
|
||||
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
|
||||
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
import static com.android.internal.util.XmlUtils.readBooleanAttribute;
|
||||
import static com.android.internal.util.XmlUtils.readIntAttribute;
|
||||
@@ -3545,6 +3546,23 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int startActivityFromRecents(int taskId, Bundle options) {
|
||||
if (checkCallingPermission(START_TASKS_FROM_RECENTS) != PackageManager.PERMISSION_GRANTED) {
|
||||
String msg = "Permission Denial: startActivityFromRecents called without " +
|
||||
START_TASKS_FROM_RECENTS;
|
||||
Slog.w(TAG, msg);
|
||||
throw new SecurityException(msg);
|
||||
}
|
||||
final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
|
||||
if (task == null) {
|
||||
throw new ActivityNotFoundException("Task " + taskId + " not found.");
|
||||
}
|
||||
return startActivityInPackage(task.mCallingUid, task.mCallingPackage,
|
||||
task.intent, null, null, null, 0, 0, options, task.userId,
|
||||
null);
|
||||
}
|
||||
|
||||
final int startActivityInPackage(int uid, String callingPackage,
|
||||
Intent intent, String resolvedType, IBinder resultTo,
|
||||
String resultWho, int requestCode, int startFlags, Bundle options, int userId,
|
||||
|
||||
@@ -68,6 +68,8 @@ final class TaskRecord {
|
||||
private static final String ATTR_TASK_AFFILIATION = "task_affiliation";
|
||||
private static final String ATTR_PREV_AFFILIATION = "prev_affiliation";
|
||||
private static final String ATTR_NEXT_AFFILIATION = "next_affiliation";
|
||||
private static final String ATTR_CALLING_UID = "calling_uid";
|
||||
private static final String ATTR_CALLING_PACKAGE = "calling_package";
|
||||
private static final String LAST_ACTIVITY_ICON_SUFFIX = "_last_activity_icon_";
|
||||
|
||||
private static final String TASK_THUMBNAIL_SUFFIX = "_task_thumbnail";
|
||||
@@ -144,6 +146,10 @@ final class TaskRecord {
|
||||
TaskRecord mNextAffiliate; // next task in affiliated chain.
|
||||
int mNextAffiliateTaskId = -1; // next id for persistence.
|
||||
|
||||
// For relaunching the task from recents as though it was launched by the original launcher.
|
||||
int mCallingUid;
|
||||
String mCallingPackage;
|
||||
|
||||
final ActivityManagerService mService;
|
||||
|
||||
TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
|
||||
@@ -167,7 +173,7 @@ final class TaskRecord {
|
||||
String _lastDescription, ArrayList<ActivityRecord> activities, long _firstActiveTime,
|
||||
long _lastActiveTime, long lastTimeMoved, boolean neverRelinquishIdentity,
|
||||
ActivityManager.TaskDescription _lastTaskDescription, int taskAffiliation,
|
||||
int prevTaskId, int nextTaskId) {
|
||||
int prevTaskId, int nextTaskId, int callingUid, String callingPackage) {
|
||||
mService = service;
|
||||
mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX +
|
||||
TaskPersister.IMAGE_EXTENSION;
|
||||
@@ -196,6 +202,8 @@ final class TaskRecord {
|
||||
mAffiliatedTaskId = taskAffiliation;
|
||||
mPrevAffiliateTaskId = prevTaskId;
|
||||
mNextAffiliateTaskId = nextTaskId;
|
||||
mCallingUid = callingUid;
|
||||
mCallingPackage = callingPackage;
|
||||
}
|
||||
|
||||
void touchActiveTime() {
|
||||
@@ -458,6 +466,8 @@ final class TaskRecord {
|
||||
if (mActivities.isEmpty()) {
|
||||
taskType = r.mActivityType;
|
||||
isPersistable = r.isPersistable();
|
||||
mCallingUid = r.launchedFromUid;
|
||||
mCallingPackage = r.launchedFromPackage;
|
||||
// Clamp to [1, 100].
|
||||
maxRecents = Math.min(Math.max(r.info.maxRecents, 1), 100);
|
||||
} else {
|
||||
@@ -765,6 +775,8 @@ final class TaskRecord {
|
||||
out.attribute(null, ATTR_TASK_AFFILIATION, String.valueOf(mAffiliatedTaskId));
|
||||
out.attribute(null, ATTR_PREV_AFFILIATION, String.valueOf(mPrevAffiliateTaskId));
|
||||
out.attribute(null, ATTR_NEXT_AFFILIATION, String.valueOf(mNextAffiliateTaskId));
|
||||
out.attribute(null, ATTR_CALLING_UID, String.valueOf(mCallingUid));
|
||||
out.attribute(null, ATTR_CALLING_PACKAGE, mCallingPackage == null ? "" : mCallingPackage);
|
||||
|
||||
if (affinityIntent != null) {
|
||||
out.startTag(null, TAG_AFFINITYINTENT);
|
||||
@@ -816,6 +828,8 @@ final class TaskRecord {
|
||||
int taskAffiliation = -1;
|
||||
int prevTaskId = -1;
|
||||
int nextTaskId = -1;
|
||||
int callingUid = -1;
|
||||
String callingPackage = "";
|
||||
|
||||
for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
|
||||
final String attrName = in.getAttributeName(attrNdx);
|
||||
@@ -858,6 +872,10 @@ final class TaskRecord {
|
||||
prevTaskId = Integer.valueOf(attrValue);
|
||||
} else if (ATTR_NEXT_AFFILIATION.equals(attrName)) {
|
||||
nextTaskId = Integer.valueOf(attrValue);
|
||||
} else if (ATTR_CALLING_UID.equals(attrName)) {
|
||||
callingUid = Integer.valueOf(attrValue);
|
||||
} else if (ATTR_CALLING_PACKAGE.equals(attrName)) {
|
||||
callingPackage = attrValue;
|
||||
} else {
|
||||
Slog.w(TAG, "TaskRecord: Unknown attribute=" + attrName);
|
||||
}
|
||||
@@ -898,7 +916,8 @@ final class TaskRecord {
|
||||
affinityIntent, affinity, realActivity, origActivity, rootHasReset,
|
||||
autoRemoveRecents, askedCompatMode, taskType, userId, lastDescription, activities,
|
||||
firstActiveTime, lastActiveTime, lastTimeOnTop, neverRelinquishIdentity,
|
||||
taskDescription, taskAffiliation, prevTaskId, nextTaskId);
|
||||
taskDescription, taskAffiliation, prevTaskId, nextTaskId, callingUid,
|
||||
callingPackage);
|
||||
|
||||
for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
|
||||
activities.get(activityNdx).task = task;
|
||||
|
||||
Reference in New Issue
Block a user