summaryrefslogtreecommitdiffstats
path: root/core/java/com/android/internal
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/com/android/internal')
-rwxr-xr-xcore/java/com/android/internal/os/PkgUsageStats.java22
-rw-r--r--core/java/com/android/internal/os/RuntimeInit.java13
-rw-r--r--core/java/com/android/internal/os/WrapperInit.java23
-rw-r--r--core/java/com/android/internal/os/ZygoteConnection.java22
-rw-r--r--core/java/com/android/internal/os/ZygoteInit.java11
-rw-r--r--core/java/com/android/internal/util/Protocol.java5
-rw-r--r--core/java/com/android/internal/view/menu/ActionMenuPresenter.java80
-rw-r--r--core/java/com/android/internal/view/menu/BaseMenuPresenter.java10
-rw-r--r--core/java/com/android/internal/view/menu/IconMenuPresenter.java54
-rw-r--r--core/java/com/android/internal/view/menu/ListMenuPresenter.java27
-rw-r--r--core/java/com/android/internal/view/menu/MenuBuilder.java57
-rw-r--r--core/java/com/android/internal/view/menu/MenuPopupHelper.java15
-rw-r--r--core/java/com/android/internal/view/menu/MenuPresenter.java21
-rw-r--r--core/java/com/android/internal/widget/ActionBarView.java15
14 files changed, 349 insertions, 26 deletions
diff --git a/core/java/com/android/internal/os/PkgUsageStats.java b/core/java/com/android/internal/os/PkgUsageStats.java
index 1ac191b..8c2c405 100755
--- a/core/java/com/android/internal/os/PkgUsageStats.java
+++ b/core/java/com/android/internal/os/PkgUsageStats.java
@@ -19,6 +19,9 @@ package com.android.internal.os;
import android.os.Parcel;
import android.os.Parcelable;
+import java.util.HashMap;
+import java.util.Map;
+
/**
* implementation of PkgUsageStats associated with an
* application package.
@@ -28,6 +31,7 @@ public class PkgUsageStats implements Parcelable {
public String packageName;
public int launchCount;
public long usageTime;
+ public Map<String, Long> componentResumeTimes;
public static final Parcelable.Creator<PkgUsageStats> CREATOR
= new Parcelable.Creator<PkgUsageStats>() {
@@ -46,31 +50,45 @@ public class PkgUsageStats implements Parcelable {
+ " " + packageName + "}";
}
- public PkgUsageStats(String pkgName, int count, long time) {
+ public PkgUsageStats(String pkgName, int count, long time, Map<String, Long> lastResumeTimes) {
packageName = pkgName;
launchCount = count;
usageTime = time;
+ componentResumeTimes = new HashMap<String, Long>(lastResumeTimes);
}
public PkgUsageStats(Parcel source) {
packageName = source.readString();
launchCount = source.readInt();
usageTime = source.readLong();
+ final int N = source.readInt();
+ componentResumeTimes = new HashMap<String, Long>(N);
+ for (int i = 0; i < N; i++) {
+ String component = source.readString();
+ long lastResumeTime = source.readLong();
+ componentResumeTimes.put(component, lastResumeTime);
+ }
}
public PkgUsageStats(PkgUsageStats pStats) {
packageName = pStats.packageName;
launchCount = pStats.launchCount;
usageTime = pStats.usageTime;
+ componentResumeTimes = new HashMap<String, Long>(pStats.componentResumeTimes);
}
public int describeContents() {
return 0;
}
- public void writeToParcel(Parcel dest, int parcelableFlags){
+ public void writeToParcel(Parcel dest, int parcelableFlags) {
dest.writeString(packageName);
dest.writeInt(launchCount);
dest.writeLong(usageTime);
+ dest.writeInt(componentResumeTimes.size());
+ for (Map.Entry<String, Long> ent : componentResumeTimes.entrySet()) {
+ dest.writeString(ent.getKey());
+ dest.writeLong(ent.getValue());
+ }
}
}
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index f13e770..53516c0 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -252,9 +252,10 @@ public class RuntimeInit {
* <li> <code> [--] &lt;start class name&gt; &lt;args&gt;
* </ul>
*
+ * @param targetSdkVersion target SDK version
* @param argv arg strings
*/
- public static final void zygoteInit(String[] argv)
+ public static final void zygoteInit(int targetSdkVersion, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
@@ -263,7 +264,7 @@ public class RuntimeInit {
commonInit();
zygoteInitNative();
- applicationInit(argv);
+ applicationInit(targetSdkVersion, argv);
}
/**
@@ -274,20 +275,22 @@ public class RuntimeInit {
* which calls {@link WrapperInit#main} which then calls this method.
* So we don't need to call commonInit() here.
*
+ * @param targetSdkVersion target SDK version
* @param argv arg strings
*/
- public static void wrapperInit(String[] argv)
+ public static void wrapperInit(int targetSdkVersion, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from wrapper");
- applicationInit(argv);
+ applicationInit(targetSdkVersion, argv);
}
- private static void applicationInit(String[] argv)
+ private static void applicationInit(int targetSdkVersion, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
// We want to be fairly aggressive about heap utilization, to avoid
// holding on to a lot of memory that isn't needed.
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
+ VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
final Arguments args;
try {
diff --git a/core/java/com/android/internal/os/WrapperInit.java b/core/java/com/android/internal/os/WrapperInit.java
index 860a08c..c6b3e7c 100644
--- a/core/java/com/android/internal/os/WrapperInit.java
+++ b/core/java/com/android/internal/os/WrapperInit.java
@@ -47,16 +47,22 @@ public class WrapperInit {
* wrapper process instead of by forking Zygote.
*
* The first argument specifies the file descriptor for a pipe that should receive
- * the pid of this process, or 0 if none. The remaining arguments are passed to
- * the runtime.
+ * the pid of this process, or 0 if none.
+ *
+ * The second argument is the target SDK version for the app.
+ *
+ * The remaining arguments are passed to the runtime.
*
* @param args The command-line arguments.
*/
public static void main(String[] args) {
try {
+ // Parse our mandatory arguments.
+ int fdNum = Integer.parseInt(args[0], 10);
+ int targetSdkVersion = Integer.parseInt(args[1], 10);
+
// Tell the Zygote what our actual PID is (since it only knows about the
// wrapper that it directly forked).
- int fdNum = Integer.parseInt(args[0], 10);
if (fdNum != 0) {
try {
FileDescriptor fd = ZygoteInit.createFileDescriptor(fdNum);
@@ -73,9 +79,9 @@ public class WrapperInit {
ZygoteInit.preload();
// Launch the application.
- String[] runtimeArgs = new String[args.length - 1];
- System.arraycopy(args, 1, runtimeArgs, 0, runtimeArgs.length);
- RuntimeInit.wrapperInit(runtimeArgs);
+ String[] runtimeArgs = new String[args.length - 2];
+ System.arraycopy(args, 2, runtimeArgs, 0, runtimeArgs.length);
+ RuntimeInit.wrapperInit(targetSdkVersion, runtimeArgs);
} catch (ZygoteInit.MethodAndArgsCaller caller) {
caller.run();
}
@@ -87,11 +93,12 @@ public class WrapperInit {
*
* @param invokeWith The wrapper command.
* @param niceName The nice name for the application, or null if none.
+ * @param targetSdkVersion The target SDK version for the app.
* @param pipeFd The pipe to which the application's pid should be written, or null if none.
* @param args Arguments for {@link RuntimeInit.main}.
*/
public static void execApplication(String invokeWith, String niceName,
- FileDescriptor pipeFd, String[] args) {
+ int targetSdkVersion, FileDescriptor pipeFd, String[] args) {
StringBuilder command = new StringBuilder(invokeWith);
command.append(" /system/bin/app_process /system/bin --application");
if (niceName != null) {
@@ -99,6 +106,8 @@ public class WrapperInit {
}
command.append(" com.android.internal.os.WrapperInit ");
command.append(pipeFd != null ? pipeFd.getInt$() : 0);
+ command.append(' ');
+ command.append(targetSdkVersion);
Zygote.appendQuotedShellArgs(command, args);
Zygote.execShell(command.toString());
}
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 7cb002c..9af7e96 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -18,6 +18,7 @@ package com.android.internal.os;
import android.net.Credentials;
import android.net.LocalSocket;
+import android.os.Build;
import android.os.Process;
import android.os.SystemProperties;
import android.util.Log;
@@ -333,6 +334,10 @@ class ZygoteConnection {
*/
int debugFlags;
+ /** from --target-sdk-version. */
+ int targetSdkVersion;
+ boolean targetSdkVersionSpecified;
+
/** from --classpath */
String classpath;
@@ -402,6 +407,14 @@ class ZygoteConnection {
gidSpecified = true;
gid = Integer.parseInt(
arg.substring(arg.indexOf('=') + 1));
+ } else if (arg.startsWith("--target-sdk-version=")) {
+ if (targetSdkVersionSpecified) {
+ throw new IllegalArgumentException(
+ "Duplicate target-sdk-version specified");
+ }
+ targetSdkVersionSpecified = true;
+ targetSdkVersion = Integer.parseInt(
+ arg.substring(arg.indexOf('=') + 1));
} else if (arg.equals("--enable-debugger")) {
debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
} else if (arg.equals("--enable-safemode")) {
@@ -821,9 +834,11 @@ class ZygoteConnection {
if (parsedArgs.runtimeInit) {
if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(parsedArgs.invokeWith,
- parsedArgs.niceName, pipeFd, parsedArgs.remainingArgs);
+ parsedArgs.niceName, parsedArgs.targetSdkVersion,
+ pipeFd, parsedArgs.remainingArgs);
} else {
- RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
+ RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
+ parsedArgs.remainingArgs);
}
} else {
String className;
@@ -885,6 +900,7 @@ class ZygoteConnection {
}
}
+ boolean usingWrapper = false;
if (pipeFd != null && pid > 0) {
DataInputStream is = new DataInputStream(new FileInputStream(pipeFd));
int innerPid = -1;
@@ -909,6 +925,7 @@ class ZygoteConnection {
if (parentPid > 0) {
Log.i(TAG, "Wrapped process has pid " + innerPid);
pid = innerPid;
+ usingWrapper = true;
} else {
Log.w(TAG, "Wrapped process reported a pid that is not a child of "
+ "the process that we forked: childPid=" + pid
@@ -919,6 +936,7 @@ class ZygoteConnection {
try {
mSocketOutStream.writeInt(pid);
+ mSocketOutStream.writeBoolean(usingWrapper);
} catch (IOException ex) {
Log.e(TAG, "Error reading from command socket", ex);
return true;
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index b4a7e52..6ec186d 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -48,7 +48,7 @@ import java.util.ArrayList;
* Startup class for the zygote process.
*
* Pre-initializes some classes, and then waits for commands on a UNIX domain
- * socket. Based on these commands, forks of child processes that inherit
+ * socket. Based on these commands, forks off child processes that inherit
* the initial state of the VM.
*
* Please see {@link ZygoteConnection.Arguments} for documentation on the
@@ -453,12 +453,13 @@ public class ZygoteInit {
if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(parsedArgs.invokeWith,
- parsedArgs.niceName, null, parsedArgs.remainingArgs);
+ parsedArgs.niceName, parsedArgs.targetSdkVersion,
+ null, parsedArgs.remainingArgs);
} else {
/*
* Pass the remaining arguments to SystemServer.
*/
- RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
+ RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
}
/* should never reach here */
@@ -491,7 +492,9 @@ public class ZygoteInit {
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
- parsedArgs.gids, parsedArgs.debugFlags, null,
+ parsedArgs.gids,
+ parsedArgs.debugFlags,
+ null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
diff --git a/core/java/com/android/internal/util/Protocol.java b/core/java/com/android/internal/util/Protocol.java
index 2e7ec58..b754d94 100644
--- a/core/java/com/android/internal/util/Protocol.java
+++ b/core/java/com/android/internal/util/Protocol.java
@@ -26,6 +26,9 @@ package com.android.internal.util;
* codes with Message.what starting at Protocol.WIFI + 1 and less than or equal to Protocol.WIFI +
* Protocol.MAX_MESSAGE
*
+ * NOTE: After a value is created and source released a value shouldn't be changed to
+ * maintain backwards compatibility.
+ *
* {@hide}
*/
public class Protocol {
@@ -40,7 +43,7 @@ public class Protocol {
public static final int BASE_DHCP = 0x00030000;
public static final int BASE_DATA_CONNECTION = 0x00040000;
public static final int BASE_DATA_CONNECTION_AC = 0x00041000;
- public static final int BASE_DATA_CONNECTION_TRACKER = 0x00050000;
+ public static final int BASE_DATA_CONNECTION_TRACKER = 0x00042000;
//TODO: define all used protocols
}
diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
index b86eb13..9c06d69 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
@@ -20,7 +20,8 @@ import com.android.internal.view.menu.ActionMenuView.ActionMenuChildView;
import android.content.Context;
import android.content.res.Resources;
-import android.util.Log;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.util.SparseBooleanArray;
import android.view.MenuItem;
import android.view.SoundEffectConstants;
@@ -60,6 +61,9 @@ public class ActionMenuPresenter extends BaseMenuPresenter {
private OpenOverflowRunnable mPostedOpenRunnable;
+ final PopupPresenterCallback mPopupPresenterCallback = new PopupPresenterCallback();
+ int mOpenSubMenuId;
+
public ActionMenuPresenter() {
super(com.android.internal.R.layout.action_menu_layout,
com.android.internal.R.layout.action_menu_item_layout);
@@ -196,8 +200,12 @@ public class ActionMenuPresenter extends BaseMenuPresenter {
topSubMenu = (SubMenuBuilder) topSubMenu.getParentMenu();
}
View anchor = findViewForItem(topSubMenu.getItem());
- if (anchor == null) return false;
+ if (anchor == null) {
+ if (mOverflowButton == null) return false;
+ anchor = mOverflowButton;
+ }
+ mOpenSubMenuId = subMenu.getItem().getItemId();
mActionButtonPopup = new ActionButtonSubmenu(mContext, subMenu);
mActionButtonPopup.setAnchorView(anchor);
mActionButtonPopup.show();
@@ -426,6 +434,57 @@ public class ActionMenuPresenter extends BaseMenuPresenter {
super.onCloseMenu(menu, allMenusAreClosing);
}
+ @Override
+ public Parcelable onSaveInstanceState() {
+ SavedState state = new SavedState();
+ state.openSubMenuId = mOpenSubMenuId;
+ return state;
+ }
+
+ @Override
+ public void onRestoreInstanceState(Parcelable state) {
+ SavedState saved = (SavedState) state;
+ if (saved.openSubMenuId > 0) {
+ MenuItem item = mMenu.findItem(saved.openSubMenuId);
+ if (item != null) {
+ SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu();
+ onSubMenuSelected(subMenu);
+ }
+ }
+ }
+
+ private static class SavedState implements Parcelable {
+ public int openSubMenuId;
+
+ SavedState() {
+ }
+
+ SavedState(Parcel in) {
+ openSubMenuId = in.readInt();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(openSubMenuId);
+ }
+
+ public static final Parcelable.Creator<SavedState> CREATOR
+ = new Parcelable.Creator<SavedState>() {
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+
private class OverflowMenuButton extends ImageButton implements ActionMenuChildView {
public OverflowMenuButton(Context context) {
super(context, null, com.android.internal.R.attr.actionOverflowButtonStyle);
@@ -460,6 +519,7 @@ public class ActionMenuPresenter extends BaseMenuPresenter {
public OverflowPopup(Context context, MenuBuilder menu, View anchorView,
boolean overflowOnly) {
super(context, menu, anchorView, overflowOnly);
+ setCallback(mPopupPresenterCallback);
}
@Override
@@ -482,6 +542,8 @@ public class ActionMenuPresenter extends BaseMenuPresenter {
// Give a reasonable anchor to nested submenus.
setAnchorView(mOverflowButton == null ? (View) mMenuView : mOverflowButton);
}
+
+ setCallback(mPopupPresenterCallback);
}
@Override
@@ -489,6 +551,20 @@ public class ActionMenuPresenter extends BaseMenuPresenter {
super.onDismiss();
mSubMenu.close();
mActionButtonPopup = null;
+ mOpenSubMenuId = 0;
+ }
+ }
+
+ private class PopupPresenterCallback implements MenuPresenter.Callback {
+
+ @Override
+ public boolean onOpenSubMenu(MenuBuilder subMenu) {
+ mOpenSubMenuId = ((SubMenuBuilder) subMenu).getItem().getItemId();
+ return false;
+ }
+
+ @Override
+ public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
}
}
diff --git a/core/java/com/android/internal/view/menu/BaseMenuPresenter.java b/core/java/com/android/internal/view/menu/BaseMenuPresenter.java
index ddbb08c..ed9d34a 100644
--- a/core/java/com/android/internal/view/menu/BaseMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/BaseMenuPresenter.java
@@ -39,6 +39,8 @@ public abstract class BaseMenuPresenter implements MenuPresenter {
protected MenuView mMenuView;
+ private int mId;
+
/**
* Construct a new BaseMenuPresenter.
*
@@ -200,4 +202,12 @@ public abstract class BaseMenuPresenter implements MenuPresenter {
public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) {
return false;
}
+
+ public int getId() {
+ return mId;
+ }
+
+ public void setId(int id) {
+ mId = id;
+ }
}
diff --git a/core/java/com/android/internal/view/menu/IconMenuPresenter.java b/core/java/com/android/internal/view/menu/IconMenuPresenter.java
index f717904..56128d4 100644
--- a/core/java/com/android/internal/view/menu/IconMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/IconMenuPresenter.java
@@ -23,6 +23,7 @@ import android.os.Parcelable;
import android.util.SparseArray;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
+import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
@@ -35,7 +36,12 @@ public class IconMenuPresenter extends BaseMenuPresenter {
private IconMenuItemView mMoreView;
private int mMaxItems = -1;
+ int mOpenSubMenuId;
+ SubMenuPresenterCallback mSubMenuPresenterCallback = new SubMenuPresenterCallback();
+ MenuDialogHelper mOpenSubMenu;
+
private static final String VIEWS_TAG = "android:menu:icon";
+ private static final String OPEN_SUBMENU_KEY = "android:menu:icon:submenu";
public IconMenuPresenter() {
super(com.android.internal.R.layout.icon_menu_layout,
@@ -86,7 +92,11 @@ public class IconMenuPresenter extends BaseMenuPresenter {
if (!subMenu.hasVisibleItems()) return false;
// The window manager will give us a token.
- new MenuDialogHelper(subMenu).show(null);
+ MenuDialogHelper helper = new MenuDialogHelper(subMenu);
+ helper.setPresenterCallback(mSubMenuPresenterCallback);
+ helper.show(null);
+ mOpenSubMenu = helper;
+ mOpenSubMenuId = subMenu.getItem().getItemId();
super.onSubMenuSelected(subMenu);
return true;
}
@@ -137,5 +147,47 @@ public class IconMenuPresenter extends BaseMenuPresenter {
if (viewStates != null) {
((View) mMenuView).restoreHierarchyState(viewStates);
}
+ int subMenuId = inState.getInt(OPEN_SUBMENU_KEY, 0);
+ if (subMenuId > 0 && mMenu != null) {
+ MenuItem item = mMenu.findItem(subMenuId);
+ if (item != null) {
+ onSubMenuSelected((SubMenuBuilder) item.getSubMenu());
+ }
+ }
+ }
+
+ @Override
+ public Parcelable onSaveInstanceState() {
+ if (mMenuView == null) {
+ return null;
+ }
+
+ Bundle state = new Bundle();
+ saveHierarchyState(state);
+ if (mOpenSubMenuId > 0) {
+ state.putInt(OPEN_SUBMENU_KEY, mOpenSubMenuId);
+ }
+ return state;
+ }
+
+ @Override
+ public void onRestoreInstanceState(Parcelable state) {
+ restoreHierarchyState((Bundle) state);
+ }
+
+ class SubMenuPresenterCallback implements MenuPresenter.Callback {
+ @Override
+ public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
+ mOpenSubMenuId = 0;
+ mOpenSubMenu.dismiss();
+ mOpenSubMenu = null;
+ }
+
+ @Override
+ public boolean onOpenSubMenu(MenuBuilder subMenu) {
+ mOpenSubMenuId = ((SubMenuBuilder) subMenu).getItem().getItemId();
+ return false;
+ }
+
}
}
diff --git a/core/java/com/android/internal/view/menu/ListMenuPresenter.java b/core/java/com/android/internal/view/menu/ListMenuPresenter.java
index 27e4191..146c7ac 100644
--- a/core/java/com/android/internal/view/menu/ListMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ListMenuPresenter.java
@@ -47,6 +47,8 @@ public class ListMenuPresenter implements MenuPresenter, AdapterView.OnItemClick
private Callback mCallback;
private MenuAdapter mAdapter;
+ private int mId;
+
public static final String VIEWS_TAG = "android:menu:list";
/**
@@ -182,6 +184,31 @@ public class ListMenuPresenter implements MenuPresenter, AdapterView.OnItemClick
}
}
+ public void setId(int id) {
+ mId = id;
+ }
+
+ @Override
+ public int getId() {
+ return mId;
+ }
+
+ @Override
+ public Parcelable onSaveInstanceState() {
+ if (mMenuView == null) {
+ return null;
+ }
+
+ Bundle state = new Bundle();
+ saveHierarchyState(state);
+ return state;
+ }
+
+ @Override
+ public void onRestoreInstanceState(Parcelable state) {
+ restoreHierarchyState((Bundle) state);
+ }
+
private class MenuAdapter extends BaseAdapter {
public int getCount() {
ArrayList<MenuItemImpl> items = mMenu.getNonActionItems();
diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java
index fdfa954..a4edbc5 100644
--- a/core/java/com/android/internal/view/menu/MenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/MenuBuilder.java
@@ -25,8 +25,8 @@ import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
+import android.os.Bundle;
import android.os.Parcelable;
-import android.util.Log;
import android.util.SparseArray;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.KeyCharacterMap;
@@ -38,7 +38,6 @@ import android.view.View;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
-import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -49,6 +48,8 @@ import java.util.concurrent.CopyOnWriteArrayList;
public class MenuBuilder implements Menu {
private static final String LOGTAG = "MenuBuilder";
+ private static final String PRESENTER_KEY = "android:menu:presenters";
+
private static final int[] sCategoryToOrder = new int[] {
1, /* No category */
4, /* CONTAINER */
@@ -254,6 +255,58 @@ public class MenuBuilder implements Menu {
return result;
}
+ private void dispatchSaveInstanceState(Bundle outState) {
+ if (mPresenters.isEmpty()) return;
+
+ SparseArray<Parcelable> presenterStates = new SparseArray<Parcelable>();
+
+ for (WeakReference<MenuPresenter> ref : mPresenters) {
+ final MenuPresenter presenter = ref.get();
+ if (presenter == null) {
+ mPresenters.remove(ref);
+ } else {
+ final int id = presenter.getId();
+ if (id > 0) {
+ final Parcelable state = presenter.onSaveInstanceState();
+ if (state != null) {
+ presenterStates.put(id, state);
+ }
+ }
+ }
+ }
+
+ outState.putSparseParcelableArray(PRESENTER_KEY, presenterStates);
+ }
+
+ private void dispatchRestoreInstanceState(Bundle state) {
+ SparseArray<Parcelable> presenterStates = state.getSparseParcelableArray(PRESENTER_KEY);
+
+ if (presenterStates == null || mPresenters.isEmpty()) return;
+
+ for (WeakReference<MenuPresenter> ref : mPresenters) {
+ final MenuPresenter presenter = ref.get();
+ if (presenter == null) {
+ mPresenters.remove(ref);
+ } else {
+ final int id = presenter.getId();
+ if (id > 0) {
+ Parcelable parcel = presenterStates.get(id);
+ if (parcel != null) {
+ presenter.onRestoreInstanceState(parcel);
+ }
+ }
+ }
+ }
+ }
+
+ public void savePresenterStates(Bundle outState) {
+ dispatchSaveInstanceState(outState);
+ }
+
+ public void restorePresenterStates(Bundle state) {
+ dispatchRestoreInstanceState(state);
+ }
+
public void setCallback(Callback cb) {
mCallback = cb;
}
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index cffbb4e..4ecc828 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -18,6 +18,7 @@ package com.android.internal.view.menu;
import android.content.Context;
import android.content.res.Resources;
+import android.os.Parcelable;
import android.util.DisplayMetrics;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -296,4 +297,18 @@ public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.On
return convertView;
}
}
+
+ @Override
+ public int getId() {
+ return 0;
+ }
+
+ @Override
+ public Parcelable onSaveInstanceState() {
+ return null;
+ }
+
+ @Override
+ public void onRestoreInstanceState(Parcelable state) {
+ }
}
diff --git a/core/java/com/android/internal/view/menu/MenuPresenter.java b/core/java/com/android/internal/view/menu/MenuPresenter.java
index bd66448..d913a39 100644
--- a/core/java/com/android/internal/view/menu/MenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/MenuPresenter.java
@@ -17,6 +17,7 @@
package com.android.internal.view.menu;
import android.content.Context;
+import android.os.Parcelable;
import android.view.Menu;
import android.view.ViewGroup;
@@ -125,4 +126,24 @@ public interface MenuPresenter {
* @return true if this presenter collapsed the action view, false otherwise.
*/
public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item);
+
+ /**
+ * Returns an ID for determining how to save/restore instance state.
+ * @return a valid ID value.
+ */
+ public int getId();
+
+ /**
+ * Returns a Parcelable describing the current state of the presenter.
+ * It will be passed to the {@link #onRestoreInstanceState(Parcelable)}
+ * method of the presenter sharing the same ID later.
+ * @return The saved instance state
+ */
+ public Parcelable onSaveInstanceState();
+
+ /**
+ * Supplies the previously saved instance state to be restored.
+ * @param state The previously saved instance state
+ */
+ public void onRestoreInstanceState(Parcelable state);
}
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 09bc1fc..595753a 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -337,6 +337,7 @@ public class ActionBarView extends AbsActionBarView {
if (mActionMenuPresenter == null) {
mActionMenuPresenter = new ActionMenuPresenter();
mActionMenuPresenter.setCallback(cb);
+ mActionMenuPresenter.setId(com.android.internal.R.id.action_menu_presenter);
mExpandedMenuPresenter = new ExpandedActionViewMenuPresenter();
}
@@ -1301,5 +1302,19 @@ public class ActionBarView extends AbsActionBarView {
item.setActionViewExpanded(false);
return true;
}
+
+ @Override
+ public int getId() {
+ return 0;
+ }
+
+ @Override
+ public Parcelable onSaveInstanceState() {
+ return null;
+ }
+
+ @Override
+ public void onRestoreInstanceState(Parcelable state) {
+ }
}
}