diff options
Diffstat (limited to 'core/java/android')
62 files changed, 1141 insertions, 732 deletions
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java index b74c824..014a7af 100644 --- a/core/java/android/app/ActionBar.java +++ b/core/java/android/app/ActionBar.java @@ -1061,6 +1061,10 @@ public abstract class ActionBar { return false; } + /** @hide */ + public void setWindowTitle(CharSequence title) { + } + /** * Listener interface for ActionBar navigation events. * diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 2e66a4c..c80eeb9 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -4145,10 +4145,9 @@ public class Activity extends ContextThemeWrapper intent.prepareToLeaveProcess(); result = ActivityManagerNative.getDefault() .startActivity(mMainThread.getApplicationThread(), getBasePackageName(), - intent, intent.resolveTypeIfNeeded(getContentResolver()), - mToken, mEmbeddedID, requestCode, - ActivityManager.START_FLAG_ONLY_IF_NEEDED, null, null, - options); + intent, intent.resolveTypeIfNeeded(getContentResolver()), mToken, + mEmbeddedID, requestCode, ActivityManager.START_FLAG_ONLY_IF_NEEDED, + null, options); } catch (RemoteException e) { // Empty } @@ -4704,6 +4703,26 @@ public class Activity extends ContextThemeWrapper } /** + * Ask that the local app instance of this activity be released to free up its memory. + * This is asking for the activity to be destroyed, but does <b>not</b> finish the activity -- + * a new instance of the activity will later be re-created if needed due to the user + * navigating back to it. + * + * @return Returns true if the activity was in a state that it has started the process + * of destroying its current instance; returns false if for any reason this could not + * be done: it is currently visible to the user, it is already being destroyed, it is + * being finished, it hasn't yet saved its state, etc. + */ + public boolean releaseInstance() { + try { + return ActivityManagerNative.getDefault().releaseActivityInstance(mToken); + } catch (RemoteException e) { + // Empty + } + return false; + } + + /** * Called when an activity you launched exits, giving you the requestCode * you started it with, the resultCode it returned, and any additional * data from it. The <var>resultCode</var> will be @@ -5019,9 +5038,9 @@ public class Activity extends ContextThemeWrapper win.setTitleColor(color); } } - } - if (mActionBar != null) { - mActionBar.setTitle(title); + if (mActionBar != null) { + mActionBar.setWindowTitle(title); + } } } diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index b86621f..ffb9c95 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -67,6 +67,8 @@ public class ActivityManager { private static String TAG = "ActivityManager"; private static boolean localLOGV = false; + private static int gMaxRecentTasks = -1; + private final Context mContext; private final Handler mHandler; @@ -193,13 +195,6 @@ public class ActivityManager { public static final int START_FLAG_OPENGL_TRACES = 1<<2; /** - * Flag for IActivityManaqer.startActivity: if the app is being - * launched for profiling, automatically stop the profiler once done. - * @hide - */ - public static final int START_FLAG_AUTO_STOP_PROFILER = 1<<3; - - /** * Result for IActivityManaqer.broadcastIntent: success! * @hide */ @@ -449,7 +444,7 @@ public class ActivityManager { // Really brain dead right now -- just take this from the configured // vm heap size, and assume it is in megabytes and thus ends with "m". String vmHeapSize = SystemProperties.get("dalvik.vm.heapsize", "16m"); - return Integer.parseInt(vmHeapSize.substring(0, vmHeapSize.length()-1)); + return Integer.parseInt(vmHeapSize.substring(0, vmHeapSize.length() - 1)); } /** @@ -480,6 +475,33 @@ public class ActivityManager { } /** + * Return the maximum number of recents entries that we will maintain and show. + * @hide + */ + static public int getMaxRecentTasksStatic() { + if (gMaxRecentTasks < 0) { + return gMaxRecentTasks = isLowRamDeviceStatic() ? 50 : 100; + } + return gMaxRecentTasks; + } + + /** + * Return the default limit on the number of recents that an app can make. + * @hide + */ + static public int getDefaultAppRecentsLimitStatic() { + return getMaxRecentTasksStatic() / 6; + } + + /** + * Return the maximum limit on the number of recents that an app can make. + * @hide + */ + static public int getMaxAppRecentsLimitStatic() { + return getMaxRecentTasksStatic() / 2; + } + + /** * Information you can set and retrieve about the current activity within the recent task list. */ public static class TaskDescription implements Parcelable { @@ -796,6 +818,12 @@ public class ActivityManager { public static final int RECENT_INCLUDE_PROFILES = 0x0004; /** + * Ignores all tasks that are on the home stack. + * @hide + */ + public static final int RECENT_IGNORE_HOME_STACK_TASKS = 0x0008; + + /** * <p></p>Return a list of the tasks that the user has recently launched, with * the most recent being first and older ones after in order. * @@ -985,7 +1013,7 @@ public class ActivityManager { ArrayList<AppTask> tasks = new ArrayList<AppTask>(); List<IAppTask> appTasks; try { - appTasks = ActivityManagerNative.getDefault().getAppTasks(); + appTasks = ActivityManagerNative.getDefault().getAppTasks(mContext.getPackageName()); } catch (RemoteException e) { // System dead, we will be dead too soon! return null; @@ -1185,13 +1213,13 @@ public class ActivityManager { public void writeToParcel(Parcel dest, int flags) { if (mainThumbnail != null) { dest.writeInt(1); - mainThumbnail.writeToParcel(dest, 0); + mainThumbnail.writeToParcel(dest, flags); } else { dest.writeInt(0); } if (thumbnailFileDescriptor != null) { dest.writeInt(1); - thumbnailFileDescriptor.writeToParcel(dest, 0); + thumbnailFileDescriptor.writeToParcel(dest, flags); } else { dest.writeInt(0); } @@ -2617,6 +2645,40 @@ public class ActivityManager { } /** + * Bring this task to the foreground. If it contains activities, they will be + * brought to the foreground with it and their instances re-created if needed. + * If it doesn't contain activities, the root activity of the task will be + * re-launched. + */ + public void moveToFront() { + try { + mAppTaskImpl.moveToFront(); + } catch (RemoteException e) { + Slog.e(TAG, "Invalid AppTask", e); + } + } + + /** + * Start an activity in this task. Brings the task to the foreground. If this task + * is not currently active (that is, its id < 0), then the activity being started + * needs to be started as a new task and the Intent's ComponentName must match the + * base ComponenentName of the recent task entry. Otherwise, the activity being + * started must <b>not</b> be launched as a new task -- not through explicit intent + * flags nor implicitly as the singleTask or singleInstance launch modes. + * + * <p>See {@link Activity#startActivity(android.content.Intent, android.os.Bundle) + * Activity.startActivity} for more information.</p> + * + * @param intent The Intent describing the new activity to be launched on the task. + * @param options Optional launch options. + */ + public void startActivity(Context context, Intent intent, Bundle options) { + ActivityThread thread = ActivityThread.currentActivityThread(); + thread.getInstrumentation().execStartActivityFromAppTask(context, + thread.getApplicationThread(), mAppTaskImpl, intent, options); + } + + /** * Modify the {@link Intent#FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS} flag in the root * Intent of this AppTask. * diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 5b81cc3..1f7e450 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -17,6 +17,7 @@ package android.app; import android.app.ActivityManager.StackInfo; +import android.app.ProfilerInfo; import android.content.ComponentName; import android.content.IIntentReceiver; import android.content.IIntentSender; @@ -132,14 +133,12 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM String resultWho = data.readString(); int requestCode = data.readInt(); int startFlags = data.readInt(); - String profileFile = data.readString(); - ParcelFileDescriptor profileFd = data.readInt() != 0 - ? data.readFileDescriptor() : null; + ProfilerInfo profilerInfo = data.readInt() != 0 + ? ProfilerInfo.CREATOR.createFromParcel(data) : null; Bundle options = data.readInt() != 0 ? Bundle.CREATOR.createFromParcel(data) : null; int result = startActivity(app, callingPackage, intent, resolvedType, - resultTo, resultWho, requestCode, startFlags, - profileFile, profileFd, options); + resultTo, resultWho, requestCode, startFlags, profilerInfo, options); reply.writeNoException(); reply.writeInt(result); return true; @@ -157,15 +156,13 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM String resultWho = data.readString(); int requestCode = data.readInt(); int startFlags = data.readInt(); - String profileFile = data.readString(); - ParcelFileDescriptor profileFd = data.readInt() != 0 - ? ParcelFileDescriptor.CREATOR.createFromParcel(data) : null; + ProfilerInfo profilerInfo = data.readInt() != 0 + ? ProfilerInfo.CREATOR.createFromParcel(data) : null; Bundle options = data.readInt() != 0 ? Bundle.CREATOR.createFromParcel(data) : null; int userId = data.readInt(); int result = startActivityAsUser(app, callingPackage, intent, resolvedType, - resultTo, resultWho, requestCode, startFlags, - profileFile, profileFd, options, userId); + resultTo, resultWho, requestCode, startFlags, profilerInfo, options, userId); reply.writeNoException(); reply.writeInt(result); return true; @@ -183,14 +180,12 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM String resultWho = data.readString(); int requestCode = data.readInt(); int startFlags = data.readInt(); - String profileFile = data.readString(); - ParcelFileDescriptor profileFd = data.readInt() != 0 - ? data.readFileDescriptor() : null; + ProfilerInfo profilerInfo = data.readInt() != 0 + ? ProfilerInfo.CREATOR.createFromParcel(data) : null; Bundle options = data.readInt() != 0 ? Bundle.CREATOR.createFromParcel(data) : null; int result = startActivityAsCaller(app, callingPackage, intent, resolvedType, - resultTo, resultWho, requestCode, startFlags, - profileFile, profileFd, options); + resultTo, resultWho, requestCode, startFlags, profilerInfo, options); reply.writeNoException(); reply.writeInt(result); return true; @@ -208,15 +203,13 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM String resultWho = data.readString(); int requestCode = data.readInt(); int startFlags = data.readInt(); - String profileFile = data.readString(); - ParcelFileDescriptor profileFd = data.readInt() != 0 - ? ParcelFileDescriptor.CREATOR.createFromParcel(data) : null; + ProfilerInfo profilerInfo = data.readInt() != 0 + ? ProfilerInfo.CREATOR.createFromParcel(data) : null; Bundle options = data.readInt() != 0 ? Bundle.CREATOR.createFromParcel(data) : null; int userId = data.readInt(); WaitResult result = startActivityAndWait(app, callingPackage, intent, resolvedType, - resultTo, resultWho, requestCode, startFlags, - profileFile, profileFd, options, userId); + resultTo, resultWho, requestCode, startFlags, profilerInfo, options, userId); reply.writeNoException(); result.writeToParcel(reply, 0); return true; @@ -284,15 +277,13 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM IVoiceInteractor interactor = IVoiceInteractor.Stub.asInterface( data.readStrongBinder()); int startFlags = data.readInt(); - String profileFile = data.readString(); - ParcelFileDescriptor profileFd = data.readInt() != 0 - ? ParcelFileDescriptor.CREATOR.createFromParcel(data) : null; + ProfilerInfo profilerInfo = data.readInt() != 0 + ? ProfilerInfo.CREATOR.createFromParcel(data) : null; Bundle options = data.readInt() != 0 ? Bundle.CREATOR.createFromParcel(data) : null; int userId = data.readInt(); - int result = startVoiceActivity(callingPackage, callingPid, callingUid, - intent, resolvedType, session, interactor, startFlags, - profileFile, profileFd, options, userId); + int result = startVoiceActivity(callingPackage, callingPid, callingUid, intent, + resolvedType, session, interactor, startFlags, profilerInfo, options, userId); reply.writeNoException(); reply.writeInt(result); return true; @@ -365,6 +356,23 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } + case RELEASE_ACTIVITY_INSTANCE_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IBinder token = data.readStrongBinder(); + boolean res = releaseActivityInstance(token); + reply.writeNoException(); + reply.writeInt(res ? 1 : 0); + return true; + } + + case RELEASE_SOME_ACTIVITIES_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IApplicationThread app = ApplicationThreadNative.asInterface(data.readStrongBinder()); + releaseSomeActivities(app); + reply.writeNoException(); + return true; + } + case WILL_ACTIVITY_BE_VISIBLE_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder token = data.readStrongBinder(); @@ -554,7 +562,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM case GET_APP_TASKS_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); - List<IAppTask> list = getAppTasks(); + String callingPackage = data.readString(); + List<IAppTask> list = getAppTasks(callingPackage); reply.writeNoException(); int N = list != null ? list.size() : -1; reply.writeInt(N); @@ -1383,8 +1392,9 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM data.enforceInterface(IActivityManager.descriptor); IBinder app = data.readStrongBinder(); String tag = data.readString(); + boolean system = data.readInt() != 0; ApplicationErrorReport.CrashInfo ci = new ApplicationErrorReport.CrashInfo(data); - boolean res = handleApplicationWtf(app, tag, ci); + boolean res = handleApplicationWtf(app, tag, system, ci); reply.writeNoException(); reply.writeInt(res ? 1 : 0); return true; @@ -1450,22 +1460,21 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM config.writeToParcel(reply, 0); return true; } - + case PROFILE_CONTROL_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); String process = data.readString(); int userId = data.readInt(); boolean start = data.readInt() != 0; int profileType = data.readInt(); - String path = data.readString(); - ParcelFileDescriptor fd = data.readInt() != 0 - ? ParcelFileDescriptor.CREATOR.createFromParcel(data) : null; - boolean res = profileControl(process, userId, start, path, fd, profileType); + ProfilerInfo profilerInfo = data.readInt() != 0 + ? ProfilerInfo.CREATOR.createFromParcel(data) : null; + boolean res = profileControl(process, userId, start, profilerInfo, profileType); reply.writeNoException(); reply.writeInt(res ? 1 : 0); return true; } - + case SHUTDOWN_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); boolean res = shutdown(data.readInt()); @@ -2325,8 +2334,7 @@ class ActivityManagerProxy implements IActivityManager public int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, - int startFlags, String profileFile, - ParcelFileDescriptor profileFd, Bundle options) throws RemoteException { + int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); @@ -2338,10 +2346,9 @@ class ActivityManagerProxy implements IActivityManager data.writeString(resultWho); data.writeInt(requestCode); data.writeInt(startFlags); - data.writeString(profileFile); - if (profileFd != null) { + if (profilerInfo != null) { data.writeInt(1); - profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); + profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } else { data.writeInt(0); } @@ -2361,8 +2368,8 @@ class ActivityManagerProxy implements IActivityManager public int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, - int startFlags, String profileFile, - ParcelFileDescriptor profileFd, Bundle options, int userId) throws RemoteException { + int startFlags, ProfilerInfo profilerInfo, Bundle options, + int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); @@ -2374,10 +2381,9 @@ class ActivityManagerProxy implements IActivityManager data.writeString(resultWho); data.writeInt(requestCode); data.writeInt(startFlags); - data.writeString(profileFile); - if (profileFd != null) { + if (profilerInfo != null) { data.writeInt(1); - profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); + profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } else { data.writeInt(0); } @@ -2397,8 +2403,7 @@ class ActivityManagerProxy implements IActivityManager } public int startActivityAsCaller(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, - int startFlags, String profileFile, - ParcelFileDescriptor profileFd, Bundle options) throws RemoteException { + int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); @@ -2410,10 +2415,9 @@ class ActivityManagerProxy implements IActivityManager data.writeString(resultWho); data.writeInt(requestCode); data.writeInt(startFlags); - data.writeString(profileFile); - if (profileFd != null) { + if (profilerInfo != null) { data.writeInt(1); - profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); + profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } else { data.writeInt(0); } @@ -2432,8 +2436,8 @@ class ActivityManagerProxy implements IActivityManager } public WaitResult startActivityAndWait(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, - int requestCode, int startFlags, String profileFile, - ParcelFileDescriptor profileFd, Bundle options, int userId) throws RemoteException { + int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options, + int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); @@ -2445,10 +2449,9 @@ class ActivityManagerProxy implements IActivityManager data.writeString(resultWho); data.writeInt(requestCode); data.writeInt(startFlags); - data.writeString(profileFile); - if (profileFd != null) { + if (profilerInfo != null) { data.writeInt(1); - profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); + profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } else { data.writeInt(0); } @@ -2532,8 +2535,8 @@ class ActivityManagerProxy implements IActivityManager } public int startVoiceActivity(String callingPackage, int callingPid, int callingUid, Intent intent, String resolvedType, IVoiceInteractionSession session, - IVoiceInteractor interactor, int startFlags, String profileFile, - ParcelFileDescriptor profileFd, Bundle options, int userId) throws RemoteException { + IVoiceInteractor interactor, int startFlags, ProfilerInfo profilerInfo, + Bundle options, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); @@ -2545,10 +2548,9 @@ class ActivityManagerProxy implements IActivityManager data.writeStrongBinder(session.asBinder()); data.writeStrongBinder(interactor.asBinder()); data.writeInt(startFlags); - data.writeString(profileFile); - if (profileFd != null) { + if (profilerInfo != null) { data.writeInt(1); - profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); + profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } else { data.writeInt(0); } @@ -2660,6 +2662,28 @@ class ActivityManagerProxy implements IActivityManager data.recycle(); reply.recycle(); } + public boolean releaseActivityInstance(IBinder token) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(token); + mRemote.transact(RELEASE_ACTIVITY_INSTANCE_TRANSACTION, data, reply, 0); + reply.readException(); + boolean res = reply.readInt() != 0; + data.recycle(); + reply.recycle(); + return res; + } + public void releaseSomeActivities(IApplicationThread app) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(app.asBinder()); + mRemote.transact(RELEASE_SOME_ACTIVITIES_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } public boolean willActivityBeVisible(IBinder token) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); @@ -2880,10 +2904,11 @@ class ActivityManagerProxy implements IActivityManager reply.recycle(); return res; } - public List<IAppTask> getAppTasks() throws RemoteException { + public List<IAppTask> getAppTasks(String callingPackage) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); + data.writeString(callingPackage); mRemote.transact(GET_APP_TASKS_TRANSACTION, data, reply, 0); reply.readException(); ArrayList<IAppTask> list = null; @@ -4045,7 +4070,7 @@ class ActivityManagerProxy implements IActivityManager data.recycle(); } - public boolean handleApplicationWtf(IBinder app, String tag, + public boolean handleApplicationWtf(IBinder app, String tag, boolean system, ApplicationErrorReport.CrashInfo crashInfo) throws RemoteException { Parcel data = Parcel.obtain(); @@ -4053,6 +4078,7 @@ class ActivityManagerProxy implements IActivityManager data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(app); data.writeString(tag); + data.writeInt(system ? 1 : 0); crashInfo.writeToParcel(data, 0); mRemote.transact(HANDLE_APPLICATION_WTF_TRANSACTION, data, reply, 0); reply.readException(); @@ -4148,9 +4174,9 @@ class ActivityManagerProxy implements IActivityManager data.recycle(); return res; } - + public boolean profileControl(String process, int userId, boolean start, - String path, ParcelFileDescriptor fd, int profileType) throws RemoteException + ProfilerInfo profilerInfo, int profileType) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); @@ -4159,10 +4185,9 @@ class ActivityManagerProxy implements IActivityManager data.writeInt(userId); data.writeInt(start ? 1 : 0); data.writeInt(profileType); - data.writeString(path); - if (fd != null) { + if (profilerInfo != null) { data.writeInt(1); - fd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); + profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } else { data.writeInt(0); } @@ -4173,7 +4198,7 @@ class ActivityManagerProxy implements IActivityManager data.recycle(); return res; } - + public boolean shutdown(int timeout) throws RemoteException { Parcel data = Parcel.obtain(); diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index 4c02314..9dd4605 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -128,6 +128,10 @@ public class ActivityOptions { public static final int ANIM_DEFAULT = 6; /** @hide */ public static final int ANIM_LAUNCH_TASK_BEHIND = 7; + /** @hide */ + public static final int ANIM_THUMBNAIL_ASPECT_SCALE_UP = 8; + /** @hide */ + public static final int ANIM_THUMBNAIL_ASPECT_SCALE_DOWN = 9; private String mPackageName; private int mAnimationType = ANIM_NONE; @@ -338,6 +342,67 @@ public class ActivityOptions { } /** + * Create an ActivityOptions specifying an animation where the new activity + * window and a thumbnail is aspect-scaled to a new location. + * + * @param source The View that this thumbnail is animating from. This + * defines the coordinate space for <var>startX</var> and <var>startY</var>. + * @param thumbnail The bitmap that will be shown as the initial thumbnail + * of the animation. + * @param startX The x starting location of the bitmap, relative to <var>source</var>. + * @param startY The y starting location of the bitmap, relative to <var>source</var>. + * @param listener Optional OnAnimationStartedListener to find out when the + * requested animation has started running. If for some reason the animation + * is not executed, the callback will happen immediately. + * @return Returns a new ActivityOptions object that you can use to + * supply these options as the options Bundle when starting an activity. + * @hide + */ + public static ActivityOptions makeThumbnailAspectScaleUpAnimation(View source, + Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) { + return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY, listener, + true); + } + + /** + * Create an ActivityOptions specifying an animation where the new activity + * window and a thumbnail is aspect-scaled to a new location. + * + * @param source The View that this thumbnail is animating to. This + * defines the coordinate space for <var>startX</var> and <var>startY</var>. + * @param thumbnail The bitmap that will be shown as the final thumbnail + * of the animation. + * @param startX The x end location of the bitmap, relative to <var>source</var>. + * @param startY The y end location of the bitmap, relative to <var>source</var>. + * @param listener Optional OnAnimationStartedListener to find out when the + * requested animation has started running. If for some reason the animation + * is not executed, the callback will happen immediately. + * @return Returns a new ActivityOptions object that you can use to + * supply these options as the options Bundle when starting an activity. + * @hide + */ + public static ActivityOptions makeThumbnailAspectScaleDownAnimation(View source, + Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) { + return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY, listener, + false); + } + + private static ActivityOptions makeAspectScaledThumbnailAnimation(View source, Bitmap thumbnail, + int startX, int startY, OnAnimationStartedListener listener, boolean scaleUp) { + ActivityOptions opts = new ActivityOptions(); + opts.mPackageName = source.getContext().getPackageName(); + opts.mAnimationType = scaleUp ? ANIM_THUMBNAIL_ASPECT_SCALE_UP : + ANIM_THUMBNAIL_ASPECT_SCALE_DOWN; + opts.mThumbnail = thumbnail; + int[] pts = new int[2]; + source.getLocationOnScreen(pts); + opts.mStartX = pts[0] + startX; + opts.mStartY = pts[1] + startY; + opts.setOnAnimationStartedListener(source.getHandler(), listener); + return opts; + } + + /** * Create an ActivityOptions to transition between Activities using cross-Activity scene * animations. This method carries the position of one shared element to the started Activity. * The position of <code>sharedElement</code> will be used as the epicenter for the @@ -444,12 +509,17 @@ public class ActivityOptions { * android.R.styleable#AndroidManifestActivity_launchMode launchMode} values of * <code>singleInstance</code> or <code>singleTask</code>. */ - public static ActivityOptions makeLaunchTaskBehindAnimation() { + public static ActivityOptions makeTaskLaunchBehind() { final ActivityOptions opts = new ActivityOptions(); opts.mAnimationType = ANIM_LAUNCH_TASK_BEHIND; return opts; } + @Deprecated + public static ActivityOptions makeLaunchTaskBehindAnimation() { + return makeTaskLaunchBehind(); + } + /** @hide */ public boolean getLaunchTaskBehind() { return mAnimationType == ANIM_LAUNCH_TASK_BEHIND; @@ -479,7 +549,9 @@ public class ActivityOptions { case ANIM_THUMBNAIL_SCALE_UP: case ANIM_THUMBNAIL_SCALE_DOWN: - mThumbnail = (Bitmap)opts.getParcelable(KEY_ANIM_THUMBNAIL); + case ANIM_THUMBNAIL_ASPECT_SCALE_UP: + case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN: + mThumbnail = (Bitmap) opts.getParcelable(KEY_ANIM_THUMBNAIL); mStartX = opts.getInt(KEY_ANIM_START_X, 0); mStartY = opts.getInt(KEY_ANIM_START_Y, 0); mAnimationStartedListener = IRemoteCallback.Stub.asInterface( @@ -630,6 +702,8 @@ public class ActivityOptions { break; case ANIM_THUMBNAIL_SCALE_UP: case ANIM_THUMBNAIL_SCALE_DOWN: + case ANIM_THUMBNAIL_ASPECT_SCALE_UP: + case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN: mThumbnail = otherOptions.mThumbnail; mStartX = otherOptions.mStartX; mStartY = otherOptions.mStartY; @@ -686,6 +760,8 @@ public class ActivityOptions { break; case ANIM_THUMBNAIL_SCALE_UP: case ANIM_THUMBNAIL_SCALE_DOWN: + case ANIM_THUMBNAIL_ASPECT_SCALE_UP: + case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN: b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail); b.putInt(KEY_ANIM_START_X, mStartX); b.putInt(KEY_ANIM_START_Y, mStartY); diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 2136209..d70e5df 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -102,8 +102,6 @@ import com.android.org.conscrypt.OpenSSLSocketImpl; import com.android.org.conscrypt.TrustedCertificateStore; import com.google.android.collect.Lists; -import dalvik.system.VMRuntime; - import java.io.File; import java.io.FileDescriptor; import java.io.FileOutputStream; @@ -126,6 +124,7 @@ import libcore.io.EventLogger; import libcore.io.IoUtils; import dalvik.system.CloseGuard; +import dalvik.system.VMDebug; import dalvik.system.VMRuntime; final class RemoteServiceException extends AndroidRuntimeException { @@ -201,6 +200,7 @@ public final class ActivityThread { String mInstrumentedLibDir = null; boolean mSystemThread = false; boolean mJitEnabled = false; + boolean mSomeActivitiesChanged = false; // These can be accessed by multiple threads; mPackages is the lock. // XXX For now we keep around information about all packages we have @@ -283,9 +283,7 @@ public final class ActivityThread { Configuration createdConfig; ActivityClientRecord nextIdle; - String profileFile; - ParcelFileDescriptor profileFd; - boolean autoStopProfiler; + ProfilerInfo profilerInfo; ActivityInfo activityInfo; CompatibilityInfo compatInfo; @@ -437,9 +435,7 @@ public final class ActivityThread { CompatibilityInfo compatInfo; /** Initial values for {@link Profiler}. */ - String initProfileFile; - ParcelFileDescriptor initProfileFd; - boolean initAutoStopProfiler; + ProfilerInfo initProfilerInfo; public String toString() { return "AppBindData{appInfo=" + appInfo + "}"; @@ -449,10 +445,12 @@ public final class ActivityThread { static final class Profiler { String profileFile; ParcelFileDescriptor profileFd; + int samplingInterval; boolean autoStopProfiler; boolean profiling; boolean handlingProfiling; - public void setProfiler(String file, ParcelFileDescriptor fd) { + public void setProfiler(ProfilerInfo profilerInfo) { + ParcelFileDescriptor fd = profilerInfo.profileFd; if (profiling) { if (fd != null) { try { @@ -470,16 +468,18 @@ public final class ActivityThread { // Ignore } } - profileFile = file; + profileFile = profilerInfo.profileFile; profileFd = fd; + samplingInterval = profilerInfo.samplingInterval; + autoStopProfiler = profilerInfo.autoStopProfiler; } public void startProfiling() { if (profileFd == null || profiling) { return; } try { - Debug.startMethodTracing(profileFile, profileFd.getFileDescriptor(), - 8 * 1024 * 1024, 0); + VMDebug.startMethodTracing(profileFile, profileFd.getFileDescriptor(), + 8 * 1024 * 1024, 0, samplingInterval != 0, samplingInterval); profiling = true; } catch (RuntimeException e) { Slog.w(TAG, "Profiling failed on path " + profileFile); @@ -528,11 +528,6 @@ public final class ActivityThread { String who; } - static final class ProfilerControlData { - String path; - ParcelFileDescriptor fd; - } - static final class DumpHeapData { String path; ParcelFileDescriptor fd; @@ -613,7 +608,7 @@ public final class ActivityThread { IVoiceInteractor voiceInteractor, int procState, Bundle state, PersistableBundle persistentState, List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, boolean notResumed, boolean isForward, - String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) { + ProfilerInfo profilerInfo) { updateProcessState(procState, false); @@ -634,9 +629,7 @@ public final class ActivityThread { r.startsNotResumed = notResumed; r.isForward = isForward; - r.profileFile = profileName; - r.profileFd = profileFd; - r.autoStopProfiler = autoStopProfiler; + r.profilerInfo = profilerInfo; updatePendingConfiguration(curConfig); @@ -743,11 +736,10 @@ public final class ActivityThread { sendMessage(H.STOP_SERVICE, token); } - public final void bindApplication(String processName, - ApplicationInfo appInfo, List<ProviderInfo> providers, - ComponentName instrumentationName, String profileFile, - ParcelFileDescriptor profileFd, boolean autoStopProfiler, - Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher, + public final void bindApplication(String processName, ApplicationInfo appInfo, + List<ProviderInfo> providers, ComponentName instrumentationName, + ProfilerInfo profilerInfo, Bundle instrumentationArgs, + IInstrumentationWatcher instrumentationWatcher, IUiAutomationConnection instrumentationUiConnection, int debugMode, boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent, Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services, @@ -811,9 +803,7 @@ public final class ActivityThread { data.persistent = persistent; data.config = config; data.compatInfo = compatInfo; - data.initProfileFile = profileFile; - data.initProfileFd = profileFd; - data.initAutoStopProfiler = false; + data.initProfilerInfo = profilerInfo; sendMessage(H.BIND_APPLICATION, data); } @@ -879,12 +869,8 @@ public final class ActivityThread { sendMessage(H.ACTIVITY_CONFIGURATION_CHANGED, token); } - public void profilerControl(boolean start, String path, ParcelFileDescriptor fd, - int profileType) { - ProfilerControlData pcd = new ProfilerControlData(); - pcd.path = path; - pcd.fd = fd; - sendMessage(H.PROFILER_CONTROL, pcd, start ? 1 : 0, profileType); + public void profilerControl(boolean start, ProfilerInfo profilerInfo, int profileType) { + sendMessage(H.PROFILER_CONTROL, profilerInfo, start ? 1 : 0, profileType); } public void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd) { @@ -1418,7 +1404,7 @@ public final class ActivityThread { Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; case PROFILER_CONTROL: - handleProfilerControl(msg.arg1 != 0, (ProfilerControlData)msg.obj, msg.arg2); + handleProfilerControl(msg.arg1 != 0, (ProfilerInfo)msg.obj, msg.arg2); break; case CREATE_BACKUP_AGENT: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupCreateAgent"); @@ -2353,11 +2339,11 @@ public final class ActivityThread { // If we are getting ready to gc after going to the background, well // we are back active so skip it. unscheduleGcIdler(); + mSomeActivitiesChanged = true; - if (r.profileFd != null) { - mProfiler.setProfiler(r.profileFile, r.profileFd); + if (r.profilerInfo != null) { + mProfiler.setProfiler(r.profilerInfo); mProfiler.startProfiling(); - mProfiler.autoStopProfiler = r.autoStopProfiler; } // Make sure we are running with the most recent config. @@ -2495,6 +2481,7 @@ public final class ActivityThread { public void handleCancelVisibleBehind(IBinder token) { ActivityClientRecord r = mActivities.get(token); if (r != null) { + mSomeActivitiesChanged = true; final Activity activity = r.activity; if (activity.mVisibleBehind) { activity.mCalled = false; @@ -2984,6 +2971,7 @@ public final class ActivityThread { // If we are getting ready to gc after going to the background, well // we are back active so skip it. unscheduleGcIdler(); + mSomeActivitiesChanged = true; // TODO Push resumeArgs into the activity for consideration ActivityClientRecord r = performResumeActivity(token, clearHide); @@ -3175,6 +3163,7 @@ public final class ActivityThread { ActivityManagerNative.getDefault().activityPaused(token, r.persistentState); } catch (RemoteException ex) { } + mSomeActivitiesChanged = true; } } @@ -3413,6 +3402,7 @@ public final class ActivityThread { info.state = r.state; info.persistentState = r.persistentState; mH.post(info); + mSomeActivitiesChanged = true; } final void performRestartActivity(IBinder token) { @@ -3446,6 +3436,7 @@ public final class ActivityThread { TAG, "Handle window " + r + " visibility: " + show); updateVisibility(r, show); } + mSomeActivitiesChanged = true; } private void handleSleeping(IBinder token, boolean sleeping) { @@ -3743,6 +3734,7 @@ public final class ActivityThread { // If the system process has died, it's game over for everyone. } } + mSomeActivitiesChanged = true; } public final void requestRelaunchActivity(IBinder token, @@ -3805,6 +3797,7 @@ public final class ActivityThread { // If we are getting ready to gc after going to the background, well // we are back active so skip it. unscheduleGcIdler(); + mSomeActivitiesChanged = true; Configuration changedConfig = null; int configChanges = 0; @@ -4107,24 +4100,25 @@ public final class ActivityThread { performConfigurationChanged(r.activity, mCompatConfiguration); freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(mCompatConfiguration)); + + mSomeActivitiesChanged = true; } - final void handleProfilerControl(boolean start, ProfilerControlData pcd, int profileType) { + final void handleProfilerControl(boolean start, ProfilerInfo profilerInfo, int profileType) { if (start) { try { switch (profileType) { - default: - mProfiler.setProfiler(pcd.path, pcd.fd); - mProfiler.autoStopProfiler = false; + default: + mProfiler.setProfiler(profilerInfo); mProfiler.startProfiling(); break; } } catch (RuntimeException e) { - Slog.w(TAG, "Profiling failed on path " + pcd.path + Slog.w(TAG, "Profiling failed on path " + profilerInfo.profileFile + " -- can the process access this path?"); } finally { try { - pcd.fd.close(); + profilerInfo.profileFd.close(); } catch (IOException e) { Slog.w(TAG, "Failure closing profile fd", e); } @@ -4256,9 +4250,12 @@ public final class ActivityThread { mCompatConfiguration = new Configuration(data.config); mProfiler = new Profiler(); - mProfiler.profileFile = data.initProfileFile; - mProfiler.profileFd = data.initProfileFd; - mProfiler.autoStopProfiler = data.initAutoStopProfiler; + if (data.initProfilerInfo != null) { + mProfiler.profileFile = data.initProfilerInfo.profileFile; + mProfiler.profileFd = data.initProfilerInfo.profileFd; + mProfiler.samplingInterval = data.initProfilerInfo.samplingInterval; + mProfiler.autoStopProfiler = data.initProfilerInfo.autoStopProfiler; + } // send up app name; do this *before* waiting for debugger Process.setArgV0(data.processName); @@ -4273,7 +4270,7 @@ public final class ActivityThread { HardwareRenderer.disable(false); } } - + if (mProfiler.profileFd != null) { mProfiler.startProfiling(); } @@ -5045,17 +5042,38 @@ public final class ActivityThread { android.ddm.DdmHandleAppName.setAppName("<pre-initialized>", UserHandle.myUserId()); RuntimeInit.setApplicationObject(mAppThread.asBinder()); - IActivityManager mgr = ActivityManagerNative.getDefault(); + final IActivityManager mgr = ActivityManagerNative.getDefault(); try { mgr.attachApplication(mAppThread); } catch (RemoteException ex) { // Ignore } + // Watch for getting close to heap limit. + BinderInternal.addGcWatcher(new Runnable() { + @Override public void run() { + if (!mSomeActivitiesChanged) { + return; + } + Runtime runtime = Runtime.getRuntime(); + long dalvikMax = runtime.maxMemory(); + long dalvikUsed = runtime.totalMemory() - runtime.freeMemory(); + if (dalvikUsed > ((3*dalvikMax)/4)) { + if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024) + + " total=" + (runtime.totalMemory()/1024) + + " used=" + (dalvikUsed/1024)); + mSomeActivitiesChanged = false; + try { + mgr.releaseSomeActivities(mAppThread); + } catch (RemoteException e) { + } + } + } + }); } else { // Don't set application object here -- if the system crashes, // we can't display an alert, we just want to die die die. android.ddm.DdmHandleAppName.setAppName("system_process", - UserHandle.myUserId()); + UserHandle.myUserId()); try { mInstrumentation = new Instrumentation(); ContextImpl context = ContextImpl.createAppContext( diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java index 52b69e1..63e8707 100644 --- a/core/java/android/app/ApplicationThreadNative.java +++ b/core/java/android/app/ApplicationThreadNative.java @@ -129,7 +129,7 @@ public abstract class ApplicationThreadNative extends Binder scheduleSendResult(b, ri); return true; } - + case SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); @@ -148,17 +148,13 @@ public abstract class ApplicationThreadNative extends Binder List<Intent> pi = data.createTypedArrayList(Intent.CREATOR); boolean notResumed = data.readInt() != 0; boolean isForward = data.readInt() != 0; - String profileName = data.readString(); - ParcelFileDescriptor profileFd = data.readInt() != 0 - ? ParcelFileDescriptor.CREATOR.createFromParcel(data) : null; - boolean autoStopProfiler = data.readInt() != 0; - scheduleLaunchActivity(intent, b, ident, info, curConfig, compatInfo, - voiceInteractor, procState, state, persistentState, - ri, pi, notResumed, isForward, profileName, profileFd, - autoStopProfiler); + ProfilerInfo profilerInfo = data.readInt() != 0 + ? ProfilerInfo.CREATOR.createFromParcel(data) : null; + scheduleLaunchActivity(intent, b, ident, info, curConfig, compatInfo, voiceInteractor, + procState, state, persistentState, ri, pi, notResumed, isForward, profilerInfo); return true; } - + case SCHEDULE_RELAUNCH_ACTIVITY_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); @@ -274,10 +270,8 @@ public abstract class ApplicationThreadNative extends Binder data.createTypedArrayList(ProviderInfo.CREATOR); ComponentName testName = (data.readInt() != 0) ? new ComponentName(data) : null; - String profileName = data.readString(); - ParcelFileDescriptor profileFd = data.readInt() != 0 - ? ParcelFileDescriptor.CREATOR.createFromParcel(data) : null; - boolean autoStopProfiler = data.readInt() != 0; + ProfilerInfo profilerInfo = data.readInt() != 0 + ? ProfilerInfo.CREATOR.createFromParcel(data) : null; Bundle testArgs = data.readBundle(); IBinder binder = data.readStrongBinder(); IInstrumentationWatcher testWatcher = IInstrumentationWatcher.Stub.asInterface(binder); @@ -292,11 +286,9 @@ public abstract class ApplicationThreadNative extends Binder CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data); HashMap<String, IBinder> services = data.readHashMap(null); Bundle coreSettings = data.readBundle(); - bindApplication(packageName, info, - providers, testName, profileName, profileFd, autoStopProfiler, - testArgs, testWatcher, uiAutomationConnection, testMode, - openGlTrace, restrictedBackupMode, persistent, config, compatInfo, - services, coreSettings); + bindApplication(packageName, info, providers, testName, profilerInfo, testArgs, + testWatcher, uiAutomationConnection, testMode, openGlTrace, + restrictedBackupMode, persistent, config, compatInfo, services, coreSettings); return true; } @@ -403,7 +395,7 @@ public abstract class ApplicationThreadNative extends Binder scheduleLowMemory(); return true; } - + case SCHEDULE_ACTIVITY_CONFIGURATION_CHANGED_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); @@ -411,19 +403,18 @@ public abstract class ApplicationThreadNative extends Binder scheduleActivityConfigurationChanged(b); return true; } - + case PROFILER_CONTROL_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); boolean start = data.readInt() != 0; int profileType = data.readInt(); - String path = data.readString(); - ParcelFileDescriptor fd = data.readInt() != 0 - ? ParcelFileDescriptor.CREATOR.createFromParcel(data) : null; - profilerControl(start, path, fd, profileType); + ProfilerInfo profilerInfo = data.readInt() != 0 + ? ProfilerInfo.CREATOR.createFromParcel(data) : null; + profilerControl(start, profilerInfo, profileType); return true; } - + case SET_SCHEDULING_GROUP_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); @@ -774,8 +765,7 @@ class ApplicationThreadProxy implements IApplicationThread { IVoiceInteractor voiceInteractor, int procState, Bundle state, PersistableBundle persistentState, List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, boolean notResumed, boolean isForward, - String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) - throws RemoteException { + ProfilerInfo profilerInfo) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); intent.writeToParcel(data, 0); @@ -792,14 +782,12 @@ class ApplicationThreadProxy implements IApplicationThread { data.writeTypedList(pendingNewIntents); data.writeInt(notResumed ? 1 : 0); data.writeInt(isForward ? 1 : 0); - data.writeString(profileName); - if (profileFd != null) { + if (profilerInfo != null) { data.writeInt(1); - profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); + profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } else { data.writeInt(0); } - data.writeInt(autoStopProfiler ? 1 : 0); mRemote.transact(SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); data.recycle(); @@ -959,9 +947,8 @@ class ApplicationThreadProxy implements IApplicationThread { } public final void bindApplication(String packageName, ApplicationInfo info, - List<ProviderInfo> providers, ComponentName testName, String profileName, - ParcelFileDescriptor profileFd, boolean autoStopProfiler, Bundle testArgs, - IInstrumentationWatcher testWatcher, + List<ProviderInfo> providers, ComponentName testName, ProfilerInfo profilerInfo, + Bundle testArgs, IInstrumentationWatcher testWatcher, IUiAutomationConnection uiAutomationConnection, int debugMode, boolean openGlTrace, boolean restrictedBackupMode, boolean persistent, Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services, @@ -977,14 +964,12 @@ class ApplicationThreadProxy implements IApplicationThread { data.writeInt(1); testName.writeToParcel(data, 0); } - data.writeString(profileName); - if (profileFd != null) { + if (profilerInfo != null) { data.writeInt(1); - profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); + profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } else { data.writeInt(0); } - data.writeInt(autoStopProfiler ? 1 : 0); data.writeBundle(testArgs); data.writeStrongInterface(testWatcher); data.writeStrongInterface(uiAutomationConnection); @@ -1111,7 +1096,7 @@ class ApplicationThreadProxy implements IApplicationThread { IBinder.FLAG_ONEWAY); data.recycle(); } - + public final void scheduleActivityConfigurationChanged( IBinder token) throws RemoteException { Parcel data = Parcel.obtain(); @@ -1121,17 +1106,16 @@ class ApplicationThreadProxy implements IApplicationThread { IBinder.FLAG_ONEWAY); data.recycle(); } - - public void profilerControl(boolean start, String path, - ParcelFileDescriptor fd, int profileType) throws RemoteException { + + public void profilerControl(boolean start, ProfilerInfo profilerInfo, int profileType) + throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); data.writeInt(start ? 1 : 0); data.writeInt(profileType); - data.writeString(path); - if (fd != null) { + if (profilerInfo != null) { data.writeInt(1); - fd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); + profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } else { data.writeInt(0); } @@ -1139,7 +1123,7 @@ class ApplicationThreadProxy implements IApplicationThread { IBinder.FLAG_ONEWAY); data.recycle(); } - + public void setSchedulingGroup(int group) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); @@ -1148,7 +1132,7 @@ class ApplicationThreadProxy implements IApplicationThread { IBinder.FLAG_ONEWAY); data.recycle(); } - + public void dispatchPackageBroadcast(int cmd, String[] packages) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); @@ -1157,9 +1141,8 @@ class ApplicationThreadProxy implements IApplicationThread { mRemote.transact(DISPATCH_PACKAGE_BROADCAST_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); data.recycle(); - } - + public void scheduleCrash(String msg) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); @@ -1167,7 +1150,6 @@ class ApplicationThreadProxy implements IApplicationThread { mRemote.transact(SCHEDULE_CRASH_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); data.recycle(); - } public void dumpHeap(boolean managed, String path, diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index da343ac..91a0aed 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -92,8 +92,6 @@ import android.net.nsd.INsdManager; import android.net.nsd.NsdManager; import android.net.wifi.IWifiManager; import android.net.wifi.WifiManager; -import android.net.wifi.passpoint.IWifiPasspointManager; -import android.net.wifi.passpoint.WifiPasspointManager; import android.net.wifi.p2p.IWifiP2pManager; import android.net.wifi.p2p.WifiP2pManager; import android.net.wifi.IWifiScanner; @@ -122,7 +120,6 @@ import android.os.SystemVibrator; import android.os.UserManager; import android.os.storage.IMountService; import android.os.storage.StorageManager; -import android.phone.PhoneManager; import android.print.IPrintManager; import android.print.PrintManager; import android.service.fingerprint.IFingerprintService; @@ -570,11 +567,6 @@ class ContextImpl extends Context { return new TelecommManager(ctx.getOuterContext()); }}); - registerService(PHONE_SERVICE, new ServiceFetcher() { - public Object createService(ContextImpl ctx) { - return new PhoneManager(ctx.getOuterContext()); - }}); - registerService(UI_MODE_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { return new UiModeManager(); @@ -606,13 +598,6 @@ class ContextImpl extends Context { return new WifiManager(ctx.getOuterContext(), service); }}); - registerService(WIFI_PASSPOINT_SERVICE, new ServiceFetcher() { - public Object createService(ContextImpl ctx) { - IBinder b = ServiceManager.getService(WIFI_PASSPOINT_SERVICE); - IWifiPasspointManager service = IWifiPasspointManager.Stub.asInterface(b); - return new WifiPasspointManager(ctx.getOuterContext(), service); - }}); - registerService(WIFI_P2P_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { IBinder b = ServiceManager.getService(WIFI_P2P_SERVICE); @@ -1262,7 +1247,7 @@ class ContextImpl extends Context { ActivityManagerNative.getDefault().startActivityAsUser( mMainThread.getApplicationThread(), getBasePackageName(), intent, intent.resolveTypeIfNeeded(getContentResolver()), - null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, null, options, + null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, options, user.getIdentifier()); } catch (RemoteException re) { } diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 1664408..99428e8 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -61,22 +61,19 @@ import java.util.List; * {@hide} */ public interface IActivityManager extends IInterface { - public int startActivity(IApplicationThread caller, String callingPackage, - Intent intent, String resolvedType, IBinder resultTo, String resultWho, - int requestCode, int flags, String profileFile, - ParcelFileDescriptor profileFd, Bundle options) throws RemoteException; - public int startActivityAsUser(IApplicationThread caller, String callingPackage, - Intent intent, String resolvedType, IBinder resultTo, String resultWho, - int requestCode, int flags, String profileFile, - ParcelFileDescriptor profileFd, Bundle options, int userId) throws RemoteException; + public int startActivity(IApplicationThread caller, String callingPackage, Intent intent, + String resolvedType, IBinder resultTo, String resultWho, int requestCode, int flags, + ProfilerInfo profilerInfo, Bundle options) throws RemoteException; + public int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent, + String resolvedType, IBinder resultTo, String resultWho, int requestCode, int flags, + ProfilerInfo profilerInfo, Bundle options, int userId) throws RemoteException; public int startActivityAsCaller(IApplicationThread caller, String callingPackage, - Intent intent, String resolvedType, IBinder resultTo, String resultWho, - int requestCode, int flags, String profileFile, - ParcelFileDescriptor profileFd, Bundle options) throws RemoteException; + Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, + int flags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException; public WaitResult startActivityAndWait(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, - int requestCode, int flags, String profileFile, - ParcelFileDescriptor profileFd, Bundle options, int userId) throws RemoteException; + int requestCode, int flags, ProfilerInfo profilerInfo, Bundle options, + int userId) throws RemoteException; public int startActivityWithConfig(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, Configuration newConfig, @@ -87,8 +84,8 @@ public interface IActivityManager extends IInterface { int flagsMask, int flagsValues, Bundle options) throws RemoteException; public int startVoiceActivity(String callingPackage, int callingPid, int callingUid, Intent intent, String resolvedType, IVoiceInteractionSession session, - IVoiceInteractor interactor, int flags, String profileFile, - ParcelFileDescriptor profileFd, Bundle options, int userId) throws RemoteException; + IVoiceInteractor interactor, int flags, ProfilerInfo profilerInfo, Bundle options, + int userId) throws RemoteException; public boolean startNextMatchingActivity(IBinder callingActivity, Intent intent, Bundle options) throws RemoteException; public int startActivityFromRecents(int taskId, Bundle options) throws RemoteException; @@ -97,6 +94,8 @@ public interface IActivityManager extends IInterface { public void finishSubActivity(IBinder token, String resultWho, int requestCode) throws RemoteException; public boolean finishActivityAffinity(IBinder token) throws RemoteException; public void finishVoiceTask(IVoiceInteractionSession session) throws RemoteException; + public boolean releaseActivityInstance(IBinder token) throws RemoteException; + public void releaseSomeActivities(IApplicationThread app) throws RemoteException; public boolean willActivityBeVisible(IBinder token) throws RemoteException; public Intent registerReceiver(IApplicationThread caller, String callerPackage, IIntentReceiver receiver, IntentFilter filter, @@ -119,7 +118,7 @@ public interface IActivityManager extends IInterface { public void activityDestroyed(IBinder token) throws RemoteException; public String getCallingPackage(IBinder token) throws RemoteException; public ComponentName getCallingActivity(IBinder token) throws RemoteException; - public List<IAppTask> getAppTasks() throws RemoteException; + public List<IAppTask> getAppTasks(String callingPackage) throws RemoteException; public int addAppTask(IBinder activityToken, Intent intent, ActivityManager.TaskDescription description, Bitmap thumbnail) throws RemoteException; public Point getAppTaskThumbnailSize() throws RemoteException; @@ -267,7 +266,7 @@ public interface IActivityManager extends IInterface { // Special low-level communication with activity manager. public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) throws RemoteException; - public boolean handleApplicationWtf(IBinder app, String tag, + public boolean handleApplicationWtf(IBinder app, String tag, boolean system, ApplicationErrorReport.CrashInfo crashInfo) throws RemoteException; // A StrictMode violation to be handled. The violationMask is a @@ -294,13 +293,13 @@ public interface IActivityManager extends IInterface { throws RemoteException; // Get device configuration public ConfigurationInfo getDeviceConfigurationInfo() throws RemoteException; - + // Turn on/off profiling in a particular process. public boolean profileControl(String process, int userId, boolean start, - String path, ParcelFileDescriptor fd, int profileType) throws RemoteException; - + ProfilerInfo profilerInfo, int profileType) throws RemoteException; + public boolean shutdown(int timeout) throws RemoteException; - + public void stopAppSwitches() throws RemoteException; public void resumeAppSwitches() throws RemoteException; @@ -771,4 +770,6 @@ public interface IActivityManager extends IInterface { int START_ACTIVITY_AS_CALLER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+232; int ADD_APP_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+233; int GET_APP_TASK_THUMBNAIL_SIZE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+234; + int RELEASE_ACTIVITY_INSTANCE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+235; + int RELEASE_SOME_ACTIVITIES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+236; } diff --git a/core/java/android/app/IAppTask.aidl b/core/java/android/app/IAppTask.aidl index 4e38c36..37fead9 100644 --- a/core/java/android/app/IAppTask.aidl +++ b/core/java/android/app/IAppTask.aidl @@ -17,10 +17,15 @@ package android.app; import android.app.ActivityManager; +import android.content.Intent; +import android.os.Bundle; /** @hide */ interface IAppTask { void finishAndRemoveTask(); ActivityManager.RecentTaskInfo getTaskInfo(); + void moveToFront(); + int startActivity(IBinder whoThread, String callingPackage, + in Intent intent, String resolvedType, in Bundle options); void setExcludeFromRecents(boolean exclude); } diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java index 01b6fdf..a7546d9 100644 --- a/core/java/android/app/IApplicationThread.java +++ b/core/java/android/app/IApplicationThread.java @@ -62,8 +62,7 @@ public interface IApplicationThread extends IInterface { IVoiceInteractor voiceInteractor, int procState, Bundle state, PersistableBundle persistentState, List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, boolean notResumed, boolean isForward, - String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) - throws RemoteException; + ProfilerInfo profilerInfo) throws RemoteException; void scheduleRelaunchActivity(IBinder token, List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, int configChanges, boolean notResumed, Configuration config) throws RemoteException; @@ -94,10 +93,9 @@ public interface IApplicationThread extends IInterface { static final int DEBUG_ON = 1; static final int DEBUG_WAIT = 2; void bindApplication(String packageName, ApplicationInfo info, List<ProviderInfo> providers, - ComponentName testName, String profileName, ParcelFileDescriptor profileFd, - boolean autoStopProfiler, Bundle testArguments, IInstrumentationWatcher testWatcher, - IUiAutomationConnection uiAutomationConnection, int debugMode, - boolean openGlTrace, boolean restrictedBackupMode, boolean persistent, + ComponentName testName, ProfilerInfo profilerInfo, Bundle testArguments, + IInstrumentationWatcher testWatcher, IUiAutomationConnection uiAutomationConnection, + int debugMode, boolean openGlTrace, boolean restrictedBackupMode, boolean persistent, Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings) throws RemoteException; void scheduleExit() throws RemoteException; @@ -117,7 +115,7 @@ public interface IApplicationThread extends IInterface { boolean sticky, int sendingUser, int processState) throws RemoteException; void scheduleLowMemory() throws RemoteException; void scheduleActivityConfigurationChanged(IBinder token) throws RemoteException; - void profilerControl(boolean start, String path, ParcelFileDescriptor fd, int profileType) + void profilerControl(boolean start, ProfilerInfo profilerInfo, int profileType) throws RemoteException; void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd) throws RemoteException; diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl index 2b97c6b..07e9a94 100644 --- a/core/java/android/app/INotificationManager.aidl +++ b/core/java/android/app/INotificationManager.aidl @@ -58,7 +58,7 @@ interface INotificationManager void cancelNotificationFromListener(in INotificationListener token, String pkg, String tag, int id); void cancelNotificationsFromListener(in INotificationListener token, in String[] keys); - ParceledListSlice getActiveNotificationsFromListener(in INotificationListener token); + ParceledListSlice getActiveNotificationsFromListener(in INotificationListener token, in String[] keys); void requestHintsFromListener(in INotificationListener token, int hints); int getHintsFromListener(in INotificationListener token); @@ -71,4 +71,4 @@ interface INotificationManager oneway void setZenModeCondition(in Condition condition); oneway void setAutomaticZenModeConditions(in Uri[] conditionIds); Condition[] getAutomaticZenModeConditions(); -}
\ No newline at end of file +} diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index b28d7cc..ba3a234 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -1481,7 +1481,7 @@ public class Instrumentation { .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, - requestCode, 0, null, null, options); + requestCode, 0, null, options); checkStartActivityResult(result, intent); } catch (RemoteException e) { } @@ -1598,7 +1598,7 @@ public class Instrumentation { .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mWho : null, - requestCode, 0, null, null, options); + requestCode, 0, null, options); checkStartActivityResult(result, intent); } catch (RemoteException e) { } @@ -1658,7 +1658,7 @@ public class Instrumentation { .startActivityAsUser(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, - requestCode, 0, null, null, options, user.getIdentifier()); + requestCode, 0, null, options, user.getIdentifier()); checkStartActivityResult(result, intent); } catch (RemoteException e) { } @@ -1695,13 +1695,47 @@ public class Instrumentation { .startActivityAsCaller(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, - requestCode, 0, null, null, options); + requestCode, 0, null, options); checkStartActivityResult(result, intent); } catch (RemoteException e) { } return null; } + /** + * Special version! + * @hide + */ + public void execStartActivityFromAppTask( + Context who, IBinder contextThread, IAppTask appTask, + Intent intent, Bundle options) { + IApplicationThread whoThread = (IApplicationThread) contextThread; + if (mActivityMonitors != null) { + synchronized (mSync) { + final int N = mActivityMonitors.size(); + for (int i=0; i<N; i++) { + final ActivityMonitor am = mActivityMonitors.get(i); + if (am.match(who, null, intent)) { + am.mHits++; + if (am.isBlocking()) { + return; + } + break; + } + } + } + } + try { + intent.migrateExtraStreamToClipData(); + intent.prepareToLeaveProcess(); + int result = appTask.startActivity(whoThread.asBinder(), who.getBasePackageName(), + intent, intent.resolveTypeIfNeeded(who.getContentResolver()), options); + checkStartActivityResult(result, intent); + } catch (RemoteException e) { + } + return; + } + /*package*/ final void init(ActivityThread thread, Context instrContext, Context appContext, ComponentName component, IInstrumentationWatcher watcher, IUiAutomationConnection uiAutomationConnection) { diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index e0c7816..d143b86 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -51,8 +51,8 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.lang.ref.WeakReference; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.net.URL; import java.util.ArrayList; import java.util.Collections; @@ -594,55 +594,6 @@ public final class LoadedApk { return app; } - private void rewriteIntField(Field field, int packageId) throws IllegalAccessException { - int requiredModifiers = Modifier.STATIC | Modifier.PUBLIC; - int bannedModifiers = Modifier.FINAL; - - int mod = field.getModifiers(); - if ((mod & requiredModifiers) != requiredModifiers || - (mod & bannedModifiers) != 0) { - throw new IllegalArgumentException("Field " + field.getName() + - " is not rewritable"); - } - - if (field.getType() != int.class && field.getType() != Integer.class) { - throw new IllegalArgumentException("Field " + field.getName() + - " is not an integer"); - } - - try { - int resId = field.getInt(null); - field.setInt(null, (resId & 0x00ffffff) | (packageId << 24)); - } catch (IllegalAccessException e) { - // This should not occur (we check above if we can write to it) - throw new IllegalArgumentException(e); - } - } - - private void rewriteIntArrayField(Field field, int packageId) { - int requiredModifiers = Modifier.STATIC | Modifier.PUBLIC; - - if ((field.getModifiers() & requiredModifiers) != requiredModifiers) { - throw new IllegalArgumentException("Field " + field.getName() + - " is not rewritable"); - } - - if (field.getType() != int[].class) { - throw new IllegalArgumentException("Field " + field.getName() + - " is not an integer array"); - } - - try { - int[] array = (int[]) field.get(null); - for (int i = 0; i < array.length; i++) { - array[i] = (array[i] & 0x00ffffff) | (packageId << 24); - } - } catch (IllegalAccessException e) { - // This should not occur (we check above if we can write to it) - throw new IllegalArgumentException(e); - } - } - private void rewriteRValues(ClassLoader cl, String packageName, int id) { final Class<?> rClazz; try { @@ -650,35 +601,30 @@ public final class LoadedApk { } catch (ClassNotFoundException e) { // This is not necessarily an error, as some packages do not ship with resources // (or they do not need rewriting). - Log.i(TAG, "Could not find R class for package '" + packageName + "'"); + Log.i(TAG, "No resource references to update in package " + packageName); return; } + final Method callback; try { - Class<?>[] declaredClasses = rClazz.getDeclaredClasses(); - for (Class<?> clazz : declaredClasses) { - try { - if (clazz.getSimpleName().equals("styleable")) { - for (Field field : clazz.getDeclaredFields()) { - if (field.getType() == int[].class) { - rewriteIntArrayField(field, id); - } - } - - } else { - for (Field field : clazz.getDeclaredFields()) { - rewriteIntField(field, id); - } - } - } catch (Exception e) { - throw new IllegalArgumentException("Failed to rewrite R values for " + - clazz.getName(), e); - } - } + callback = rClazz.getMethod("onResourcesLoaded", int.class); + } catch (NoSuchMethodException e) { + // No rewriting to be done. + return; + } - } catch (Exception e) { - throw new IllegalArgumentException("Failed to rewrite R values", e); + Throwable cause; + try { + callback.invoke(null, id); + return; + } catch (IllegalAccessException e) { + cause = e; + } catch (InvocationTargetException e) { + cause = e.getCause(); } + + throw new RuntimeException("Failed to rewrite resource references for " + packageName, + cause); } public void removeContextRegistrations(Context context, diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index f7300aa..e1dc8bf 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -32,6 +32,7 @@ import android.media.AudioManager; import android.media.session.MediaSession; import android.net.Uri; import android.os.BadParcelableException; +import android.os.Build; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; @@ -1904,7 +1905,8 @@ public class Notification implements Parcelable mPriority = PRIORITY_DEFAULT; mPeople = new ArrayList<String>(); - mColorUtil = NotificationColorUtil.getInstance(); + mColorUtil = context.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.L ? + NotificationColorUtil.getInstance() : null; } /** @@ -2610,7 +2612,7 @@ public class Notification implements Parcelable if (mLargeIcon != null) { contentView.setImageViewBitmap(R.id.icon, mLargeIcon); - processLargeIcon(mLargeIcon, contentView); + processLargeLegacyIcon(mLargeIcon, contentView); contentView.setImageViewResource(R.id.right_icon, mSmallIcon); contentView.setViewVisibility(R.id.right_icon, View.VISIBLE); processSmallRightIcon(mSmallIcon, contentView); @@ -2813,13 +2815,10 @@ public class Notification implements Parcelable } private void processLegacyAction(Action action, RemoteViews button) { - if (isLegacy()) { - if (mColorUtil.isGrayscale(mContext, action.icon)) { - button.setTextViewCompoundDrawablesRelativeColorFilter(R.id.action0, 0, - mContext.getResources().getColor( - R.color.notification_action_legacy_color_filter), - PorterDuff.Mode.MULTIPLY); - } + if (!isLegacy() || mColorUtil.isGrayscale(mContext, action.icon)) { + button.setTextViewCompoundDrawablesRelativeColorFilter(R.id.action0, 0, + mContext.getResources().getColor(R.color.notification_action_color_filter), + PorterDuff.Mode.MULTIPLY); } } @@ -2845,8 +2844,8 @@ public class Notification implements Parcelable * if it's grayscale). */ // TODO: also check bounds, transparency, that sort of thing. - private void processLargeIcon(Bitmap largeIcon, RemoteViews contentView) { - if (!isLegacy() || mColorUtil.isGrayscale(largeIcon)) { + private void processLargeLegacyIcon(Bitmap largeIcon, RemoteViews contentView) { + if (isLegacy() && mColorUtil.isGrayscale(largeIcon)) { applyLargeIconBackground(contentView); } else { removeLargeIconBackground(contentView); diff --git a/core/java/android/app/ProfilerInfo.java b/core/java/android/app/ProfilerInfo.java new file mode 100644 index 0000000..cea7c3c --- /dev/null +++ b/core/java/android/app/ProfilerInfo.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2014 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.os.Parcel; +import android.os.Parcelable; +import android.os.ParcelFileDescriptor; + +/** + * System private API for passing profiler settings. + * + * {@hide} + */ +public class ProfilerInfo implements Parcelable { + + /* Name of profile output file. */ + public final String profileFile; + + /* File descriptor for profile output file, can be null. */ + public ParcelFileDescriptor profileFd; + + /* Indicates sample profiling when nonzero, interval in microseconds. */ + public final int samplingInterval; + + /* Automatically stop the profiler when the app goes idle. */ + public final boolean autoStopProfiler; + + public ProfilerInfo(String filename, ParcelFileDescriptor fd, int interval, boolean autoStop) { + profileFile = filename; + profileFd = fd; + samplingInterval = interval; + autoStopProfiler = autoStop; + } + + public int describeContents() { + if (profileFd != null) { + return profileFd.describeContents(); + } else { + return 0; + } + } + + public void writeToParcel(Parcel out, int flags) { + out.writeString(profileFile); + if (profileFd != null) { + out.writeInt(1); + profileFd.writeToParcel(out, flags); + } else { + out.writeInt(0); + } + out.writeInt(samplingInterval); + out.writeInt(autoStopProfiler ? 1 : 0); + } + + public static final Parcelable.Creator<ProfilerInfo> CREATOR = + new Parcelable.Creator<ProfilerInfo>() { + public ProfilerInfo createFromParcel(Parcel in) { + return new ProfilerInfo(in); + } + + public ProfilerInfo[] newArray(int size) { + return new ProfilerInfo[size]; + } + }; + + private ProfilerInfo(Parcel in) { + profileFile = in.readString(); + profileFd = in.readInt() != 0 ? ParcelFileDescriptor.CREATOR.createFromParcel(in) : null; + samplingInterval = in.readInt(); + autoStopProfiler = in.readInt() != 0; + } +} diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 41bbb87..a13bb3a 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -126,7 +126,7 @@ public class DevicePolicyManager { * message containing an Nfc record with MIME type {@link #MIME_TYPE_PROVISIONING_NFC}. */ public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME - = "android.app.extra.DEVICE_ADMIN_PACKAGE_NAME"; + = "android.app.extra.deviceAdminPackageName"; /** * A String extra holding the default name of the profile that is created during managed profile @@ -149,7 +149,7 @@ public class DevicePolicyManager { * It is usually used to avoid that the user has to enter their email address twice. */ public static final String EXTRA_PROVISIONING_EMAIL_ADDRESS - = "android.app.extra.MANAGED_PROFILE_EMAIL_ADDRESS"; + = "android.app.extra.ManagedProfileEmailAddress"; /** * A String extra holding the time zone {@link android.app.AlarmManager} that the device @@ -1374,7 +1374,7 @@ public class DevicePolicyManager { * @param admin The name of the admin component to check, or null to aggregate * all admins. * @return time in milliseconds for the given admin or the minimum value (strictest) of - * all admins if admin is null. + * all admins if admin is null. Returns 0 if there are no restrictions. */ public long getMaximumTimeToLock(ComponentName admin) { return getMaximumTimeToLock(admin, UserHandle.myUserId()); @@ -1885,7 +1885,7 @@ public class DevicePolicyManager { * security exception will be thrown. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. - * @param disabled Whether or not screen capture should be disabled. + * @param disabled Whether screen capture is disabled or not. */ public void setScreenCaptureDisabled(ComponentName admin, boolean disabled) { if (mService != null) { @@ -1920,6 +1920,42 @@ public class DevicePolicyManager { } /** + * Called by a device owner to set whether auto time is required. If auto time is + * required the user cannot set the date and time, but has to use network date and time. + * + * <p>Note: if auto time is required the user can still manually set the time zone. + * + * <p>The calling device admin must be a device owner. If it is not, a security exception will + * be thrown. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param required Whether auto time is set required or not. + */ + public void setAutoTimeRequired(ComponentName admin, boolean required) { + if (mService != null) { + try { + mService.setAutoTimeRequired(admin, UserHandle.myUserId(), required); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + } + + /** + * @return true if auto time is required. + */ + public boolean getAutoTimeRequired() { + if (mService != null) { + try { + return mService.getAutoTimeRequired(); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + return false; + } + + /** * Called by an application that is administering the device to disable keyguard customizations, * such as widgets. After setting this, keyguard features will be disabled according to the * provided feature list. diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 1e17bb6..23f36fb 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -186,4 +186,7 @@ interface IDevicePolicyManager { boolean addCrossProfileWidgetProvider(in ComponentName admin, String packageName); boolean removeCrossProfileWidgetProvider(in ComponentName admin, String packageName); List<String> getCrossProfileWidgetProviders(in ComponentName admin); + + void setAutoTimeRequired(in ComponentName who, int userHandle, boolean required); + boolean getAutoTimeRequired(); } diff --git a/core/java/android/app/backup/WallpaperBackupHelper.java b/core/java/android/app/backup/WallpaperBackupHelper.java index 9e8ab2c..0567500 100644 --- a/core/java/android/app/backup/WallpaperBackupHelper.java +++ b/core/java/android/app/backup/WallpaperBackupHelper.java @@ -141,13 +141,13 @@ public class WallpaperBackupHelper extends FileBackupHelperBase implements Backu if (widthRatio > 0 && widthRatio < 1.33 && heightRatio > 0 && heightRatio < 1.33) { // sufficiently close to our resolution; go ahead and use it - if (DEBUG) Slog.d(TAG, "wallpaper dimension match; using"); + Slog.d(TAG, "Applying restored wallpaper image."); f.renameTo(new File(WALLPAPER_IMAGE)); // TODO: spin a service to copy the restored image to sd/usb storage, // since it does not exist anywhere other than the private wallpaper // file. } else { - if (DEBUG) Slog.d(TAG, "dimensions too far off: wr=" + widthRatio + Slog.i(TAG, "Dimensions too far off; using default wallpaper. wr=" + widthRatio + " hr=" + heightRatio); f.delete(); } diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java index d1ebc5f..2431ad0 100644 --- a/core/java/android/app/usage/UsageEvents.java +++ b/core/java/android/app/usage/UsageEvents.java @@ -65,7 +65,12 @@ public final class UsageEvents implements Parcelable { /** * {@hide} */ - public ComponentName mComponent; + public String mPackage; + + /** + * {@hide} + */ + public String mClass; /** * {@hide} @@ -78,10 +83,26 @@ public final class UsageEvents implements Parcelable { public int mEventType; /** - * The component this event represents. + * TODO(adamlesinski): Removed before release. + * {@hide} */ public ComponentName getComponent() { - return mComponent; + return new ComponentName(mPackage, mClass); + } + + /** + * The package name of the source of this event. + */ + public String getPackageName() { + return mPackage; + } + + /** + * The class name of the source of this event. This may be null for + * certain events. + */ + public String getClassName() { + return mClass; } /** @@ -115,7 +136,7 @@ public final class UsageEvents implements Parcelable { * In order to save space, since ComponentNames will be duplicated everywhere, * we use a map and index into it. */ - private ComponentName[] mComponentNameTable; + private String[] mStringPool; /** * Construct the iterator from a parcel. @@ -125,7 +146,7 @@ public final class UsageEvents implements Parcelable { mEventCount = in.readInt(); mIndex = in.readInt(); if (mEventCount > 0) { - mComponentNameTable = in.createTypedArray(ComponentName.CREATOR); + mStringPool = in.createStringArray(); final int listByteLength = in.readInt(); final int positionInParcel = in.readInt(); @@ -149,8 +170,8 @@ public final class UsageEvents implements Parcelable { * Construct the iterator in preparation for writing it to a parcel. * {@hide} */ - public UsageEvents(List<Event> events, ComponentName[] nameTable) { - mComponentNameTable = nameTable; + public UsageEvents(List<Event> events, String[] stringPool) { + mStringPool = stringPool; mEventCount = events.size(); mEventsToWrite = events; } @@ -178,8 +199,19 @@ public final class UsageEvents implements Parcelable { return false; } - final int index = mParcel.readInt(); - eventOut.mComponent = mComponentNameTable[index]; + final int packageIndex = mParcel.readInt(); + if (packageIndex >= 0) { + eventOut.mPackage = mStringPool[packageIndex]; + } else { + eventOut.mPackage = null; + } + + final int classIndex = mParcel.readInt(); + if (classIndex >= 0) { + eventOut.mClass = mStringPool[classIndex]; + } else { + eventOut.mClass = null; + } eventOut.mEventType = mParcel.readInt(); eventOut.mTimeStamp = mParcel.readLong(); mIndex++; @@ -206,12 +238,20 @@ public final class UsageEvents implements Parcelable { return 0; } + private int findStringIndex(String str) { + final int index = Arrays.binarySearch(mStringPool, str); + if (index < 0) { + throw new IllegalStateException("String '" + str + "' is not in the string pool"); + } + return index; + } + @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mEventCount); dest.writeInt(mIndex); if (mEventCount > 0) { - dest.writeTypedArray(mComponentNameTable, flags); + dest.writeStringArray(mStringPool); if (mEventsToWrite != null) { // Write out the events @@ -221,12 +261,21 @@ public final class UsageEvents implements Parcelable { for (int i = 0; i < mEventCount; i++) { final Event event = mEventsToWrite.get(i); - int index = Arrays.binarySearch(mComponentNameTable, event.getComponent()); - if (index < 0) { - throw new IllegalStateException(event.getComponent().toShortString() + - " is not in the component name table"); + final int packageIndex; + if (event.mPackage != null) { + packageIndex = findStringIndex(event.mPackage); + } else { + packageIndex = -1; + } + + final int classIndex; + if (event.mClass != null) { + classIndex = findStringIndex(event.mClass); + } else { + classIndex = -1; } - p.writeInt(index); + p.writeInt(packageIndex); + p.writeInt(classIndex); p.writeInt(event.getEventType()); p.writeLong(event.getTimeStamp()); } diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java index 69716e5..24c6793 100644 --- a/core/java/android/appwidget/AppWidgetHost.java +++ b/core/java/android/appwidget/AppWidgetHost.java @@ -24,7 +24,6 @@ import android.annotation.Nullable; import android.app.Activity; import android.content.ActivityNotFoundException; import android.content.Context; -import android.content.Intent; import android.content.IntentSender; import android.os.Binder; import android.os.Bundle; @@ -155,7 +154,7 @@ public class AppWidgetHost { int[] updatedIds; ArrayList<RemoteViews> updatedViews = new ArrayList<RemoteViews>(); try { - updatedIds = sService.startListening(mCallbacks, mContext.getPackageName(), mHostId, + updatedIds = sService.startListening(mCallbacks, mContext.getOpPackageName(), mHostId, updatedViews); } catch (RemoteException e) { @@ -174,7 +173,7 @@ public class AppWidgetHost { */ public void stopListening() { try { - sService.stopListening(mContext.getPackageName(), mHostId); + sService.stopListening(mContext.getOpPackageName(), mHostId); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); @@ -192,7 +191,7 @@ public class AppWidgetHost { */ public int allocateAppWidgetId() { try { - return sService.allocateAppWidgetId(mContext.getPackageName(), mHostId); + return sService.allocateAppWidgetId(mContext.getOpPackageName(), mHostId); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); @@ -222,7 +221,7 @@ public class AppWidgetHost { int appWidgetId, int intentFlags, int requestCode, @Nullable Bundle options) { try { IntentSender intentSender = sService.createAppWidgetConfigIntentSender( - mContext.getPackageName(), appWidgetId, intentFlags); + mContext.getOpPackageName(), appWidgetId, intentFlags); if (intentSender != null) { activity.startIntentSenderForResult(intentSender, requestCode, null, 0, 0, 0, options); @@ -246,7 +245,7 @@ public class AppWidgetHost { if (sService == null) { bindService(); } - return sService.getAppWidgetIdsForHost(mContext.getPackageName(), mHostId); + return sService.getAppWidgetIdsForHost(mContext.getOpPackageName(), mHostId); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); } @@ -263,7 +262,7 @@ public class AppWidgetHost { synchronized (mViews) { mViews.remove(appWidgetId); try { - sService.deleteAppWidgetId(mContext.getPackageName(), appWidgetId); + sService.deleteAppWidgetId(mContext.getOpPackageName(), appWidgetId); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); @@ -281,7 +280,7 @@ public class AppWidgetHost { */ public void deleteHost() { try { - sService.deleteHost(mContext.getPackageName(), mHostId); + sService.deleteHost(mContext.getOpPackageName(), mHostId); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); @@ -319,7 +318,7 @@ public class AppWidgetHost { } RemoteViews views; try { - views = sService.getAppWidgetViews(mContext.getPackageName(), appWidgetId); + views = sService.getAppWidgetViews(mContext.getOpPackageName(), appWidgetId); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); } diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java index 086eb7d..bd45c7e 100644 --- a/core/java/android/appwidget/AppWidgetManager.java +++ b/core/java/android/appwidget/AppWidgetManager.java @@ -441,7 +441,7 @@ public class AppWidgetManager { * @hide */ public AppWidgetManager(Context context, IAppWidgetService service) { - mPackageName = context.getPackageName(); + mPackageName = context.getOpPackageName(); mService = service; mDisplayMetrics = context.getResources().getDisplayMetrics(); } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index a13a928..b7d7c25 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -2203,8 +2203,6 @@ public abstract class Context { * @see android.media.MediaRouter * @see #TELEPHONY_SERVICE * @see android.telephony.TelephonyManager - * @see #PHONE_SERVICE - * @see android.phone.PhoneManager * @see #INPUT_METHOD_SERVICE * @see android.view.inputmethod.InputMethodManager * @see #UI_MODE_SERVICE @@ -2514,6 +2512,7 @@ public abstract class Context { * * @see #getSystemService * @see android.app.FingerprintManager + * @hide */ public static final String FINGERPRINT_SERVICE = "fingerprint"; @@ -2558,16 +2557,6 @@ public abstract class Context { /** * Use with {@link #getSystemService} to retrieve a - * {@link android.phone.PhoneManager} to manage phone-related features - * of the device. - * - * @see #getSystemService - * @see android.phone.PhoneManager - */ - public static final String PHONE_SERVICE = "phone_service"; // "phone" used by telephony. - - /** - * Use with {@link #getSystemService} to retrieve a * {@link android.text.ClipboardManager} for accessing and modifying * the contents of the global clipboard. * diff --git a/core/java/android/content/pm/IPackageInstaller.aidl b/core/java/android/content/pm/IPackageInstaller.aidl index 97be8f0..c6c0ff6 100644 --- a/core/java/android/content/pm/IPackageInstaller.aidl +++ b/core/java/android/content/pm/IPackageInstaller.aidl @@ -25,6 +25,8 @@ import android.content.IntentSender; /** {@hide} */ interface IPackageInstaller { int createSession(in PackageInstaller.SessionParams params, String installerPackageName, int userId); + void abandonSession(int sessionId); + IPackageInstallerSession openSession(int sessionId); PackageInstaller.SessionInfo getSessionInfo(int sessionId); diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index 9afdbf7..c928a18 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -312,6 +312,14 @@ public class PackageInstaller { } } + public void abandonSession(int sessionId) { + try { + mInstaller.abandonSession(sessionId); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } + /** * Return details for a specific session. To succeed, the caller must either * own this session, or be the current home app. diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 56b7164..5492775 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -1217,6 +1217,14 @@ public abstract class PackageManager { /** * Feature for {@link #getSystemAvailableFeatures} and + * {@link #hasSystemFeature}: The heart rate sensor on this device is an Electrocargiogram. + */ + @SdkConstant(SdkConstantType.FEATURE) + public static final String FEATURE_SENSOR_HEART_RATE_ECG = + "android.hardware.sensor.heartrate.ecg"; + + /** + * Feature for {@link #getSystemAvailableFeatures} and * {@link #hasSystemFeature}: The device includes a relative humidity sensor. */ @SdkConstant(SdkConstantType.FEATURE) diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 142206a..6d40dcf 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -25,6 +25,7 @@ import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK; import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES; import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION; +import android.app.ActivityManager; import android.content.ComponentName; import android.content.Intent; import android.content.IntentFilter; @@ -354,7 +355,11 @@ public class PackageParser { } public static final boolean isApkFile(File file) { - return file.getName().endsWith(".apk"); + return isApkPath(file.getName()); + } + + private static boolean isApkPath(String path) { + return path.endsWith(".apk"); } /* @@ -754,26 +759,41 @@ public class PackageParser { "Not a coreApp: " + packageDir); } - final File baseApk = new File(lite.baseCodePath); - final Package pkg = parseBaseApk(baseApk, flags); - if (pkg == null) { - throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, - "Failed to parse base APK: " + baseApk); - } + final AssetManager assets = new AssetManager(); + try { + // Load the base and all splits into the AssetManager + // so that resources can be overriden when parsing the manifests. + loadApkIntoAssetManager(assets, lite.baseCodePath, flags); + + if (!ArrayUtils.isEmpty(lite.splitCodePaths)) { + for (String path : lite.splitCodePaths) { + loadApkIntoAssetManager(assets, path, flags); + } + } - if (!ArrayUtils.isEmpty(lite.splitNames)) { - final int num = lite.splitNames.length; - pkg.splitNames = lite.splitNames; - pkg.splitCodePaths = lite.splitCodePaths; - pkg.splitFlags = new int[num]; + final File baseApk = new File(lite.baseCodePath); + final Package pkg = parseBaseApk(baseApk, assets, flags); + if (pkg == null) { + throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, + "Failed to parse base APK: " + baseApk); + } + + if (!ArrayUtils.isEmpty(lite.splitNames)) { + final int num = lite.splitNames.length; + pkg.splitNames = lite.splitNames; + pkg.splitCodePaths = lite.splitCodePaths; + pkg.splitFlags = new int[num]; - for (int i = 0; i < num; i++) { - parseSplitApk(pkg, i, flags); + for (int i = 0; i < num; i++) { + parseSplitApk(pkg, i, assets, flags); + } } - } - pkg.codePath = packageDir.getAbsolutePath(); - return pkg; + pkg.codePath = packageDir.getAbsolutePath(); + return pkg; + } finally { + IoUtils.closeQuietly(assets); + } } /** @@ -796,35 +816,48 @@ public class PackageParser { } } - final Package pkg = parseBaseApk(apkFile, flags); - pkg.codePath = apkFile.getAbsolutePath(); - return pkg; + final AssetManager assets = new AssetManager(); + try { + final Package pkg = parseBaseApk(apkFile, assets, flags); + pkg.codePath = apkFile.getAbsolutePath(); + return pkg; + } finally { + IoUtils.closeQuietly(assets); + } } - private Package parseBaseApk(File apkFile, int flags) throws PackageParserException { + private static int loadApkIntoAssetManager(AssetManager assets, String apkPath, int flags) + throws PackageParserException { + if ((flags & PARSE_MUST_BE_APK) != 0 && !isApkPath(apkPath)) { + throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, + "Invalid package file: " + apkPath); + } + + // The AssetManager guarantees uniqueness for asset paths, so if this asset path + // already exists in the AssetManager, addAssetPath will only return the cookie + // assigned to it. + int cookie = assets.addAssetPath(apkPath); + if (cookie == 0) { + throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, + "Failed adding asset path: " + apkPath); + } + return cookie; + } + + private Package parseBaseApk(File apkFile, AssetManager assets, int flags) + throws PackageParserException { final String apkPath = apkFile.getAbsolutePath(); mParseError = PackageManager.INSTALL_SUCCEEDED; mArchiveSourcePath = apkFile.getAbsolutePath(); - if ((flags & PARSE_MUST_BE_APK) != 0 && !isApkFile(apkFile)) { - throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, - "Invalid package file: " + apkPath); - } - if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath); - AssetManager assets = null; + final int cookie = loadApkIntoAssetManager(assets, apkPath, flags); + Resources res = null; XmlResourceParser parser = null; try { - assets = new AssetManager(); - int cookie = assets.addAssetPath(apkPath); - if (cookie == 0) { - throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, - "Failed adding asset path: " + apkPath); - } - res = new Resources(assets, mMetrics, null); assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Build.VERSION.RESOURCES_SDK_INT); @@ -849,11 +882,10 @@ public class PackageParser { "Failed to read manifest from " + apkPath, e); } finally { IoUtils.closeQuietly(parser); - IoUtils.closeQuietly(assets); } } - private void parseSplitApk(Package pkg, int splitIndex, int flags) + private void parseSplitApk(Package pkg, int splitIndex, AssetManager assets, int flags) throws PackageParserException { final String apkPath = pkg.splitCodePaths[splitIndex]; final File apkFile = new File(apkPath); @@ -861,24 +893,13 @@ public class PackageParser { mParseError = PackageManager.INSTALL_SUCCEEDED; mArchiveSourcePath = apkPath; - if ((flags & PARSE_MUST_BE_APK) != 0 && !isApkFile(apkFile)) { - throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, - "Invalid package file: " + apkPath); - } - if (DEBUG_JAR) Slog.d(TAG, "Scanning split APK: " + apkPath); - AssetManager assets = null; + final int cookie = loadApkIntoAssetManager(assets, apkPath, flags); + Resources res = null; XmlResourceParser parser = null; try { - assets = new AssetManager(); - int cookie = assets.addAssetPath(apkPath); - if (cookie == 0) { - throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, - "Failed adding asset path: " + apkPath); - } - res = new Resources(assets, mMetrics, null); assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Build.VERSION.RESOURCES_SDK_INT); @@ -898,7 +919,6 @@ public class PackageParser { "Failed to read manifest from " + apkPath, e); } finally { IoUtils.closeQuietly(parser); - IoUtils.closeQuietly(assets); } } @@ -3058,7 +3078,7 @@ public class PackageParser { ActivityInfo.DOCUMENT_LAUNCH_NONE); a.info.maxRecents = sa.getInt( com.android.internal.R.styleable.AndroidManifestActivity_maxRecents, - 15); + ActivityManager.getDefaultAppRecentsLimitStatic()); a.info.screenOrientation = sa.getInt( com.android.internal.R.styleable.AndroidManifestActivity_screenOrientation, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java index d19418b..e63fd07 100644 --- a/core/java/android/content/res/Configuration.java +++ b/core/java/android/content/res/Configuration.java @@ -533,6 +533,18 @@ public final class Configuration implements Parcelable, Comparable<Configuration public static final int DENSITY_DPI_UNDEFINED = 0; /** + * Value for {@link #densityDpi} for resources that scale to any density (vector drawables). + * {@hide} + */ + public static final int DENSITY_DPI_ANY = 0xfffe; + + /** + * Value for {@link #densityDpi} for resources that are not meant to be scaled. + * {@hide} + */ + public static final int DENSITY_DPI_NONE = 0xffff; + + /** * The target screen density being rendered to, * corresponding to * <a href="{@docRoot}guide/topics/resources/providing-resources.html#DensityQualifier">density</a> @@ -1453,7 +1465,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration } switch (config.densityDpi) { - case 0: + case DENSITY_DPI_UNDEFINED: break; case 120: parts.add("ldpi"); @@ -1476,6 +1488,11 @@ public final class Configuration implements Parcelable, Comparable<Configuration case 640: parts.add("xxxhdpi"); break; + case DENSITY_DPI_ANY: + parts.add("anydpi"); + break; + case DENSITY_DPI_NONE: + parts.add("nodpi"); default: parts.add(config.densityDpi + "dpi"); break; diff --git a/core/java/android/database/ContentObserver.java b/core/java/android/database/ContentObserver.java index e4fbc28..5f01e30 100644 --- a/core/java/android/database/ContentObserver.java +++ b/core/java/android/database/ContentObserver.java @@ -18,6 +18,7 @@ package android.database; import android.net.Uri; import android.os.Handler; +import android.os.UserHandle; /** * Receives call backs for changes to content. @@ -130,6 +131,21 @@ public abstract class ContentObserver { } /** + * Dispatches a change notification to the observer. Includes the changed + * content Uri when available and also the user whose content changed. + * + * @param selfChange True if this is a self-change notification. + * @param uri The Uri of the changed content, or null if unknown. + * @param userId The user whose content changed. Can be either a specific + * user or {@link UserHandle#USER_ALL}. + * + * @hide + */ + public void onChange(boolean selfChange, Uri uri, int userId) { + onChange(selfChange, uri); + } + + /** * Dispatches a change notification to the observer. * <p> * If a {@link Handler} was supplied to the {@link ContentObserver} constructor, @@ -159,25 +175,45 @@ public abstract class ContentObserver { * @param uri The Uri of the changed content, or null if unknown. */ public final void dispatchChange(boolean selfChange, Uri uri) { + dispatchChange(selfChange, uri, UserHandle.getCallingUserId()); + } + + /** + * Dispatches a change notification to the observer. Includes the changed + * content Uri when available and also the user whose content changed. + * <p> + * If a {@link Handler} was supplied to the {@link ContentObserver} constructor, + * then a call to the {@link #onChange} method is posted to the handler's message queue. + * Otherwise, the {@link #onChange} method is invoked immediately on this thread. + * </p> + * + * @param selfChange True if this is a self-change notification. + * @param uri The Uri of the changed content, or null if unknown. + * @param userId The user whose content changed. + */ + private void dispatchChange(boolean selfChange, Uri uri, int userId) { if (mHandler == null) { - onChange(selfChange, uri); + onChange(selfChange, uri, userId); } else { - mHandler.post(new NotificationRunnable(selfChange, uri)); + mHandler.post(new NotificationRunnable(selfChange, uri, userId)); } } + private final class NotificationRunnable implements Runnable { private final boolean mSelfChange; private final Uri mUri; + private final int mUserId; - public NotificationRunnable(boolean selfChange, Uri uri) { + public NotificationRunnable(boolean selfChange, Uri uri, int userId) { mSelfChange = selfChange; mUri = uri; + mUserId = userId; } @Override public void run() { - ContentObserver.this.onChange(mSelfChange, mUri); + ContentObserver.this.onChange(mSelfChange, mUri, mUserId); } } @@ -189,10 +225,10 @@ public abstract class ContentObserver { } @Override - public void onChange(boolean selfChange, Uri uri) { + public void onChange(boolean selfChange, Uri uri, int userId) { ContentObserver contentObserver = mContentObserver; if (contentObserver != null) { - contentObserver.dispatchChange(selfChange, uri); + contentObserver.dispatchChange(selfChange, uri, userId); } } diff --git a/core/java/android/database/CursorToBulkCursorAdaptor.java b/core/java/android/database/CursorToBulkCursorAdaptor.java index 7dcfae2..02eddf2 100644 --- a/core/java/android/database/CursorToBulkCursorAdaptor.java +++ b/core/java/android/database/CursorToBulkCursorAdaptor.java @@ -17,9 +17,7 @@ package android.database; import android.net.Uri; -import android.os.Bundle; -import android.os.IBinder; -import android.os.RemoteException; +import android.os.*; /** @@ -33,7 +31,7 @@ import android.os.RemoteException; * * {@hide} */ -public final class CursorToBulkCursorAdaptor extends BulkCursorNative +public final class CursorToBulkCursorAdaptor extends BulkCursorNative implements IBinder.DeathRecipient { private static final String TAG = "Cursor"; @@ -66,7 +64,7 @@ public final class CursorToBulkCursorAdaptor extends BulkCursorNative // Do nothing, the far side is dead } } - + public boolean unlinkToDeath(DeathRecipient recipient) { return mRemote.asBinder().unlinkToDeath(recipient, 0); } @@ -80,7 +78,7 @@ public final class CursorToBulkCursorAdaptor extends BulkCursorNative @Override public void onChange(boolean selfChange, Uri uri) { try { - mRemote.onChange(selfChange, uri); + mRemote.onChange(selfChange, uri, android.os.Process.myUid()); } catch (RemoteException ex) { // Do nothing, the far side is dead } diff --git a/core/java/android/database/IContentObserver.aidl b/core/java/android/database/IContentObserver.aidl index 13aff05..22dc9fe 100644 --- a/core/java/android/database/IContentObserver.aidl +++ b/core/java/android/database/IContentObserver.aidl @@ -2,16 +2,16 @@ ** ** Copyright 2007, 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 +** 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 +** 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 +** 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. */ @@ -29,5 +29,5 @@ interface IContentObserver * observed. selfUpdate is true if the update was caused by a call to * commit on the cursor that is being observed. */ - oneway void onChange(boolean selfUpdate, in Uri uri); + oneway void onChange(boolean selfUpdate, in Uri uri, int userId); } diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java index 3c61e39..4b5ced9 100644 --- a/core/java/android/hardware/hdmi/HdmiControlManager.java +++ b/core/java/android/hardware/hdmi/HdmiControlManager.java @@ -48,6 +48,12 @@ public final class HdmiControlManager { @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_OSD_MESSAGE = "android.hardware.hdmi.action.OSD_MESSAGE"; + // --- Messages for ACTION_OSD_MESSAGE --- + /** + * Message that ARC enabled device is connected to invalid port (non-ARC port). + */ + public static final int OSD_MESSAGE_ARC_CONNECTED_INVALID_PORT = 1; + /** * Used as an extra field in the intent {@link #ACTION_OSD_MESSAGE}. Contains the ID of * the message to display on screen. diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 30be4da..4bfef41 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -284,98 +284,6 @@ public class ConnectivityManager { public static final String EXTRA_IS_CAPTIVE_PORTAL = "captivePortal"; /** - * Broadcast Action: A connection has been established to a new network - * but a captive portal has been detected preventing internet connectivity. - * This broadcast is sent out prior to providing the user with a - * notification allowing them to sign into the network, as such it should - * only be used by apps that can automatically and silently (without user - * interaction) log into specific captive portals. It should not be used - * by apps that prompt the user to sign in, as the user has not yet - * indicated they want to proceed with signing in. - * The new network is not the default network so it can only be accessed via - * the {@link Network} extra {@link #EXTRA_NETWORK}. - * This is an ordered broadcast and so it is perfectly acceptable for - * multiple receivers to in turn consider whether they are best suited to - * address the captive portal. - * A receiver should abort the broadcast if they are sure they are the - * appropriate handler of the captive portal. If the broadcast is aborted, - * the result code must be set to one of the following: - * <ul> - * <li>{@link #CAPTIVE_PORTAL_SIGNED_IN} The receiver has signed into the - * captive portal. After being verified to provide internet - * connectivity, this network will be made the default (assuming - * it is preferred over all other active networks). - * </li> - * <li>{@link #CAPTIVE_PORTAL_DISCONNECT} The receiver is familiar with - * this captive portal and knows sign-in is impossible or the user - * has indicated they do not want to pursue sign-in. No other apps - * will be given the option of signing in to the network. - * </li> - * </ul> - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_CAPTIVE_PORTAL_DETECTED = - "android.net.conn.CAPTIVE_PORTAL_DETECTED"; - - /** - * Broadcast Action: A connection has been established to a new network, - * a captive portal has been detected preventing internet connectivity, - * the user was notified, and elected to sign into the captive portal. - * It may be used by apps that prompt the user to sign in. - * The new network is not the default network so it can only be accessed via - * the {@link Network} extra {@link #EXTRA_NETWORK}. - * This is an ordered broadcast and so it is perfectly acceptable for - * multiple receivers to in turn consider whether they are best suited to - * address the captive portal. - * A receiver should abort the broadcast if they are sure they are the - * appropriate handler of the captive portal. If the broadcast is aborted, - * the result code must be set to one of the following: - * <ul> - * <li>{@link #CAPTIVE_PORTAL_SIGNED_IN} The receiver has signed into the - * captive portal. After being verified to provide internet - * connectivity, this network will be made the default (assuming - * it is preferred over all other active networks). - * </li> - * <li>{@link #CAPTIVE_PORTAL_DISCONNECT} The user has indicated they do - * not want to pursue sign-in. No other apps will be given the - * option of signing in to the network. - * </li> - * </ul> - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_CAPTIVE_PORTAL_SIGN_IN = - "android.net.conn.CAPTIVE_PORTAL_SIGN_IN"; - - /** - * The lookup key for a {@link Network} object passed along with a - * {@link #ACTION_CAPTIVE_PORTAL_DETECTED} or - * {@link #ACTION_CAPTIVE_PORTAL_SIGN_IN} intent. This network is not the - * default network and must be accessed using this {@link Network} object. - * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}. - */ - public static final String EXTRA_NETWORK = "network"; - - /** - * Specified as a result code of a {@link #ACTION_CAPTIVE_PORTAL_DETECTED} or - * {@link #ACTION_CAPTIVE_PORTAL_SIGN_IN} receiver to indicate - * the receiver has signed into the - * captive portal. After being verified to provide internet - * connectivity, this network will be made the default (assuming - * it is preferred over all other active networks). - */ - public static final int CAPTIVE_PORTAL_SIGNED_IN = 1; - - /** - * Specified as a result code of a {@link #ACTION_CAPTIVE_PORTAL_DETECTED} or - * {@link #ACTION_CAPTIVE_PORTAL_SIGN_IN} receiver to indicate - * the receiver is familiar with - * this captive portal and knows sign-in is impossible or the user - * has indicated they do not want to pursue sign-in. No other apps will - * be given the option of signing in to the network. - */ - public static final int CAPTIVE_PORTAL_DISCONNECT = 2; - - /** * The absence of a connection type. * @hide */ diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java index 99bccd0..050be40 100644 --- a/core/java/android/net/VpnService.java +++ b/core/java/android/net/VpnService.java @@ -24,6 +24,7 @@ import android.app.PendingIntent; import android.app.Service; import android.content.Context; import android.content.Intent; +import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.net.NetworkUtils; import android.os.Binder; @@ -32,6 +33,7 @@ import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.UserHandle; import com.android.internal.net.VpnConfig; @@ -518,12 +520,23 @@ public class VpnService extends Service { return this; } + private void verifyApp(String packageName) throws PackageManager.NameNotFoundException { + IPackageManager pm = IPackageManager.Stub.asInterface( + ServiceManager.getService("package")); + try { + pm.getApplicationInfo(packageName, 0, UserHandle.getCallingUserId()); + } catch (RemoteException e) { + throw new IllegalStateException(e); + } + } + /** * Adds an application that's allowed to access the VPN connection. * * If this method is called at least once, only applications added through this method (and * no others) are allowed access. Else (if this method is never called), all applications - * are allowed by default. + * are allowed by default. If some applications are added, other, un-added applications + * will use networking as if the VPN wasn't running. * * A {@link Builder} may have only a set of allowed applications OR a set of disallowed * ones, but not both. Calling this method after {@link #addDisallowedApplication} has @@ -540,7 +553,14 @@ public class VpnService extends Service { */ public Builder addAllowedApplication(String packageName) throws PackageManager.NameNotFoundException { - // TODO + if (mConfig.disallowedApplications != null) { + throw new UnsupportedOperationException("addDisallowedApplication already called"); + } + verifyApp(packageName); + if (mConfig.allowedApplications == null) { + mConfig.allowedApplications = new ArrayList<String>(); + } + mConfig.allowedApplications.add(packageName); return this; } @@ -548,7 +568,7 @@ public class VpnService extends Service { * Adds an application that's denied access to the VPN connection. * * By default, all applications are allowed access, except for those denied through this - * method. + * method. Denied applications will use networking as if the VPN wasn't running. * * A {@link Builder} may have only a set of allowed applications OR a set of disallowed * ones, but not both. Calling this method after {@link #addAllowedApplication} has already @@ -565,7 +585,14 @@ public class VpnService extends Service { */ public Builder addDisallowedApplication(String packageName) throws PackageManager.NameNotFoundException { - // TODO + if (mConfig.allowedApplications != null) { + throw new UnsupportedOperationException("addAllowedApplication already called"); + } + verifyApp(packageName); + if (mConfig.disallowedApplications == null) { + mConfig.disallowedApplications = new ArrayList<String>(); + } + mConfig.disallowedApplications.add(packageName); return this; } diff --git a/core/java/android/os/FileBridge.java b/core/java/android/os/FileBridge.java index afa5885..bf8d15c 100644 --- a/core/java/android/os/FileBridge.java +++ b/core/java/android/os/FileBridge.java @@ -119,9 +119,9 @@ public class FileBridge extends Thread { } } catch (ErrnoException e) { - Log.e(TAG, "Failed during bridge: ", e); + Log.wtf(TAG, "Failed during bridge", e); } catch (IOException e) { - Log.e(TAG, "Failed during bridge: ", e); + Log.wtf(TAG, "Failed during bridge", e); } finally { IoUtils.closeQuietly(mTarget); IoUtils.closeQuietly(mServer); diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index 4f35b16..513e47e 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -2272,6 +2272,8 @@ public final class ContactsContract { * The default value is "0" * </p> * <p>Type: INTEGER</p> + * + * @hide */ public static final String NAME_VERIFIED = "name_verified"; @@ -8066,6 +8068,21 @@ public final class ContactsContract { } /** + * Pins a contact at a provided position, or unpins a contact. + * + * @param contentResolver to perform the pinning operation on. + * @param pinnedPosition the position to pin the contact at. To unpin a contact, use + * {@link PinnedPositions#UNPINNED}. + */ + public static void pin( + ContentResolver contentResolver, long contactId, int pinnedPosition) { + final Uri uri = Uri.withAppendedPath(Contacts.CONTENT_URI, String.valueOf(contactId)); + final ContentValues values = new ContentValues(); + values.put(Contacts.PINNED, pinnedPosition); + contentResolver.update(uri, values, null, null); + } + + /** * Default value for the pinned position of an unpinned contact. */ public static final int UNPINNED = 0; diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 2241716..95d1351 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -6320,8 +6320,7 @@ public final class Settings { * processes as soon as they are no longer needed. If 0, the normal * extended lifetime is used. */ - public static final String ALWAYS_FINISH_ACTIVITIES = - "always_finish_activities"; + public static final String ALWAYS_FINISH_ACTIVITIES = "always_finish_activities"; /** * Use Dock audio output for media: diff --git a/core/java/android/service/fingerprint/FingerprintManager.java b/core/java/android/service/fingerprint/FingerprintManager.java index 5fd597b..178cc8b 100644 --- a/core/java/android/service/fingerprint/FingerprintManager.java +++ b/core/java/android/service/fingerprint/FingerprintManager.java @@ -33,6 +33,7 @@ import android.util.Slog; /** * A class that coordinates access to the fingerprint hardware. + * @hide */ public class FingerprintManager { diff --git a/core/java/android/service/fingerprint/FingerprintManagerReceiver.java b/core/java/android/service/fingerprint/FingerprintManagerReceiver.java index e5193f5..85677ba 100644 --- a/core/java/android/service/fingerprint/FingerprintManagerReceiver.java +++ b/core/java/android/service/fingerprint/FingerprintManagerReceiver.java @@ -15,6 +15,9 @@ package android.service.fingerprint; * limitations under the License. */ +/** + * @hide + */ public class FingerprintManagerReceiver { /** * Fingerprint enrollment progress update. Enrollment is considered complete if diff --git a/core/java/android/service/fingerprint/FingerprintUtils.java b/core/java/android/service/fingerprint/FingerprintUtils.java index f4b5526..a4caf8e 100644 --- a/core/java/android/service/fingerprint/FingerprintUtils.java +++ b/core/java/android/service/fingerprint/FingerprintUtils.java @@ -23,6 +23,10 @@ import android.util.Log; import java.util.Arrays; +/** + * Utility class for dealing with fingerprints and fingerprint settings. + * @hide + */ public class FingerprintUtils { private static final boolean DEBUG = true; diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java index 119f7f6..450b9a7 100644 --- a/core/java/android/service/notification/NotificationListenerService.java +++ b/core/java/android/service/notification/NotificationListenerService.java @@ -307,10 +307,22 @@ public abstract class NotificationListenerService extends Service { * @return An array of active notifications, sorted in natural order. */ public StatusBarNotification[] getActiveNotifications() { + return getActiveNotifications(null); + } + + /** + * Request one or more notifications by key. Useful if you have been keeping track of + * notifications but didn't want to retain the bits, and now need to go back and extract + * more data out of those notifications. + * + * @return An array of notifications corresponding to the requested keys, in the + * same order as the key list. + */ + public StatusBarNotification[] getActiveNotifications(String[] keys) { if (!isBound()) return null; try { ParceledListSlice<StatusBarNotification> parceledList = - getNotificationInterface().getActiveNotificationsFromListener(mWrapper); + getNotificationInterface().getActiveNotificationsFromListener(mWrapper, keys); List<StatusBarNotification> list = parceledList.getList(); int N = list.size(); @@ -527,7 +539,7 @@ public abstract class NotificationListenerService extends Service { private String mKey; private int mRank = -1; private boolean mIsAmbient; - private boolean mMeetsInterruptionFilter; + private boolean mMatchesInterruptionFilter; public Ranking() {} @@ -559,17 +571,27 @@ public abstract class NotificationListenerService extends Service { /** * Returns whether the notification meets the user's interruption * filter. + * + * @removed */ public boolean meetsInterruptionFilter() { - return mMeetsInterruptionFilter; + return mMatchesInterruptionFilter; + } + + /** + * Returns whether the notification matches the user's interruption + * filter. + */ + public boolean matchesInterruptionFilter() { + return mMatchesInterruptionFilter; } private void populate(String key, int rank, boolean isAmbient, - boolean meetsInterruptionFilter) { + boolean matchesInterruptionFilter) { mKey = key; mRank = rank; mIsAmbient = isAmbient; - mMeetsInterruptionFilter = meetsInterruptionFilter; + mMatchesInterruptionFilter = matchesInterruptionFilter; } } diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java index 884fa9f..65e6988 100644 --- a/core/java/android/service/voice/VoiceInteractionService.java +++ b/core/java/android/service/voice/VoiceInteractionService.java @@ -201,17 +201,6 @@ public class VoiceInteractionService extends Service { } /** - * FIXME: Remove once the prebuilts are updated. - * - * @hide - */ - @Deprecated - public final AlwaysOnHotwordDetector createAlwaysOnHotwordDetector( - String keyphrase, String locale, AlwaysOnHotwordDetector.Callback callback) { - return createAlwaysOnHotwordDetector(keyphrase, new Locale(locale), callback); - } - - /** * Creates an {@link AlwaysOnHotwordDetector} for the given keyphrase and locale. * This instance must be retained and used by the client. * Calling this a second time invalidates the previously created hotword detector diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java index 81c69d1..0b02552 100644 --- a/core/java/android/transition/Visibility.java +++ b/core/java/android/transition/Visibility.java @@ -84,7 +84,7 @@ public abstract class Visibility extends Transition { public Visibility(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.VisibilityTransition); - int mode = a.getInt(R.styleable.VisibilityTransition_visibilityMode, 0); + int mode = a.getInt(R.styleable.VisibilityTransition_transitionVisibilityMode, 0); a.recycle(); if (mode != 0) { setMode(mode); @@ -97,7 +97,7 @@ public abstract class Visibility extends Transition { * * @param mode The behavior supported by this transition, a combination of * {@link #MODE_IN} and {@link #MODE_OUT}. - * @attr ref android.R.styleable#VisibilityTransition_visibilityMode + * @attr ref android.R.styleable#VisibilityTransition_transitionVisibilityMode */ public void setMode(int mode) { if ((mode & ~(MODE_IN | MODE_OUT)) != 0) { @@ -111,7 +111,7 @@ public abstract class Visibility extends Transition { * * Returns whether appearing and/or disappearing Views are supported. A combination of * {@link #MODE_IN} and {@link #MODE_OUT}. - * @attr ref android.R.styleable#VisibilityTransition_visibilityMode + * @attr ref android.R.styleable#VisibilityTransition_transitionVisibilityMode */ public int getMode() { return mMode; diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java index 3889cb6..7c9861f 100644 --- a/core/java/android/util/ArrayMap.java +++ b/core/java/android/util/ArrayMap.java @@ -323,7 +323,17 @@ public final class ArrayMap<K, V> implements Map<K, V> { */ @Override public boolean containsKey(Object key) { - return key == null ? (indexOfNull() >= 0) : (indexOf(key, key.hashCode()) >= 0); + return indexOfKey(key) >= 0; + } + + /** + * Returns the index of a key in the set. + * + * @param key The key to search for. + * @return Returns the index of the key if it exists, else a negative integer. + */ + public int indexOfKey(Object key) { + return key == null ? indexOfNull() : indexOf(key, key.hashCode()); } int indexOfValue(Object value) { @@ -365,7 +375,7 @@ public final class ArrayMap<K, V> implements Map<K, V> { */ @Override public V get(Object key) { - final int index = key == null ? indexOfNull() : indexOf(key, key.hashCode()); + final int index = indexOfKey(key); return index >= 0 ? (V)mArray[(index<<1)+1] : null; } @@ -561,7 +571,7 @@ public final class ArrayMap<K, V> implements Map<K, V> { */ @Override public V remove(Object key) { - int index = key == null ? indexOfNull() : indexOf(key, key.hashCode()); + final int index = indexOfKey(key); if (index >= 0) { return removeAt(index); } @@ -747,7 +757,7 @@ public final class ArrayMap<K, V> implements Map<K, V> { @Override protected int colIndexOfKey(Object key) { - return key == null ? indexOfNull() : indexOf(key, key.hashCode()); + return indexOfKey(key); } @Override diff --git a/core/java/android/util/ArraySet.java b/core/java/android/util/ArraySet.java index 8f7aefd..423e48b 100644 --- a/core/java/android/util/ArraySet.java +++ b/core/java/android/util/ArraySet.java @@ -291,7 +291,17 @@ public final class ArraySet<E> implements Collection<E>, Set<E> { */ @Override public boolean contains(Object key) { - return key == null ? (indexOfNull() >= 0) : (indexOf(key, key.hashCode()) >= 0); + return indexOf(key) >= 0; + } + + /** + * Returns the index of a value in the set. + * + * @param key The value to search for. + * @return Returns the index of the value if it exists, else a negative integer. + */ + public int indexOf(Object key) { + return key == null ? indexOfNull() : indexOf(key, key.hashCode()); } /** @@ -396,7 +406,7 @@ public final class ArraySet<E> implements Collection<E>, Set<E> { */ @Override public boolean remove(Object object) { - int index = object == null ? indexOfNull() : indexOf(object, object.hashCode()); + final int index = indexOf(object); if (index >= 0) { removeAt(index); return true; @@ -586,12 +596,12 @@ public final class ArraySet<E> implements Collection<E>, Set<E> { @Override protected int colIndexOfKey(Object key) { - return key == null ? indexOfNull() : indexOf(key, key.hashCode()); + return indexOf(key); } @Override protected int colIndexOfValue(Object value) { - return value == null ? indexOfNull() : indexOf(value, value.hashCode()); + return indexOf(value); } @Override diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java index 2b81072..a9b3571 100644 --- a/core/java/android/util/Log.java +++ b/core/java/android/util/Log.java @@ -96,12 +96,12 @@ public final class Log { * @hide */ public interface TerribleFailureHandler { - void onTerribleFailure(String tag, TerribleFailure what); + void onTerribleFailure(String tag, TerribleFailure what, boolean system); } private static TerribleFailureHandler sWtfHandler = new TerribleFailureHandler() { - public void onTerribleFailure(String tag, TerribleFailure what) { - RuntimeInit.wtf(tag, what); + public void onTerribleFailure(String tag, TerribleFailure what, boolean system) { + RuntimeInit.wtf(tag, what, system); } }; @@ -253,7 +253,7 @@ public final class Log { * @param msg The message you would like logged. */ public static int wtf(String tag, String msg) { - return wtf(LOG_ID_MAIN, tag, msg, null, false); + return wtf(LOG_ID_MAIN, tag, msg, null, false, false); } /** @@ -262,7 +262,7 @@ public final class Log { * @hide */ public static int wtfStack(String tag, String msg) { - return wtf(LOG_ID_MAIN, tag, msg, null, true); + return wtf(LOG_ID_MAIN, tag, msg, null, true, false); } /** @@ -272,7 +272,7 @@ public final class Log { * @param tr An exception to log. */ public static int wtf(String tag, Throwable tr) { - return wtf(LOG_ID_MAIN, tag, tr.getMessage(), tr, false); + return wtf(LOG_ID_MAIN, tag, tr.getMessage(), tr, false, false); } /** @@ -283,14 +283,15 @@ public final class Log { * @param tr An exception to log. May be null. */ public static int wtf(String tag, String msg, Throwable tr) { - return wtf(LOG_ID_MAIN, tag, msg, tr, false); + return wtf(LOG_ID_MAIN, tag, msg, tr, false, false); } - static int wtf(int logId, String tag, String msg, Throwable tr, boolean localStack) { + static int wtf(int logId, String tag, String msg, Throwable tr, boolean localStack, + boolean system) { TerribleFailure what = new TerribleFailure(msg, tr); int bytes = println_native(logId, ASSERT, tag, msg + '\n' + getStackTraceString(localStack ? what : tr)); - sWtfHandler.onTerribleFailure(tag, what); + sWtfHandler.onTerribleFailure(tag, what, system); return bytes; } diff --git a/core/java/android/util/Slog.java b/core/java/android/util/Slog.java index b25d80f..7a5fd50 100644 --- a/core/java/android/util/Slog.java +++ b/core/java/android/util/Slog.java @@ -74,19 +74,19 @@ public final class Slog { } public static int wtf(String tag, String msg) { - return Log.wtf(Log.LOG_ID_SYSTEM, tag, msg, null, false); + return Log.wtf(Log.LOG_ID_SYSTEM, tag, msg, null, false, true); } public static int wtfStack(String tag, String msg) { - return Log.wtf(Log.LOG_ID_SYSTEM, tag, msg, null, true); + return Log.wtf(Log.LOG_ID_SYSTEM, tag, msg, null, true, true); } public static int wtf(String tag, Throwable tr) { - return Log.wtf(Log.LOG_ID_SYSTEM, tag, tr.getMessage(), tr, false); + return Log.wtf(Log.LOG_ID_SYSTEM, tag, tr.getMessage(), tr, false, true); } public static int wtf(String tag, String msg, Throwable tr) { - return Log.wtf(Log.LOG_ID_SYSTEM, tag, msg, tr, false); + return Log.wtf(Log.LOG_ID_SYSTEM, tag, msg, tr, false, true); } public static int println(int priority, String tag, String msg) { diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index a410aa9..ceea9f8 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -179,6 +179,18 @@ class GLES20Canvas extends HardwareCanvas { private static native void nSetHighContrastText(long renderer, boolean highContrastText); @Override + public void insertReorderBarrier() { + nInsertReorderBarrier(mRenderer, true); + } + + @Override + public void insertInorderBarrier() { + nInsertReorderBarrier(mRenderer, false); + } + + private static native void nInsertReorderBarrier(long renderer, boolean enableReorder); + + @Override public int onPreDraw(Rect dirty) { if (dirty != null) { return nPrepareDirty(mRenderer, dirty.left, dirty.top, dirty.right, dirty.bottom, diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 7deb9c8..5d6d998 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -93,6 +93,8 @@ interface IWindowManager int startHeight); void overridePendingAppTransitionThumb(in Bitmap srcThumb, int startX, int startY, IRemoteCallback startedCallback, boolean scaleUp); + void overridePendingAppTransitionAspectScaledThumb(in Bitmap srcThumb, int startX, + int startY, IRemoteCallback startedCallback, boolean scaleUp); void executeAppTransition(); void setAppStartingWindow(IBinder token, String pkg, int theme, in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index 50341fc..3af214d 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -99,15 +99,13 @@ public class ThreadedRenderer extends HardwareRenderer { private boolean mRootNodeNeedsUpdate; ThreadedRenderer(Context context, boolean translucent) { - final TypedArray a = context.obtainStyledAttributes( - null, R.styleable.Lighting, R.attr.lightingStyle, 0); + final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0); mLightY = a.getDimension(R.styleable.Lighting_lightY, 0); mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0); mLightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0); - mAmbientShadowAlpha = Math.round( - 255 * a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0)); - mSpotShadowAlpha = Math.round( - 255 * a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0)); + mAmbientShadowAlpha = + (int) (255 * a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0) + 0.5f); + mSpotShadowAlpha = (int) (255 * a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0) + 0.5f); a.recycle(); long rootNodePtr = nCreateRootRenderNode(); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 6f58582..2d58ecf 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -15110,7 +15110,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, final AccessibilityNodeInfo virtualView = viewRoot.getAccessibilityFocusedVirtualView(); if (virtualView != null) { - virtualView.getBoundsInParent(bounds); + virtualView.getBoundsInScreen(bounds); + final int[] offset = mAttachInfo.mTmpLocation; + getLocationOnScreen(offset); + bounds.offset(-offset[0], -offset[1]); } else { bounds.set(0, 0, mRight - mLeft, mBottom - mTop); } diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 19dd583..adad082 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -3072,7 +3072,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager boolean more = false; final long drawingTime = getDrawingTime(); - + if (usingRenderNodeProperties) canvas.insertReorderBarrier(); // Only use the preordered list if not HW accelerated, since the HW pipeline will do the // draw reordering internally final ArrayList<View> preorderedList = usingRenderNodeProperties @@ -3099,6 +3099,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager more |= drawChild(canvas, child, drawingTime); } } + if (usingRenderNodeProperties) canvas.insertInorderBarrier(); if (debugDraw()) { onDebugDraw(canvas); @@ -7021,27 +7022,23 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager if (another == null) { return 1; } - if (getClass() != another.getClass()) { - return 1; - } - final int topDiference = mLocation.top - another.mLocation.top; - if (topDiference != 0) { - return topDiference; - } - // LTR + // We are ordering left-to-right, top-to-bottom. if (mLayoutDirection == LAYOUT_DIRECTION_LTR) { final int leftDifference = mLocation.left - another.mLocation.left; - // First more to the left than second. if (leftDifference != 0) { return leftDifference; } } else { // RTL final int rightDifference = mLocation.right - another.mLocation.right; - // First more to the right than second. if (rightDifference != 0) { return -rightDifference; } } + // We are ordering left-to-right, top-to-bottom. + final int topDifference = mLocation.top - another.mLocation.top; + if (topDifference != 0) { + return topDifference; + } // Break tie by height. final int heightDiference = mLocation.height() - another.mLocation.height(); if (heightDiference != 0) { diff --git a/core/java/android/view/accessibility/AccessibilityCache.java b/core/java/android/view/accessibility/AccessibilityCache.java index ca6437a..ead757e 100644 --- a/core/java/android/view/accessibility/AccessibilityCache.java +++ b/core/java/android/view/accessibility/AccessibilityCache.java @@ -54,7 +54,12 @@ final class AccessibilityCache { if (DEBUG) { Log.i(LOG_TAG, "Caching window: " + window.getId()); } - mWindowCache.put(window.getId(), window); + final int windowId = window.getId(); + AccessibilityWindowInfo oldWindow = mWindowCache.get(windowId); + if (oldWindow != null) { + oldWindow.recycle(); + } + mWindowCache.put(windowId, AccessibilityWindowInfo.obtain(window)); } } @@ -183,14 +188,13 @@ final class AccessibilityCache { sortedWindows.put(window.getLayer(), window); } - List<AccessibilityWindowInfo> windows = new ArrayList<>(); + List<AccessibilityWindowInfo> windows = new ArrayList<>(windowCount); for (int i = windowCount - 1; i >= 0; i--) { AccessibilityWindowInfo window = sortedWindows.valueAt(i); windows.add(AccessibilityWindowInfo.obtain(window)); + sortedWindows.removeAt(i); } - sortedWindows.clear(); - return windows; } return null; diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java index 80b5c50..ad55f5f 100644 --- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java +++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java @@ -55,6 +55,7 @@ public final class AccessibilityWindowInfo implements Parcelable { private static final int BOOLEAN_PROPERTY_ACTIVE = 1 << 0; private static final int BOOLEAN_PROPERTY_FOCUSED = 1 << 1; + private static final int BOOLEAN_PROPERTY_ACCESSIBLITY_FOCUSED = 1 << 2; // Housekeeping. private static final int MAX_POOL_SIZE = 10; @@ -258,6 +259,26 @@ public final class AccessibilityWindowInfo implements Parcelable { } /** + * Gets if this window has accessibility focus. + * + * @return Whether has accessibility focus. + */ + public boolean isAccessibilityFocused() { + return getBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBLITY_FOCUSED); + } + + /** + * Sets if this window has accessibility focus. + * + * @param Whether has accessibility focus. + * + * @hide + */ + public void setAccessibilityFocused(boolean focused) { + setBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBLITY_FOCUSED, focused); + } + + /** * Gets the number of child windows. * * @return The child count. diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java index 7c30d2a..de7d2d0 100644 --- a/core/java/android/webkit/CookieManager.java +++ b/core/java/android/webkit/CookieManager.java @@ -98,7 +98,7 @@ public class CookieManager { * @param webview the {@link WebView} instance to get the cookie policy for * @return true if the {@link WebView} accepts third party cookies */ - public synchronized boolean acceptThirdPartyCookies(WebView webview) { + public boolean acceptThirdPartyCookies(WebView webview) { throw new MustOverrideException(); } diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java index 49d47fe..7df1fa3 100644 --- a/core/java/android/widget/DatePickerCalendarDelegate.java +++ b/core/java/android/widget/DatePickerCalendarDelegate.java @@ -16,9 +16,6 @@ package android.widget; -import android.animation.Keyframe; -import android.animation.ObjectAnimator; -import android.animation.PropertyValuesHolder; import android.content.Context; import android.content.res.ColorStateList; import android.content.res.Configuration; @@ -60,10 +57,7 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i private static final int DEFAULT_START_YEAR = 1900; private static final int DEFAULT_END_YEAR = 2100; - private static final int PULSE_ANIMATOR_DURATION = 544; - private static final int ANIMATION_DURATION = 300; - private static final int ANIMATION_DELAY = 650; private static final int MONTH_INDEX = 0; private static final int DAY_INDEX = 1; @@ -73,8 +67,13 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i private SimpleDateFormat mDayFormat = new SimpleDateFormat("d", Locale.getDefault()); private TextView mDayOfWeekView; - private LinearLayout mDateLayout; + + /** Layout that contains the current month, day, and year. */ + private LinearLayout mMonthDayYearLayout; + + /** Clickable layout that contains the current day and year. */ private LinearLayout mMonthAndDayLayout; + private TextView mHeaderMonthTextView; private TextView mHeaderDayOfMonthTextView; private TextView mHeaderYearTextView; @@ -93,8 +92,6 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i private DatePicker.OnDateChangedListener mDateChangedListener; - private boolean mDelayAnimation = true; - private int mCurrentView = UNINITIALIZED; private Calendar mCurrentDate; @@ -112,7 +109,6 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i mMinDate = getCalendarForLocale(mMinDate, locale); mMaxDate = getCalendarForLocale(mMaxDate, locale); mTempDate = getCalendarForLocale(mMaxDate, locale); - mCurrentDate = getCalendarForLocale(mCurrentDate, locale); mMinDate.set(DEFAULT_START_YEAR, 1, 1); @@ -129,7 +125,12 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i mDelegator.addView(mainView); mDayOfWeekView = (TextView) mainView.findViewById(R.id.date_picker_header); - mDateLayout = (LinearLayout) mainView.findViewById(R.id.day_picker_selector_layout); + + // Layout that contains the current date and day name header. + final LinearLayout dateLayout = (LinearLayout) mainView.findViewById( + R.id.day_picker_selector_layout); + mMonthDayYearLayout = (LinearLayout) mainView.findViewById( + R.id.date_picker_month_day_year_layout); mMonthAndDayLayout = (LinearLayout) mainView.findViewById( R.id.date_picker_month_and_day_layout); mMonthAndDayLayout.setOnClickListener(this); @@ -156,7 +157,7 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i R.styleable.DatePicker_headerSelectedTextColor, defaultHighlightColor); final int headerBackgroundColor = a.getColor(R.styleable.DatePicker_headerBackgroundColor, Color.TRANSPARENT); - mDateLayout.setBackgroundColor(headerBackgroundColor); + dateLayout.setBackgroundColor(headerBackgroundColor); final int monthTextAppearanceResId = a.getResourceId( R.styleable.DatePicker_headerMonthTextAppearance, -1); @@ -189,6 +190,10 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i mYearPickerView = new YearPickerView(mContext); mYearPickerView.init(this); + final int yearSelectedCircleColor = a.getColor(R.styleable.DatePicker_yearListSelectorColor, + defaultHighlightColor); + mYearPickerView.setYearSelectedCircleColor(yearSelectedCircleColor); + final ColorStateList calendarTextColor = a.getColorStateList( R.styleable.DatePicker_calendarTextColor); final int calendarSelectedTextColor = a.getColor( @@ -205,10 +210,12 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i mAnimator.addView(mDayPickerView); mAnimator.addView(mYearPickerView); mAnimator.setDateMillis(mCurrentDate.getTimeInMillis()); - Animation animation = new AlphaAnimation(0.0f, 1.0f); + + final Animation animation = new AlphaAnimation(0.0f, 1.0f); animation.setDuration(ANIMATION_DURATION); mAnimator.setInAnimation(animation); - Animation animation2 = new AlphaAnimation(1.0f, 0.0f); + + final Animation animation2 = new AlphaAnimation(1.0f, 0.0f); animation2.setDuration(ANIMATION_DURATION); mAnimator.setOutAnimation(animation2); @@ -276,30 +283,28 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i mDayOfWeekView.setText(mCurrentDate.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, Locale.getDefault())); } - final String bestDateTimePattern = - DateFormat.getBestDateTimePattern(mCurrentLocale, "yMMMd"); // Compute indices of Month, Day and Year views - int[] viewIndices = getMonthDayYearIndexes(bestDateTimePattern); - - // Restart from a clean state - mMonthAndDayLayout.removeAllViews(); - mDateLayout.removeView(mHeaderYearTextView); + final String bestDateTimePattern = + DateFormat.getBestDateTimePattern(mCurrentLocale, "yMMMd"); + final int[] viewIndices = getMonthDayYearIndexes(bestDateTimePattern); - // Position the Year View at the correct location + // Position the Year and MonthAndDay views within the header. + mMonthDayYearLayout.removeAllViews(); if (viewIndices[YEAR_INDEX] == 0) { - mDateLayout.addView(mHeaderYearTextView, 1); + mMonthDayYearLayout.addView(mHeaderYearTextView); + mMonthDayYearLayout.addView(mMonthAndDayLayout); } else { - mDateLayout.addView(mHeaderYearTextView, 2); + mMonthDayYearLayout.addView(mMonthAndDayLayout); + mMonthDayYearLayout.addView(mHeaderYearTextView); } - // Position Day and Month Views + // Position Day and Month views within the MonthAndDay view. + mMonthAndDayLayout.removeAllViews(); if (viewIndices[MONTH_INDEX] > viewIndices[DAY_INDEX]) { - // Day View is first mMonthAndDayLayout.addView(mHeaderDayOfMonthTextView); mMonthAndDayLayout.addView(mHeaderMonthTextView); } else { - // Month View is first mMonthAndDayLayout.addView(mHeaderMonthTextView); mMonthAndDayLayout.addView(mHeaderDayOfMonthTextView); } @@ -329,12 +334,6 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i switch (viewIndex) { case MONTH_AND_DAY_VIEW: - ObjectAnimator pulseAnimator = getPulseAnimator(mMonthAndDayLayout, 0.9f, - 1.05f); - if (mDelayAnimation) { - pulseAnimator.setStartDelay(ANIMATION_DELAY); - mDelayAnimation = false; - } mDayPickerView.onDateChanged(); if (mCurrentView != viewIndex) { mMonthAndDayLayout.setSelected(true); @@ -342,19 +341,13 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i mAnimator.setDisplayedChild(MONTH_AND_DAY_VIEW); mCurrentView = viewIndex; } - pulseAnimator.start(); - int flags = DateUtils.FORMAT_SHOW_DATE; - String dayString = DateUtils.formatDateTime(mContext, millis, flags); + final int flags = DateUtils.FORMAT_SHOW_DATE; + final String dayString = DateUtils.formatDateTime(mContext, millis, flags); mAnimator.setContentDescription(mDayPickerDescription + ": " + dayString); mAnimator.announceForAccessibility(mSelectDay); break; case YEAR_VIEW: - pulseAnimator = getPulseAnimator(mHeaderYearTextView, 0.85f, 1.1f); - if (mDelayAnimation) { - pulseAnimator.setStartDelay(ANIMATION_DELAY); - mDelayAnimation = false; - } mYearPickerView.onDateChanged(); if (mCurrentView != viewIndex) { mMonthAndDayLayout.setSelected(false); @@ -362,9 +355,8 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i mAnimator.setDisplayedChild(YEAR_VIEW); mCurrentView = viewIndex; } - pulseAnimator.start(); - CharSequence yearString = mYearFormat.format(millis); + final CharSequence yearString = mYearFormat.format(millis); mAnimator.setContentDescription(mYearPickerDescription + ": " + yearString); mAnimator.announceForAccessibility(mSelectYear); break; @@ -789,25 +781,4 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i } }; } - - /** - * Render an animator to pulsate a view in place. - * @param labelToAnimate the view to pulsate. - * @return The animator object. Use .start() to begin. - */ - public static ObjectAnimator getPulseAnimator(View labelToAnimate, float decreaseRatio, - float increaseRatio) { - Keyframe k0 = Keyframe.ofFloat(0f, 1f); - Keyframe k1 = Keyframe.ofFloat(0.275f, decreaseRatio); - Keyframe k2 = Keyframe.ofFloat(0.69f, increaseRatio); - Keyframe k3 = Keyframe.ofFloat(1f, 1f); - - PropertyValuesHolder scaleX = PropertyValuesHolder.ofKeyframe(View.SCALE_X, k0, k1, k2, k3); - PropertyValuesHolder scaleY = PropertyValuesHolder.ofKeyframe(View.SCALE_Y, k0, k1, k2, k3); - ObjectAnimator pulseAnimator = - ObjectAnimator.ofPropertyValuesHolder(labelToAnimate, scaleX, scaleY); - pulseAnimator.setDuration(PULSE_ANIMATOR_DURATION); - - return pulseAnimator; - } } diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java index c44bd46..ca4095e 100644 --- a/core/java/android/widget/DayPickerView.java +++ b/core/java/android/widget/DayPickerView.java @@ -73,11 +73,6 @@ class DayPickerView extends ListView implements AbsListView.OnScrollListener, private ScrollStateRunnable mScrollStateChangedRunnable = new ScrollStateRunnable(this); - public DayPickerView(Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - public DayPickerView(Context context, DatePickerController controller) { super(context); init(); diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java index 5d21e0b..602f955 100644 --- a/core/java/android/widget/RemoteViewsAdapter.java +++ b/core/java/android/widget/RemoteViewsAdapter.java @@ -157,7 +157,7 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback RemoteViewsAdapter adapter; final AppWidgetManager mgr = AppWidgetManager.getInstance(context); if ((adapter = mAdapter.get()) != null) { - mgr.bindRemoteViewsService(context.getPackageName(), appWidgetId, + mgr.bindRemoteViewsService(context.getOpPackageName(), appWidgetId, intent, asBinder()); } else { Slog.w(TAG, "bind: adapter was null"); diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java index ae44047..8917f39 100644 --- a/core/java/android/widget/TimePickerClockDelegate.java +++ b/core/java/android/widget/TimePickerClockDelegate.java @@ -18,7 +18,6 @@ package android.widget; import android.content.Context; import android.content.res.Configuration; -import android.content.res.Resources; import android.content.res.TypedArray; import android.os.Parcel; import android.os.Parcelable; @@ -34,6 +33,7 @@ import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import com.android.internal.R; +import java.text.DateFormatSymbols; import java.util.Calendar; import java.util.Locale; @@ -149,7 +149,7 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate { mAmPmStrings = getAmPmStrings(context); // am/pm - View amPmView = mDelegator.findViewById(R.id.amPm); + final View amPmView = mDelegator.findViewById(R.id.amPm); if (amPmView instanceof Button) { mAmPmSpinner = null; mAmPmSpinnerInput = null; diff --git a/core/java/android/widget/TimePickerSpinnerDelegate.java b/core/java/android/widget/TimePickerSpinnerDelegate.java index dd1bf4f..6169d2e 100644 --- a/core/java/android/widget/TimePickerSpinnerDelegate.java +++ b/core/java/android/widget/TimePickerSpinnerDelegate.java @@ -16,9 +16,6 @@ package android.widget; -import android.animation.Keyframe; -import android.animation.ObjectAnimator; -import android.animation.PropertyValuesHolder; import android.content.Context; import android.content.res.ColorStateList; import android.content.res.Configuration; @@ -43,6 +40,7 @@ import android.view.accessibility.AccessibilityNodeInfo; import com.android.internal.R; +import java.text.DateFormatSymbols; import java.util.ArrayList; import java.util.Calendar; import java.util.Locale; @@ -73,12 +71,6 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im private static final int HOURS_IN_HALF_DAY = 12; - // Delay in ms before starting the pulse animation - private static final int PULSE_ANIMATOR_DELAY = 300; - - // Duration in ms of the pulse animation - private static final int PULSE_ANIMATOR_DURATION = 544; - private TextView mHourView; private TextView mMinuteView; private TextView mAmPmTextView; @@ -98,7 +90,6 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im private String mDoublePlaceholderText; private String mDeletedKeyFormat; private boolean mInKbMode; - private boolean mIsTimeValid = true; private ArrayList<Integer> mTypedTimes = new ArrayList<Integer>(); private Node mLegalTimesTree; private int mAmKeyCode; @@ -215,14 +206,14 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im mHourView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - setCurrentItemShowing(HOUR_INDEX, true, false, true); + setCurrentItemShowing(HOUR_INDEX, true, true); tryVibrate(); } }); mMinuteView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - setCurrentItemShowing(MINUTE_INDEX, true, false, true); + setCurrentItemShowing(MINUTE_INDEX, true, true); tryVibrate(); } }); @@ -245,7 +236,7 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im private void updateRadialPicker(int index) { mRadialTimePickerView.initialize(mInitialHourOfDay, mInitialMinute, mIs24HourView); - setCurrentItemShowing(index, false, true, true); + setCurrentItemShowing(index, false, true); } private int computeMaxWidthOfNumbers(int max) { @@ -633,7 +624,7 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im updateHeaderHour(newValue, false); String announcement = String.format("%d", newValue); if (mAllowAutoAdvance && autoAdvance) { - setCurrentItemShowing(MINUTE_INDEX, true, true, false); + setCurrentItemShowing(MINUTE_INDEX, true, false); announcement += ". " + mSelectMinutes; } else { mRadialTimePickerView.setContentDescription( @@ -753,11 +744,9 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im /** * Show either Hours or Minutes. */ - private void setCurrentItemShowing(int index, boolean animateCircle, boolean delayLabelAnimate, - boolean announce) { + private void setCurrentItemShowing(int index, boolean animateCircle, boolean announce) { mRadialTimePickerView.setCurrentItemShowing(index, animateCircle); - TextView labelToAnimate; if (index == HOUR_INDEX) { int hours = mRadialTimePickerView.getCurrentHour(); if (!mIs24HourView) { @@ -767,24 +756,16 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im if (announce) { mRadialTimePickerView.announceForAccessibility(mSelectHours); } - labelToAnimate = mHourView; } else { int minutes = mRadialTimePickerView.getCurrentMinute(); mRadialTimePickerView.setContentDescription(mMinutePickerDescription + ": " + minutes); if (announce) { mRadialTimePickerView.announceForAccessibility(mSelectMinutes); } - labelToAnimate = mMinuteView; } mHourView.setSelected(index == HOUR_INDEX); mMinuteView.setSelected(index == MINUTE_INDEX); - - ObjectAnimator pulseAnimator = getPulseAnimator(labelToAnimate, 0.85f, 1.1f); - if (delayLabelAnimate) { - pulseAnimator.setStartDelay(PULSE_ANIMATOR_DELAY); - } - pulseAnimator.start(); } /** @@ -980,7 +961,7 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im if (!mIs24HourView) { updateAmPmDisplay(hour < 12 ? AM : PM); } - setCurrentItemShowing(mRadialTimePickerView.getCurrentItemShowing(), true, true, true); + setCurrentItemShowing(mRadialTimePickerView.getCurrentItemShowing(), true, true); onValidationChanged(true); } else { boolean[] enteredZeros = {false, false}; @@ -1289,26 +1270,4 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im return false; } } - - /** - * Render an animator to pulsate a view in place. - * - * @param labelToAnimate the view to pulsate. - * @return The animator object. Use .start() to begin. - */ - private static ObjectAnimator getPulseAnimator(View labelToAnimate, float decreaseRatio, - float increaseRatio) { - final Keyframe k0 = Keyframe.ofFloat(0f, 1f); - final Keyframe k1 = Keyframe.ofFloat(0.275f, decreaseRatio); - final Keyframe k2 = Keyframe.ofFloat(0.69f, increaseRatio); - final Keyframe k3 = Keyframe.ofFloat(1f, 1f); - - PropertyValuesHolder scaleX = PropertyValuesHolder.ofKeyframe(View.SCALE_X, k0, k1, k2, k3); - PropertyValuesHolder scaleY = PropertyValuesHolder.ofKeyframe(View.SCALE_Y, k0, k1, k2, k3); - ObjectAnimator pulseAnimator = - ObjectAnimator.ofPropertyValuesHolder(labelToAnimate, scaleX, scaleY); - pulseAnimator.setDuration(PULSE_ANIMATOR_DURATION); - - return pulseAnimator; - } } diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java index 0b15eb6..818efaa 100644 --- a/core/java/android/widget/Toolbar.java +++ b/core/java/android/widget/Toolbar.java @@ -156,6 +156,12 @@ public class Toolbar extends ViewGroup { private boolean mCollapsible; + private final Runnable mShowOverflowMenuRunnable = new Runnable() { + @Override public void run() { + showOverflowMenu(); + } + }; + public Toolbar(Context context) { this(context, null); } @@ -404,6 +410,7 @@ public class Toolbar extends ViewGroup { ensureLogoView(); if (mLogoView.getParent() == null) { addSystemView(mLogoView); + updateChildVisibilityForExpandedActionView(mLogoView); } } else if (mLogoView != null && mLogoView.getParent() != null) { removeView(mLogoView); @@ -545,6 +552,7 @@ public class Toolbar extends ViewGroup { } if (mTitleTextView.getParent() == null) { addSystemView(mTitleTextView); + updateChildVisibilityForExpandedActionView(mTitleTextView); } } else if (mTitleTextView != null && mTitleTextView.getParent() != null) { removeView(mTitleTextView); @@ -598,6 +606,7 @@ public class Toolbar extends ViewGroup { } if (mSubtitleTextView.getParent() == null) { addSystemView(mSubtitleTextView); + updateChildVisibilityForExpandedActionView(mSubtitleTextView); } } else if (mSubtitleTextView != null && mSubtitleTextView.getParent() != null) { removeView(mSubtitleTextView); @@ -728,6 +737,7 @@ public class Toolbar extends ViewGroup { ensureNavButtonView(); if (mNavButtonView.getParent() == null) { addSystemView(mNavButtonView); + updateChildVisibilityForExpandedActionView(mNavButtonView); } } else if (mNavButtonView != null && mNavButtonView.getParent() != null) { removeView(mNavButtonView); @@ -979,6 +989,13 @@ public class Toolbar extends ViewGroup { @Override protected Parcelable onSaveInstanceState() { SavedState state = new SavedState(super.onSaveInstanceState()); + + if (mExpandedMenuPresenter != null && mExpandedMenuPresenter.mCurrentExpandedItem != null) { + state.expandedMenuItemId = mExpandedMenuPresenter.mCurrentExpandedItem.getItemId(); + } + + state.isOverflowOpen = isOverflowMenuShowing(); + return state; } @@ -986,6 +1003,29 @@ public class Toolbar extends ViewGroup { protected void onRestoreInstanceState(Parcelable state) { final SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); + + final Menu menu = mMenuView != null ? mMenuView.peekMenu() : null; + if (ss.expandedMenuItemId != 0 && mExpandedMenuPresenter != null && menu != null) { + final MenuItem item = menu.findItem(ss.expandedMenuItemId); + if (item != null) { + item.expandActionView(); + } + } + + if (ss.isOverflowOpen) { + postShowOverflowMenu(); + } + } + + private void postShowOverflowMenu() { + removeCallbacks(mShowOverflowMenuRunnable); + post(mShowOverflowMenuRunnable); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + removeCallbacks(mShowOverflowMenuRunnable); } /** @@ -1591,6 +1631,13 @@ public class Toolbar extends ViewGroup { } } + private void updateChildVisibilityForExpandedActionView(View child) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (lp.mViewType != LayoutParams.EXPANDED && child != mMenuView) { + child.setVisibility(mExpandedActionView != null ? GONE : VISIBLE); + } + } + /** * Force the toolbar to collapse to zero-height during measurement if * it could be considered "empty" (no visible elements with nonzero measured size) @@ -1673,8 +1720,13 @@ public class Toolbar extends ViewGroup { } static class SavedState extends BaseSavedState { + public int expandedMenuItemId; + public boolean isOverflowOpen; + public SavedState(Parcel source) { super(source); + expandedMenuItemId = source.readInt(); + isOverflowOpen = source.readInt() != 0; } public SavedState(Parcelable superState) { @@ -1684,6 +1736,8 @@ public class Toolbar extends ViewGroup { @Override public void writeToParcel(Parcel out, int flags) { super.writeToParcel(out, flags); + out.writeInt(expandedMenuItemId); + out.writeInt(isOverflowOpen ? 1 : 0); } public static final Creator<SavedState> CREATOR = new Creator<SavedState>() { diff --git a/core/java/android/widget/YearPickerView.java b/core/java/android/widget/YearPickerView.java index 94c21dc..2bf07f9 100644 --- a/core/java/android/widget/YearPickerView.java +++ b/core/java/android/widget/YearPickerView.java @@ -70,15 +70,6 @@ class YearPickerView extends ListView implements AdapterView.OnItemClickListener R.dimen.datepicker_year_picker_padding_top); setPadding(0, paddingTop, 0, 0); - // Use Theme attributes if possible - final TypedArray a = context.obtainStyledAttributes( - attrs, R.styleable.DatePicker, defStyleAttr, defStyleRes); - final int colorResId = a.getResourceId(R.styleable.DatePicker_yearListSelectorColor, - R.color.datepicker_default_circle_background_color_holo_light); - mYearSelectedCircleColor = res.getColor(colorResId); - - a.recycle(); - setOnItemClickListener(this); setDividerHeight(0); } |
