diff options
author | Dianne Hackborn <hackbod@google.com> | 2012-04-26 19:25:41 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-04-26 19:25:41 -0700 |
commit | 493f74e5a4ed948a72575d11840a8366b5e9f672 (patch) | |
tree | c8faa348d7a4f55b64bbaa9bc3c86f53d552dee8 | |
parent | e6eb9291423988e4f2e82367d760490397222fe3 (diff) | |
parent | ecc5a9cca000b62d2a649b795460fd791a206a89 (diff) | |
download | frameworks_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.txt | 1 | ||||
-rw-r--r-- | core/java/android/app/Activity.java | 30 | ||||
-rw-r--r-- | core/java/android/app/ActivityManagerNative.java | 23 | ||||
-rw-r--r-- | core/java/android/app/IActivityManager.java | 2 | ||||
-rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 26 | ||||
-rwxr-xr-x | services/java/com/android/server/am/ActivityStack.java | 45 |
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; |