summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/app/Activity.java218
-rw-r--r--core/java/android/app/ActivityManager.java1
-rw-r--r--core/java/android/app/ActivityManagerNative.java72
-rw-r--r--core/java/android/app/IActivityManager.java8
-rw-r--r--core/java/android/app/TaskStackBuilder.java212
-rw-r--r--core/java/android/content/pm/ActivityInfo.java8
-rw-r--r--core/java/android/content/pm/PackageParser.java28
-rw-r--r--core/java/com/android/internal/app/ActionBarImpl.java14
8 files changed, 553 insertions, 8 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index b277efb..3e123ba 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -29,6 +29,8 @@ import android.content.Intent;
import android.content.IntentSender;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -65,13 +67,13 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
-import android.view.WindowManagerImpl;
import android.view.View.OnCreateContextMenuListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewManager;
import android.view.Window;
import android.view.WindowManager;
+import android.view.WindowManagerImpl;
import android.view.accessibility.AccessibilityEvent;
import android.widget.AdapterView;
@@ -704,6 +706,7 @@ public class Activity extends ContextThemeWrapper
/*package*/ boolean mVisibleFromServer = false;
/*package*/ boolean mVisibleFromClient = true;
/*package*/ ActionBarImpl mActionBar = null;
+ private boolean mEnableDefaultActionBarUp;
private CharSequence mTitle;
private int mTitleColor = 0;
@@ -865,6 +868,13 @@ public class Activity extends ContextThemeWrapper
if (mLastNonConfigurationInstances != null) {
mAllLoaderManagers = mLastNonConfigurationInstances.loaders;
}
+ if (mActivityInfo.parentActivityName != null) {
+ if (mActionBar == null) {
+ mEnableDefaultActionBarUp = true;
+ } else {
+ mActionBar.setDefaultDisplayHomeAsUpEnabled(true);
+ }
+ }
if (savedInstanceState != null) {
Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
mFragments.restoreAllState(p, mLastNonConfigurationInstances != null
@@ -1829,6 +1839,7 @@ public class Activity extends ContextThemeWrapper
}
mActionBar = new ActionBarImpl(this);
+ mActionBar.setDefaultDisplayHomeAsUpEnabled(mEnableDefaultActionBarUp);
}
/**
@@ -2630,7 +2641,7 @@ public class Activity extends ContextThemeWrapper
* facilities.
*
* <p>Derived classes should call through to the base class for it to
- * perform the default menu handling.
+ * perform the default menu handling.</p>
*
* @param item The menu item that was selected.
*
@@ -2643,10 +2654,105 @@ public class Activity extends ContextThemeWrapper
if (mParent != null) {
return mParent.onOptionsItemSelected(item);
}
+ if (item.getItemId() == android.R.id.home && mActionBar != null &&
+ (mActionBar.getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
+ if (mParent == null) {
+ onNavigateUp();
+ } else {
+ mParent.onNavigateUpFromChild(this);
+ }
+ return true;
+ }
return false;
}
/**
+ * This method is called whenever the user chooses to navigate Up within your application's
+ * activity hierarchy from the action bar.
+ *
+ * <p>If the attribute {@link android.R.attr#parentActivityName parentActivityName}
+ * was specified in the manifest for this activity or an activity-alias to it,
+ * default Up navigation will be handled automatically. If any activity
+ * along the parent chain requires extra Intent arguments, the Activity subclass
+ * should override the method {@link #onPrepareNavigateUpTaskStack(TaskStackBuilder)}
+ * to supply those arguments.</p>
+ *
+ * <p>See <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back Stack</a>
+ * from the developer guide and <a href="{@docRoot}design/patterns/navigation.html">Navigation</a>
+ * from the design guide for more information about navigating within your app.</p>
+ *
+ * <p>See the {@link TaskStackBuilder} class and the Activity methods
+ * {@link #getParentActivityIntent()}, {@link #shouldUpRecreateTask(Intent)}, and
+ * {@link #navigateUpTo(Intent)} for help implementing custom Up navigation.
+ * The AppNavigation sample application in the Android SDK is also available for reference.</p>
+ *
+ * @return true if Up navigation completed successfully and this Activity was finished,
+ * false otherwise.
+ */
+ public boolean onNavigateUp() {
+ // Automatically handle hierarchical Up navigation if the proper
+ // metadata is available.
+ Intent upIntent = getParentActivityIntent();
+ if (upIntent != null) {
+ if (shouldUpRecreateTask(upIntent)) {
+ TaskStackBuilder b = TaskStackBuilder.from(this);
+ onCreateNavigateUpTaskStack(b);
+ onPrepareNavigateUpTaskStack(b);
+ b.startActivities();
+ finish();
+ } else {
+ navigateUpTo(upIntent);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * This is called when a child activity of this one attempts to navigate up.
+ * The default implementation simply calls onNavigateUp() on this activity (the parent).
+ *
+ * @param child The activity making the call.
+ */
+ public boolean onNavigateUpFromChild(Activity child) {
+ return onNavigateUp();
+ }
+
+ /**
+ * Define the synthetic task stack that will be generated during Up navigation from
+ * a different task.
+ *
+ * <p>The default implementation of this method adds the parent chain of this activity
+ * as specified in the manifest to the supplied {@link TaskStackBuilder}. Applications
+ * may choose to override this method to construct the desired task stack in a different
+ * way.</p>
+ *
+ * <p>Applications that wish to supply extra Intent parameters to the parent stack defined
+ * by the manifest should override {@link #onPrepareNavigateUpTaskStack(TaskStackBuilder)}.</p>
+ *
+ * @param builder An empty TaskStackBuilder - the application should add intents representing
+ * the desired task stack
+ */
+ public void onCreateNavigateUpTaskStack(TaskStackBuilder builder) {
+ builder.addParentStack(this);
+ }
+
+ /**
+ * Prepare the synthetic task stack that will be generated during Up navigation
+ * from a different task.
+ *
+ * <p>This method receives the {@link TaskStackBuilder} with the constructed series of
+ * Intents as generated by {@link #onCreateNavigateUpTaskStack(TaskStackBuilder)}.
+ * If any extra data should be added to these intents before launching the new task,
+ * the application should override this method and add that data here.</p>
+ *
+ * @param builder A TaskStackBuilder that has been populated with Intents by
+ * onCreateNavigateUpTaskStack.
+ */
+ public void onPrepareNavigateUpTaskStack(TaskStackBuilder builder) {
+ }
+
+ /**
* This hook is called whenever the options menu is being closed (either by the user canceling
* the menu with the back/menu button, or when an item is selected).
*
@@ -4658,6 +4764,114 @@ public class Activity extends ContextThemeWrapper
public void onActionModeFinished(ActionMode mode) {
}
+ /**
+ * Returns true if the app should recreate the task when navigating 'up' from this activity
+ * by using targetIntent.
+ *
+ * <p>If this method returns false the app can trivially call
+ * {@link #navigateUpTo(Intent)} using the same parameters to correctly perform
+ * up navigation. If this method returns false, the app should synthesize a new task stack
+ * by using {@link TaskStackBuilder} or another similar mechanism to perform up navigation.</p>
+ *
+ * @param targetIntent An intent representing the target destination for up navigation
+ * @return true if navigating up should recreate a new task stack, false if the same task
+ * should be used for the destination
+ */
+ public boolean shouldUpRecreateTask(Intent targetIntent) {
+ try {
+ PackageManager pm = getPackageManager();
+ ComponentName cn = targetIntent.getComponent();
+ if (cn == null) {
+ cn = targetIntent.resolveActivity(pm);
+ }
+ ActivityInfo info = pm.getActivityInfo(cn, 0);
+ if (info.taskAffinity == null) {
+ return false;
+ }
+ return !ActivityManagerNative.getDefault()
+ .targetTaskAffinityMatchesActivity(mToken, info.taskAffinity);
+ } catch (RemoteException e) {
+ return false;
+ } catch (NameNotFoundException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Navigate from this activity to the activity specified by upIntent, finishing this activity
+ * in the process. If the activity indicated by upIntent already exists in the task's history,
+ * this activity and all others before the indicated activity in the history stack will be
+ * finished. If the indicated activity does not appear in the history stack, this is equivalent
+ * to simply calling finish() on this activity.
+ *
+ * <p>This method should be used when performing up navigation from within the same task
+ * as the destination. If up navigation should cross tasks in some cases, see
+ * {@link #shouldUpRecreateTask(Intent)}.</p>
+ *
+ * @param upIntent An intent representing the target destination for up navigation
+ *
+ * @return true if up navigation successfully reached the activity indicated by upIntent and
+ * upIntent was delivered to it. false if an instance of the indicated activity could
+ * not be found and this activity was simply finished normally.
+ */
+ public boolean navigateUpTo(Intent upIntent) {
+ if (mParent == null) {
+ ComponentName destInfo = upIntent.getComponent();
+ if (destInfo == null) {
+ destInfo = upIntent.resolveActivity(getPackageManager());
+ if (destInfo == null) {
+ return false;
+ }
+ upIntent = new Intent(upIntent);
+ upIntent.setComponent(destInfo);
+ }
+ int resultCode;
+ Intent resultData;
+ synchronized (this) {
+ resultCode = mResultCode;
+ resultData = mResultData;
+ }
+ if (resultData != null) {
+ resultData.setAllowFds(false);
+ }
+ try {
+ return ActivityManagerNative.getDefault().navigateUpTo(mToken, upIntent,
+ resultCode, resultData);
+ } catch (RemoteException e) {
+ return false;
+ }
+ } else {
+ return mParent.navigateUpToFromChild(this, upIntent);
+ }
+ }
+
+ /**
+ * This is called when a child activity of this one calls its
+ * {@link #navigateUpTo} method. The default implementation simply calls
+ * navigateUpTo(upIntent) on this activity (the parent).
+ *
+ * @param child The activity making the call.
+ * @param upIntent An intent representing the target destination for up navigation
+ *
+ * @return true if up navigation successfully reached the activity indicated by upIntent and
+ * upIntent was delivered to it. false if an instance of the indicated activity could
+ * not be found and this activity was simply finished normally.
+ */
+ public boolean navigateUpToFromChild(Activity child, Intent upIntent) {
+ return navigateUpTo(upIntent);
+ }
+
+ /**
+ * Obtain an {@link Intent} that will launch an explicit target activity specified by
+ * this activity's logical parent. The logical parent is named in the application's manifest
+ * by the {@link android.R.attr#parentActivityName parentActivityName} attribute.
+ *
+ * @return a new Intent targeting the defined parent of this activity
+ */
+ public Intent getParentActivityIntent() {
+ return new Intent().setClassName(this, mActivityInfo.parentActivityName);
+ }
+
// ------------------ Internal API ------------------
final void setParent(Activity parent) {
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 531a695..11b4c3a 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1774,5 +1774,4 @@ public class ActivityManager {
return false;
}
}
-
}
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 5917cbf..000abc5 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -17,10 +17,10 @@
package android.app;
import android.content.ComponentName;
+import android.content.IIntentReceiver;
+import android.content.IIntentSender;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.IIntentSender;
-import android.content.IIntentReceiver;
import android.content.IntentSender;
import android.content.pm.ApplicationInfo;
import android.content.pm.ConfigurationInfo;
@@ -32,11 +32,11 @@ import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Debug;
-import android.os.Parcelable;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
import android.os.IBinder;
import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
+import android.os.Parcelable;
+import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StrictMode;
import android.text.TextUtils;
@@ -1605,6 +1605,31 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
+ case TARGET_TASK_AFFINITY_MATCHES_ACTIVITY_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ IBinder token = data.readStrongBinder();
+ String destAffinity = data.readString();
+ boolean res = targetTaskAffinityMatchesActivity(token, destAffinity);
+ reply.writeNoException();
+ reply.writeInt(res ? 1 : 0);
+ return true;
+ }
+
+ case NAVIGATE_UP_TO_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ IBinder token = data.readStrongBinder();
+ Intent target = Intent.CREATOR.createFromParcel(data);
+ int resultCode = data.readInt();
+ Intent resultData = null;
+ if (data.readInt() != 0) {
+ resultData = Intent.CREATOR.createFromParcel(data);
+ }
+ boolean res = navigateUpTo(token, target, resultCode, resultData);
+ reply.writeNoException();
+ reply.writeInt(res ? 1 : 0);
+ return true;
+ }
+
}
return super.onTransact(code, data, reply, flags);
@@ -3662,5 +3687,42 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
}
+ public boolean targetTaskAffinityMatchesActivity(IBinder token, String destAffinity)
+ throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeStrongBinder(token);
+ data.writeString(destAffinity);
+ mRemote.transact(TARGET_TASK_AFFINITY_MATCHES_ACTIVITY_TRANSACTION, data, reply, 0);
+ reply.readException();
+ boolean result = reply.readInt() != 0;
+ data.recycle();
+ reply.recycle();
+ return result;
+ }
+
+ public boolean navigateUpTo(IBinder token, Intent target, int resultCode, Intent resultData)
+ throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeStrongBinder(token);
+ target.writeToParcel(data, 0);
+ data.writeInt(resultCode);
+ if (resultData != null) {
+ data.writeInt(1);
+ resultData.writeToParcel(data, 0);
+ } else {
+ data.writeInt(0);
+ }
+ mRemote.transact(NAVIGATE_UP_TO_TRANSACTION, data, reply, 0);
+ reply.readException();
+ boolean result = reply.readInt() != 0;
+ data.recycle();
+ reply.recycle();
+ return result;
+ }
+
private IBinder mRemote;
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 2b1eb43..0f287c1 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -341,6 +341,12 @@ public interface IActivityManager extends IInterface {
public void dismissKeyguardOnNextActivity() throws RemoteException;
+ public boolean targetTaskAffinityMatchesActivity(IBinder token, String destAffinity)
+ throws RemoteException;
+
+ public boolean navigateUpTo(IBinder token, Intent target, int resultCode, Intent resultData)
+ throws RemoteException;
+
/*
* Private non-Binder interfaces
*/
@@ -578,4 +584,6 @@ public interface IActivityManager extends IInterface {
int GET_MY_MEMORY_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+142;
int KILL_PROCESSES_BELOW_FOREGROUND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+143;
int GET_CURRENT_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+144;
+ int TARGET_TASK_AFFINITY_MATCHES_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+145;
+ int NAVIGATE_UP_TO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+146;
}
diff --git a/core/java/android/app/TaskStackBuilder.java b/core/java/android/app/TaskStackBuilder.java
new file mode 100644
index 0000000..ee7c6ad
--- /dev/null
+++ b/core/java/android/app/TaskStackBuilder.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2012 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;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * Utility class for constructing synthetic back stacks for cross-task navigation
+ * on Android 3.0 and newer.
+ *
+ * <p>In API level 11 (Android 3.0/Honeycomb) the recommended conventions for
+ * app navigation using the back key changed. The back key's behavior is local
+ * to the current task and does not capture navigation across different tasks.
+ * Navigating across tasks and easily reaching the previous task is accomplished
+ * through the "recents" UI, accessible through the software-provided Recents key
+ * on the navigation or system bar. On devices with the older hardware button configuration
+ * the recents UI can be accessed with a long press on the Home key.</p>
+ *
+ * <p>When crossing from one task stack to another post-Android 3.0,
+ * the application should synthesize a back stack/history for the new task so that
+ * the user may navigate out of the new task and back to the Launcher by repeated
+ * presses of the back key. Back key presses should not navigate across task stacks.</p>
+ *
+ * <p>TaskStackBuilder provides a way to obey the correct conventions
+ * around cross-task navigation.</p>
+ *
+ * <div class="special reference">
+ * <h3>About Navigation</h3>
+ * For more detailed information about tasks, the back stack, and navigation design guidelines,
+ * please read
+ * <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back Stack</a>
+ * from the developer guide and <a href="{@docRoot}design/patterns/navigation.html">Navigation</a>
+ * from the design guide.
+ * </div>
+ */
+public class TaskStackBuilder implements Iterable<Intent> {
+ private static final String TAG = "TaskStackBuilder";
+
+ private final ArrayList<Intent> mIntents = new ArrayList<Intent>();
+ private final Context mSourceContext;
+
+ private TaskStackBuilder(Context a) {
+ mSourceContext = a;
+ }
+
+ /**
+ * Return a new TaskStackBuilder for launching a fresh task stack consisting
+ * of a series of activities.
+ *
+ * @param context The context that will launch the new task stack or generate a PendingIntent
+ * @return A new TaskStackBuilder
+ */
+ public static TaskStackBuilder from(Context context) {
+ return new TaskStackBuilder(context);
+ }
+
+ /**
+ * Add a new Intent to the task stack. The most recently added Intent will invoke
+ * the Activity at the top of the final task stack.
+ *
+ * @param nextIntent Intent for the next Activity in the synthesized task stack
+ * @return This TaskStackBuilder for method chaining
+ */
+ public TaskStackBuilder addNextIntent(Intent nextIntent) {
+ mIntents.add(nextIntent);
+ return this;
+ }
+
+ /**
+ * Add the activity parent chain as specified by the
+ * {@link android.R.attr#parentActivityName parentActivityName} attribute of the activity
+ * (or activity-alias) element in the application's manifest to the task stack builder.
+ *
+ * @param sourceActivity All parents of this activity will be added
+ * @return This TaskStackBuilder for method chaining
+ */
+ public TaskStackBuilder addParentStack(Activity sourceActivity) {
+ final int insertAt = mIntents.size();
+ Intent parent = sourceActivity.getParentActivityIntent();
+ PackageManager pm = sourceActivity.getPackageManager();
+ while (parent != null) {
+ mIntents.add(insertAt, parent);
+ try {
+ ActivityInfo info = pm.getActivityInfo(parent.getComponent(), 0);
+ String parentActivity = info.parentActivityName;
+ if (parentActivity != null) {
+ parent = new Intent().setComponent(
+ new ComponentName(mSourceContext, parentActivity));
+ } else {
+ parent = null;
+ }
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Bad ComponentName while traversing activity parent metadata");
+ throw new IllegalArgumentException(e);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Add the activity parent chain as specified by the
+ * {@link android.R.attr#parentActivityName parentActivityName} attribute of the activity
+ * (or activity-alias) element in the application's manifest to the task stack builder.
+ *
+ * @param sourceActivityClass All parents of this activity will be added
+ * @return This TaskStackBuilder for method chaining
+ */
+ public TaskStackBuilder addParentStack(Class<?> sourceActivityClass) {
+ final int insertAt = mIntents.size();
+ PackageManager pm = mSourceContext.getPackageManager();
+ try {
+ ActivityInfo info = pm.getActivityInfo(
+ new ComponentName(mSourceContext, sourceActivityClass), 0);
+ String parentActivity = info.parentActivityName;
+ Intent parent = new Intent().setComponent(
+ new ComponentName(mSourceContext, parentActivity));
+ while (parent != null) {
+ mIntents.add(insertAt, parent);
+ info = pm.getActivityInfo(parent.getComponent(), 0);
+ parentActivity = info.parentActivityName;
+ if (parentActivity != null) {
+ parent = new Intent().setComponent(
+ new ComponentName(mSourceContext, parentActivity));
+ } else {
+ parent = null;
+ }
+ }
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Bad ComponentName while traversing activity parent metadata");
+ throw new IllegalArgumentException(e);
+ }
+ return this;
+ }
+
+ /**
+ * @return the number of intents added so far.
+ */
+ public int getIntentCount() {
+ return mIntents.size();
+ }
+
+ /**
+ * Get the intent at the specified index.
+ * Useful if you need to modify the flags or extras of an intent that was previously added,
+ * for example with {@link #addParentStack(Activity)}.
+ *
+ * @param index Index from 0-getIntentCount()
+ * @return the intent at position index
+ */
+ public Intent getIntent(int index) {
+ return mIntents.get(index);
+ }
+
+ public Iterator<Intent> iterator() {
+ return mIntents.iterator();
+ }
+
+ /**
+ * Start the task stack constructed by this builder.
+ */
+ public void startActivities() {
+ if (mIntents.isEmpty()) {
+ throw new IllegalStateException(
+ "No intents added to TaskStackBuilder; cannot startActivities");
+ }
+
+ Intent[] intents = mIntents.toArray(new Intent[mIntents.size()]);
+ intents[0].addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+ Intent.FLAG_ACTIVITY_CLEAR_TASK |
+ Intent.FLAG_ACTIVITY_TASK_ON_HOME);
+ mSourceContext.startActivities(intents);
+ }
+
+ /**
+ * Obtain a {@link PendingIntent} for launching the task constructed by this builder so far.
+ *
+ * @param requestCode Private request code for the sender
+ * @param flags May be {@link PendingIntent#FLAG_ONE_SHOT},
+ * {@link PendingIntent#FLAG_NO_CREATE}, {@link PendingIntent#FLAG_CANCEL_CURRENT},
+ * {@link PendingIntent#FLAG_UPDATE_CURRENT}, or any of the flags supported by
+ * {@link Intent#fillIn(Intent, int)} to control which unspecified parts of the
+ * intent that can be supplied when the actual send happens.
+ * @return The obtained PendingIntent
+ */
+ public PendingIntent getPendingIntent(int requestCode, int flags) {
+ Intent[] intents = mIntents.toArray(new Intent[mIntents.size()]);
+ return PendingIntent.getActivities(mSourceContext, requestCode, intents, flags);
+ }
+}
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 0e6694d..6b16e74 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -450,6 +450,11 @@ public class ActivityInfo extends ComponentInfo
*/
public static final int UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW = 1;
+ /**
+ * If defined, the activity named here is the logical parent of this activity.
+ */
+ public String parentActivityName;
+
public ActivityInfo() {
}
@@ -465,6 +470,7 @@ public class ActivityInfo extends ComponentInfo
configChanges = orig.configChanges;
softInputMode = orig.softInputMode;
uiOptions = orig.uiOptions;
+ parentActivityName = orig.parentActivityName;
}
/**
@@ -524,6 +530,7 @@ public class ActivityInfo extends ComponentInfo
dest.writeInt(configChanges);
dest.writeInt(softInputMode);
dest.writeInt(uiOptions);
+ dest.writeString(parentActivityName);
}
public static final Parcelable.Creator<ActivityInfo> CREATOR
@@ -548,5 +555,6 @@ public class ActivityInfo extends ComponentInfo
configChanges = source.readInt();
softInputMode = source.readInt();
uiOptions = source.readInt();
+ parentActivityName = source.readString();
}
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index a79b86a..15ccda3 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -2030,6 +2030,19 @@ public class PackageParser {
com.android.internal.R.styleable.AndroidManifestActivity_uiOptions,
a.info.applicationInfo.uiOptions);
+ String parentName = sa.getNonConfigurationString(
+ com.android.internal.R.styleable.AndroidManifestActivity_parentActivityName, 0);
+ if (parentName != null) {
+ String parentClassName = buildClassName(a.info.packageName, parentName, outError);
+ if (outError[0] == null) {
+ a.info.parentActivityName = parentClassName;
+ } else {
+ Log.e(TAG, "Activity " + a.info.name + " specified invalid parentActivityName " +
+ parentName);
+ outError[0] = null;
+ }
+ }
+
String str;
str = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestActivity_permission, 0);
@@ -2274,6 +2287,7 @@ public class PackageParser {
info.theme = target.info.theme;
info.softInputMode = target.info.softInputMode;
info.uiOptions = target.info.uiOptions;
+ info.parentActivityName = target.info.parentActivityName;
Activity a = new Activity(mParseActivityAliasArgs, info);
if (outError[0] != null) {
@@ -2295,6 +2309,20 @@ public class PackageParser {
a.info.permission = str.length() > 0 ? str.toString().intern() : null;
}
+ String parentName = sa.getNonConfigurationString(
+ com.android.internal.R.styleable.AndroidManifestActivityAlias_parentActivityName,
+ 0);
+ if (parentName != null) {
+ String parentClassName = buildClassName(a.info.packageName, parentName, outError);
+ if (outError[0] == null) {
+ a.info.parentActivityName = parentClassName;
+ } else {
+ Log.e(TAG, "Activity alias " + a.info.name +
+ " specified invalid parentActivityName " + parentName);
+ outError[0] = null;
+ }
+ }
+
sa.recycle();
if (outError[0] != null) {
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index 3115eff..f1dffa1 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -85,6 +85,8 @@ public class ActionBarImpl extends ActionBar {
private TabImpl mSelectedTab;
private int mSavedTabPosition = INVALID_POSITION;
+ private boolean mDisplayHomeAsUpSet;
+
ActionModeImpl mActionMode;
ActionMode mDeferredDestroyActionMode;
ActionMode.Callback mDeferredModeDestroyCallback;
@@ -375,11 +377,17 @@ public class ActionBarImpl extends ActionBar {
}
public void setDisplayOptions(int options) {
+ if ((options & DISPLAY_HOME_AS_UP) != 0) {
+ mDisplayHomeAsUpSet = true;
+ }
mActionView.setDisplayOptions(options);
}
public void setDisplayOptions(int options, int mask) {
final int current = mActionView.getDisplayOptions();
+ if ((mask & DISPLAY_HOME_AS_UP) != 0) {
+ mDisplayHomeAsUpSet = true;
+ }
mActionView.setDisplayOptions((options & mask) | (current & ~mask));
}
@@ -1072,4 +1080,10 @@ public class ActionBarImpl extends ActionBar {
public void setLogo(Drawable logo) {
mActionView.setLogo(logo);
}
+
+ public void setDefaultDisplayHomeAsUpEnabled(boolean enable) {
+ if (!mDisplayHomeAsUpSet) {
+ setDisplayHomeAsUpEnabled(enable);
+ }
+ }
}