diff options
Diffstat (limited to 'core/java/com/android/internal')
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> [--] <start class name> <args> * </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) { + } } } |