Merge "Change ActivityView startActivity state sequence" into lmp-mr1-modular-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
358188f589
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package android.app;
|
package android.app;
|
||||||
|
|
||||||
|
import static android.app.ActivityManager.START_CANCELED;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.ContextWrapper;
|
import android.content.ContextWrapper;
|
||||||
import android.content.IIntentSender;
|
import android.content.IIntentSender;
|
||||||
@@ -23,6 +25,7 @@ import android.content.Intent;
|
|||||||
import android.content.IntentSender;
|
import android.content.IntentSender;
|
||||||
import android.graphics.SurfaceTexture;
|
import android.graphics.SurfaceTexture;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.os.OperationCanceledException;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
@@ -55,10 +58,6 @@ public class ActivityView extends ViewGroup {
|
|||||||
private int mLastVisibility;
|
private int mLastVisibility;
|
||||||
private ActivityViewCallback mActivityViewCallback;
|
private ActivityViewCallback mActivityViewCallback;
|
||||||
|
|
||||||
// Only one IIntentSender or Intent may be queued at a time. Most recent one wins.
|
|
||||||
IIntentSender mQueuedPendingIntent;
|
|
||||||
Intent mQueuedIntent;
|
|
||||||
|
|
||||||
public ActivityView(Context context) {
|
public ActivityView(Context context) {
|
||||||
this(context, null);
|
this(context, null);
|
||||||
}
|
}
|
||||||
@@ -167,14 +166,13 @@ public class ActivityView extends ViewGroup {
|
|||||||
if (mActivityContainer == null) {
|
if (mActivityContainer == null) {
|
||||||
throw new IllegalStateException("Attempt to call startActivity after release");
|
throw new IllegalStateException("Attempt to call startActivity after release");
|
||||||
}
|
}
|
||||||
|
if (mSurface == null) {
|
||||||
|
throw new IllegalStateException("Surface not yet created.");
|
||||||
|
}
|
||||||
if (DEBUG) Log.v(TAG, "startActivity(): intent=" + intent + " " +
|
if (DEBUG) Log.v(TAG, "startActivity(): intent=" + intent + " " +
|
||||||
(isAttachedToDisplay() ? "" : "not") + " attached");
|
(isAttachedToDisplay() ? "" : "not") + " attached");
|
||||||
if (mSurface != null) {
|
if (mActivityContainer.startActivity(intent) == START_CANCELED) {
|
||||||
mActivityContainer.startActivity(intent);
|
throw new OperationCanceledException();
|
||||||
} else {
|
|
||||||
mActivityContainer.checkEmbeddedAllowed(intent);
|
|
||||||
mQueuedIntent = intent;
|
|
||||||
mQueuedPendingIntent = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,15 +180,14 @@ public class ActivityView extends ViewGroup {
|
|||||||
if (mActivityContainer == null) {
|
if (mActivityContainer == null) {
|
||||||
throw new IllegalStateException("Attempt to call startActivity after release");
|
throw new IllegalStateException("Attempt to call startActivity after release");
|
||||||
}
|
}
|
||||||
|
if (mSurface == null) {
|
||||||
|
throw new IllegalStateException("Surface not yet created.");
|
||||||
|
}
|
||||||
if (DEBUG) Log.v(TAG, "startActivityIntentSender(): intentSender=" + intentSender + " " +
|
if (DEBUG) Log.v(TAG, "startActivityIntentSender(): intentSender=" + intentSender + " " +
|
||||||
(isAttachedToDisplay() ? "" : "not") + " attached");
|
(isAttachedToDisplay() ? "" : "not") + " attached");
|
||||||
final IIntentSender iIntentSender = intentSender.getTarget();
|
final IIntentSender iIntentSender = intentSender.getTarget();
|
||||||
if (mSurface != null) {
|
if (mActivityContainer.startActivityIntentSender(iIntentSender) == START_CANCELED) {
|
||||||
mActivityContainer.startActivityIntentSender(iIntentSender);
|
throw new OperationCanceledException();
|
||||||
} else {
|
|
||||||
mActivityContainer.checkEmbeddedAllowedIntentSender(iIntentSender);
|
|
||||||
mQueuedPendingIntent = iIntentSender;
|
|
||||||
mQueuedIntent = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,15 +195,14 @@ public class ActivityView extends ViewGroup {
|
|||||||
if (mActivityContainer == null) {
|
if (mActivityContainer == null) {
|
||||||
throw new IllegalStateException("Attempt to call startActivity after release");
|
throw new IllegalStateException("Attempt to call startActivity after release");
|
||||||
}
|
}
|
||||||
|
if (mSurface == null) {
|
||||||
|
throw new IllegalStateException("Surface not yet created.");
|
||||||
|
}
|
||||||
if (DEBUG) Log.v(TAG, "startActivityPendingIntent(): PendingIntent=" + pendingIntent + " "
|
if (DEBUG) Log.v(TAG, "startActivityPendingIntent(): PendingIntent=" + pendingIntent + " "
|
||||||
+ (isAttachedToDisplay() ? "" : "not") + " attached");
|
+ (isAttachedToDisplay() ? "" : "not") + " attached");
|
||||||
final IIntentSender iIntentSender = pendingIntent.getTarget();
|
final IIntentSender iIntentSender = pendingIntent.getTarget();
|
||||||
if (mSurface != null) {
|
if (mActivityContainer.startActivityIntentSender(iIntentSender) == START_CANCELED) {
|
||||||
mActivityContainer.startActivityIntentSender(iIntentSender);
|
throw new OperationCanceledException();
|
||||||
} else {
|
|
||||||
mActivityContainer.checkEmbeddedAllowedIntentSender(iIntentSender);
|
|
||||||
mQueuedPendingIntent = iIntentSender;
|
|
||||||
mQueuedIntent = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,26 +239,24 @@ public class ActivityView extends ViewGroup {
|
|||||||
mSurface = null;
|
mSurface = null;
|
||||||
throw new RuntimeException("ActivityView: Unable to create ActivityContainer. " + e);
|
throw new RuntimeException("ActivityView: Unable to create ActivityContainer. " + e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DEBUG) Log.v(TAG, "attachToSurfaceWhenReady: " + (mQueuedIntent != null ||
|
|
||||||
mQueuedPendingIntent != null ? "" : "no") + " queued intent");
|
|
||||||
if (mQueuedIntent != null) {
|
|
||||||
mActivityContainer.startActivity(mQueuedIntent);
|
|
||||||
mQueuedIntent = null;
|
|
||||||
} else if (mQueuedPendingIntent != null) {
|
|
||||||
mActivityContainer.startActivityIntentSender(mQueuedPendingIntent);
|
|
||||||
mQueuedPendingIntent = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the callback to use to report certain state changes.
|
* Set the callback to use to report certain state changes.
|
||||||
* @param callback The callback to report events to.
|
*
|
||||||
|
* Note: If the surface has been created prior to this call being made, then
|
||||||
|
* ActivityViewCallback.onSurfaceAvailable will be called from within setCallback.
|
||||||
|
*
|
||||||
|
* @param callback The callback to report events to.
|
||||||
*
|
*
|
||||||
* @see ActivityViewCallback
|
* @see ActivityViewCallback
|
||||||
*/
|
*/
|
||||||
public void setCallback(ActivityViewCallback callback) {
|
public void setCallback(ActivityViewCallback callback) {
|
||||||
mActivityViewCallback = callback;
|
mActivityViewCallback = callback;
|
||||||
|
|
||||||
|
if (mSurface != null) {
|
||||||
|
mActivityViewCallback.onSurfaceAvailable(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static abstract class ActivityViewCallback {
|
public static abstract class ActivityViewCallback {
|
||||||
@@ -272,6 +266,16 @@ public class ActivityView extends ViewGroup {
|
|||||||
* have at most one callback registered.
|
* have at most one callback registered.
|
||||||
*/
|
*/
|
||||||
public abstract void onAllActivitiesComplete(ActivityView view);
|
public abstract void onAllActivitiesComplete(ActivityView view);
|
||||||
|
/**
|
||||||
|
* Called when the surface is ready to be drawn to. Calling startActivity prior to this
|
||||||
|
* callback will result in an IllegalStateException.
|
||||||
|
*/
|
||||||
|
public abstract void onSurfaceAvailable(ActivityView view);
|
||||||
|
/**
|
||||||
|
* Called when the surface has been removed. Calling startActivity after this callback
|
||||||
|
* will result in an IllegalStateException.
|
||||||
|
*/
|
||||||
|
public abstract void onSurfaceDestroyed(ActivityView view);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ActivityViewSurfaceTextureListener implements SurfaceTextureListener {
|
private class ActivityViewSurfaceTextureListener implements SurfaceTextureListener {
|
||||||
@@ -286,6 +290,9 @@ public class ActivityView extends ViewGroup {
|
|||||||
mWidth = width;
|
mWidth = width;
|
||||||
mHeight = height;
|
mHeight = height;
|
||||||
attachToSurfaceWhenReady();
|
attachToSurfaceWhenReady();
|
||||||
|
if (mActivityViewCallback != null) {
|
||||||
|
mActivityViewCallback.onSurfaceAvailable(ActivityView.this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -311,6 +318,9 @@ public class ActivityView extends ViewGroup {
|
|||||||
throw new RuntimeException(
|
throw new RuntimeException(
|
||||||
"ActivityView: Unable to set surface of ActivityContainer. " + e);
|
"ActivityView: Unable to set surface of ActivityContainer. " + e);
|
||||||
}
|
}
|
||||||
|
if (mActivityViewCallback != null) {
|
||||||
|
mActivityViewCallback.onSurfaceDestroyed(ActivityView.this);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -325,7 +335,7 @@ public class ActivityView extends ViewGroup {
|
|||||||
private final WeakReference<ActivityView> mActivityViewWeakReference;
|
private final WeakReference<ActivityView> mActivityViewWeakReference;
|
||||||
|
|
||||||
ActivityContainerCallback(ActivityView activityView) {
|
ActivityContainerCallback(ActivityView activityView) {
|
||||||
mActivityViewWeakReference = new WeakReference<ActivityView>(activityView);
|
mActivityViewWeakReference = new WeakReference<>(activityView);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -391,24 +401,6 @@ public class ActivityView extends ViewGroup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkEmbeddedAllowed(Intent intent) {
|
|
||||||
try {
|
|
||||||
mIActivityContainer.checkEmbeddedAllowed(intent);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw new RuntimeException(
|
|
||||||
"ActivityView: Unable to startActivity from Intent. " + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void checkEmbeddedAllowedIntentSender(IIntentSender intentSender) {
|
|
||||||
try {
|
|
||||||
mIActivityContainer.checkEmbeddedAllowedIntentSender(intentSender);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw new RuntimeException(
|
|
||||||
"ActivityView: Unable to startActivity from IntentSender. " + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int getDisplayId() {
|
int getDisplayId() {
|
||||||
try {
|
try {
|
||||||
return mIActivityContainer.getDisplayId();
|
return mIActivityContainer.getDisplayId();
|
||||||
|
|||||||
@@ -29,8 +29,6 @@ interface IActivityContainer {
|
|||||||
void setSurface(in Surface surface, int width, int height, int density);
|
void setSurface(in Surface surface, int width, int height, int density);
|
||||||
int startActivity(in Intent intent);
|
int startActivity(in Intent intent);
|
||||||
int startActivityIntentSender(in IIntentSender intentSender);
|
int startActivityIntentSender(in IIntentSender intentSender);
|
||||||
void checkEmbeddedAllowed(in Intent intent);
|
|
||||||
void checkEmbeddedAllowedIntentSender(in IIntentSender intentSender);
|
|
||||||
int getDisplayId();
|
int getDisplayId();
|
||||||
boolean injectEvent(in InputEvent event);
|
boolean injectEvent(in InputEvent event);
|
||||||
void release();
|
void release();
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ import android.hardware.display.DisplayManagerGlobal;
|
|||||||
import android.hardware.display.VirtualDisplay;
|
import android.hardware.display.VirtualDisplay;
|
||||||
import android.hardware.input.InputManager;
|
import android.hardware.input.InputManager;
|
||||||
import android.hardware.input.InputManagerInternal;
|
import android.hardware.input.InputManagerInternal;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Debug;
|
import android.os.Debug;
|
||||||
@@ -855,6 +856,11 @@ public final class ActivityStackSupervisor implements DisplayListener {
|
|||||||
|
|
||||||
ActivityContainer container = (ActivityContainer)iContainer;
|
ActivityContainer container = (ActivityContainer)iContainer;
|
||||||
synchronized (mService) {
|
synchronized (mService) {
|
||||||
|
if (container != null && container.mParentActivity != null &&
|
||||||
|
container.mParentActivity.state != ActivityState.RESUMED) {
|
||||||
|
// Cannot start a child activity if the parent is not resumed.
|
||||||
|
return ActivityManager.START_CANCELED;
|
||||||
|
}
|
||||||
final int realCallingPid = Binder.getCallingPid();
|
final int realCallingPid = Binder.getCallingPid();
|
||||||
final int realCallingUid = Binder.getCallingUid();
|
final int realCallingUid = Binder.getCallingUid();
|
||||||
int callingPid;
|
int callingPid;
|
||||||
@@ -3788,18 +3794,21 @@ public final class ActivityStackSupervisor implements DisplayListener {
|
|||||||
@Override
|
@Override
|
||||||
public final int startActivity(Intent intent) {
|
public final int startActivity(Intent intent) {
|
||||||
mService.enforceNotIsolatedCaller("ActivityContainer.startActivity");
|
mService.enforceNotIsolatedCaller("ActivityContainer.startActivity");
|
||||||
int userId = mService.handleIncomingUser(Binder.getCallingPid(),
|
final int userId = mService.handleIncomingUser(Binder.getCallingPid(),
|
||||||
Binder.getCallingUid(), mCurrentUser, false,
|
Binder.getCallingUid(), mCurrentUser, false,
|
||||||
ActivityManagerService.ALLOW_FULL_ONLY, "ActivityContainer", null);
|
ActivityManagerService.ALLOW_FULL_ONLY, "ActivityContainer", null);
|
||||||
|
|
||||||
// TODO: Switch to user app stacks here.
|
// TODO: Switch to user app stacks here.
|
||||||
intent.addFlags(FORCE_NEW_TASK_FLAGS);
|
|
||||||
String mimeType = intent.getType();
|
String mimeType = intent.getType();
|
||||||
if (mimeType == null && intent.getData() != null
|
final Uri data = intent.getData();
|
||||||
&& "content".equals(intent.getData().getScheme())) {
|
if (mimeType == null && data != null && "content".equals(data.getScheme())) {
|
||||||
mimeType = mService.getProviderMimeType(intent.getData(), userId);
|
mimeType = mService.getProviderMimeType(data, userId);
|
||||||
}
|
}
|
||||||
return startActivityMayWait(null, -1, null, intent, mimeType, null, null, null, null, 0,
|
checkEmbeddedAllowedInner(userId, intent, mimeType);
|
||||||
0, null, null, null, null, userId, this, null);
|
|
||||||
|
intent.addFlags(FORCE_NEW_TASK_FLAGS);
|
||||||
|
return startActivityMayWait(null, -1, null, intent, mimeType, null, null, null, null,
|
||||||
|
0, 0, null, null, null, null, userId, this, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -3810,21 +3819,19 @@ public final class ActivityStackSupervisor implements DisplayListener {
|
|||||||
throw new IllegalArgumentException("Bad PendingIntent object");
|
throw new IllegalArgumentException("Bad PendingIntent object");
|
||||||
}
|
}
|
||||||
|
|
||||||
return ((PendingIntentRecord)intentSender).sendInner(0, null, null, null, null, null,
|
final int userId = mService.handleIncomingUser(Binder.getCallingPid(),
|
||||||
null, 0, FORCE_NEW_TASK_FLAGS, FORCE_NEW_TASK_FLAGS, null, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkEmbeddedAllowedInner(Intent intent, String resolvedType) {
|
|
||||||
int userId = mService.handleIncomingUser(Binder.getCallingPid(),
|
|
||||||
Binder.getCallingUid(), mCurrentUser, false,
|
Binder.getCallingUid(), mCurrentUser, false,
|
||||||
ActivityManagerService.ALLOW_FULL_ONLY, "ActivityContainer", null);
|
ActivityManagerService.ALLOW_FULL_ONLY, "ActivityContainer", null);
|
||||||
if (resolvedType == null) {
|
|
||||||
resolvedType = intent.getType();
|
final PendingIntentRecord pendingIntent = (PendingIntentRecord) intentSender;
|
||||||
if (resolvedType == null && intent.getData() != null
|
checkEmbeddedAllowedInner(userId, pendingIntent.key.requestIntent,
|
||||||
&& "content".equals(intent.getData().getScheme())) {
|
pendingIntent.key.requestResolvedType);
|
||||||
resolvedType = mService.getProviderMimeType(intent.getData(), userId);
|
|
||||||
}
|
return pendingIntent.sendInner(0, null, null, null, null, null, null, 0,
|
||||||
}
|
FORCE_NEW_TASK_FLAGS, FORCE_NEW_TASK_FLAGS, null, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkEmbeddedAllowedInner(int userId, Intent intent, String resolvedType) {
|
||||||
ActivityInfo aInfo = resolveActivity(intent, resolvedType, 0, null, userId);
|
ActivityInfo aInfo = resolveActivity(intent, resolvedType, 0, null, userId);
|
||||||
if (aInfo != null && (aInfo.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) == 0) {
|
if (aInfo != null && (aInfo.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) == 0) {
|
||||||
throw new SecurityException(
|
throw new SecurityException(
|
||||||
@@ -3832,23 +3839,6 @@ public final class ActivityStackSupervisor implements DisplayListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Throw a SecurityException if allowEmbedded is not true */
|
|
||||||
@Override
|
|
||||||
public final void checkEmbeddedAllowed(Intent intent) {
|
|
||||||
checkEmbeddedAllowedInner(intent, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Throw a SecurityException if allowEmbedded is not true */
|
|
||||||
@Override
|
|
||||||
public final void checkEmbeddedAllowedIntentSender(IIntentSender intentSender) {
|
|
||||||
if (!(intentSender instanceof PendingIntentRecord)) {
|
|
||||||
throw new IllegalArgumentException("Bad PendingIntent object");
|
|
||||||
}
|
|
||||||
PendingIntentRecord pendingIntent = (PendingIntentRecord) intentSender;
|
|
||||||
checkEmbeddedAllowedInner(pendingIntent.key.requestIntent,
|
|
||||||
pendingIntent.key.requestResolvedType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBinder asBinder() {
|
public IBinder asBinder() {
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ import android.os.RemoteException;
|
|||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
|
||||||
|
import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
@@ -201,6 +203,13 @@ final class PendingIntentRecord extends IIntentSender.Stub {
|
|||||||
IBinder resultTo, String resultWho, int requestCode,
|
IBinder resultTo, String resultWho, int requestCode,
|
||||||
int flagsMask, int flagsValues, Bundle options, IActivityContainer container) {
|
int flagsMask, int flagsValues, Bundle options, IActivityContainer container) {
|
||||||
synchronized(owner) {
|
synchronized(owner) {
|
||||||
|
final ActivityContainer activityContainer = (ActivityContainer)container;
|
||||||
|
if (activityContainer != null && activityContainer.mParentActivity != null &&
|
||||||
|
activityContainer.mParentActivity.state
|
||||||
|
!= ActivityStack.ActivityState.RESUMED) {
|
||||||
|
// Cannot start a child activity if the parent is not resumed.
|
||||||
|
return ActivityManager.START_CANCELED;
|
||||||
|
}
|
||||||
if (!canceled) {
|
if (!canceled) {
|
||||||
sent = true;
|
sent = true;
|
||||||
if ((key.flags&PendingIntent.FLAG_ONE_SHOT) != 0) {
|
if ((key.flags&PendingIntent.FLAG_ONE_SHOT) != 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user