diff options
Diffstat (limited to 'core/java/android')
68 files changed, 879 insertions, 829 deletions
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java index 7c13dbe..0aa8fdd 100644 --- a/core/java/android/animation/AnimatorSet.java +++ b/core/java/android/animation/AnimatorSet.java @@ -636,6 +636,7 @@ public final class AnimatorSet extends Animator { anim.mNodes = new ArrayList<Node>(); anim.mSortedNodes = new ArrayList<Node>(); anim.mReversible = mReversible; + anim.mSetListener = null; // Walk through the old nodes list, cloning each node and adding it to the new nodemap. // One problem is that the old node dependencies point to nodes in the old AnimatorSet. diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 89a9692..701ab1d 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -4756,7 +4756,7 @@ public class Activity extends ContextThemeWrapper * Activity through a returning activity transition, giving you the resultCode * and any additional data from it. This method will only be called if the activity * set a result code other than {@link #RESULT_CANCELED} and it supports activity - * transitions with {@link Window#FEATURE_CONTENT_TRANSITIONS}. + * transitions with {@link Window#FEATURE_ACTIVITY_TRANSITIONS}. * * <p>The purpose of this function is to let the called Activity send a hint about * its state so that this underlying Activity can prepare to be exposed. A call to @@ -5781,7 +5781,7 @@ public class Activity extends ContextThemeWrapper * When {@link android.app.ActivityOptions#makeSceneTransitionAnimation(Activity, * android.view.View, String)} was used to start an Activity, <var>callback</var> * will be called to handle shared elements on the <i>launched</i> Activity. This requires - * {@link Window#FEATURE_CONTENT_TRANSITIONS}. + * {@link Window#FEATURE_ACTIVITY_TRANSITIONS}. * * @param callback Used to manipulate shared element transitions on the launched Activity. */ @@ -5797,7 +5797,7 @@ public class Activity extends ContextThemeWrapper * android.view.View, String)} was used to start an Activity, <var>callback</var> * will be called to handle shared elements on the <i>launching</i> Activity. Most * calls will only come when returning from the started Activity. - * This requires {@link Window#FEATURE_CONTENT_TRANSITIONS}. + * This requires {@link Window#FEATURE_ACTIVITY_TRANSITIONS}. * * @param callback Used to manipulate shared element transitions on the launching Activity. */ diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 394b183..677fcef 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -2295,6 +2295,13 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM reply.writeNoException(); return true; } + + case BOOT_ANIMATION_COMPLETE_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + bootAnimationComplete(); + reply.writeNoException(); + return true; + } } return super.onTransact(code, data, reply, flags); @@ -5301,5 +5308,16 @@ class ActivityManagerProxy implements IActivityManager reply.recycle(); } + @Override + public void bootAnimationComplete() throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + mRemote.transact(BOOT_ANIMATION_COMPLETE_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } + private IBinder mRemote; } diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index 213c7f6..cd6a4f5 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -414,7 +414,7 @@ public class ActivityOptions { * exit Transition. The position of the shared element in the launched Activity will be the * epicenter of its entering Transition. * - * <p>This requires {@link android.view.Window#FEATURE_CONTENT_TRANSITIONS} to be + * <p>This requires {@link android.view.Window#FEATURE_ACTIVITY_TRANSITIONS} to be * enabled on the calling Activity to cause an exit transition. The same must be in * the called Activity to get an entering transition.</p> * @param activity The Activity whose window contains the shared elements. @@ -438,7 +438,7 @@ public class ActivityOptions { * will be used as the epicenter for the exit Transition. The position of the associated * shared element in the launched Activity will be the epicenter of its entering Transition. * - * <p>This requires {@link android.view.Window#FEATURE_CONTENT_TRANSITIONS} to be + * <p>This requires {@link android.view.Window#FEATURE_ACTIVITY_TRANSITIONS} to be * enabled on the calling Activity to cause an exit transition. The same must be in * the called Activity to get an entering transition.</p> * @param activity The Activity whose window contains the shared elements. @@ -453,7 +453,7 @@ public class ActivityOptions { public static ActivityOptions makeSceneTransitionAnimation(Activity activity, Pair<View, String>... sharedElements) { ActivityOptions opts = new ActivityOptions(); - if (!activity.getWindow().hasFeature(Window.FEATURE_CONTENT_TRANSITIONS)) { + if (!activity.getWindow().hasFeature(Window.FEATURE_ACTIVITY_TRANSITIONS)) { opts.mAnimationType = ANIM_DEFAULT; return opts; } diff --git a/core/java/android/app/ActivityTransitionState.java b/core/java/android/app/ActivityTransitionState.java index ad4a22b..bc2e6ca 100644 --- a/core/java/android/app/ActivityTransitionState.java +++ b/core/java/android/app/ActivityTransitionState.java @@ -144,7 +144,7 @@ class ActivityTransitionState { } public void setEnterActivityOptions(Activity activity, ActivityOptions options) { - if (activity.getWindow().hasFeature(Window.FEATURE_CONTENT_TRANSITIONS) + if (activity.getWindow().hasFeature(Window.FEATURE_ACTIVITY_TRANSITIONS) && options != null && mEnterActivityOptions == null && mEnterTransitionCoordinator == null && options.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) { @@ -272,7 +272,7 @@ class ActivityTransitionState { } public void startExitOutTransition(Activity activity, Bundle options) { - if (!activity.getWindow().hasFeature(Window.FEATURE_CONTENT_TRANSITIONS)) { + if (!activity.getWindow().hasFeature(Window.FEATURE_ACTIVITY_TRANSITIONS)) { return; } ActivityOptions activityOptions = new ActivityOptions(options); diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 404268c..6860683 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -66,6 +66,7 @@ import android.view.Display; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; +import com.android.internal.util.UserIcons; import dalvik.system.VMRuntime; @@ -1645,30 +1646,6 @@ final class ApplicationPackageManager extends PackageManager { /** * @hide */ - public void addCrossProfileIntentsForPackage(String packageName, - int sourceUserId, int targetUserId) { - try { - mPM.addCrossProfileIntentsForPackage(packageName, sourceUserId, targetUserId); - } catch (RemoteException e) { - // Should never happen! - } - } - - /** - * @hide - */ - public void removeCrossProfileIntentsForPackage(String packageName, - int sourceUserId, int targetUserId) { - try { - mPM.removeCrossProfileIntentsForPackage(packageName, sourceUserId, targetUserId); - } catch (RemoteException e) { - // Should never happen! - } - } - - /** - * @hide - */ @Override public void clearCrossProfileIntentFilters(int sourceUserId) { try { @@ -1684,7 +1661,11 @@ final class ApplicationPackageManager extends PackageManager { */ public Drawable loadItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo) { if (itemInfo.showUserIcon != UserHandle.USER_NULL) { - return new BitmapDrawable(getUserManager().getUserIcon(itemInfo.showUserIcon)); + Bitmap bitmap = getUserManager().getUserIcon(itemInfo.showUserIcon); + if (bitmap == null) { + return UserIcons.getDefaultUserIcon(itemInfo.showUserIcon, /* light= */ false); + } + return new BitmapDrawable(bitmap); } Drawable dr = null; if (itemInfo.packageName != null) { diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java index 8227915..b09f169 100644 --- a/core/java/android/app/BackStackRecord.java +++ b/core/java/android/app/BackStackRecord.java @@ -38,7 +38,6 @@ import android.view.ViewTreeObserver; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; -import java.util.Collection; final class BackStackState implements Parcelable { final int[] mOps; @@ -745,13 +744,8 @@ final class BackStackRecord extends FragmentTransaction implements SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>(); SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>(); - calculateFragments(firstOutFragments, lastInFragments); - - TransitionState state = null; - if (firstOutFragments.size() != 0 || lastInFragments.size() != 0) { - state = beginTransition(firstOutFragments, lastInFragments, false); - } + beginTransition(firstOutFragments, lastInFragments, false); Op op = mHead; while (op != null) { @@ -842,10 +836,6 @@ final class BackStackRecord extends FragmentTransaction implements if (mAddToBackStack) { mManager.addBackStackState(this); } - - if (state != null) { - updateTransitionEndState(state, firstOutFragments, lastInFragments, false); - } } private static void setFirstOut(SparseArray<Fragment> fragments, Fragment fragment) { @@ -920,43 +910,6 @@ final class BackStackRecord extends FragmentTransaction implements op = op.next; } - - if (!haveTransitions(firstOutFragments, lastInFragments, false)) { - firstOutFragments.clear(); - lastInFragments.clear(); - } - } - - /** - * @return true if custom transitions exist on any fragment in firstOutFragments or - * lastInFragments or false otherwise. - */ - private static boolean haveTransitions(SparseArray<Fragment> firstOutFragments, - SparseArray<Fragment> lastInFragments, boolean isBack) { - for (int i = firstOutFragments.size() - 1; i >= 0; i--) { - Fragment f = firstOutFragments.valueAt(i); - if (isBack) { - if (f.getReturnTransition() != null || - f.getSharedElementReturnTransition() != null) { - return true; - } - } else if (f.getExitTransition() != null) { - return true; - } - } - - for (int i = lastInFragments.size() - 1; i >= 0; i--) { - Fragment f = lastInFragments.valueAt(i); - if (isBack) { - if (f.getReenterTransition() != null) { - return true; - } - } else if (f.getEnterTransition() != null || - f.getSharedElementEnterTransition() != null) { - return true; - } - } - return false; } /** @@ -1003,11 +956,6 @@ final class BackStackRecord extends FragmentTransaction implements op = op.next; } - - if (!haveTransitions(firstOutFragments, lastInFragments, true)) { - firstOutFragments.clear(); - lastInFragments.clear(); - } } /** @@ -1038,8 +986,8 @@ final class BackStackRecord extends FragmentTransaction implements * @param isBack true if this is popping the back stack or false if this is a * forward operation. * @return The TransitionState used to complete the operation of the transition - * in {@link #updateTransitionEndState(android.app.BackStackRecord.TransitionState, - * android.util.SparseArray, android.util.SparseArray, boolean)}. + * in {@link #setNameOverrides(android.app.BackStackRecord.TransitionState, java.util.ArrayList, + * java.util.ArrayList)}. */ private TransitionState beginTransition(SparseArray<Fragment> firstOutFragments, SparseArray<Fragment> lastInFragments, boolean isBack) { @@ -1050,16 +998,11 @@ final class BackStackRecord extends FragmentTransaction implements // add any, then no views will be targeted. state.nonExistentView = new View(mManager.mActivity); - ArrayMap<String, View> tempViews1 = new ArrayMap<String, View>(); - ArrayMap<String, View> tempViews2 = new ArrayMap<String, View>(); - ArrayList<String> tempNames = new ArrayList<String>(); - ArrayList<View> tempViewList = new ArrayList<View>(); - // Go over all leaving fragments. for (int i = 0; i < firstOutFragments.size(); i++) { int containerId = firstOutFragments.keyAt(i); configureTransitions(containerId, state, isBack, firstOutFragments, - lastInFragments, tempViews1, tempViews2, tempNames, tempViewList); + lastInFragments); } // Now go over all entering fragments that didn't have a leaving fragment. @@ -1067,28 +1010,33 @@ final class BackStackRecord extends FragmentTransaction implements int containerId = lastInFragments.keyAt(i); if (firstOutFragments.get(containerId) == null) { configureTransitions(containerId, state, isBack, firstOutFragments, - lastInFragments, tempViews1, tempViews2, tempNames, tempViewList); + lastInFragments); } } + return state; + } - if (state.overallTransitions.size() == 0) { - state = null; + private static Transition cloneTransition(Transition transition) { + if (transition != null) { + transition = transition.clone(); } - return state; + return transition; } private static Transition getEnterTransition(Fragment inFragment, boolean isBack) { if (inFragment == null) { return null; } - return isBack ? inFragment.getReenterTransition() : inFragment.getEnterTransition(); + return cloneTransition(isBack ? inFragment.getReenterTransition() : + inFragment.getEnterTransition()); } private static Transition getExitTransition(Fragment outFragment, boolean isBack) { if (outFragment == null) { return null; } - return isBack ? outFragment.getReturnTransition() : outFragment.getExitTransition(); + return cloneTransition(isBack ? outFragment.getReturnTransition() : + outFragment.getExitTransition()); } private static Transition getSharedElementTransition(Fragment inFragment, Fragment outFragment, @@ -1096,34 +1044,32 @@ final class BackStackRecord extends FragmentTransaction implements if (inFragment == null || outFragment == null) { return null; } - return isBack ? outFragment.getSharedElementReturnTransition() : - inFragment.getSharedElementEnterTransition(); + return cloneTransition(isBack ? outFragment.getSharedElementReturnTransition() : + inFragment.getSharedElementEnterTransition()); } - private static Transition captureExitingViews(Transition exitTransition, Fragment outFragment, - ArrayList<View> viewList) { + private static ArrayList<View> captureExitingViews(Transition exitTransition, + Fragment outFragment) { + ArrayList<View> viewList = null; if (exitTransition != null) { + viewList = new ArrayList<View>(); View root = outFragment.getView(); - viewList.clear(); root.captureTransitioningViews(viewList); - if (viewList.isEmpty()) { - exitTransition = null; - } else { - addTransitioningViews(exitTransition, viewList); - } + addTargets(exitTransition, viewList); } - return exitTransition; + return viewList; } private ArrayMap<String, View> remapSharedElements(TransitionState state, Fragment outFragment, - ArrayMap<String, View> namedViews, ArrayMap<String, View> tempViews2, boolean isBack) { + boolean isBack) { + ArrayMap<String, View> namedViews = new ArrayMap<String, View>(); if (mSharedElementSourceNames != null) { outFragment.getView().findNamedViews(namedViews); if (isBack) { namedViews.retainAll(mSharedElementTargetNames); } else { namedViews = remapNames(mSharedElementSourceNames, mSharedElementTargetNames, - namedViews, tempViews2); + namedViews); } } @@ -1147,41 +1093,94 @@ final class BackStackRecord extends FragmentTransaction implements * We will add to the views before the end state of the transition is captured so that the * views will appear. At the start of the transition, we clear the list of targets so that * we can restore the state of the transition and use it again. + * + * <p>The shared element transition maps its shared elements immediately prior to + * capturing the final state of the Transition.</p> */ - private void prepareEnterTransition(TransitionState state, final Transition enterTransition, - final View container, final Fragment inFragment) { - if (enterTransition != null) { - final ArrayList<View> enteringViews = new ArrayList<View>(); - final View nonExistentView = state.nonExistentView; - enterTransition.addTarget(state.nonExistentView); - enterTransition.addListener(new Transition.TransitionListenerAdapter() { - @Override - public void onTransitionStart(Transition transition) { - transition.removeListener(this); - transition.removeTarget(nonExistentView); - int numViews = enteringViews.size(); - for (int i = 0; i < numViews; i++) { - transition.removeTarget(enteringViews.get(i)); - } - } - }); - container.getViewTreeObserver().addOnPreDrawListener( - new ViewTreeObserver.OnPreDrawListener() { - @Override - public boolean onPreDraw() { - container.getViewTreeObserver().removeOnPreDrawListener(this); + private ArrayList<View> addTransitionTargets(final TransitionState state, + final Transition enterTransition, final Transition sharedElementTransition, + final Transition overallTransition, final View container, + final Fragment inFragment, final Fragment outFragment, + final ArrayList<View> hiddenFragmentViews, final boolean isBack) { + if (enterTransition == null && sharedElementTransition == null && + overallTransition == null) { + return null; + } + final ArrayList<View> enteringViews = new ArrayList<View>(); + container.getViewTreeObserver().addOnPreDrawListener( + new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + container.getViewTreeObserver().removeOnPreDrawListener(this); + + // Don't include any newly-hidden fragments in the transition. + excludeHiddenFragments(hiddenFragmentViews, inFragment.mContainerId, + overallTransition); + + if (sharedElementTransition != null) { + ArrayMap<String, View> namedViews = mapSharedElementsIn( + state, isBack, inFragment); + + setEpicenterIn(namedViews, state); + + callSharedElementEnd(state, inFragment, outFragment, isBack, + namedViews); + } + + if (enterTransition != null) { View view = inFragment.getView(); if (view != null) { view.captureTransitioningViews(enteringViews); - addTransitioningViews(enterTransition, enteringViews); + addTargets(enterTransition, enteringViews); } - return true; + setSharedElementEpicenter(enterTransition, state); } - }); - setSharedElementEpicenter(enterTransition, state); + return true; + } + }); + return enteringViews; + } + + private void callSharedElementEnd(TransitionState state, Fragment inFragment, + Fragment outFragment, boolean isBack, ArrayMap<String, View> namedViews) { + SharedElementCallback sharedElementCallback = isBack ? + outFragment.mEnterTransitionCallback : + inFragment.mEnterTransitionCallback; + ArrayList<String> names = new ArrayList<String>(namedViews.keySet()); + ArrayList<View> views = new ArrayList<View>(namedViews.values()); + sharedElementCallback.onSharedElementEnd(names, views, null); + } + + private void setEpicenterIn(ArrayMap<String, View> namedViews, TransitionState state) { + if (mSharedElementTargetNames != null && !namedViews.isEmpty()) { + // now we know the epicenter of the entering transition. + View epicenter = namedViews + .get(mSharedElementTargetNames.get(0)); + if (epicenter != null) { + state.enteringEpicenterView = epicenter; + } } } + private ArrayMap<String, View> mapSharedElementsIn(TransitionState state, + boolean isBack, Fragment inFragment) { + // Now map the shared elements in the incoming fragment + ArrayMap<String, View> namedViews = mapEnteringSharedElements(state, inFragment, isBack); + + // remap shared elements and set the name mapping used + // in the shared element transition. + if (isBack) { + inFragment.mExitTransitionCallback.onMapSharedElements( + mSharedElementTargetNames, namedViews); + setBackNameOverrides(state, namedViews, true); + } else { + inFragment.mEnterTransitionCallback.onMapSharedElements( + mSharedElementTargetNames, namedViews); + setNameOverrides(state, namedViews, true); + } + return namedViews; + } + private static Transition mergeTransitions(Transition enterTransition, Transition exitTransition, Transition sharedElementTransition, Fragment inFragment, boolean isBack) { @@ -1209,26 +1208,16 @@ final class BackStackRecord extends FragmentTransaction implements * Configures custom transitions for a specific fragment container. * * @param containerId The container ID of the fragments to configure the transition for. - * @param state The Transition State to be shared with {@link #updateTransitionEndState( - * android.app.BackStackRecord.TransitionState, android.util.SparseArray, - * android.util.SparseArray, boolean)} later. + * @param state The Transition State keeping track of the executing transitions. * @param firstOutFragments The list of first fragments to be removed, keyed on the * container ID. * @param lastInFragments The list of last fragments to be added, keyed on the * container ID. * @param isBack true if this is popping the back stack or false if this is a * forward operation. - * @param tempViews1 A temporary mapping of names to Views, used to avoid allocation - * inside a loop. - * @param tempViews2 A temporary mapping of names to Views, used to avoid allocation - * inside a loop. - * @param tempNames A temporary list of Strings, used to avoid allocation inside a loop. - * @param tempViewList A temporary list of Views, used to avoid allocation inside a loop. */ private void configureTransitions(int containerId, TransitionState state, boolean isBack, - SparseArray<Fragment> firstOutFragments, SparseArray<Fragment> lastInFragments, - ArrayMap<String, View> tempViews1, ArrayMap<String, View> tempViews2, - ArrayList<String> tempNames, ArrayList<View> tempViewList) { + SparseArray<Fragment> firstOutFragments, SparseArray<Fragment> lastInFragments) { ViewGroup sceneRoot = (ViewGroup) mManager.mContainer.findViewById(containerId); if (sceneRoot != null) { Fragment inFragment = lastInFragments.get(containerId); @@ -1238,146 +1227,150 @@ final class BackStackRecord extends FragmentTransaction implements Transition sharedElementTransition = getSharedElementTransition(inFragment, outFragment, isBack); Transition exitTransition = getExitTransition(outFragment, isBack); - exitTransition = captureExitingViews(exitTransition, outFragment, tempViewList); - ArrayMap<String, View> namedViews = tempViews1; - namedViews.clear(); - if (sharedElementTransition != null) { - namedViews = remapSharedElements(state, - outFragment, namedViews, tempViews2, isBack); + if (enterTransition == null && sharedElementTransition == null && + exitTransition == null) { + return; // no transitions! + } + ArrayList<View> exitingViews = captureExitingViews(exitTransition, outFragment); + if (exitingViews == null || exitingViews.isEmpty()) { + exitTransition = null; } - // Notify the start of the transition. - SharedElementCallback callback = isBack ? - outFragment.mEnterTransitionCallback : - inFragment.mEnterTransitionCallback; - tempNames.clear(); - tempNames.addAll(namedViews.keySet()); - tempViewList.clear(); - tempViewList.addAll(namedViews.values()); - callback.onSharedElementStart(tempNames, tempViewList, null); + ArrayMap<String, View> namedViews = null; + if (sharedElementTransition != null) { + namedViews = remapSharedElements(state, outFragment, isBack); + + // Notify the start of the transition. + SharedElementCallback callback = isBack ? + outFragment.mEnterTransitionCallback : + inFragment.mEnterTransitionCallback; + ArrayList<String> names = new ArrayList<String>(namedViews.keySet()); + ArrayList<View> views = new ArrayList<View>(namedViews.values()); + callback.onSharedElementStart(names, views, null); + } // Set the epicenter of the exit transition - if (mSharedElementTargetNames != null && exitTransition != null) { + if (mSharedElementTargetNames != null && exitTransition != null && namedViews != null) { View epicenterView = namedViews.get(mSharedElementTargetNames.get(0)); if (epicenterView != null) { setEpicenter(exitTransition, epicenterView); } } - prepareEnterTransition(state, enterTransition, sceneRoot, inFragment); - Transition transition = mergeTransitions(enterTransition, exitTransition, sharedElementTransition, inFragment, isBack); if (transition != null) { - state.overallTransitions.put(containerId, transition); + ArrayList<View> hiddenFragments = new ArrayList<View>(); + ArrayList<View> enteringViews = addTransitionTargets(state, enterTransition, + sharedElementTransition, transition, sceneRoot, inFragment, outFragment, + hiddenFragments, isBack); + transition.setNameOverrides(state.nameOverrides); // We want to exclude hidden views later, so we need a non-null list in the // transition now. transition.excludeTarget(state.nonExistentView, true); // Now exclude all currently hidden fragments. - excludeHiddenFragments(state, containerId, transition); - cleanupHiddenFragments(transition, state); + excludeHiddenFragments(hiddenFragments, containerId, transition); TransitionManager.beginDelayedTransition(sceneRoot, transition); + // Remove the view targeting after the transition starts + removeTargetedViewsFromTransitions(sceneRoot, state.nonExistentView, + enterTransition, enteringViews, exitTransition, exitingViews, + transition, hiddenFragments); } } } /** + * After the transition has started, remove all targets that we added to the transitions + * so that the transitions are left in a clean state. + */ + private void removeTargetedViewsFromTransitions( + final ViewGroup sceneRoot, final View nonExistingView, + final Transition enterTransition, final ArrayList<View> enteringViews, + final Transition exitTransition, final ArrayList<View> exitingViews, + final Transition overallTransition, final ArrayList<View> hiddenViews) { + if (enterTransition != null || exitTransition != null) { + sceneRoot.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + sceneRoot.getViewTreeObserver().removeOnPreDrawListener(this); + if (enterTransition != null) { + enterTransition.removeTarget(nonExistingView); + removeTargets(enterTransition, enteringViews); + } + if (exitTransition != null) { + removeTargets(exitTransition, exitingViews); + } + int numViews = hiddenViews.size(); + for (int i = 0; i < numViews; i++) { + overallTransition.excludeTarget(hiddenViews.get(i), false); + } + overallTransition.excludeTarget(nonExistingView, false); + return true; + } + }); + } + } + + private static void removeTargets(Transition transition, ArrayList<View> views) { + int numViews = views.size(); + for (int i = 0; i < numViews; i++) { + transition.removeTarget(views.get(i)); + } + } + + private static void addTargets(Transition transition, ArrayList<View> views) { + int numViews = views.size(); + for (int i = 0; i < numViews; i++) { + transition.addTarget(views.get(i)); + } + } + + /** * Remaps a name-to-View map, substituting different names for keys. * * @param inMap A list of keys found in the map, in the order in toGoInMap * @param toGoInMap A list of keys to use for the new map, in the order of inMap * @param namedViews The current mapping - * @param tempMap A temporary mapping that will be filled with the new values. - * @return tempMap after it has been mapped with the new names as keys. + * @return a new Map after it has been mapped with the new names as keys. */ private static ArrayMap<String, View> remapNames(ArrayList<String> inMap, - ArrayList<String> toGoInMap, ArrayMap<String, View> namedViews, - ArrayMap<String, View> tempMap) { - tempMap.clear(); + ArrayList<String> toGoInMap, ArrayMap<String, View> namedViews) { + ArrayMap<String, View> remappedViews = new ArrayMap<String, View>(); if (!namedViews.isEmpty()) { int numKeys = inMap.size(); for (int i = 0; i < numKeys; i++) { View view = namedViews.get(inMap.get(i)); + if (view != null) { - tempMap.put(toGoInMap.get(i), view); + remappedViews.put(toGoInMap.get(i), view); } } } - return tempMap; + return remappedViews; } /** - * After making all fragment changes, this updates the custom transitions to take into - * account the entering views and any remapping. + * Maps shared elements to views in the entering fragment. * * @param state The transition State as returned from {@link #beginTransition( * android.util.SparseArray, android.util.SparseArray, boolean)}. - * @param outFragments The list of first fragments to be removed, keyed on the - * container ID. - * @param inFragments The list of last fragments to be added, keyed on the - * container ID. + * @param inFragment The last fragment to be added. * @param isBack true if this is popping the back stack or false if this is a * forward operation. */ - private void updateTransitionEndState(TransitionState state, SparseArray<Fragment> outFragments, - SparseArray<Fragment> inFragments, boolean isBack) { - ArrayMap<String, View> tempViews1 = new ArrayMap<String, View>(); - ArrayMap<String, View> tempViews2 = new ArrayMap<String, View>(); - ArrayList<String> tempNames = new ArrayList<String>(); - ArrayList<View> tempViews = new ArrayList<View>(); - - int numInFragments = inFragments.size(); - for (int i = 0; i < numInFragments; i++) { - Fragment inFragment = inFragments.valueAt(i); - tempViews1.clear(); - ArrayMap<String, View> namedViews = mapEnteringSharedElements(inFragment, tempViews1, - tempViews2, isBack); - // remap shared elements and set the name mapping used in the shared element transition. - if (isBack) { - inFragment.mExitTransitionCallback.onMapSharedElements( - mSharedElementTargetNames, namedViews); - setBackNameOverrides(state, namedViews, true); - } else { - inFragment.mEnterTransitionCallback.onMapSharedElements( - mSharedElementTargetNames, namedViews); - setNameOverrides(state, namedViews, true); - } - - if (mSharedElementTargetNames != null && !namedViews.isEmpty()) { - // now we know the epicenter of the entering transition. - View epicenter = namedViews.get(mSharedElementTargetNames.get(0)); - if (epicenter != null) { - state.enteringEpicenterView = epicenter; - } - } - - int containerId = inFragments.keyAt(i); - SharedElementCallback sharedElementCallback = isBack ? - outFragments.get(containerId).mEnterTransitionCallback : - inFragment.mEnterTransitionCallback; - tempNames.clear(); - tempNames.addAll(namedViews.keySet()); - tempViews.clear(); - tempViews.addAll(namedViews.values()); - sharedElementCallback.onSharedElementEnd(tempNames, tempViews, null); - } - - // Don't include any newly-hidden fragments in the transition. - excludeHiddenFragments(state); - } - - private ArrayMap<String, View> mapEnteringSharedElements(Fragment inFragment, - ArrayMap<String, View> namedViews, ArrayMap<String, View> tempViews2, boolean isBack) { + private ArrayMap<String, View> mapEnteringSharedElements(TransitionState state, + Fragment inFragment, boolean isBack) { + ArrayMap<String, View> namedViews = new ArrayMap<String, View>(); View root = inFragment.getView(); if (root != null) { if (mSharedElementSourceNames != null) { root.findNamedViews(namedViews); if (isBack) { namedViews = remapNames(mSharedElementSourceNames, - mSharedElementTargetNames, namedViews, tempViews2); + mSharedElementTargetNames, namedViews); } else { namedViews.retainAll(mSharedElementTargetNames); } @@ -1386,21 +1379,7 @@ final class BackStackRecord extends FragmentTransaction implements return namedViews; } - private static void cleanupHiddenFragments(Transition transition, TransitionState state) { - final ArrayList<View> hiddenViews = state.hiddenFragmentViews; - transition.addListener(new Transition.TransitionListenerAdapter() { - @Override - public void onTransitionStart(Transition transition) { - transition.removeListener(this); - int numViews = hiddenViews.size(); - for (int i = 0; i < numViews; i++) { - transition.excludeTarget(hiddenViews.get(i), false); - } - } - }); - } - - private void excludeHiddenFragments(TransitionState state, int containerId, + private void excludeHiddenFragments(final ArrayList<View> hiddenFragmentViews, int containerId, Transition transition) { if (mManager.mAdded != null) { for (int i = 0; i < mManager.mAdded.size(); i++) { @@ -1408,44 +1387,19 @@ final class BackStackRecord extends FragmentTransaction implements if (fragment.mView != null && fragment.mContainer != null && fragment.mContainerId == containerId) { if (fragment.mHidden) { - if (!state.hiddenFragmentViews.contains(fragment.mView)) { + if (!hiddenFragmentViews.contains(fragment.mView)) { transition.excludeTarget(fragment.mView, true); - state.hiddenFragmentViews.add(fragment.mView); + hiddenFragmentViews.add(fragment.mView); } } else { transition.excludeTarget(fragment.mView, false); - state.hiddenFragmentViews.remove(fragment.mView); + hiddenFragmentViews.remove(fragment.mView); } } } } } - private void excludeHiddenFragments(TransitionState state) { - int numTransitions = state.overallTransitions.size(); - for (int i = 0; i < numTransitions; i++) { - Transition transition = state.overallTransitions.valueAt(i); - int containerId = state.overallTransitions.keyAt(i); - excludeHiddenFragments(state, containerId, transition); - } - } - - private static void addTransitioningViews(Transition transition, final Collection<View> views) { - for (View view : views) { - transition.addTarget(view); - } - - transition.addListener(new Transition.TransitionListenerAdapter() { - @Override - public void onTransitionStart(Transition transition) { - transition.removeListener(this); - for (View view : views) { - transition.removeTarget(view); - } - } - }); - } - private static void setEpicenter(Transition transition, View view) { final Rect epicenter = new Rect(); view.getBoundsOnScreen(epicenter); @@ -1566,10 +1520,7 @@ final class BackStackRecord extends FragmentTransaction implements if (doStateMove) { mManager.moveToState(mManager.mCurState, FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle, true); - if (state != null) { - updateTransitionEndState(state, firstOutFragments, lastInFragments, true); - state = null; - } + state = null; } if (mIndex >= 0) { @@ -1609,11 +1560,14 @@ final class BackStackRecord extends FragmentTransaction implements for (int i = 0; i < count; i++) { String source = mSharedElementSourceNames.get(i); String originalTarget = mSharedElementTargetNames.get(i); - String target = namedViews.get(originalTarget).getTransitionName(); - if (isEnd) { - setNameOverride(state.nameOverrides, source, target); - } else { - setNameOverride(state.nameOverrides, target, source); + View view = namedViews.get(originalTarget); + if (view != null) { + String target = view.getTransitionName(); + if (isEnd) { + setNameOverride(state.nameOverrides, source, target); + } else { + setNameOverride(state.nameOverrides, target, source); + } } } } @@ -1649,10 +1603,7 @@ final class BackStackRecord extends FragmentTransaction implements } public class TransitionState { - public SparseArray<Transition> overallTransitions = new SparseArray<Transition>(); public ArrayMap<String, String> nameOverrides = new ArrayMap<String, String>(); - public ArrayList<View> hiddenFragmentViews = new ArrayList<View>(); - public View enteringEpicenterView; public View nonExistentView; } diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 91a0aed..64eafb0 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -2237,7 +2237,6 @@ class ContextImpl extends Context { mUser = user; mPackageInfo = packageInfo; - mContentResolver = new ApplicationContentResolver(this, mainThread, user); mResourcesManager = ResourcesManager.getInstance(); mDisplay = display; mOverrideConfiguration = overrideConfiguration; @@ -2284,6 +2283,8 @@ class ContextImpl extends Context { mOpPackageName = mBasePackageName; } } + + mContentResolver = new ApplicationContentResolver(this, mainThread, user); } void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) { diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java index 9c7728e..9ca150d 100644 --- a/core/java/android/app/EnterTransitionCoordinator.java +++ b/core/java/android/app/EnterTransitionCoordinator.java @@ -136,11 +136,12 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { if (sharedElements.isEmpty() || !sharedElements.valueAt(0).isLayoutRequested()) { viewsReady(sharedElements); } else { - sharedElements.valueAt(0).getViewTreeObserver() + final View sharedElement = sharedElements.valueAt(0); + sharedElement.getViewTreeObserver() .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { - sharedElements.valueAt(0).getViewTreeObserver().removeOnPreDrawListener(this); + sharedElement.getViewTreeObserver().removeOnPreDrawListener(this); viewsReady(sharedElements); return true; } @@ -328,7 +329,10 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { @Override public void run() { if (mAnimations++ < MIN_ANIMATION_FRAMES) { - getDecor().postOnAnimation(this); + View decorView = getDecor(); + if (decorView != null) { + decorView.postOnAnimation(this); + } } else if (mResultReceiver != null) { mResultReceiver.send(MSG_HIDE_SHARED_ELEMENTS, null); mResultReceiver = null; // all done sending messages. diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java index 672ef7b..4374622 100644 --- a/core/java/android/app/Fragment.java +++ b/core/java/android/app/Fragment.java @@ -166,11 +166,12 @@ final class FragmentState implements Parcelable { * activity: if the activity is stopped, no fragments inside of it can be * started; when the activity is destroyed, all fragments will be destroyed. * - * <p>All subclasses of Fragment must include a public empty constructor. + * <p>All subclasses of Fragment must include a public no-argument constructor. * The framework will often re-instantiate a fragment class when needed, * in particular during state restore, and needs to be able to find this - * constructor to instantiate it. If the empty constructor is not available, - * a runtime exception will occur in some cases during state restore. + * constructor to instantiate it. If the no-argument constructor is not + * available, a runtime exception will occur in some cases during state + * restore. * * <p>Topics covered here: * <ol> diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 9483680..8fa1fd5 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -327,6 +327,8 @@ public interface IActivityManager extends IInterface { public void notifyActivityDrawn(IBinder token) throws RemoteException; public ActivityOptions getActivityOptions(IBinder token) throws RemoteException; + public void bootAnimationComplete() throws RemoteException; + public void setImmersive(IBinder token, boolean immersive) throws RemoteException; public boolean isImmersive(IBinder token) throws RemoteException; public boolean isTopActivityImmersive() throws RemoteException; @@ -772,4 +774,5 @@ public interface IActivityManager extends IInterface { 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; + int BOOT_ANIMATION_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+237; } diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl index 7d4512b..bdcff38 100644 --- a/core/java/android/app/INotificationManager.aidl +++ b/core/java/android/app/INotificationManager.aidl @@ -71,7 +71,6 @@ interface INotificationManager ComponentName getEffectsSuppressor(); boolean matchesCallFilter(in Bundle extras); - boolean matchesCallFilterAsUser(in Bundle extras, int userId); ZenModeConfig getZenModeConfig(); boolean setZenModeConfig(in ZenModeConfig config); diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index f9e4895..31b39eb 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -2680,6 +2680,8 @@ public class Notification implements Parcelable contentView.setViewVisibility(R.id.line3, View.GONE); contentView.setViewVisibility(R.id.overflow_divider, View.GONE); contentView.setViewVisibility(R.id.progress, View.GONE); + contentView.setViewVisibility(R.id.chronometer, View.GONE); + contentView.setViewVisibility(R.id.time, View.GONE); } private RemoteViews applyStandardTemplate(int resId) { @@ -2775,8 +2777,6 @@ public class Notification implements Parcelable contentView.setViewVisibility(R.id.time, View.VISIBLE); contentView.setLong(R.id.time, "setTime", mWhen); } - } else { - contentView.setViewVisibility(R.id.time, View.GONE); } // Adjust padding depending on line count and font size. diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java index e2f175c..836f682 100644 --- a/core/java/android/app/admin/DeviceAdminReceiver.java +++ b/core/java/android/app/admin/DeviceAdminReceiver.java @@ -221,6 +221,12 @@ public class DeviceAdminReceiver extends BroadcastReceiver { */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_PROFILE_PROVISIONING_COMPLETE = + "android.app.action.PROFILE_PROVISIONING_COMPLETE"; + + /** + * Do not use, replaced by {@link #ACTION_PROFILE_PROVISIONING_COMPLETE} + */ + private static final String LEGACY_ACTION_PROFILE_PROVISIONING_COMPLETE = "android.app.action.ACTION_PROFILE_PROVISIONING_COMPLETE"; /** @@ -431,6 +437,9 @@ public class DeviceAdminReceiver extends BroadcastReceiver { onPasswordExpiring(context, intent); } else if (ACTION_PROFILE_PROVISIONING_COMPLETE.equals(action)) { onProfileProvisioningComplete(context, intent); + // TODO: remove when nobody depends on this + } else if (LEGACY_ACTION_PROFILE_PROVISIONING_COMPLETE.equals(action)) { + onProfileProvisioningComplete(context, intent); } else if (ACTION_LOCK_TASK_ENTERING.equals(action)) { String pkg = intent.getStringExtra(EXTRA_LOCK_TASK_PACKAGE); onLockTaskModeEntering(context, intent, pkg); diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 5b02313..13ed8d1 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -38,6 +38,7 @@ import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; +import android.security.Credentials; import android.service.restrictions.RestrictionsReceiver; import android.util.Log; @@ -49,6 +50,8 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.net.InetSocketAddress; import java.net.Proxy; +import java.security.PrivateKey; +import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; @@ -111,7 +114,7 @@ public class DevicePolicyManager { */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_PROVISION_MANAGED_PROFILE - = "android.app.action.ACTION_PROVISION_MANAGED_PROFILE"; + = "android.app.action.PROVISION_MANAGED_PROFILE"; /** * A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that allows @@ -138,21 +141,23 @@ 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.deviceAdminPackageName"; + = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME"; /** * A String extra that, holds the email address of the account which a managed profile is * created for. Used with {@link #ACTION_PROVISION_MANAGED_PROFILE} and * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE}. * + * <p> This extra is part of the {@link #EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE}. + * * <p> If the {@link #ACTION_PROVISION_MANAGED_PROFILE} intent that starts managed provisioning * contains this extra, it is forwarded in the * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE} intent to the mobile * device management application that was set as the profile owner during provisioning. * It is usually used to avoid that the user has to enter their email address twice. */ - public static final String KEY_PROVISIONING_EMAIL_ADDRESS - = "android.app.key.PROVISIONING_EMAIL_ADDRESS"; + public static final String EXTRA_PROVISIONING_EMAIL_ADDRESS + = "android.app.extra.PROVISIONING_EMAIL_ADDRESS"; /** * A String extra holding the time zone {@link android.app.AlarmManager} that the device @@ -1838,6 +1843,32 @@ public class DevicePolicyManager { } /** + * Called by a device or profile owner to install a certificate and private key pair. The + * keypair will be visible to all apps within the profile. + * + * @param who Which {@link DeviceAdminReceiver} this request is associated with. + * @param privKey The private key to install. + * @param cert The certificate to install. + * @param alias The private key alias under which to install the certificate. If a certificate + * with that alias already exists, it will be overwritten. + * @return {@code true} if the keys were installed, {@code false} otherwise. + */ + public boolean installKeyPair(ComponentName who, PrivateKey privKey, Certificate cert, + String alias) { + try { + final byte[] pemCert = Credentials.convertToPem(cert); + return mService.installKeyPair(who, privKey.getEncoded(), pemCert, alias); + } catch (CertificateException e) { + Log.w(TAG, "Error encoding certificate", e); + } catch (IOException e) { + Log.w(TAG, "Error writing certificate", e); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + return false; + } + + /** * Returns the alias of a given CA certificate in the certificate store, or null if it * doesn't exist. */ @@ -3245,11 +3276,15 @@ public class DevicePolicyManager { * Called by profile or device owners to update {@link Settings.Secure} settings. Validation * that the value of the setting is in the correct form for the setting type should be performed * by the caller. - * <p>The settings that can be updated with this method are: + * <p>The settings that can be updated by a profile or device owner with this method are: * <ul> * <li>{@link Settings.Secure#DEFAULT_INPUT_METHOD}</li> * <li>{@link Settings.Secure#SKIP_FIRST_USE_HINTS}</li> * </ul> + * <p>A device owner can additionally update the following settings: + * <ul> + * <li>{@link Settings.Secure#LOCATION_MODE}</li> + * </ul> * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param setting The name of the setting to update. * @param value The value to update the setting to. diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 57d8b95..c8e1780 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -126,6 +126,8 @@ interface IDevicePolicyManager { void uninstallCaCert(in ComponentName admin, in String alias); void enforceCanManageCaCerts(in ComponentName admin); + boolean installKeyPair(in ComponentName who, in byte[] privKeyBuffer, in byte[] certBuffer, String alias); + void addPersistentPreferredActivity(in ComponentName admin, in IntentFilter filter, in ComponentName activity); void clearPackagePersistentPreferredActivities(in ComponentName admin, String packageName); diff --git a/core/java/android/app/job/JobParameters.java b/core/java/android/app/job/JobParameters.java index 724856a..62734f2 100644 --- a/core/java/android/app/job/JobParameters.java +++ b/core/java/android/app/job/JobParameters.java @@ -32,12 +32,15 @@ public class JobParameters implements Parcelable { private final int jobId; private final PersistableBundle extras; private final IBinder callback; + private final boolean overrideDeadlineExpired; /** @hide */ - public JobParameters(int jobId, PersistableBundle extras, IBinder callback) { + public JobParameters(IBinder callback, int jobId, PersistableBundle extras, + boolean overrideDeadlineExpired) { this.jobId = jobId; this.extras = extras; this.callback = callback; + this.overrideDeadlineExpired = overrideDeadlineExpired; } /** @@ -56,6 +59,16 @@ public class JobParameters implements Parcelable { return extras; } + /** + * For jobs with {@link android.app.job.JobInfo.Builder#setOverrideDeadline(long)} set, this + * provides an easy way to tell whether the job is being executed due to the deadline + * expiring. Note: If the job is running because its deadline expired, it implies that its + * constraints will not be met. + */ + public boolean isOverrideDeadlineExpired() { + return overrideDeadlineExpired; + } + /** @hide */ public IJobCallback getCallback() { return IJobCallback.Stub.asInterface(callback); @@ -65,6 +78,7 @@ public class JobParameters implements Parcelable { jobId = in.readInt(); extras = in.readPersistableBundle(); callback = in.readStrongBinder(); + overrideDeadlineExpired = in.readInt() == 1; } @Override @@ -77,6 +91,7 @@ public class JobParameters implements Parcelable { dest.writeInt(jobId); dest.writePersistableBundle(extras); dest.writeStrongBinder(callback); + dest.writeInt(overrideDeadlineExpired ? 1 : 0); } public static final Creator<JobParameters> CREATOR = new Creator<JobParameters>() { diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java index d77a77b..2276229 100644 --- a/core/java/android/bluetooth/BluetoothGatt.java +++ b/core/java/android/bluetooth/BluetoothGatt.java @@ -51,6 +51,7 @@ public final class BluetoothGatt implements BluetoothProfile { private int mConnState; private final Object mStateLock = new Object(); private Boolean mDeviceBusy = false; + private Boolean mIsCongested = false; private int mTransport; private static final int CONN_STATE_IDLE = 0; @@ -616,7 +617,7 @@ public final class BluetoothGatt implements BluetoothProfile { + " congested=" + congested); if (!address.equals(mDevice.getAddress())) return; try { - mCallback.onConnectionCongested(BluetoothGatt.this, congested); + mIsCongested = congested; } catch (Exception ex) { Log.w(TAG, "Unhandled exception in callback", ex); } diff --git a/core/java/android/bluetooth/BluetoothGattCallback.java b/core/java/android/bluetooth/BluetoothGattCallback.java index 19900ec..a915620 100644 --- a/core/java/android/bluetooth/BluetoothGattCallback.java +++ b/core/java/android/bluetooth/BluetoothGattCallback.java @@ -152,18 +152,4 @@ public abstract class BluetoothGattCallback { */ public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) { } - - /** - * Callback indicating that a remote device connection congestestion status has changed. - * - * An application should refrain from sending additional data to a remote device when - * a callback is received with the congested flag set to true. Once the congestion status - * is cleared up, the application will receive an additional callback with the congested - * flag set to false. - * - * @param gatt The GATT client associated with the remote device - * @param congested true, if the connection is currently congested - */ - public void onConnectionCongested(BluetoothGatt gatt, boolean congested) { - } } diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java index c8df60e..a7f117b 100644 --- a/core/java/android/bluetooth/BluetoothGattServer.java +++ b/core/java/android/bluetooth/BluetoothGattServer.java @@ -48,6 +48,7 @@ public final class BluetoothGattServer implements BluetoothProfile { private BluetoothAdapter mAdapter; private IBluetoothGatt mService; private BluetoothGattServerCallback mCallback; + private Boolean mIsCongested = false; private Object mServerIfLock = new Object(); private int mServerIf; @@ -297,7 +298,7 @@ public final class BluetoothGattServer implements BluetoothProfile { if (device == null) return; try { - mCallback.onConnectionCongested(device, congested); + mIsCongested = congested; } catch (Exception ex) { Log.w(TAG, "Unhandled exception in callback", ex); } diff --git a/core/java/android/bluetooth/BluetoothGattServerCallback.java b/core/java/android/bluetooth/BluetoothGattServerCallback.java index b0ddc26..1dd06f2 100644 --- a/core/java/android/bluetooth/BluetoothGattServerCallback.java +++ b/core/java/android/bluetooth/BluetoothGattServerCallback.java @@ -145,18 +145,4 @@ public abstract class BluetoothGattServerCallback { */ public void onNotificationSent(BluetoothDevice device, int status) { } - - /** - * Callback indicating that a remote device connection congestestion status has changed. - * - * An application should refrain from sending additional data (notifications, indications - * etc.) to a remote device when a callback is received with the congested flag set - * to true. Once the congestion status is cleared up, the application will receive an - * additional callback with the congested flag set to false. - * - * @param device The remote device that triggered the congestion state change - * @param congested true, if the connection is currently congested - */ - public void onConnectionCongested(BluetoothDevice device, boolean congested) { - } } diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java index b2b48e8..a09fee9 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -1763,7 +1763,7 @@ public abstract class ContentResolver { * @param extras any extras to pass to the SyncAdapter. */ public static void requestSync(Account account, String authority, Bundle extras) { - requestSyncAsUser(account, authority, UserHandle.getCallingUserId(), extras); + requestSyncAsUser(account, authority, UserHandle.myUserId(), extras); } /** @@ -1938,7 +1938,7 @@ public abstract class ContentResolver { * @param sync true if the provider should be synced when tickles are received for it */ public static void setSyncAutomatically(Account account, String authority, boolean sync) { - setSyncAutomaticallyAsUser(account, authority, sync, UserHandle.getCallingUserId()); + setSyncAutomaticallyAsUser(account, authority, sync, UserHandle.myUserId()); } /** @@ -2165,7 +2165,7 @@ public abstract class ContentResolver { * @param sync the master auto-sync setting that applies to all the providers and accounts */ public static void setMasterSyncAutomatically(boolean sync) { - setMasterSyncAutomaticallyAsUser(sync, UserHandle.getCallingUserId()); + setMasterSyncAutomaticallyAsUser(sync, UserHandle.myUserId()); } /** @@ -2297,7 +2297,7 @@ public abstract class ContentResolver { * @return true if there is a pending sync with the matching account and authority */ public static boolean isSyncPending(Account account, String authority) { - return isSyncPendingAsUser(account, authority, UserHandle.getCallingUserId()); + return isSyncPendingAsUser(account, authority, UserHandle.myUserId()); } /** diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index f979a0c..4f20705 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -2037,6 +2037,7 @@ public abstract class Context { * argument for use by system server and other multi-user aware code. * @hide */ + @SystemApi public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags, UserHandle user) { throw new RuntimeException("Not implemented. Must override in a subclass."); } @@ -3062,6 +3063,14 @@ public abstract class Context { * "content://foo". It will not remove any prefix grants that exist at a * higher level. * + * <p>Prior to {@link android.os.Build.VERSION_CODES#L}, if you did not have + * regular permission access to a Uri, but had received access to it through + * a specific Uri permission grant, you could not revoke that grant with this + * function and a {@link SecurityException} would be thrown. As of + * {@link android.os.Build.VERSION_CODES#L}, this function will not throw a security exception, + * but will remove whatever permission grants to the Uri had been given to the app + * (or none).</p> + * * @param uri The Uri you would like to revoke access to. * @param modeFlags The desired access modes. Any combination of * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index 8d3126d..641f843 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -657,6 +657,7 @@ public class ActivityInfo extends ComponentInfo softInputMode = orig.softInputMode; uiOptions = orig.uiOptions; parentActivityName = orig.parentActivityName; + maxRecents = orig.maxRecents; } /** @@ -728,6 +729,7 @@ public class ActivityInfo extends ComponentInfo dest.writeInt(uiOptions); dest.writeString(parentActivityName); dest.writeInt(persistableMode); + dest.writeInt(maxRecents); } public static final Parcelable.Creator<ActivityInfo> CREATOR @@ -754,5 +756,6 @@ public class ActivityInfo extends ComponentInfo uiOptions = source.readInt(); parentActivityName = source.readString(); persistableMode = source.readInt(); + maxRecents = source.readInt(); } } diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 3e1f60a..6d9c58b 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -259,12 +259,6 @@ interface IPackageManager { void addCrossProfileIntentFilter(in IntentFilter intentFilter, String ownerPackage, int ownerUserId, int sourceUserId, int targetUserId, int flags); - void addCrossProfileIntentsForPackage(in String packageName, int sourceUserId, - int targetUserId); - - void removeCrossProfileIntentsForPackage(String packageName, int sourceUserId, - int targetUserId); - void clearCrossProfileIntentFilters(int sourceUserId, String ownerPackage, int ownerUserId); /** diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java index d49bc50..5ee0b67 100644 --- a/core/java/android/content/pm/LauncherApps.java +++ b/core/java/android/content/pm/LauncherApps.java @@ -500,11 +500,18 @@ public class LauncherApps { } } - /** STOPSHIP remove when launcher 3 has been updated */ + /** + * TODO Remove after 2014-09-22 + * @hide + */ public void addCallback(Callback callback) { registerCallback(callback); } - /** STOPSHIP remove when launcher 3 has been updated */ + + /** + * TODO Remove after 2014-09-22 + * @hide + */ public void removeCallback(Callback callback) { unregisterCallback(callback); } diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 5ce968b..8f3d90f 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -3893,22 +3893,6 @@ public abstract class PackageManager { public abstract void clearCrossProfileIntentFilters(int sourceUserId); /** - * Forwards all intents for {@link packageName} for user {@link sourceUserId} to user - * {@link targetUserId}. - * @hide - */ - public abstract void addCrossProfileIntentsForPackage(String packageName, - int sourceUserId, int targetUserId); - - /** - * Removes all intents for {@link packageName} for user {@link sourceUserId} to user - * {@link targetUserId}. - * @hide - */ - public abstract void removeCrossProfileIntentsForPackage(String packageName, - int sourceUserId, int targetUserId); - - /** * @hide */ public abstract Drawable loadItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo); diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index ddb0a6d..ffde7ce 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -3308,7 +3308,8 @@ public class PackageParser { info.softInputMode = target.info.softInputMode; info.uiOptions = target.info.uiOptions; info.parentActivityName = target.info.parentActivityName; - + info.maxRecents = target.info.maxRecents; + Activity a = new Activity(mParseActivityAliasArgs, info); if (outError[0] != null) { sa.recycle(); diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java index 843f117..0057f61 100644 --- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java @@ -143,7 +143,6 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession { } checkNotClosed(); - checkLegalToCapture(); handler = checkHandler(handler, callback); @@ -166,7 +165,6 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession { } checkNotClosed(); - checkLegalToCapture(); handler = checkHandler(handler, callback); @@ -188,7 +186,6 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession { } checkNotClosed(); - checkLegalToCapture(); handler = checkHandler(handler, callback); @@ -211,7 +208,6 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession { } checkNotClosed(); - checkLegalToCapture(); handler = checkHandler(handler, callback); @@ -542,13 +538,6 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession { } } - private void checkLegalToCapture() { - if (mAborting) { - throw new IllegalStateException( - "Session is aborting captures; new captures are not permitted"); - } - } - private void checkNotClosed() { if (mClosed) { throw new IllegalStateException( diff --git a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java index 3c0e0e4..c36b63a 100644 --- a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java +++ b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java @@ -165,6 +165,12 @@ public class LegacyMetadataMapper { private static void mapCharacteristicsFromParameters(CameraMetadataNative m, Camera.Parameters p) { + + /* + * colorCorrection.* + */ + m.set(COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES, + new int[] { COLOR_CORRECTION_ABERRATION_MODE_FAST }); /* * control.ae* */ @@ -196,6 +202,12 @@ public class LegacyMetadataMapper { mapJpeg(m, p); /* + * noiseReduction.* + */ + m.set(NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES, + new int[] { NOISE_REDUCTION_MODE_FAST }); + + /* * scaler.* */ mapScaler(m, p); @@ -626,6 +638,7 @@ public class LegacyMetadataMapper { // Note: We only list public keys. Native HALs should list ALL keys regardless of visibility. Key<?> availableKeys[] = new Key<?>[] { + CameraCharacteristics.COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES , CameraCharacteristics.CONTROL_AE_AVAILABLE_ANTIBANDING_MODES , CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES , CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES , @@ -642,6 +655,7 @@ public class LegacyMetadataMapper { CameraCharacteristics.JPEG_AVAILABLE_THUMBNAIL_SIZES , CameraCharacteristics.LENS_FACING , CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS , + CameraCharacteristics.NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES , CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES , CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_STREAMS , CameraCharacteristics.REQUEST_PARTIAL_RESULT_COUNT , @@ -653,6 +667,7 @@ public class LegacyMetadataMapper { CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE , CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE , CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE , + CameraCharacteristics.SENSOR_INFO_TIMESTAMP_SOURCE , CameraCharacteristics.SENSOR_ORIENTATION , CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES , CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT , @@ -676,6 +691,7 @@ public class LegacyMetadataMapper { */ { CaptureRequest.Key<?> defaultAvailableKeys[] = new CaptureRequest.Key<?>[] { + CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE, CaptureRequest.CONTROL_AE_ANTIBANDING_MODE, CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, CaptureRequest.CONTROL_AE_LOCK, @@ -699,6 +715,7 @@ public class LegacyMetadataMapper { CaptureRequest.JPEG_THUMBNAIL_QUALITY, CaptureRequest.JPEG_THUMBNAIL_SIZE, CaptureRequest.LENS_FOCAL_LENGTH, + CaptureRequest.NOISE_REDUCTION_MODE, CaptureRequest.SCALER_CROP_REGION, CaptureRequest.STATISTICS_FACE_DETECT_MODE, }; @@ -723,6 +740,7 @@ public class LegacyMetadataMapper { */ { CaptureResult.Key<?> defaultAvailableKeys[] = new CaptureResult.Key<?>[] { + CaptureResult.COLOR_CORRECTION_ABERRATION_MODE , CaptureResult.CONTROL_AE_ANTIBANDING_MODE , CaptureResult.CONTROL_AE_EXPOSURE_COMPENSATION , CaptureResult.CONTROL_AE_LOCK , @@ -740,6 +758,7 @@ public class LegacyMetadataMapper { CaptureResult.JPEG_QUALITY , CaptureResult.JPEG_THUMBNAIL_QUALITY , CaptureResult.LENS_FOCAL_LENGTH , + CaptureResult.NOISE_REDUCTION_MODE , CaptureResult.REQUEST_PIPELINE_DEPTH , CaptureResult.SCALER_CROP_REGION , CaptureResult.SENSOR_TIMESTAMP , @@ -844,6 +863,13 @@ public class LegacyMetadataMapper { m.set(SENSOR_INFO_PHYSICAL_SIZE, new SizeF(width, height)); // in mm } + + /* + * sensor.info.timestampSource + */ + { + m.set(SENSOR_INFO_TIMESTAMP_SOURCE, SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN); + } } private static void mapStatistics(CameraMetadataNative m, Parameters p) { diff --git a/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java b/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java index 42ee4fa..42fe897 100644 --- a/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java +++ b/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java @@ -80,6 +80,20 @@ public class LegacyRequestMapper { } } + /* + * colorCorrection.* + */ + // colorCorrection.aberrationMode + { + int aberrationMode = ParamsUtils.getOrDefault(request, + COLOR_CORRECTION_ABERRATION_MODE, + /*defaultValue*/COLOR_CORRECTION_ABERRATION_MODE_FAST); + + if (aberrationMode != COLOR_CORRECTION_ABERRATION_MODE_FAST) { + Log.w(TAG, "convertRequestToMetadata - Ignoring unsupported " + + "colorCorrection.aberrationMode = " + aberrationMode); + } + } /* * control.ae* @@ -419,6 +433,21 @@ public class LegacyRequestMapper { } } } + + /* + * noiseReduction.* + */ + // noiseReduction.mode + { + int mode = ParamsUtils.getOrDefault(request, + NOISE_REDUCTION_MODE, + /*defaultValue*/NOISE_REDUCTION_MODE_FAST); + + if (mode != NOISE_REDUCTION_MODE_FAST) { + Log.w(TAG, "convertRequestToMetadata - Ignoring unsupported " + + "noiseReduction.mode = " + mode); + } + } } private static boolean checkForCompleteGpsData(Location location) { diff --git a/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java b/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java index ddaa6ee..bad1d28 100644 --- a/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java +++ b/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java @@ -28,14 +28,12 @@ import android.hardware.camera2.legacy.ParameterUtils.ZoomData; import android.hardware.camera2.params.MeteringRectangle; import android.hardware.camera2.utils.ListUtils; import android.hardware.camera2.utils.ParamsUtils; -import android.location.Location; import android.util.Log; import android.util.Size; import java.util.ArrayList; import java.util.List; -import static com.android.internal.util.Preconditions.*; import static android.hardware.camera2.CaptureResult.*; /** @@ -73,7 +71,7 @@ public class LegacyResultMapper { result = new CameraMetadataNative(mCachedResult); cached = true; } else { - result = convertResultMetadata(legacyRequest, timestamp); + result = convertResultMetadata(legacyRequest); cached = false; // Always cache a *copy* of the metadata result, @@ -106,12 +104,9 @@ public class LegacyResultMapper { * Generate capture result metadata from the legacy camera request. * * @param legacyRequest a non-{@code null} legacy request containing the latest parameters - * @param timestamp the timestamp to use for this result in nanoseconds. - * * @return a {@link CameraMetadataNative} object containing result metadata. */ - private static CameraMetadataNative convertResultMetadata(LegacyRequest legacyRequest, - long timestamp) { + private static CameraMetadataNative convertResultMetadata(LegacyRequest legacyRequest) { CameraCharacteristics characteristics = legacyRequest.characteristics; CaptureRequest request = legacyRequest.captureRequest; Size previewSize = legacyRequest.previewSize; @@ -125,6 +120,15 @@ public class LegacyResultMapper { request.get(CaptureRequest.SCALER_CROP_REGION), previewSize, params); /* + * colorCorrection + */ + // colorCorrection.aberrationMode + { + // Always hardcoded to FAST + result.set(COLOR_CORRECTION_ABERRATION_MODE, COLOR_CORRECTION_ABERRATION_MODE_FAST); + } + + /* * control */ @@ -274,7 +278,12 @@ public class LegacyResultMapper { Log.w(TAG, "Null thumbnail size received from parameters."); } - // TODO: Remaining result metadata tags conversions. + /* + * noiseReduction.* + */ + // noiseReduction.mode + result.set(NOISE_REDUCTION_MODE, NOISE_REDUCTION_MODE_FAST); + return result; } diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java index e6ff17b..e6da670 100644 --- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java +++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java @@ -374,6 +374,9 @@ public class RequestThreadManager { } mIntermediateBufferSize = bestPreviewDimen; + mParams.setPreviewSize(mIntermediateBufferSize.getWidth(), + mIntermediateBufferSize.getHeight()); + if (DEBUG) { Log.d(TAG, "Intermediate buffer selected with dimens: " + bestPreviewDimen.toString()); diff --git a/core/java/android/hardware/hdmi/HdmiTvClient.java b/core/java/android/hardware/hdmi/HdmiTvClient.java index c37fb5b..9d92fd9 100644 --- a/core/java/android/hardware/hdmi/HdmiTvClient.java +++ b/core/java/android/hardware/hdmi/HdmiTvClient.java @@ -36,9 +36,9 @@ public final class HdmiTvClient extends HdmiClient { private static final String TAG = "HdmiTvClient"; /** - * Size of MHL scratchpad register. + * Size of MHL register for vendor command */ - public static final int SCRATCHPAD_DATA_SIZE = 16; + public static final int VENDOR_DATA_SIZE = 16; HdmiTvClient(IHdmiControlService service) { super(service); @@ -332,31 +332,31 @@ public final class HdmiTvClient extends HdmiClient { } /** - * Interface used to get incoming MHL scratchpad command. + * Interface used to get incoming MHL vendor command. */ - public interface HdmiMhlScratchpadCommandListener { + public interface HdmiMhlVendorCommandListener { void onReceived(int portId, int offset, int length, byte[] data); } /** - * Set {@link HdmiMhlScratchpadCommandListener} to get incoming MHL sSratchpad command. + * Set {@link HdmiMhlVendorCommandListener} to get incoming MHL vendor command. * - * @param listener to receive incoming MHL Scratchpad command + * @param listener to receive incoming MHL vendor command */ - public void setHdmiMhlScratchpadCommandListener(HdmiMhlScratchpadCommandListener listener) { + public void setHdmiMhlVendorCommandListener(HdmiMhlVendorCommandListener listener) { if (listener == null) { throw new IllegalArgumentException("listener must not be null."); } try { - mService.addHdmiMhlScratchpadCommandListener(getListenerWrapper(listener)); + mService.addHdmiMhlVendorCommandListener(getListenerWrapper(listener)); } catch (RemoteException e) { - Log.e(TAG, "failed to set hdmi mhl scratchpad command listener: ", e); + Log.e(TAG, "failed to set hdmi mhl vendor command listener: ", e); } } - private IHdmiMhlScratchpadCommandListener getListenerWrapper( - final HdmiMhlScratchpadCommandListener listener) { - return new IHdmiMhlScratchpadCommandListener.Stub() { + private IHdmiMhlVendorCommandListener getListenerWrapper( + final HdmiMhlVendorCommandListener listener) { + return new IHdmiMhlVendorCommandListener.Stub() { @Override public void onReceived(int portId, int offset, int length, byte[] data) { listener.onReceived(portId, offset, length, data); @@ -365,29 +365,29 @@ public final class HdmiTvClient extends HdmiClient { } /** - * Send MHL Scratchpad command to the device connected to a port of the given portId. + * Send MHL vendor command to the device connected to a port of the given portId. * - * @param portId id of port to send MHL Scratchpad command + * @param portId id of port to send MHL vendor command * @param offset offset in the in given data * @param length length of data. offset + length should be bound to length of data. - * @param data container for Scratchpad data. It should be 16 bytes. + * @param data container for vendor command data. It should be 16 bytes. * @throws IllegalArgumentException if the given parameters are invalid */ - public void sendScratchpadCommand(int portId, int offset, int length, byte[] data) { - if (data == null || data.length != SCRATCHPAD_DATA_SIZE) { - throw new IllegalArgumentException("Invalid scratchpad data."); + public void sendMhlVendorCommand(int portId, int offset, int length, byte[] data) { + if (data == null || data.length != VENDOR_DATA_SIZE) { + throw new IllegalArgumentException("Invalid vendor command data."); } - if (offset < 0 || offset >= SCRATCHPAD_DATA_SIZE) { + if (offset < 0 || offset >= VENDOR_DATA_SIZE) { throw new IllegalArgumentException("Invalid offset:" + offset); } - if (length < 0 || offset + length > SCRATCHPAD_DATA_SIZE) { + if (length < 0 || offset + length > VENDOR_DATA_SIZE) { throw new IllegalArgumentException("Invalid length:" + length); } try { - mService.sendScratchpadCommand(portId, offset, length, data); + mService.sendMhlVendorCommand(portId, offset, length, data); } catch (RemoteException e) { - Log.e(TAG, "failed to send scratchpad command: ", e); + Log.e(TAG, "failed to send vendor command: ", e); } } } diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl index 3bd45ed..4866a9a 100644 --- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl +++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl @@ -22,7 +22,7 @@ import android.hardware.hdmi.IHdmiControlCallback; import android.hardware.hdmi.IHdmiDeviceEventListener; import android.hardware.hdmi.IHdmiHotplugEventListener; import android.hardware.hdmi.IHdmiInputChangeListener; -import android.hardware.hdmi.IHdmiMhlScratchpadCommandListener; +import android.hardware.hdmi.IHdmiMhlVendorCommandListener; import android.hardware.hdmi.IHdmiRecordListener; import android.hardware.hdmi.IHdmiSystemAudioModeChangeListener; import android.hardware.hdmi.IHdmiVendorCommandListener; @@ -62,11 +62,12 @@ interface IHdmiControlService { void sendVendorCommand(int deviceType, int targetAddress, in byte[] params, boolean hasVendorId); void addVendorCommandListener(IHdmiVendorCommandListener listener, int deviceType); + void sendStandby(int deviceType, int deviceId); void setHdmiRecordListener(IHdmiRecordListener callback); void startOneTouchRecord(int recorderAddress, in byte[] recordSource); void stopOneTouchRecord(int recorderAddress); void startTimerRecording(int recorderAddress, int sourceType, in byte[] recordSource); void clearTimerRecording(int recorderAddress, int sourceType, in byte[] recordSource); - void sendScratchpadCommand(int portId, int offset, int length, in byte[] data); - void addHdmiMhlScratchpadCommandListener(IHdmiMhlScratchpadCommandListener listener); + void sendMhlVendorCommand(int portId, int offset, int length, in byte[] data); + void addHdmiMhlVendorCommandListener(IHdmiMhlVendorCommandListener listener); } diff --git a/core/java/android/hardware/hdmi/IHdmiMhlScratchpadCommandListener.aidl b/core/java/android/hardware/hdmi/IHdmiMhlVendorCommandListener.aidl index 4176597..4696677 100644 --- a/core/java/android/hardware/hdmi/IHdmiMhlScratchpadCommandListener.aidl +++ b/core/java/android/hardware/hdmi/IHdmiMhlVendorCommandListener.aidl @@ -17,11 +17,10 @@ package android.hardware.hdmi; /** - * Callback interface definition for MHL client to get the scratchpad - * command. + * Callback interface definition for MHL client to get the vendor command. * * @hide */ - oneway interface IHdmiMhlScratchpadCommandListener { + oneway interface IHdmiMhlVendorCommandListener { void onReceived(int portId, int offset, int length, in byte[] data); } diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 70b402d..7c69a7d 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -48,6 +48,8 @@ import java.net.InetAddress; import java.util.concurrent.atomic.AtomicInteger; import java.util.HashMap; +import libcore.net.event.NetworkEventDispatcher; + /** * Class that answers queries about the state of network connectivity. It also * notifies applications when network connectivity changes. Get an instance @@ -2467,7 +2469,20 @@ public class ConnectivityManager { * @return {@code true} on success, {@code false} if the {@link Network} is no longer valid. */ public static boolean setProcessDefaultNetwork(Network network) { - return NetworkUtils.bindProcessToNetwork(network == null ? NETID_UNSET : network.netId); + int netId = (network == null) ? NETID_UNSET : network.netId; + if (netId == NetworkUtils.getNetworkBoundToProcess()) { + return true; + } + if (NetworkUtils.bindProcessToNetwork(netId)) { + // Must flush DNS cache as new network may have different DNS resolutions. + InetAddress.clearDnsCache(); + // Must flush socket pool as idle sockets will be bound to previous network and may + // cause subsequent fetches to be performed on old network. + NetworkEventDispatcher.getInstance().onNetworkConfigurationChanged(); + return true; + } else { + return false; + } } /** diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java index e686be7..58f0fc0 100644 --- a/core/java/android/net/Network.java +++ b/core/java/android/net/Network.java @@ -37,6 +37,8 @@ import javax.net.SocketFactory; import com.android.okhttp.ConnectionPool; import com.android.okhttp.HostResolver; +import com.android.okhttp.HttpHandler; +import com.android.okhttp.HttpsHandler; import com.android.okhttp.OkHttpClient; /** @@ -58,7 +60,10 @@ public class Network implements Parcelable { // Objects used to perform per-network operations such as getSocketFactory // and openConnection, and a lock to protect access to them. private volatile NetworkBoundSocketFactory mNetworkBoundSocketFactory = null; - private volatile OkHttpClient mOkHttpClient = null; + // mLock should be used to control write access to mConnectionPool and mHostResolver. + // maybeInitHttpClient() must be called prior to reading either variable. + private volatile ConnectionPool mConnectionPool = null; + private volatile HostResolver mHostResolver = null; private Object mLock = new Object(); // Default connection pool values. These are evaluated at startup, just @@ -195,37 +200,34 @@ public class Network implements Parcelable { return mNetworkBoundSocketFactory; } - // TODO: This creates an OkHttpClient with its own connection pool for + // TODO: This creates a connection pool and host resolver for // every Network object, instead of one for every NetId. This is // suboptimal, because an app could potentially have more than one // Network object for the same NetId, causing increased memory footprint // and performance penalties due to lack of connection reuse (connection // setup time, congestion window growth time, etc.). // - // Instead, investigate only having one OkHttpClient for every NetId, - // perhaps by using a static HashMap of NetIds to OkHttpClient objects. The - // tricky part is deciding when to remove an OkHttpClient; a WeakHashMap - // shouldn't be used because whether a Network is referenced doesn't - // correlate with whether a new Network will be instantiated in the near - // future with the same NetID. A good solution would involve purging empty - // (or when all connections are timed out) ConnectionPools. + // Instead, investigate only having one connection pool and host resolver + // for every NetId, perhaps by using a static HashMap of NetIds to + // connection pools and host resolvers. The tricky part is deciding when + // to remove a map entry; a WeakHashMap shouldn't be used because whether + // a Network is referenced doesn't correlate with whether a new Network + // will be instantiated in the near future with the same NetID. A good + // solution would involve purging empty (or when all connections are timed + // out) ConnectionPools. private void maybeInitHttpClient() { - if (mOkHttpClient == null) { - synchronized (mLock) { - if (mOkHttpClient == null) { - HostResolver hostResolver = new HostResolver() { - @Override - public InetAddress[] getAllByName(String host) throws UnknownHostException { - return Network.this.getAllByName(host); - } - }; - ConnectionPool pool = new ConnectionPool(httpMaxConnections, - httpKeepAliveDurationMs); - mOkHttpClient = new OkHttpClient() - .setSocketFactory(getSocketFactory()) - .setHostResolver(hostResolver) - .setConnectionPool(pool); - } + synchronized (mLock) { + if (mHostResolver == null) { + mHostResolver = new HostResolver() { + @Override + public InetAddress[] getAllByName(String host) throws UnknownHostException { + return Network.this.getAllByName(host); + } + }; + } + if (mConnectionPool == null) { + mConnectionPool = new ConnectionPool(httpMaxConnections, + httpKeepAliveDurationMs); } } } @@ -242,13 +244,23 @@ public class Network implements Parcelable { public URLConnection openConnection(URL url) throws IOException { maybeInitHttpClient(); String protocol = url.getProtocol(); - URLStreamHandler handler = mOkHttpClient.createURLStreamHandler(protocol); - if (handler == null) { + OkHttpClient client; + // TODO: HttpHandler creates OkHttpClients that share the default ResponseCache. + // Could this cause unexpected behavior? + // TODO: Should the network's proxy be specified? + if (protocol.equals("http")) { + client = HttpHandler.createHttpOkHttpClient(null /* proxy */); + } else if (protocol.equals("https")) { + client = HttpsHandler.createHttpsOkHttpClient(null /* proxy */); + } else { // OkHttpClient only supports HTTP and HTTPS and returns a null URLStreamHandler if // passed another protocol. throw new MalformedURLException("Invalid URL or unrecognized protocol " + protocol); } - return new URL(url, "", handler).openConnection(); + return client.setSocketFactory(getSocketFactory()) + .setHostResolver(mHostResolver) + .setConnectionPool(mConnectionPool) + .open(url); } /** diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index 8df9916..80e5b91 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -223,6 +223,9 @@ public abstract class NetworkAgent extends Handler { * Called by the bearer code when it has a new score for this network. */ public void sendNetworkScore(int score) { + if (score < 0) { + throw new IllegalArgumentException("Score must be >= 0"); + } queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, new Integer(score)); } diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java index 050be40..c848993 100644 --- a/core/java/android/net/VpnService.java +++ b/core/java/android/net/VpnService.java @@ -62,7 +62,8 @@ import java.util.List; * conflict with each other. The system takes several actions to address * these issues. Here are some key points: * <ul> - * <li>User action is required to create a VPN connection.</li> + * <li>User action is required the first time an application creates a VPN + * connection.</li> * <li>There can be only one VPN connection running at the same time. The * existing interface is deactivated when a new one is created.</li> * <li>A system-managed notification is shown during the lifetime of a @@ -82,8 +83,8 @@ import java.util.List; * other methods in this class, and the right can be revoked at any time. * Here are the general steps to create a VPN connection: * <ol> - * <li>When the user press the button to connect, call {@link #prepare} - * and launch the returned intent.</li> + * <li>When the user presses the button to connect, call {@link #prepare} + * and launch the returned intent, if non-null.</li> * <li>When the application becomes prepared, start the service.</li> * <li>Create a tunnel to the remote server and negotiate the network * parameters for the VPN connection.</li> @@ -130,7 +131,8 @@ public class VpnService extends Service { /** * Prepare to establish a VPN connection. This method returns {@code null} - * if the VPN application is already prepared. Otherwise, it returns an + * if the VPN application is already prepared or if the user has previously + * consented to the VPN application. Otherwise, it returns an * {@link Intent} to a system activity. The application should launch the * activity using {@link Activity#startActivityForResult} to get itself * prepared. The activity may pop up a dialog to require user action, and @@ -144,6 +146,10 @@ public class VpnService extends Service { * it becomes prepared again, subsequent calls to other methods in this * class will fail. * + * <p>The user may disable the VPN at any time while it is activated, in + * which case this method will return an intent the next time it is + * executed to obtain the user's consent again. + * * @see #onRevoke */ public static Intent prepare(Context context) { @@ -212,6 +218,8 @@ public class VpnService extends Service { * * @return {@code true} on success. * @see Builder#addAddress + * + * @hide */ public boolean addAddress(InetAddress address, int prefixLength) { check(address, prefixLength); @@ -240,6 +248,8 @@ public class VpnService extends Service { * @param prefixLength The prefix length of the address. * * @return {@code true} on success. + * + * @hide */ public boolean removeAddress(InetAddress address, int prefixLength) { check(address, prefixLength); diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl index 3286627..b5295fb 100644 --- a/core/java/android/os/IUserManager.aidl +++ b/core/java/android/os/IUserManager.aidl @@ -41,6 +41,7 @@ interface IUserManager { int getUserSerialNumber(int userHandle); int getUserHandle(int userSerialNumber); Bundle getUserRestrictions(int userHandle); + boolean hasUserRestriction(in String restrictionKey, int userHandle); void setUserRestrictions(in Bundle restrictions, int userHandle); void setApplicationRestrictions(in String packageName, in Bundle restrictions, int userHandle); diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index 00e2e22..18b2082 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -248,7 +248,7 @@ public final class PowerManager { * {@link #PROXIMITY_SCREEN_OFF_WAKE_LOCK} wake lock until the proximity sensor * indicates that an object is not in close proximity. */ - public static final int WAIT_FOR_DISTANT_PROXIMITY = 1; + public static final int RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY = 1; /** * Brightness value for fully on. @@ -961,8 +961,8 @@ public final class PowerManager { * </p> * * @param flags Combination of flag values to modify the release behavior. - * Currently only {@link #WAIT_FOR_DISTANT_PROXIMITY} is supported. Passing 0 is - * equivalent to calling {@link #release()}. + * Currently only {@link #RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY} is supported. + * Passing 0 is equivalent to calling {@link #release()}. */ public void release(int flags) { synchronized (mToken) { diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 33fda4a..c25278f 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -630,7 +630,13 @@ public class UserManager { * @param userHandle the UserHandle of the user for whom to retrieve the restrictions. */ public boolean hasUserRestriction(String restrictionKey, UserHandle userHandle) { - return getUserRestrictions(userHandle).getBoolean(restrictionKey, false); + try { + return mService.hasUserRestriction(restrictionKey, + userHandle.getIdentifier()); + } catch (RemoteException re) { + Log.w(TAG, "Could not check user restrictions", re); + return false; + } } /** @@ -992,6 +998,7 @@ public class UserManager { * Returns a file descriptor for the user's photo. PNG data can be read from this file. * @param userHandle the user whose photo we want to read. * @return a {@link Bitmap} of the user's photo, or null if there's no photo. + * @see com.android.internal.util.UserIcons#getDefaultUserIcon for a default. * @hide */ public Bitmap getUserIcon(int userHandle) { diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 01fda47..440b1ec 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -3150,6 +3150,11 @@ public final class Settings { /** @hide */ public static boolean putStringForUser(ContentResolver resolver, String name, String value, int userHandle) { + if (LOCATION_MODE.equals(name)) { + // HACK ALERT: temporary hack to work around b/10491283. + // TODO: once b/10491283 fixed, remove this hack + return setLocationModeForUser(resolver, Integer.parseInt(value), userHandle); + } if (MOVED_TO_GLOBAL.contains(name)) { Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System" + " to android.provider.Settings.Global"); @@ -3265,11 +3270,6 @@ public final class Settings { /** @hide */ public static boolean putIntForUser(ContentResolver cr, String name, int value, int userHandle) { - if (LOCATION_MODE.equals(name)) { - // HACK ALERT: temporary hack to work around b/10491283. - // TODO: once b/10491283 fixed, remove this hack - return setLocationModeForUser(cr, value, userHandle); - } return putStringForUser(cr, name, Integer.toString(value), userHandle); } diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java index a4b6e92..9be220e 100644 --- a/core/java/android/speech/tts/TextToSpeech.java +++ b/core/java/android/speech/tts/TextToSpeech.java @@ -46,7 +46,6 @@ import java.util.Locale; import java.util.Map; import java.util.MissingResourceException; import java.util.Set; -import java.util.TreeSet; /** * @@ -1567,10 +1566,10 @@ public class TextToSpeech { @Override public Set<Locale> run(ITextToSpeechService service) throws RemoteException { List<Voice> voices = service.getVoices(); - if (voices != null) { - return new TreeSet<Locale>(); + if (voices == null) { + return new HashSet<Locale>(); } - TreeSet<Locale> locales = new TreeSet<Locale>(); + HashSet<Locale> locales = new HashSet<Locale>(); for (Voice voice : voices) { locales.add(voice.getLocale()); } @@ -1593,7 +1592,7 @@ public class TextToSpeech { @Override public Set<Voice> run(ITextToSpeechService service) throws RemoteException { List<Voice> voices = service.getVoices(); - return (voices != null) ? new TreeSet<Voice>(voices) : new TreeSet<Voice>(); + return (voices != null) ? new HashSet<Voice>(voices) : new HashSet<Voice>(); } }, null, "getVoices"); } diff --git a/core/java/android/transition/TransitionSet.java b/core/java/android/transition/TransitionSet.java index 56db674..669621eb3 100644 --- a/core/java/android/transition/TransitionSet.java +++ b/core/java/android/transition/TransitionSet.java @@ -390,7 +390,20 @@ public class TransitionSet extends Transition { ArrayList<TransitionValues> endValuesList) { startValues = removeExcludes(startValues); endValues = removeExcludes(endValues); - for (Transition childTransition : mTransitions) { + long startDelay = getStartDelay(); + int numTransitions = mTransitions.size(); + for (int i = 0; i < numTransitions; i++) { + Transition childTransition = mTransitions.get(i); + // We only set the start delay on the first transition if we are playing + // the transitions sequentially. + if (startDelay > 0 && (mPlayTogether || i == 0)) { + long childStartDelay = childTransition.getStartDelay(); + if (childStartDelay > 0) { + childTransition.setStartDelay(startDelay + childStartDelay); + } else { + childTransition.setStartDelay(startDelay); + } + } childTransition.createAnimators(sceneRoot, startValues, endValues, startValuesList, endValuesList); } @@ -419,11 +432,17 @@ public class TransitionSet extends Transition { */ @Override protected void runAnimators() { + if (mTransitions.isEmpty()) { + start(); + end(); + return; + } setupStartEndListeners(); + int numTransitions = mTransitions.size(); if (!mPlayTogether) { // Setup sequence with listeners // TODO: Need to add listeners in such a way that we can remove them later if canceled - for (int i = 1; i < mTransitions.size(); ++i) { + for (int i = 1; i < numTransitions; ++i) { Transition previousTransition = mTransitions.get(i - 1); final Transition nextTransition = mTransitions.get(i); previousTransition.addListener(new TransitionListenerAdapter() { @@ -439,8 +458,8 @@ public class TransitionSet extends Transition { firstTransition.runAnimators(); } } else { - for (Transition childTransition : mTransitions) { - childTransition.runAnimators(); + for (int i = 0; i < numTransitions; ++i) { + mTransitions.get(i).runAnimators(); } } } diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java index d648ca6..d87d0f9 100644 --- a/core/java/android/transition/Visibility.java +++ b/core/java/android/transition/Visibility.java @@ -277,6 +277,18 @@ public abstract class Visibility extends Transition { if ((mMode & MODE_IN) != MODE_IN || endValues == null) { return null; } + if (startValues == null) { + VisibilityInfo parentVisibilityInfo = null; + View endParent = (View) endValues.view.getParent(); + TransitionValues startParentValues = getMatchedTransitionValues(endParent, + false); + TransitionValues endParentValues = getTransitionValues(endParent, false); + parentVisibilityInfo = + getVisibilityChangeInfo(startParentValues, endParentValues); + if (parentVisibilityInfo.visibilityChange) { + return null; + } + } return onAppear(sceneRoot, endValues.view, startValues, endValues); } diff --git a/core/java/android/util/SizeF.java b/core/java/android/util/SizeF.java index ac4f187..2edc4a7 100644 --- a/core/java/android/util/SizeF.java +++ b/core/java/android/util/SizeF.java @@ -16,6 +16,7 @@ package android.util; +import static com.android.internal.util.Preconditions.checkNotNull; import static com.android.internal.util.Preconditions.checkArgumentFinite; /** @@ -95,6 +96,61 @@ public final class SizeF { return mWidth + "x" + mHeight; } + private static NumberFormatException invalidSizeF(String s) { + throw new NumberFormatException("Invalid SizeF: \"" + s + "\""); + } + + /** + * Parses the specified string as a size value. + * <p> + * The ASCII characters {@code \}{@code u002a} ('*') and + * {@code \}{@code u0078} ('x') are recognized as separators between + * the width and height.</p> + * <p> + * For any {@code SizeF s}: {@code SizeF.parseSizeF(s.toString()).equals(s)}. + * However, the method also handles sizes expressed in the + * following forms:</p> + * <p> + * "<i>width</i>{@code x}<i>height</i>" or + * "<i>width</i>{@code *}<i>height</i>" {@code => new SizeF(width, height)}, + * where <i>width</i> and <i>height</i> are string floats potentially + * containing a sign, such as "-10.3", "+7" or "5.2", but not containing + * an {@code 'x'} (such as a float in hexadecimal string format).</p> + * + * <pre>{@code + * SizeF.parseSizeF("3.2*+6").equals(new SizeF(3.2f, 6.0f)) == true + * SizeF.parseSizeF("-3x-6").equals(new SizeF(-3.0f, -6.0f)) == true + * SizeF.parseSizeF("4 by 3") => throws NumberFormatException + * }</pre> + * + * @param string the string representation of a size value. + * @return the size value represented by {@code string}. + * + * @throws NumberFormatException if {@code string} cannot be parsed + * as a size value. + * @throws NullPointerException if {@code string} was {@code null} + */ + public static SizeF parseSizeF(String string) + throws NumberFormatException { + checkNotNull(string, "string must not be null"); + + int sep_ix = string.indexOf('*'); + if (sep_ix < 0) { + sep_ix = string.indexOf('x'); + } + if (sep_ix < 0) { + throw invalidSizeF(string); + } + try { + return new SizeF(Float.parseFloat(string.substring(0, sep_ix)), + Float.parseFloat(string.substring(sep_ix + 1))); + } catch (NumberFormatException e) { + throw invalidSizeF(string); + } catch (IllegalArgumentException e) { + throw invalidSizeF(string); + } + } + /** * {@inheritDoc} */ diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index edb3798..d23e115 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -339,7 +339,8 @@ public abstract class HardwareRenderer { * @param attachInfo AttachInfo tied to the specified view. * @param callbacks Callbacks invoked when drawing happens. */ - abstract void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks); + abstract void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks, + boolean isStartingWindow); /** * Creates a new hardware layer. A hardware layer built by calling this diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index 5d2822d..3d1332c 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -16,6 +16,7 @@ package android.view; +import android.graphics.Color; import com.android.internal.R; import android.content.Context; @@ -267,7 +268,8 @@ public class ThreadedRenderer extends HardwareRenderer { view.mRecreateDisplayList = false; } - private void updateRootDisplayList(View view, HardwareDrawCallbacks callbacks) { + private void updateRootDisplayList(View view, HardwareDrawCallbacks callbacks, + boolean isStartingWindow) { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "getDisplayList"); updateViewTreeDisplayList(view); @@ -279,6 +281,12 @@ public class ThreadedRenderer extends HardwareRenderer { callbacks.onHardwarePreDraw(canvas); canvas.insertReorderBarrier(); + if (isStartingWindow) { + // Compensate for some situations in which a hw-accelerated surface + // will not be filled with anything by default; this is equivalent + // to the old behavior when the system process was not hw-accelerated + canvas.drawColor(Color.BLACK); + } canvas.drawRenderNode(view.getDisplayList()); canvas.insertInorderBarrier(); @@ -298,7 +306,8 @@ public class ThreadedRenderer extends HardwareRenderer { } @Override - void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks) { + void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks, + boolean isStartingWindow) { attachInfo.mIgnoreDirtyState = true; long frameTimeNanos = mChoreographer.getFrameTimeNanos(); attachInfo.mDrawingTime = frameTimeNanos / TimeUtils.NANOS_PER_MS; @@ -308,7 +317,7 @@ public class ThreadedRenderer extends HardwareRenderer { recordDuration = System.nanoTime(); } - updateRootDisplayList(view, callbacks); + updateRootDisplayList(view, callbacks, isStartingWindow); if (mProfilingEnabled) { recordDuration = System.nanoTime() - recordDuration; diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 82c5425..eb8f3bf 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -4299,6 +4299,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * </p> * * @param a the styled attributes set to initialize the fading edges from + * + * @removed */ protected void initializeFadingEdge(TypedArray a) { // This method probably shouldn't have been included in the SDK to begin with. @@ -4439,6 +4441,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * </p> * * @param a the styled attributes set to initialize the scrollbars from + * + * @removed */ protected void initializeScrollbars(TypedArray a) { // It's not safe to use this method from apps. The parameter 'a' must have been obtained diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java index a94f973..12a49d5 100644 --- a/core/java/android/view/ViewDebug.java +++ b/core/java/android/view/ViewDebug.java @@ -875,6 +875,11 @@ public class ViewDebug { data[i + 1] = theme.resolveAttribute(attributeId, outValue, true) ? outValue.coerceToString().toString() : nullString; i += 2; + + // attempt to replace reference data with its name + if (outValue.type == TypedValue.TYPE_REFERENCE) { + data[i - 1] = resources.getResourceName(outValue.resourceId); + } } catch (Resources.NotFoundException e) { // ignore resources we can't resolve } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 43ab4ef..ae6e4e7 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -711,17 +711,10 @@ public final class ViewRootImpl implements ViewParent, // can be used by code on the system process to escape that and enable // HW accelerated drawing. (This is basically for the lock screen.) - final boolean fakeHwAccelerated = (attrs.privateFlags & - WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED) != 0; final boolean forceHwAccelerated = (attrs.privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED) != 0; - if (fakeHwAccelerated) { - // This is exclusively for the preview windows the window manager - // shows for launching applications, so they will look more like - // the app being launched. - mAttachInfo.mHardwareAccelerationRequested = true; - } else if (!HardwareRenderer.sRendererDisabled + if (!HardwareRenderer.sRendererDisabled || (HardwareRenderer.sSystemRendererDisabled && forceHwAccelerated)) { if (mAttachInfo.mHardwareRenderer != null) { mAttachInfo.mHardwareRenderer.destroy(); @@ -2486,7 +2479,8 @@ public final class ViewRootImpl implements ViewParent, dirty.setEmpty(); mBlockResizeBuffer = false; - mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this); + mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this, + params.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING); } else { // If we get here with a disabled & requested hardware renderer, something went // wrong (an invalidate posted right before we destroyed the hardware surface diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index ebc683a..63ab7d2 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -111,10 +111,19 @@ public abstract class Window { public static final int FEATURE_CONTENT_TRANSITIONS = 12; /** + * Enables Activities to run Activity Transitions either through sending or receiving + * ActivityOptions bundle created with + * {@link android.app.ActivityOptions#makeSceneTransitionAnimation(android.app.Activity, + * android.util.Pair[])} or {@link android.app.ActivityOptions#makeSceneTransitionAnimation( + * android.app.Activity, View, String)}. + */ + public static final int FEATURE_ACTIVITY_TRANSITIONS = 13; + + /** * Max value used as a feature ID * @hide */ - public static final int FEATURE_MAX = FEATURE_CONTENT_TRANSITIONS; + public static final int FEATURE_MAX = FEATURE_ACTIVITY_TRANSITIONS; /** Flag for setting the progress bar's visibility to VISIBLE */ public static final int PROGRESS_VISIBILITY_ON = -1; @@ -1459,7 +1468,7 @@ public abstract class Window { * have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend * {@link android.transition.Visibility} as exiting is governed by changing visibility * from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, the views will - * remain unaffected. Requires {@link #FEATURE_CONTENT_TRANSITIONS}. + * remain unaffected. Requires {@link #FEATURE_ACTIVITY_TRANSITIONS}. * * @param transition The Transition to use to move Views out of the scene when calling a * new Activity. @@ -1475,7 +1484,7 @@ public abstract class Window { * visibility from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, * the views will remain unaffected. If nothing is set, the default will be to use the same * transition as {@link #setExitTransition(android.transition.Transition)}. - * Requires {@link #FEATURE_CONTENT_TRANSITIONS}. + * Requires {@link #FEATURE_ACTIVITY_TRANSITIONS}. * * @param transition The Transition to use to move Views into the scene when reentering from a * previously-started Activity. @@ -1489,7 +1498,7 @@ public abstract class Window { * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend * {@link android.transition.Visibility} as entering is governed by changing visibility from * {@link View#INVISIBLE} to {@link View#VISIBLE}. If <code>transition</code> is null, - * entering Views will remain unaffected. Requires {@link #FEATURE_CONTENT_TRANSITIONS}. + * entering Views will remain unaffected. Requires {@link #FEATURE_ACTIVITY_TRANSITIONS}. * * @return the Transition to use to move Views into the initial Scene. * @attr ref android.R.styleable#Window_windowEnterTransition @@ -1517,7 +1526,7 @@ public abstract class Window { * have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend * {@link android.transition.Visibility} as exiting is governed by changing visibility * from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, the views will - * remain unaffected. Requires {@link #FEATURE_CONTENT_TRANSITIONS}. + * remain unaffected. Requires {@link #FEATURE_ACTIVITY_TRANSITIONS}. * * @return the Transition to use to move Views out of the scene when calling a * new Activity. @@ -1531,7 +1540,7 @@ public abstract class Window { * or ViewGroups that have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions * will extend {@link android.transition.Visibility} as exiting is governed by changing * visibility from {@link View#VISIBLE} to {@link View#INVISIBLE}. - * Requires {@link #FEATURE_CONTENT_TRANSITIONS}. + * Requires {@link #FEATURE_ACTIVITY_TRANSITIONS}. * * @return The Transition to use to move Views into the scene when reentering from a * previously-started Activity. @@ -1544,7 +1553,7 @@ public abstract class Window { * Scene. Typical Transitions will affect size and location, such as * {@link android.transition.ChangeBounds}. A null * value will cause transferred shared elements to blink to the final position. - * Requires {@link #FEATURE_CONTENT_TRANSITIONS}. + * Requires {@link #FEATURE_ACTIVITY_TRANSITIONS}. * * @param transition The Transition to use for shared elements transferred into the content * Scene. @@ -1559,7 +1568,7 @@ public abstract class Window { * value will cause transferred shared elements to blink to the final position. * If no value is set, the default will be to use the same value as * {@link #setSharedElementEnterTransition(android.transition.Transition)}. - * Requires {@link #FEATURE_CONTENT_TRANSITIONS}. + * Requires {@link #FEATURE_ACTIVITY_TRANSITIONS}. * * @param transition The Transition to use for shared elements transferred out of the content * Scene. @@ -1569,7 +1578,7 @@ public abstract class Window { /** * Returns the Transition that will be used for shared elements transferred into the content - * Scene. Requires {@link #FEATURE_CONTENT_TRANSITIONS}. + * Scene. Requires {@link #FEATURE_ACTIVITY_TRANSITIONS}. * * @return Transition to use for sharend elements transferred into the content Scene. * @attr ref android.R.styleable#Window_windowSharedElementEnterTransition @@ -1578,7 +1587,7 @@ public abstract class Window { /** * Returns the Transition that will be used for shared elements transferred back to a - * calling Activity. Requires {@link #FEATURE_CONTENT_TRANSITIONS}. + * calling Activity. Requires {@link #FEATURE_ACTIVITY_TRANSITIONS}. * * @return Transition to use for sharend elements transferred into the content Scene. * @attr ref android.R.styleable#Window_windowSharedElementReturnTransition @@ -1590,7 +1599,7 @@ public abstract class Window { * before the shared elements are transferred to the called Activity. If the shared elements * must animate during the exit transition, this Transition should be used. Upon completion, * the shared elements may be transferred to the started Activity. - * Requires {@link #FEATURE_CONTENT_TRANSITIONS}. + * Requires {@link #FEATURE_ACTIVITY_TRANSITIONS}. * * @param transition The Transition to use for shared elements in the launching Window * prior to transferring to the launched Activity's Window. @@ -1603,7 +1612,7 @@ public abstract class Window { * Activity after it has returned the shared element to it start location. If no value * is set, this will default to * {@link #setSharedElementExitTransition(android.transition.Transition)}. - * Requires {@link #FEATURE_CONTENT_TRANSITIONS}. + * Requires {@link #FEATURE_ACTIVITY_TRANSITIONS}. * * @param transition The Transition to use for shared elements in the launching Window * after the shared element has returned to the Window. @@ -1614,7 +1623,7 @@ public abstract class Window { /** * Returns the Transition to use for shared elements in the launching Window prior * to transferring to the launched Activity's Window. - * Requires {@link #FEATURE_CONTENT_TRANSITIONS}. + * Requires {@link #FEATURE_ACTIVITY_TRANSITIONS}. * * @return the Transition to use for shared elements in the launching Window prior * to transferring to the launched Activity's Window. @@ -1625,7 +1634,7 @@ public abstract class Window { /** * Returns the Transition that will be used for shared elements reentering from a started * Activity after it has returned the shared element to it start location. - * Requires {@link #FEATURE_CONTENT_TRANSITIONS}. + * Requires {@link #FEATURE_ACTIVITY_TRANSITIONS}. * * @return the Transition that will be used for shared elements reentering from a started * Activity after it has returned the shared element to it start location. @@ -1703,7 +1712,7 @@ public abstract class Window { * Returns the duration, in milliseconds, of the window background fade * when transitioning into or away from an Activity when called with an Activity Transition. * <p>When executing the enter transition, the background starts transparent - * and fades in. This requires {@link #FEATURE_CONTENT_TRANSITIONS}. The default is + * and fades in. This requires {@link #FEATURE_ACTIVITY_TRANSITIONS}. The default is * 300 milliseconds.</p> * * @return The duration of the window background fade to opaque during enter transition. @@ -1716,7 +1725,7 @@ public abstract class Window { * Sets the duration, in milliseconds, of the window background fade * when transitioning into or away from an Activity when called with an Activity Transition. * <p>When executing the enter transition, the background starts transparent - * and fades in. This requires {@link #FEATURE_CONTENT_TRANSITIONS}. The default is + * and fades in. This requires {@link #FEATURE_ACTIVITY_TRANSITIONS}. The default is * 300 milliseconds.</p> * * @param fadeDurationMillis The duration of the window background fade to or from opaque diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 47ee52e..273ec9d 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -1024,26 +1024,6 @@ public interface WindowManager extends ViewManager { public int flags; /** - * If the window has requested hardware acceleration, but this is not - * allowed in the process it is in, then still render it as if it is - * hardware accelerated. This is used for the starting preview windows - * in the system process, which don't need to have the overhead of - * hardware acceleration (they are just a static rendering), but should - * be rendered as such to match the actual window of the app even if it - * is hardware accelerated. - * Even if the window isn't hardware accelerated, still do its rendering - * as if it was. - * Like {@link #FLAG_HARDWARE_ACCELERATED} except for trusted system windows - * that need hardware acceleration (e.g. LockScreen), where hardware acceleration - * is generally disabled. This flag must be specified in addition to - * {@link #FLAG_HARDWARE_ACCELERATED} to enable hardware acceleration for system - * windows. - * - * @hide - */ - public static final int PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED = 0x00000001; - - /** * In the system process, we globally do not use hardware acceleration * because there are many threads doing UI there and they conflict. * If certain parts of the UI that really do want to use hardware diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index 2ed125d..fec7550 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -638,6 +638,11 @@ public interface WindowManagerPolicy { public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs); /** + * Return the window that is hiding the keyguard, if such a thing exists. + */ + public WindowState getWinShowWhenLockedLw(); + + /** * Called when the system would like to show a UI to indicate that an * application is starting. You can use this to add a * APPLICATION_STARTING_TYPE window with the given appToken to the window diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java index 20adfe4..ba5d6c2 100644 --- a/core/java/android/view/inputmethod/BaseInputConnection.java +++ b/core/java/android/view/inputmethod/BaseInputConnection.java @@ -436,14 +436,6 @@ public class BaseInputConnection implements InputConnection { } /** - * The default implementation does nothing. - * @removed - */ - public final boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) { - return false; - } - - /** * The default implementation places the given text into the editable, * replacing any existing composing text. The new text is marked as * in a composing state with the composing style. diff --git a/core/java/android/view/inputmethod/CursorAnchorInfo.java b/core/java/android/view/inputmethod/CursorAnchorInfo.java index 600fffe..fd73432 100644 --- a/core/java/android/view/inputmethod/CursorAnchorInfo.java +++ b/core/java/android/view/inputmethod/CursorAnchorInfo.java @@ -120,38 +120,6 @@ public final class CursorAnchorInfo implements Parcelable { */ public static final int FLAG_IS_RTL = 0x04; - /** - * @removed - */ - public static final int CHARACTER_RECT_TYPE_MASK = 0x0f; - /** - * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the editor did not specify any type of this - * character. Editor authors should not use this flag. - * @removed - */ - public static final int CHARACTER_RECT_TYPE_UNSPECIFIED = 0; - /** - * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the character is entirely visible. - * @removed - */ - public static final int CHARACTER_RECT_TYPE_FULLY_VISIBLE = 1; - /** - * Type for {@link #CHARACTER_RECT_TYPE_MASK}: some area of the character is invisible. - * @removed - */ - public static final int CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE = 2; - /** - * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the character is entirely invisible. - * @removed - */ - public static final int CHARACTER_RECT_TYPE_INVISIBLE = 3; - /** - * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the editor gave up to calculate the rectangle - * for this character. Input method authors should ignore the returned rectangle. - * @removed - */ - public static final int CHARACTER_RECT_TYPE_NOT_FEASIBLE = 4; - public CursorAnchorInfo(final Parcel source) { mSelectionStart = source.readInt(); mSelectionEnd = source.readInt(); @@ -318,20 +286,6 @@ public final class CursorAnchorInfo implements Parcelable { } /** - * @removed - */ - public Builder setInsertionMarkerLocation(final float horizontalPosition, - final float lineTop, final float lineBaseline, final float lineBottom, - final boolean clipped){ - mInsertionMarkerHorizontal = horizontalPosition; - mInsertionMarkerTop = lineTop; - mInsertionMarkerBaseline = lineBaseline; - mInsertionMarkerBottom = lineBottom; - mInsertionMarkerFlags = clipped ? FLAG_HAS_INVISIBLE_REGION : 0; - return this; - } - - /** * Sets the location of the text insertion point (zero width cursor) as a rectangle in * local coordinates. Calling this can be skipped when there is no text insertion point; * however if there is an insertion point, editors must call this method. @@ -390,43 +344,6 @@ public final class CursorAnchorInfo implements Parcelable { } /** - * Adds the bounding box of the character specified with the index. - * - * @param index index of the character in Java chars units. Must be specified in - * ascending order across successive calls. - * @param leadingEdgeX x coordinate of the leading edge of the character in local - * coordinates, that is, left edge for LTR text and right edge for RTL text. - * @param leadingEdgeY y coordinate of the leading edge of the character in local - * coordinates. - * @param trailingEdgeX x coordinate of the trailing edge of the character in local - * coordinates, that is, right edge for LTR text and left edge for RTL text. - * @param trailingEdgeY y coordinate of the trailing edge of the character in local - * coordinates. - * @param flags flags for this character rect. See {@link #FLAG_HAS_VISIBLE_REGION} for - * example. - * @throws IllegalArgumentException If the index is a negative value, or not greater than - * all of the previously called indices. - * @removed - */ - public Builder addCharacterRect(final int index, final float leadingEdgeX, - final float leadingEdgeY, final float trailingEdgeX, final float trailingEdgeY, - final int flags) { - final int newFlags; - final float left; - final float right; - if (leadingEdgeX <= trailingEdgeX) { - newFlags = flags; - left = leadingEdgeX; - right = trailingEdgeX; - } else { - newFlags = flags | FLAG_IS_RTL; - left = trailingEdgeX; - right = leadingEdgeX; - } - return addCharacterBounds(index, left, leadingEdgeY, right, trailingEdgeY, newFlags); - } - - /** * Sets the matrix that transforms local coordinates into screen coordinates. * @param matrix transformation matrix from local coordinates into screen coordinates. null * is interpreted as an identity matrix. @@ -538,15 +455,6 @@ public final class CursorAnchorInfo implements Parcelable { } /** - * Returns the visibility of the insertion marker. - * @return {@code true} if the insertion marker is partially or entirely clipped. - * @removed - */ - public boolean isInsertionMarkerClipped() { - return (mInsertionMarkerFlags & FLAG_HAS_VISIBLE_REGION) != 0; - } - - /** * Returns the horizontal start of the insertion marker, in the local coordinates that will * be transformed with {@link #getMatrix()} when rendered on the screen. * @return x coordinate that is compatible with {@link Layout#getPrimaryHorizontal(int)}. @@ -602,25 +510,6 @@ public final class CursorAnchorInfo implements Parcelable { } /** - * Returns a new instance of {@link RectF} that indicates the location of the character - * specified with the index. - * <p> - * Note that coordinates are not necessarily contiguous or even monotonous, especially when - * RTL text and LTR text are mixed. - * </p> - * @param index index of the character in a Java chars. - * @return a new instance of {@link RectF} that represents the location of the character in - * local coordinates. null if the character is invisible or the application did not provide - * the location. Note that the {@code left} field can be greater than the {@code right} field - * if the character is in RTL text. Returns {@code null} if no location information is - * available. - * @removed - */ - public RectF getCharacterRect(final int index) { - return getCharacterBounds(index); - } - - /** * Returns the flags associated with the character bounds specified with the index. * @param index index of the character in a Java chars. * @return {@code 0} if no flag is specified. @@ -633,16 +522,6 @@ public final class CursorAnchorInfo implements Parcelable { } /** - * Returns the flags associated with the character rect specified with the index. - * @param index index of the character in a Java chars. - * @return {@code 0} if no flag is specified. - * @removed - */ - public int getCharacterRectFlags(final int index) { - return getCharacterBoundsFlags(index); - } - - /** * Returns a new instance of {@link android.graphics.Matrix} that indicates the transformation * matrix that is to be applied other positional data in this class. * @return a new instance (copy) of the transformation matrix. diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java index 093fb2f..c51d8a7 100644 --- a/core/java/android/view/inputmethod/InputConnection.java +++ b/core/java/android/view/inputmethod/InputConnection.java @@ -756,19 +756,4 @@ public interface InputConnection { * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)}. */ public boolean requestCursorUpdates(int cursorUpdateMode); - - /** - * @removed - */ - public static final int REQUEST_UPDATE_CURSOR_UPDATE_IMMEDIATE = 1 << 0; - - /** - * @removed - */ - public static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR = 1 << 1; - - /** - * @removed - */ - public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode); } diff --git a/core/java/android/view/inputmethod/InputConnectionWrapper.java b/core/java/android/view/inputmethod/InputConnectionWrapper.java index 87853de..231aa07 100644 --- a/core/java/android/view/inputmethod/InputConnectionWrapper.java +++ b/core/java/android/view/inputmethod/InputConnectionWrapper.java @@ -129,11 +129,4 @@ public class InputConnectionWrapper implements InputConnection { public boolean requestCursorUpdates(int cursorUpdateMode) { return mTarget.requestCursorUpdates(cursorUpdateMode); } - - /** - * @removed - */ - public final boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) { - return mTarget.requestCursorUpdates(cursorUpdateMode); - } } diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java index 547acfa..46a7fd0 100644 --- a/core/java/android/webkit/WebChromeClient.java +++ b/core/java/android/webkit/WebChromeClient.java @@ -416,38 +416,6 @@ public class WebChromeClient { } /** - * UploadHelper simplifies file upload operations by providing helper methods that - * would handle most common file picker/media capture requests. The application - * can use the helper to build an intent to start a file picker, and then parse - * the result returned by the activity. - * - * How to use: - * 1. Create a helper using {@link FileChooserParams#getUploadHelper} - * 2. Build an intent using {@link UploadHelper#buildIntent} - * 3. Fire the intent using {@link android.app.Activity#startActivityForResult}. - * 4. Check for ActivityNotFoundException and take a user friendly action if thrown. - * 5. Listen the result using {@link android.app.Activity#onActivityResult} - * 6. Parse the result using {@link UploadHelper#parseResult} - * 7. Send the result using filePathCallback of {@link WebChromeClient#onShowFileChooser} - */ - public static abstract class UploadHelper { - /** - * Returns an intent that would start a file picker for file selection/media capture. - */ - public abstract Intent buildIntent(); - - /** - * Parses the result returned by the file picker activity. - * - * @param resultCode the integer result code returned by the file picker activity. - * @param data the intent returned by the file picker activity. - * @return the Uris of selected file(s) or null if the resultCode indicates - * activity canceled or any other error. - */ - public abstract Uri[] parseResult(int resultCode, Intent data); - } - - /** * Parameters used in the {@link #onShowFileChooser} method. */ public static abstract class FileChooserParams { @@ -464,11 +432,17 @@ public class WebChromeClient { public static final int MODE_SAVE = 3; /** - * Returns a helper to simplify choosing and uploading files. The helper builds a default - * intent that the application can send using startActivityForResult and processes the - * results. + * Parse the result returned by the file picker activity. This method should be used with + * {@link #createIntent}. Refer to {@link #createIntent} for how to use it. + * + * @param resultCode the integer result code returned by the file picker activity. + * @param data the intent returned by the file picker activity. + * @return the Uris of selected file(s) or null if the resultCode indicates + * activity canceled or any other error. */ - public abstract UploadHelper getUploadHelper(); + public static Uri[] parseResult(int resultCode, Intent data) { + return WebViewFactory.getProvider().getStatics().parseFileChooserResult(resultCode, data); + } /** * Returns file chooser mode. @@ -500,7 +474,28 @@ public class WebChromeClient { * The file name of a default selection if specified, or null. */ public abstract String getFilenameHint(); - }; + + /** + * Creates an intent that would start a file picker for file selection. + * The Intent supports choosing files from simple file sources available + * on the device. Some advanced sources (for example, live media capture) + * may not be supported and applications wishing to support these sources + * or more advanced file operations should build their own Intent. + * + * <pre> + * How to use: + * 1. Build an intent using {@link #createIntent} + * 2. Fire the intent using {@link android.app.Activity#startActivityForResult}. + * 3. Check for ActivityNotFoundException and take a user friendly action if thrown. + * 4. Listen the result using {@link android.app.Activity#onActivityResult} + * 5. Parse the result using {@link #parseResult} only if media capture was not requested. + * 6. Send the result using filePathCallback of {@link WebChromeClient#onShowFileChooser} + * </pre> + * + * @return an Intent that supports basic file chooser sources. + */ + public abstract Intent createIntent(); + } /** * Tell the client to open a file chooser. diff --git a/core/java/android/webkit/WebViewFactoryProvider.java b/core/java/android/webkit/WebViewFactoryProvider.java index 20bb932..d37d217 100644 --- a/core/java/android/webkit/WebViewFactoryProvider.java +++ b/core/java/android/webkit/WebViewFactoryProvider.java @@ -17,6 +17,8 @@ package android.webkit; import android.content.Context; +import android.content.Intent; +import android.net.Uri; /** * This is the main entry-point into the WebView back end implementations, which the WebView @@ -64,6 +66,12 @@ public interface WebViewFactoryProvider { * {@link android.webkit.WebView#setSlowWholeDocumentDrawEnabled(boolean) } */ void enableSlowWholeDocumentDraw(); + + /** + * Implement the API method + * {@link android.webkit.WebChromeClient.FileChooserParams#parseResult(int, Intent)} + */ + Uri[] parseFileChooserResult(int resultCode, Intent intent); } Statics getStatics(); diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 94d52d5..3859e48 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -5721,14 +5721,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te public boolean requestCursorUpdates(int cursorUpdateMode) { return getTarget().requestCursorUpdates(cursorUpdateMode); } - - /** - * @removed - */ - @Override - public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) { - return getTarget().requestCursorUpdates(cursorUpdateMode); - } } /** diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 3f168e8..128a06c 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -1860,9 +1860,8 @@ public class Editor { } final int originalLength = mTextView.getText().length(); - long minMax = mTextView.prepareSpacesAroundPaste(offset, offset, content); - int min = TextUtils.unpackRangeStartFromLong(minMax); - int max = TextUtils.unpackRangeEndFromLong(minMax); + int min = offset; + int max = offset; Selection.setSelection((Spannable) mTextView.getText(), max); mTextView.replaceText_internal(min, max, content); diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java index 0289ccc..dfdf606 100644 --- a/core/java/android/widget/SearchView.java +++ b/core/java/android/widget/SearchView.java @@ -262,7 +262,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView { attrs, R.styleable.SearchView, defStyleAttr, defStyleRes); final LayoutInflater inflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE); - final int layoutResId = a.getResourceId(R.styleable.SearchView_layout, 0); + final int layoutResId = a.getResourceId(R.styleable.SearchView_layout, R.layout.search_view); inflater.inflate(layoutResId, this, true); mQueryTextView = (SearchAutoComplete) findViewById(R.id.search_src_text); @@ -288,7 +288,8 @@ public class SearchView extends LinearLayout implements CollapsibleActionView { mSearchHintIcon.setImageDrawable(a.getDrawable(R.styleable.SearchView_searchIcon)); // Extract dropdown layout resource IDs for later use. - mSuggestionRowLayout = a.getResourceId(R.styleable.SearchView_suggestionRowLayout, 0); + mSuggestionRowLayout = a.getResourceId(R.styleable.SearchView_suggestionRowLayout, + R.layout.search_dropdown_item_icons_2line); mSuggestionCommitIconResId = a.getResourceId(R.styleable.SearchView_commitIcon, 0); mSearchButton.setOnClickListener(mOnClickListener); diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java index 27763eb..a76241e 100644 --- a/core/java/android/widget/SimpleMonthView.java +++ b/core/java/android/widget/SimpleMonthView.java @@ -31,6 +31,7 @@ import android.text.format.DateFormat; import android.text.format.DateUtils; import android.text.format.Time; import android.util.AttributeSet; +import android.util.MathUtils; import android.view.MotionEvent; import android.view.View; import android.view.accessibility.AccessibilityEvent; @@ -300,7 +301,11 @@ class SimpleMonthView extends View { } private static boolean isValidDayOfWeek(int day) { - return (day >= Time.SUNDAY && day <= Time.SATURDAY); + return day >= Calendar.SUNDAY && day <= Calendar.SATURDAY; + } + + private static boolean isValidMonth(int month) { + return month >= Calendar.JANUARY && month <= Calendar.DECEMBER; } /** @@ -312,8 +317,8 @@ class SimpleMonthView extends View { * @param selectedDay the selected day of the month, or -1 for no selection. * @param month the month. * @param year the year. - * @param weekStart which day the week should start on. {@link Time#SUNDAY} through - * {@link Time#SATURDAY}. + * @param weekStart which day the week should start on. {@link Calendar#SUNDAY} through + * {@link Calendar#SATURDAY}. * @param enabledDayStart the first enabled day. * @param enabledDayEnd the last enabled day. */ @@ -325,7 +330,7 @@ class SimpleMonthView extends View { mSelectedDay = selectedDay; - if (month >= Calendar.JANUARY && month <= Calendar.DECEMBER) { + if (isValidMonth(month)) { mMonth = month; } mYear = year; diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 80ea6ea..1509e80 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -17,6 +17,7 @@ package android.widget; import android.R; +import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ClipData; import android.content.ClipboardManager; @@ -1976,23 +1977,34 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } /** - * Sets the Drawables (if any) to appear to the left of, above, - * to the right of, and below the text. Use null if you do not - * want a Drawable there. The Drawables must already have had + * Sets the Drawables (if any) to appear to the left of, above, to the + * right of, and below the text. Use {@code null} if you do not want a + * Drawable there. The Drawables must already have had * {@link Drawable#setBounds} called. + * <p> + * Calling this method will overwrite any Drawables previously set using + * {@link #setCompoundDrawablesRelative} or related methods. * * @attr ref android.R.styleable#TextView_drawableLeft * @attr ref android.R.styleable#TextView_drawableTop * @attr ref android.R.styleable#TextView_drawableRight * @attr ref android.R.styleable#TextView_drawableBottom */ - public void setCompoundDrawables(Drawable left, Drawable top, - Drawable right, Drawable bottom) { + public void setCompoundDrawables(@Nullable Drawable left, @Nullable Drawable top, + @Nullable Drawable right, @Nullable Drawable bottom) { Drawables dr = mDrawables; - final boolean drawables = left != null || top != null - || right != null || bottom != null; + // We're switching to absolute, discard relative. + if (dr != null) { + if (dr.mDrawableStart != null) dr.mDrawableStart.setCallback(null); + dr.mDrawableStart = null; + if (dr.mDrawableEnd != null) dr.mDrawableEnd.setCallback(null); + dr.mDrawableEnd = null; + dr.mDrawableSizeStart = dr.mDrawableHeightStart = 0; + dr.mDrawableSizeEnd = dr.mDrawableHeightEnd = 0; + } + final boolean drawables = left != null || top != null || right != null || bottom != null; if (!drawables) { // Clearing drawables... can we free the data structure? if (dr != null) { @@ -2101,10 +2113,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } /** - * Sets the Drawables (if any) to appear to the left of, above, - * to the right of, and below the text. Use 0 if you do not - * want a Drawable there. The Drawables' bounds will be set to - * their intrinsic bounds. + * Sets the Drawables (if any) to appear to the left of, above, to the + * right of, and below the text. Use 0 if you do not want a Drawable there. + * The Drawables' bounds will be set to their intrinsic bounds. + * <p> + * Calling this method will overwrite any Drawables previously set using + * {@link #setCompoundDrawablesRelative} or related methods. * * @param left Resource identifier of the left Drawable. * @param top Resource identifier of the top Drawable. @@ -2126,18 +2140,21 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } /** - * Sets the Drawables (if any) to appear to the left of, above, - * to the right of, and below the text. Use null if you do not - * want a Drawable there. The Drawables' bounds will be set to - * their intrinsic bounds. + * Sets the Drawables (if any) to appear to the left of, above, to the + * right of, and below the text. Use {@code null} if you do not want a + * Drawable there. The Drawables' bounds will be set to their intrinsic + * bounds. + * <p> + * Calling this method will overwrite any Drawables previously set using + * {@link #setCompoundDrawablesRelative} or related methods. * * @attr ref android.R.styleable#TextView_drawableLeft * @attr ref android.R.styleable#TextView_drawableTop * @attr ref android.R.styleable#TextView_drawableRight * @attr ref android.R.styleable#TextView_drawableBottom */ - public void setCompoundDrawablesWithIntrinsicBounds(Drawable left, Drawable top, - Drawable right, Drawable bottom) { + public void setCompoundDrawablesWithIntrinsicBounds(@Nullable Drawable left, + @Nullable Drawable top, @Nullable Drawable right, @Nullable Drawable bottom) { if (left != null) { left.setBounds(0, 0, left.getIntrinsicWidth(), left.getIntrinsicHeight()); @@ -2155,20 +2172,33 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } /** - * Sets the Drawables (if any) to appear to the start of, above, - * to the end of, and below the text. Use null if you do not - * want a Drawable there. The Drawables must already have had - * {@link Drawable#setBounds} called. + * Sets the Drawables (if any) to appear to the start of, above, to the end + * of, and below the text. Use {@code null} if you do not want a Drawable + * there. The Drawables must already have had {@link Drawable#setBounds} + * called. + * <p> + * Calling this method will overwrite any Drawables previously set using + * {@link #setCompoundDrawables} or related methods. * * @attr ref android.R.styleable#TextView_drawableStart * @attr ref android.R.styleable#TextView_drawableTop * @attr ref android.R.styleable#TextView_drawableEnd * @attr ref android.R.styleable#TextView_drawableBottom */ - public void setCompoundDrawablesRelative(Drawable start, Drawable top, - Drawable end, Drawable bottom) { + public void setCompoundDrawablesRelative(@Nullable Drawable start, @Nullable Drawable top, + @Nullable Drawable end, @Nullable Drawable bottom) { Drawables dr = mDrawables; + // We're switching to relative, discard absolute. + if (dr != null) { + if (dr.mDrawableLeft != null) dr.mDrawableLeft.setCallback(null); + dr.mDrawableLeft = dr.mDrawableLeftInitial = null; + if (dr.mDrawableRight != null) dr.mDrawableRight.setCallback(null); + dr.mDrawableRight = dr.mDrawableRightInitial = null; + dr.mDrawableSizeLeft = dr.mDrawableHeightLeft = 0; + dr.mDrawableSizeRight = dr.mDrawableHeightRight = 0; + } + final boolean drawables = start != null || top != null || end != null || bottom != null; @@ -2274,10 +2304,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } /** - * Sets the Drawables (if any) to appear to the start of, above, - * to the end of, and below the text. Use 0 if you do not - * want a Drawable there. The Drawables' bounds will be set to - * their intrinsic bounds. + * Sets the Drawables (if any) to appear to the start of, above, to the end + * of, and below the text. Use 0 if you do not want a Drawable there. The + * Drawables' bounds will be set to their intrinsic bounds. + * <p> + * Calling this method will overwrite any Drawables previously set using + * {@link #setCompoundDrawables} or related methods. * * @param start Resource identifier of the start Drawable. * @param top Resource identifier of the top Drawable. @@ -2301,18 +2333,20 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } /** - * Sets the Drawables (if any) to appear to the start of, above, - * to the end of, and below the text. Use null if you do not - * want a Drawable there. The Drawables' bounds will be set to - * their intrinsic bounds. + * Sets the Drawables (if any) to appear to the start of, above, to the end + * of, and below the text. Use {@code null} if you do not want a Drawable + * there. The Drawables' bounds will be set to their intrinsic bounds. + * <p> + * Calling this method will overwrite any Drawables previously set using + * {@link #setCompoundDrawables} or related methods. * * @attr ref android.R.styleable#TextView_drawableStart * @attr ref android.R.styleable#TextView_drawableTop * @attr ref android.R.styleable#TextView_drawableEnd * @attr ref android.R.styleable#TextView_drawableBottom */ - public void setCompoundDrawablesRelativeWithIntrinsicBounds(Drawable start, Drawable top, - Drawable end, Drawable bottom) { + public void setCompoundDrawablesRelativeWithIntrinsicBounds(@Nullable Drawable start, + @Nullable Drawable top, @Nullable Drawable end, @Nullable Drawable bottom) { if (start != null) { start.setBounds(0, 0, start.getIntrinsicWidth(), start.getIntrinsicHeight()); @@ -2337,6 +2371,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @attr ref android.R.styleable#TextView_drawableRight * @attr ref android.R.styleable#TextView_drawableBottom */ + @NonNull public Drawable[] getCompoundDrawables() { final Drawables dr = mDrawables; if (dr != null) { @@ -2356,6 +2391,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @attr ref android.R.styleable#TextView_drawableEnd * @attr ref android.R.styleable#TextView_drawableBottom */ + @NonNull public Drawable[] getCompoundDrawablesRelative() { final Drawables dr = mDrawables; if (dr != null) { @@ -8142,6 +8178,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * Returns the TextView_textColor attribute from the TypedArray, if set, or * the TextAppearance_textColor from the TextView_textAppearance attribute, * if TextView_textColor was not set directly. + * + * @removed */ public static ColorStateList getTextColors(Context context, TypedArray attrs) { // It's not safe to use this method from apps. The parameter 'attrs' @@ -8169,6 +8207,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * AttributeSet, if set, or the default color from the * TextAppearance_textColor from the TextView_textAppearance attribute, if * TextView_textColor was not set directly. + * + * @removed */ public static int getTextColor(Context context, TypedArray attrs, int def) { final ColorStateList colors = getTextColors(context, attrs); @@ -8754,57 +8794,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } /** - * Prepare text so that there are not zero or two spaces at beginning and end of region defined - * by [min, max] when replacing this region by paste. - * Note that if there were two spaces (or more) at that position before, they are kept. We just - * make sure we do not add an extra one from the paste content. - */ - long prepareSpacesAroundPaste(int min, int max, CharSequence paste) { - if (paste.length() > 0) { - if (min > 0) { - final char charBefore = mTransformed.charAt(min - 1); - final char charAfter = paste.charAt(0); - - if (Character.isSpaceChar(charBefore) && Character.isSpaceChar(charAfter)) { - // Two spaces at beginning of paste: remove one - final int originalLength = mText.length(); - deleteText_internal(min - 1, min); - // Due to filters, there is no guarantee that exactly one character was - // removed: count instead. - final int delta = mText.length() - originalLength; - min += delta; - max += delta; - } else if (!Character.isSpaceChar(charBefore) && charBefore != '\n' && - !Character.isSpaceChar(charAfter) && charAfter != '\n') { - // No space at beginning of paste: add one - final int originalLength = mText.length(); - replaceText_internal(min, min, " "); - // Taking possible filters into account as above. - final int delta = mText.length() - originalLength; - min += delta; - max += delta; - } - } - - if (max < mText.length()) { - final char charBefore = paste.charAt(paste.length() - 1); - final char charAfter = mTransformed.charAt(max); - - if (Character.isSpaceChar(charBefore) && Character.isSpaceChar(charAfter)) { - // Two spaces at end of paste: remove one - deleteText_internal(max, max + 1); - } else if (!Character.isSpaceChar(charBefore) && charBefore != '\n' && - !Character.isSpaceChar(charAfter) && charAfter != '\n') { - // No space at end of paste: add one - replaceText_internal(max, max, " "); - } - } - } - - return TextUtils.packRangeInLong(min, max); - } - - /** * Paste clipboard content between min and max positions. */ private void paste(int min, int max) { @@ -8817,9 +8806,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener CharSequence paste = clip.getItemAt(i).coerceToStyledText(getContext()); if (paste != null) { if (!didFirst) { - long minMax = prepareSpacesAroundPaste(min, max, paste); - min = TextUtils.unpackRangeStartFromLong(minMax); - max = TextUtils.unpackRangeEndFromLong(minMax); Selection.setSelection((Spannable) mText, max); ((Editable) mText).replace(min, max, paste); didFirst = true; diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java index be28199..ba2d5b8 100644 --- a/core/java/android/widget/Toolbar.java +++ b/core/java/android/widget/Toolbar.java @@ -37,7 +37,6 @@ import android.view.View; import android.view.ViewGroup; import com.android.internal.R; -import com.android.internal.app.ToolbarActionBar; import com.android.internal.view.menu.MenuBuilder; import com.android.internal.view.menu.MenuItemImpl; import com.android.internal.view.menu.MenuPresenter; @@ -1007,8 +1006,15 @@ public class Toolbar extends ViewGroup { } private void addSystemView(View v) { - final LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, - LayoutParams.WRAP_CONTENT); + final ViewGroup.LayoutParams vlp = v.getLayoutParams(); + final LayoutParams lp; + if (vlp == null) { + lp = generateDefaultLayoutParams(); + } else if (!checkLayoutParams(vlp)) { + lp = generateLayoutParams(vlp); + } else { + lp = (LayoutParams) vlp; + } lp.mViewType = LayoutParams.SYSTEM; addView(v, lp); } @@ -1280,27 +1286,36 @@ public class Toolbar extends ViewGroup { final int[] collapsingMargins = mTempMargins; collapsingMargins[0] = collapsingMargins[1] = 0; + // Align views within the minimum toolbar height, if set. + final int alignmentHeight = getMinimumHeight(); + if (shouldLayout(mNavButtonView)) { if (isRtl) { - right = layoutChildRight(mNavButtonView, right, collapsingMargins); + right = layoutChildRight(mNavButtonView, right, collapsingMargins, + alignmentHeight); } else { - left = layoutChildLeft(mNavButtonView, left, collapsingMargins); + left = layoutChildLeft(mNavButtonView, left, collapsingMargins, + alignmentHeight); } } if (shouldLayout(mCollapseButtonView)) { if (isRtl) { - right = layoutChildRight(mCollapseButtonView, right, collapsingMargins); + right = layoutChildRight(mCollapseButtonView, right, collapsingMargins, + alignmentHeight); } else { - left = layoutChildLeft(mCollapseButtonView, left, collapsingMargins); + left = layoutChildLeft(mCollapseButtonView, left, collapsingMargins, + alignmentHeight); } } if (shouldLayout(mMenuView)) { if (isRtl) { - left = layoutChildLeft(mMenuView, left, collapsingMargins); + left = layoutChildLeft(mMenuView, left, collapsingMargins, + alignmentHeight); } else { - right = layoutChildRight(mMenuView, right, collapsingMargins); + right = layoutChildRight(mMenuView, right, collapsingMargins, + alignmentHeight); } } @@ -1311,17 +1326,21 @@ public class Toolbar extends ViewGroup { if (shouldLayout(mExpandedActionView)) { if (isRtl) { - right = layoutChildRight(mExpandedActionView, right, collapsingMargins); + right = layoutChildRight(mExpandedActionView, right, collapsingMargins, + alignmentHeight); } else { - left = layoutChildLeft(mExpandedActionView, left, collapsingMargins); + left = layoutChildLeft(mExpandedActionView, left, collapsingMargins, + alignmentHeight); } } if (shouldLayout(mLogoView)) { if (isRtl) { - right = layoutChildRight(mLogoView, right, collapsingMargins); + right = layoutChildRight(mLogoView, right, collapsingMargins, + alignmentHeight); } else { - left = layoutChildLeft(mLogoView, left, collapsingMargins); + left = layoutChildLeft(mLogoView, left, collapsingMargins, + alignmentHeight); } } @@ -1434,13 +1453,15 @@ public class Toolbar extends ViewGroup { addCustomViewsWithGravity(mTempViews, Gravity.LEFT); final int leftViewsCount = mTempViews.size(); for (int i = 0; i < leftViewsCount; i++) { - left = layoutChildLeft(mTempViews.get(i), left, collapsingMargins); + left = layoutChildLeft(mTempViews.get(i), left, collapsingMargins, + alignmentHeight); } addCustomViewsWithGravity(mTempViews, Gravity.RIGHT); final int rightViewsCount = mTempViews.size(); for (int i = 0; i < rightViewsCount; i++) { - right = layoutChildRight(mTempViews.get(i), right, collapsingMargins); + right = layoutChildRight(mTempViews.get(i), right, collapsingMargins, + alignmentHeight); } // Centered views try to center with respect to the whole bar, but views pinned @@ -1459,8 +1480,10 @@ public class Toolbar extends ViewGroup { final int centerViewsCount = mTempViews.size(); for (int i = 0; i < centerViewsCount; i++) { - centerLeft = layoutChildLeft(mTempViews.get(i), centerLeft, collapsingMargins); + centerLeft = layoutChildLeft(mTempViews.get(i), centerLeft, collapsingMargins, + alignmentHeight); } + mTempViews.clear(); } @@ -1483,46 +1506,49 @@ public class Toolbar extends ViewGroup { return width; } - private int layoutChildLeft(View child, int left, int[] collapsingMargins) { + private int layoutChildLeft(View child, int left, int[] collapsingMargins, + int alignmentHeight) { final LayoutParams lp = (LayoutParams) child.getLayoutParams(); final int l = lp.leftMargin - collapsingMargins[0]; left += Math.max(0, l); collapsingMargins[0] = Math.max(0, -l); - final int top = getChildTop(child); + final int top = getChildTop(child, alignmentHeight); final int childWidth = child.getMeasuredWidth(); child.layout(left, top, left + childWidth, top + child.getMeasuredHeight()); left += childWidth + lp.rightMargin; return left; } - private int layoutChildRight(View child, int right, int[] collapsingMargins) { + private int layoutChildRight(View child, int right, int[] collapsingMargins, + int alignmentHeight) { final LayoutParams lp = (LayoutParams) child.getLayoutParams(); final int r = lp.rightMargin - collapsingMargins[1]; right -= Math.max(0, r); collapsingMargins[1] = Math.max(0, -r); - final int top = getChildTop(child); + final int top = getChildTop(child, alignmentHeight); final int childWidth = child.getMeasuredWidth(); child.layout(right - childWidth, top, right, top + child.getMeasuredHeight()); right -= childWidth + lp.leftMargin; return right; } - private int getChildTop(View child) { + private int getChildTop(View child, int alignmentHeight) { final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + final int childHeight = child.getMeasuredHeight(); + final int alignmentOffset = alignmentHeight > 0 ? (childHeight - alignmentHeight) / 2 : 0; switch (getChildVerticalGravity(lp.gravity)) { case Gravity.TOP: - return getPaddingTop(); + return getPaddingTop() - alignmentOffset; case Gravity.BOTTOM: - return getHeight() - getPaddingBottom() - - child.getMeasuredHeight() - lp.bottomMargin; + return getHeight() - getPaddingBottom() - childHeight + - lp.bottomMargin - alignmentOffset; default: case Gravity.CENTER_VERTICAL: final int paddingTop = getPaddingTop(); final int paddingBottom = getPaddingBottom(); final int height = getHeight(); - final int childHeight = child.getMeasuredHeight(); final int space = height - paddingTop - paddingBottom; int spaceAbove = (space - childHeight) / 2; if (spaceAbove < lp.topMargin) { |
