summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2012-04-26 19:25:41 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2012-04-26 19:25:41 -0700
commit493f74e5a4ed948a72575d11840a8366b5e9f672 (patch)
treec8faa348d7a4f55b64bbaa9bc3c86f53d552dee8
parente6eb9291423988e4f2e82367d760490397222fe3 (diff)
parentecc5a9cca000b62d2a649b795460fd791a206a89 (diff)
downloadframeworks_base-493f74e5a4ed948a72575d11840a8366b5e9f672.zip
frameworks_base-493f74e5a4ed948a72575d11840a8366b5e9f672.tar.gz
frameworks_base-493f74e5a4ed948a72575d11840a8366b5e9f672.tar.bz2
Merge "Add new Activity.finishAffinity() method." into jb-dev
-rw-r--r--api/current.txt1
-rw-r--r--core/java/android/app/Activity.java30
-rw-r--r--core/java/android/app/ActivityManagerNative.java23
-rw-r--r--core/java/android/app/IActivityManager.java2
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java26
-rwxr-xr-xservices/java/com/android/server/am/ActivityStack.java45
6 files changed, 109 insertions, 18 deletions
diff --git a/api/current.txt b/api/current.txt
index 882503d..9303937 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2601,6 +2601,7 @@ package android.app {
method public void finish();
method public void finishActivity(int);
method public void finishActivityFromChild(android.app.Activity, int);
+ method public void finishAffinity();
method public void finishFromChild(android.app.Activity);
method public android.app.ActionBar getActionBar();
method public final android.app.Application getApplication();
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 35bc7ff..4add7f4 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -4093,6 +4093,36 @@ public class Activity extends ContextThemeWrapper
}
/**
+ * Finish this activity as well as all activities immediately below it
+ * in the current task that have the same affinity. This is typically
+ * used when an application can be launched on to another task (such as
+ * from an ACTION_VIEW of a content type it understands) and the user
+ * has used the up navigation to switch out of the current task and in
+ * to its own task. In this case, if the user has navigated down into
+ * any other activities of the second application, all of those should
+ * be removed from the original task as part of the task switch.
+ *
+ * <p>Note that this finish does <em>not</em> allow you to deliver results
+ * to the previous activity, and an exception will be thrown if you are trying
+ * to do so.</p>
+ */
+ public void finishAffinity() {
+ if (mParent != null) {
+ throw new IllegalStateException("Can not be called from an embedded activity");
+ }
+ if (mResultCode != RESULT_CANCELED || mResultData != null) {
+ throw new IllegalStateException("Can not be called to deliver a result");
+ }
+ try {
+ if (ActivityManagerNative.getDefault().finishActivityAffinity(mToken)) {
+ mFinished = true;
+ }
+ } catch (RemoteException e) {
+ // Empty
+ }
+ }
+
+ /**
* This is called when a child activity of this one calls its
* {@link #finish} method. The default implementation simply calls
* finish() on this activity (the parent), finishing the entire group.
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 7e1589f..2f2918d 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -218,7 +218,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
reply.writeInt(result ? 1 : 0);
return true;
}
-
+
case FINISH_ACTIVITY_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder token = data.readStrongBinder();
@@ -243,6 +243,15 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
+ case FINISH_ACTIVITY_AFFINITY_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ IBinder token = data.readStrongBinder();
+ boolean res = finishActivityAffinity(token);
+ reply.writeNoException();
+ reply.writeInt(res ? 1 : 0);
+ return true;
+ }
+
case WILL_ACTIVITY_BE_VISIBLE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder token = data.readStrongBinder();
@@ -1866,6 +1875,18 @@ class ActivityManagerProxy implements IActivityManager
data.recycle();
reply.recycle();
}
+ public boolean finishActivityAffinity(IBinder token) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeStrongBinder(token);
+ mRemote.transact(FINISH_ACTIVITY_AFFINITY_TRANSACTION, data, reply, 0);
+ reply.readException();
+ boolean res = reply.readInt() != 0;
+ data.recycle();
+ reply.recycle();
+ return res;
+ }
public boolean willActivityBeVisible(IBinder token) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 3fc2280..a2c7fa4 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -72,6 +72,7 @@ public interface IActivityManager extends IInterface {
public boolean finishActivity(IBinder token, int code, Intent data)
throws RemoteException;
public void finishSubActivity(IBinder token, String resultWho, int requestCode) throws RemoteException;
+ public boolean finishActivityAffinity(IBinder token) throws RemoteException;
public boolean willActivityBeVisible(IBinder token) throws RemoteException;
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter,
@@ -590,4 +591,5 @@ public interface IActivityManager extends IInterface {
int TARGET_TASK_AFFINITY_MATCHES_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+145;
int NAVIGATE_UP_TO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+146;
int SET_LOCK_SCREEN_SHOWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+147;
+ int FINISH_ACTIVITY_AFFINITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+148;
}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 6c99cdb..429c3c4 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -2697,26 +2697,18 @@ public final class ActivityManagerService extends ActivityManagerNative
public final void finishSubActivity(IBinder token, String resultWho,
int requestCode) {
synchronized(this) {
- ActivityRecord self = mMainStack.isInStackLocked(token);
- if (self == null) {
- return;
- }
-
final long origId = Binder.clearCallingIdentity();
+ mMainStack.finishSubActivityLocked(token, resultWho, requestCode);
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
- int i;
- for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
- ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
- if (r.resultTo == self && r.requestCode == requestCode) {
- if ((r.resultWho == null && resultWho == null) ||
- (r.resultWho != null && r.resultWho.equals(resultWho))) {
- mMainStack.finishActivityLocked(r, i,
- Activity.RESULT_CANCELED, null, "request-sub");
- }
- }
- }
-
+ public boolean finishActivityAffinity(IBinder token) {
+ synchronized(this) {
+ final long origId = Binder.clearCallingIdentity();
+ boolean res = mMainStack.finishActivityAffinityLocked(token);
Binder.restoreCallingIdentity(origId);
+ return res;
}
}
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index c8e015b..25fae83 100755
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -3497,6 +3497,51 @@ final class ActivityStack {
return true;
}
+ final void finishSubActivityLocked(IBinder token, String resultWho, int requestCode) {
+ ActivityRecord self = isInStackLocked(token);
+ if (self == null) {
+ return;
+ }
+
+ int i;
+ for (i=mHistory.size()-1; i>=0; i--) {
+ ActivityRecord r = (ActivityRecord)mHistory.get(i);
+ if (r.resultTo == self && r.requestCode == requestCode) {
+ if ((r.resultWho == null && resultWho == null) ||
+ (r.resultWho != null && r.resultWho.equals(resultWho))) {
+ finishActivityLocked(r, i,
+ Activity.RESULT_CANCELED, null, "request-sub");
+ }
+ }
+ }
+ }
+
+ final boolean finishActivityAffinityLocked(IBinder token) {
+ int index = indexOfTokenLocked(token);
+ if (DEBUG_RESULTS) Slog.v(
+ TAG, "Finishing activity affinity @" + index + ": token=" + token);
+ if (index < 0) {
+ return false;
+ }
+ ActivityRecord r = mHistory.get(index);
+
+ while (index > 0) {
+ ActivityRecord cur = mHistory.get(index);
+ if (cur.task != r.task) {
+ break;
+ }
+ if (cur.taskAffinity == null && r.taskAffinity != null) {
+ break;
+ }
+ if (cur.taskAffinity != null && !cur.taskAffinity.equals(r.taskAffinity)) {
+ break;
+ }
+ finishActivityLocked(cur, index, Activity.RESULT_CANCELED, null, "request-affinity");
+ index--;
+ }
+ return true;
+ }
+
final void finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData) {
// send the result
ActivityRecord resultTo = r.resultTo;