diff options
Diffstat (limited to 'core')
48 files changed, 1508 insertions, 499 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index c79a0a5..9a3c290 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -18,10 +18,8 @@ package android.app; import android.annotation.NonNull; import android.transition.Scene; -import android.transition.Transition; import android.transition.TransitionManager; import android.util.ArrayMap; -import android.util.Pair; import android.util.SuperNotCalledException; import com.android.internal.app.ActionBarImpl; import com.android.internal.policy.PolicyManager; @@ -95,7 +93,6 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.HashMap; -import java.util.Map; /** * An activity is a single, focused thing that the user can do. Almost all @@ -3449,53 +3446,7 @@ public class Activity extends ContextThemeWrapper * @see #startActivity */ public void startActivityForResult(Intent intent, int requestCode) { - ArrayMap<String, View> sharedElements = new ArrayMap<String, View>(); - - if (mActionBar != null) { - mActionBar.captureSharedElements(sharedElements); - } - Bundle opts = mWindow.startExitTransition(sharedElements); - startActivityForResult(intent, requestCode, opts); - } - - /** - * Same as {@link #startActivityForResult(android.content.Intent, int)} except that - * shared element state is passed to the called Activity during the Activity Scene Transition. - * The Activity must have a TransitionManager with a Transition associated with exiting - * the current Scene. - * @param intent The intent to start. - * @param requestCode If >= 0, this code will be returned in - * onActivityResult() when the activity exits. - * @param sharedElements Views to be transitioned to the called Activity and their - * names as used in the called Activity. - * Views must not have null shared element name, however, if the - * Pair has a null name, the shared element name will be reused - * for the launched Activity's shared element name. - * @see android.transition.TransitionManager#setExitTransition(android.transition.Scene, android.transition.Transition) - * @see View#setSharedElementName(String) - */ - public void startActivityForResult(Intent intent, int requestCode, - Pair<View, String>... sharedElements) { - ArrayMap<String, View> sharedElementMap = new ArrayMap<String, View>(); - if (sharedElements != null) { - for (Pair<View, String> sharedElement: sharedElements) { - View view = sharedElement.first; - String sharedElementName = view.getSharedElementName(); - if (sharedElementName == null) { - throw new IllegalArgumentException("sharedElement must have a non-null " - + "sharedElementName"); - } - String name = sharedElement.second == null - ? sharedElementName : sharedElement.second; - sharedElementMap.put(name, view); - } - } - if (mActionBar != null) { - mActionBar.captureSharedElements(sharedElementMap); - } - - Bundle options = mWindow.startExitTransition(sharedElementMap); - startActivityForResult(intent, requestCode, options); + startActivityForResult(intent, requestCode, null); } /** @@ -3533,6 +3484,14 @@ public class Activity extends ContextThemeWrapper * @see #startActivity */ public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) { + TransitionManager tm = getContentTransitionManager(); + if (tm != null && options != null) { + ActivityOptions activityOptions = new ActivityOptions(options); + if (activityOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) { + getWindow().startExitTransition(activityOptions); + options = activityOptions.toBundle(); + } + } if (mParent == null) { Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( @@ -3705,25 +3664,7 @@ public class Activity extends ContextThemeWrapper */ @Override public void startActivity(Intent intent) { - startActivity(intent, (Pair<View, String>[]) null); - } - - /** - * Same as {@link #startActivity(android.content.Intent)} except that shared element - * state is passed to the called Activity during the Activity Scene Transition. - * The Activity must have a TransitionManager with a Transition associated with exiting - * the current Scene. - * @param intent The intent to start. - * @param sharedElements Views to be transitioned to the called Activity and their - * names as used in the called Activity. - * Views must not have null shared element name, however, if the - * Pair has a null name, the shared element name will be reused - * for the launched Activity's shared element name. - * @see android.transition.TransitionManager#setExitTransition(android.transition.Scene, android.transition.Transition) - * @see View#setSharedElementName(String) - */ - public void startActivity(Intent intent, Pair<View, String>... sharedElements) { - startActivityForResult(intent, -1, sharedElements); + startActivity(intent, null); } /** @@ -4779,8 +4720,7 @@ public class Activity extends ContextThemeWrapper */ public final void setProgressBarIndeterminate(boolean indeterminate) { getWindow().setFeatureInt(Window.FEATURE_PROGRESS, - indeterminate ? Window.PROGRESS_INDETERMINATE_ON - : Window.PROGRESS_INDETERMINATE_OFF); + indeterminate ? Window.PROGRESS_INDETERMINATE_ON : Window.PROGRESS_INDETERMINATE_OFF); } /** @@ -5390,6 +5330,12 @@ public class Activity extends ContextThemeWrapper mTransitionActivityOptions = activityOptions; sceneTransitionListener = new Window.SceneTransitionListener() { @Override + public void enterSharedElement(Bundle transitionArgs) { + startSharedElementTransition(transitionArgs); + mTransitionActivityOptions = null; + } + + @Override public void nullPendingTransition() { overridePendingTransition(0, 0); } @@ -5403,16 +5349,6 @@ public class Activity extends ContextThemeWrapper public void convertToTranslucent() { Activity.this.convertToTranslucent(null); } - - @Override - public void sharedElementStart(Transition transition) { - Activity.this.onCaptureSharedElementStart(transition); - } - - @Override - public void sharedElementEnd() { - Activity.this.onCaptureSharedElementEnd(); - } }; } @@ -5606,23 +5542,53 @@ public class Activity extends ContextThemeWrapper } /** - * Called when setting up Activity Scene transitions when the start state for shared - * elements has been captured. Override this method to modify the start position of shared - * elements for the entry Transition. + * Gets the entering Activity transition args. Will be null if + * {@link android.app.ActivityOptions#makeSceneTransitionAnimation(android.os.Bundle)} was + * not used to pass a Bundle to startActivity. The Bundle passed to that method in the + * calling Activity is returned here. + * <p>After startSharedElementTransition is called, this method will return null.</p> * - * @param transition The <code>Transition</code> being used to change - * bounds of shared elements in the source Activity to - * the bounds defined by the entering Scene. + * @return The Bundle passed into Bundle parameter of + * {@link android.app.ActivityOptions#makeSceneTransitionAnimation(android.os.Bundle)} + * in the calling Activity. */ - public void onCaptureSharedElementStart(Transition transition) { + public Bundle getTransitionArgs() { + if (mTransitionActivityOptions == null) { + return null; + } + return mTransitionActivityOptions.getSceneTransitionArgs(); + } + + /** + * Override to transfer a shared element from a calling Activity to this Activity. + * Shared elements will be made VISIBLE before this call. The Activity is responsible + * for transitioning the shared elements from their location to the eventual destination. + * The shared element will be laid out a the destination when this method is called. + * + * @param transitionArgs The same as returned from {@link #getTransitionArgs()}, this should + * contain information from the calling Activity to tell where the + * shared element should be placed. + */ + protected void startSharedElementTransition(Bundle transitionArgs) { } /** - * Called when setting up Activity Scene transitions when the final state for - * shared elements state has been captured. Override this method to modify the destination - * position of shared elements for the entry Transition. + * Controls how the background fade is triggered when there is an entering Activity transition. + * If fadeEarly is true, the Window background will fade in as soon as the shared elements are + * ready to switch. If fadeEarly is false, the background will fade only after the calling + * Activity's exit transition completes. By default, the Window will fade in when the calling + * Activity's exit transition completes. + * + * @param fadeEarly Set to true to fade out the exiting Activity as soon as the shared elements + * are transferred. Set to false to fade out the exiting Activity as soon as + * the shared element is transferred. + * @see android.app.ActivityOptions#makeSceneTransitionAnimation(android.os.Bundle) */ - public void onCaptureSharedElementEnd() { + public void setEarlyBackgroundTransition(boolean fadeEarly) { + if (mTransitionActivityOptions == null) { + return; + } + mWindow.setEarlyBackgroundTransition(fadeEarly); } /** diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index 32cc30b..3f97c40 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -16,6 +16,7 @@ package android.app; +import android.animation.Animator; import android.content.Context; import android.graphics.Bitmap; import android.os.Bundle; @@ -23,10 +24,12 @@ import android.os.Handler; import android.os.IRemoteCallback; import android.os.RemoteException; import android.transition.Transition; +import android.util.ArrayMap; import android.util.Log; import android.view.View; import java.util.ArrayList; +import java.util.Map; /** * Helper class for building an options Bundle that can be used with @@ -97,6 +100,12 @@ public class ActivityOptions { public static final String KEY_ANIM_START_LISTENER = "android:animStartListener"; /** + * Arguments for the scene transition about to begin. + * @hide + */ + public static final String KEY_SCENE_TRANSITION_ARGS = "android:sceneTransitionArgs"; + + /** * For Activity transitions, the calling Activity's TransitionListener used to * notify the called Activity when the shared element and the exit transitions * complete. @@ -111,10 +120,9 @@ public class ActivityOptions { private static final String KEY_TRANSITION_TARGET_LISTENER = "android:transitionTargetListener"; /** - * The names of shared elements that are transitioned to the started Activity. - * This is also the name of shared elements that the started Activity accepted. + * The shared element's texture ID (TODO: not used yet). */ - private static final String KEY_SHARED_ELEMENT_NAMES = "android:shared_element_names"; + private static final String KEY_SHARED_ELEMENT_TEXTURE_ID = "android:sharedElementTextureId"; /** @hide */ public static final int ANIM_NONE = 0; @@ -138,9 +146,9 @@ public class ActivityOptions { private int mStartY; private int mStartWidth; private int mStartHeight; + private Bundle mTransitionArgs; private IRemoteCallback mAnimationStartedListener; private IRemoteCallback mTransitionCompleteListener; - private ArrayList<String> mSharedElementNames; /** * Create an ActivityOptions specifying a custom animation to run when @@ -218,7 +226,7 @@ public class ActivityOptions { /** @hide */ public interface ActivityTransitionTarget { - void sharedElementTransitionComplete(Bundle transitionArgs); + void sharedElementTransitionComplete(); void exitTransitionComplete(); } @@ -344,6 +352,8 @@ public class ActivityOptions { * When visual elements are to carry between Activities, args should be used to tell the called * Activity about the location and size. * + * TODO: Provide facility to capture layout and bitmap of shared elements. + * * <p>When * {@link android.app.Activity#startActivities(android.content.Intent[], android.os.Bundle)} * is used with the {@link #toBundle()} result, the Activity's content scene will automatically @@ -358,16 +368,15 @@ public class ActivityOptions { * enabled on the calling Activity to cause an exit transition. The same must be in * the called Activity to get an entering transition.</p> * - * @hide + * @param args Contains information for transferring a view between this Activity and the + * target Activity. Will be used by the called Activity to transition the + * view to its eventual destination + * @see android.app.Activity#startSharedElementTransition(android.os.Bundle) */ - public static ActivityOptions makeSceneTransitionAnimation(Transition exitTransition, - ArrayList<String> sharedElementNames, Transition sharedElementTransition, - SharedElementSource sharedElementSource) { + public static ActivityOptions makeSceneTransitionAnimation(Bundle args) { ActivityOptions opts = new ActivityOptions(); opts.mAnimationType = ANIM_SCENE_TRANSITION; - opts.mTransitionCompleteListener = new ExitTransitionListener(exitTransition, - sharedElementTransition, sharedElementSource); - opts.mSharedElementNames = sharedElementNames; + opts.mTransitionArgs = args; return opts; } @@ -403,9 +412,9 @@ public class ActivityOptions { break; case ANIM_SCENE_TRANSITION: + mTransitionArgs = opts.getBundle(KEY_SCENE_TRANSITION_ARGS); mTransitionCompleteListener = IRemoteCallback.Stub.asInterface( opts.getBinder(KEY_TRANSITION_COMPLETE_LISTENER)); - mSharedElementNames = opts.getStringArrayList(KEY_SHARED_ELEMENT_NAMES); break; } } @@ -456,16 +465,17 @@ public class ActivityOptions { } /** @hide */ - public IRemoteCallback getOnAnimationStartListener() { - return mAnimationStartedListener; + public Bundle getSceneTransitionArgs() { + return mTransitionArgs; } /** @hide */ - public ArrayList<String> getSharedElementNames() { return mSharedElementNames; } + public IRemoteCallback getOnAnimationStartListener() { + return mAnimationStartedListener; + } /** @hide */ - public void dispatchSceneTransitionStarted(final ActivityTransitionTarget target, - ArrayList<String> sharedElementNames) { + public void dispatchSceneTransitionStarted(final ActivityTransitionTarget target) { boolean listenerSent = false; if (mTransitionCompleteListener != null) { IRemoteCallback callback = new IRemoteCallback.Stub() { @@ -474,13 +484,13 @@ public class ActivityOptions { if (data == null) { target.exitTransitionComplete(); } else { - target.sharedElementTransitionComplete(data); + // TODO: Use texture id + target.sharedElementTransitionComplete(); } } }; Bundle bundle = new Bundle(); bundle.putBinder(KEY_TRANSITION_TARGET_LISTENER, callback.asBinder()); - bundle.putStringArrayList(KEY_SHARED_ELEMENT_NAMES, sharedElementNames); try { mTransitionCompleteListener.sendResult(bundle); listenerSent = true; @@ -489,23 +499,12 @@ public class ActivityOptions { } } if (!listenerSent) { - target.sharedElementTransitionComplete(null); + target.sharedElementTransitionComplete(); target.exitTransitionComplete(); } } /** @hide */ - public void dispatchSharedElementsReady() { - if (mTransitionCompleteListener != null) { - try { - mTransitionCompleteListener.sendResult(null); - } catch (RemoteException e) { - Log.w(TAG, "Couldn't synchronize shared elements", e); - } - } - } - - /** @hide */ public void abort() { if (mAnimationStartedListener != null) { try { @@ -531,7 +530,6 @@ public class ActivityOptions { if (otherOptions.mPackageName != null) { mPackageName = otherOptions.mPackageName; } - mSharedElementNames = null; switch (otherOptions.mAnimationType) { case ANIM_CUSTOM: mAnimationType = otherOptions.mAnimationType; @@ -546,6 +544,7 @@ public class ActivityOptions { } mAnimationStartedListener = otherOptions.mAnimationStartedListener; mTransitionCompleteListener = null; + mTransitionArgs = null; break; case ANIM_SCALE_UP: mAnimationType = otherOptions.mAnimationType; @@ -561,6 +560,7 @@ public class ActivityOptions { } mAnimationStartedListener = null; mTransitionCompleteListener = null; + mTransitionArgs = null; break; case ANIM_THUMBNAIL_SCALE_UP: case ANIM_THUMBNAIL_SCALE_DOWN: @@ -576,13 +576,14 @@ public class ActivityOptions { } mAnimationStartedListener = otherOptions.mAnimationStartedListener; mTransitionCompleteListener = null; + mTransitionArgs = null; break; case ANIM_SCENE_TRANSITION: mAnimationType = otherOptions.mAnimationType; mTransitionCompleteListener = otherOptions.mTransitionCompleteListener; + mTransitionArgs = otherOptions.mTransitionArgs; mThumbnail = null; mAnimationStartedListener = null; - mSharedElementNames = otherOptions.mSharedElementNames; break; } } @@ -626,11 +627,11 @@ public class ActivityOptions { break; case ANIM_SCENE_TRANSITION: b.putInt(KEY_ANIM_TYPE, mAnimationType); + b.putBundle(KEY_SCENE_TRANSITION_ARGS, mTransitionArgs); if (mTransitionCompleteListener != null) { b.putBinder(KEY_TRANSITION_COMPLETE_LISTENER, mTransitionCompleteListener.asBinder()); } - b.putStringArrayList(KEY_SHARED_ELEMENT_NAMES, mSharedElementNames); break; } return b; @@ -652,28 +653,31 @@ public class ActivityOptions { /** @hide */ public interface SharedElementSource { - Bundle getSharedElementExitState(); - void acceptedSharedElements(ArrayList<String> sharedElementNames); - void hideSharedElements(); + int getTextureId(); + } + + /** + * In the calling Activity when transitioning out, sets the Transition to listen for + * changes. + * @hide + */ + public void setExitTransition(Transition transition, SharedElementSource sharedElementSource) { + mTransitionCompleteListener = new ExitTransitionListener(transition, sharedElementSource); } private static class ExitTransitionListener extends IRemoteCallback.Stub - implements Transition.TransitionListener { + implements Transition.TransitionListener, Animator.AnimatorListener { + private ArrayList<Animator> mSharedElementAnimators = new ArrayList<Animator>(); private boolean mSharedElementNotified; private Transition mExitTransition; - private Transition mSharedElementTransition; private IRemoteCallback mTransitionCompleteCallback; private boolean mExitComplete; - private boolean mSharedElementComplete; private SharedElementSource mSharedElementSource; - public ExitTransitionListener(Transition exitTransition, Transition sharedElementTransition, - SharedElementSource sharedElementSource) { + public ExitTransitionListener(Transition transition, SharedElementSource sharedElementSource) { mSharedElementSource = sharedElementSource; - mExitTransition = exitTransition; + mExitTransition = transition; mExitTransition.addListener(this); - mSharedElementTransition = sharedElementTransition; - mSharedElementTransition.addListener(this); } @Override @@ -681,36 +685,36 @@ public class ActivityOptions { if (data != null) { mTransitionCompleteCallback = IRemoteCallback.Stub.asInterface( data.getBinder(KEY_TRANSITION_TARGET_LISTENER)); - ArrayList<String> sharedElementNames - = data.getStringArrayList(KEY_SHARED_ELEMENT_NAMES); - mSharedElementSource.acceptedSharedElements(sharedElementNames); notifySharedElement(); notifyExit(); - } else { - mSharedElementSource.hideSharedElements(); } } @Override public void onTransitionStart(Transition transition) { + ArrayMap<Animator, Transition.AnimationInfo> runningAnimators + = Transition.getRunningAnimators(); + for (Map.Entry<Animator, Transition.AnimationInfo> entry : runningAnimators.entrySet()) { + if (entry.getValue().view.getSharedElementName() != null) { + mSharedElementAnimators.add(entry.getKey()); + entry.getKey().addListener(this); + } + } + notifySharedElement(); } @Override public void onTransitionEnd(Transition transition) { - if (transition == mExitTransition) { - mExitComplete = true; - notifyExit(); - mExitTransition.removeListener(this); - } else { - mSharedElementComplete = true; - notifySharedElement(); - mSharedElementTransition.removeListener(this); - } + mExitComplete = true; + notifyExit(); + mExitTransition.removeListener(this); } @Override public void onTransitionCancel(Transition transition) { - onTransitionEnd(transition); + mExitComplete = true; + notifyExit(); + mExitTransition.removeListener(this); } @Override @@ -721,13 +725,34 @@ public class ActivityOptions { public void onTransitionResume(Transition transition) { } + @Override + public void onAnimationStart(Animator animation) { + } + + @Override + public void onAnimationEnd(Animator animation) { + mSharedElementAnimators.remove(animation); + notifySharedElement(); + } + + @Override + public void onAnimationCancel(Animator animation) { + mSharedElementAnimators.remove(animation); + notifySharedElement(); + } + + @Override + public void onAnimationRepeat(Animator animation) { + } + private void notifySharedElement() { - if (!mSharedElementNotified && mSharedElementComplete + if (!mSharedElementNotified && mSharedElementAnimators.isEmpty() && mTransitionCompleteCallback != null) { mSharedElementNotified = true; try { - Bundle sharedElementState = mSharedElementSource.getSharedElementExitState(); - mTransitionCompleteCallback.sendResult(sharedElementState); + Bundle bundle = new Bundle(); + bundle.putInt(KEY_SHARED_ELEMENT_TEXTURE_ID, mSharedElementSource.getTextureId()); + mTransitionCompleteCallback.sendResult(bundle); } catch (RemoteException e) { Log.w(TAG, "Couldn't notify that the transition ended", e); } diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 7efb3f1..9b3643c 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -63,7 +63,7 @@ import android.location.ILocationManager; import android.location.LocationManager; import android.media.AudioManager; import android.media.MediaRouter; -import android.media.MediaSessionManager; +import android.media.session.MediaSessionManager; import android.net.ConnectivityManager; import android.net.IConnectivityManager; import android.net.INetworkPolicyManager; diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index d05d1a1..81a886a 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -2352,10 +2352,10 @@ public abstract class Context { /** * Use with {@link #getSystemService} to retrieve a - * {@link android.media.MediaSessionManager} for managing media Sessions. + * {@link android.media.session.MediaSessionManager} for managing media Sessions. * * @see #getSystemService - * @see android.media.MediaSessionManager + * @see android.media.session.MediaSessionManager */ public static final String MEDIA_SESSION_SERVICE = "media_session"; diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 25514f4..54d43d3 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -507,6 +507,17 @@ public class NetworkStats implements Parcelable { } /** + * Fast path for battery stats. + */ + public long getTotalPackets() { + long total = 0; + for (int i = size-1; i >= 0; i--) { + total += rxPackets[i] + txPackets[i]; + } + return total; + } + + /** * Subtract the given {@link NetworkStats}, effectively leaving the delta * between two snapshots in time. Assumes that statistics rows collect over * time, and that none of them have disappeared. diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index e91f7d7..bfce0c1 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -326,6 +326,8 @@ public abstract class BatteryStats implements Parcelable { public abstract boolean hasNetworkActivity(); public abstract long getNetworkActivityBytes(int type, int which); public abstract long getNetworkActivityPackets(int type, int which); + public abstract long getMobileRadioActiveTime(int which); + public abstract int getMobileRadioActiveCount(int which); public static abstract class Sensor { /* @@ -899,6 +901,28 @@ public abstract class BatteryStats implements Parcelable { */ public abstract long getMobileRadioActiveTime(long batteryRealtime, int which); + /** + * Returns the number of times that the mobile network has transitioned to the + * active state. + * + * {@hide} + */ + public abstract int getMobileRadioActiveCount(int which); + + /** + * Returns the time in microseconds that the mobile network has been active + * (in a high power state) but not being able to blame on an app. + * + * {@hide} + */ + public abstract long getMobileRadioActiveUnknownTime(int which); + + /** + * Return count of number of times radio was app that could not be blamed on apps. + * + * {@hide} + */ + public abstract int getMobileRadioActiveUnknownCount(int which); public static final int DATA_CONNECTION_NONE = 0; public static final int DATA_CONNECTION_GPRS = 1; @@ -1238,6 +1262,13 @@ public abstract class BatteryStats implements Parcelable { sb.append("ms "); } + private final static void formatTimeMsNoSpace(StringBuilder sb, long time) { + long sec = time / 1000; + formatTimeRaw(sb, sec); + sb.append(time - (sec * 1000)); + sb.append("ms"); + } + private final String formatRatioLocked(long num, long den) { if (den == 0L) { return "--%"; @@ -1590,6 +1621,8 @@ public abstract class BatteryStats implements Parcelable { long wifiBytesTx = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which); long mobilePacketsRx = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which); long mobilePacketsTx = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which); + long mobileActiveTime = u.getMobileRadioActiveTime(which); + int mobileActiveCount = u.getMobileRadioActiveCount(which); long wifiPacketsRx = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which); long wifiPacketsTx = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which); long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which); @@ -1598,11 +1631,12 @@ public abstract class BatteryStats implements Parcelable { if (mobileBytesRx > 0 || mobileBytesTx > 0 || wifiBytesRx > 0 || wifiBytesTx > 0 || mobilePacketsRx > 0 || mobilePacketsTx > 0 || wifiPacketsRx > 0 - || wifiPacketsTx > 0) { + || wifiPacketsTx > 0 || mobileActiveTime > 0 || mobileActiveCount > 0) { dumpLine(pw, uid, category, NETWORK_DATA, mobileBytesRx, mobileBytesTx, wifiBytesRx, wifiBytesTx, mobilePacketsRx, mobilePacketsTx, - wifiPacketsRx, wifiPacketsTx); + wifiPacketsRx, wifiPacketsTx, + mobileActiveTime, mobileActiveCount); } if (fullWifiLockOnTime != 0 || wifiScanTime != 0 @@ -1932,9 +1966,9 @@ public abstract class BatteryStats implements Parcelable { pw.print(", sent "); pw.print(wifiTxTotalPackets); pw.println(")"); sb.setLength(0); sb.append(prefix); - sb.append(" Total full wakelock time: "); formatTimeMs(sb, + sb.append(" Total full wakelock time: "); formatTimeMsNoSpace(sb, (fullWakeLockTimeTotalMicros + 500) / 1000); - sb.append(", Total partial wakelock time: "); formatTimeMs(sb, + sb.append(", Total partial wakelock time: "); formatTimeMsNoSpace(sb, (partialWakeLockTimeTotalMicros + 500) / 1000); pw.println(sb.toString()); @@ -1964,7 +1998,7 @@ public abstract class BatteryStats implements Parcelable { sb.setLength(0); sb.append(prefix); sb.append(" Signal scanning time: "); - formatTimeMs(sb, getPhoneSignalScanningTime(batteryRealtime, which) / 1000); + formatTimeMsNoSpace(sb, getPhoneSignalScanningTime(batteryRealtime, which) / 1000); pw.println(sb.toString()); sb.setLength(0); @@ -1993,9 +2027,26 @@ public abstract class BatteryStats implements Parcelable { sb.setLength(0); sb.append(prefix); sb.append(" Mobile radio active time: "); - formatTimeMs(sb, getMobileRadioActiveTime(batteryRealtime, which) / 1000); + final long mobileActiveTime = getMobileRadioActiveTime(batteryRealtime, which); + formatTimeMs(sb, mobileActiveTime / 1000); + sb.append("("); sb.append(formatRatioLocked(mobileActiveTime, whichBatteryRealtime)); + sb.append(") "); sb.append(getMobileRadioActiveCount(which)); + sb.append("x"); pw.println(sb.toString()); + final long mobileActiveUnknownTime = getMobileRadioActiveUnknownTime(which); + if (mobileActiveUnknownTime != 0) { + sb.setLength(0); + sb.append(prefix); + sb.append(" Mobile radio active unknown time: "); + formatTimeMs(sb, mobileActiveUnknownTime / 1000); + sb.append("("); + sb.append(formatRatioLocked(mobileActiveUnknownTime, whichBatteryRealtime)); + sb.append(") "); sb.append(getMobileRadioActiveUnknownCount(which)); + sb.append("x"); + pw.println(sb.toString()); + } + sb.setLength(0); sb.append(prefix); sb.append(" Wifi on: "); formatTimeMs(sb, wifiOnTime / 1000); @@ -2132,7 +2183,8 @@ public abstract class BatteryStats implements Parcelable { pw.println(); break; case APP: - pw.print(prefix); pw.print(" Uid "); pw.print(bs.uidObj.getUid()); + pw.print(prefix); pw.print(" Uid "); + UserHandle.formatUid(pw, bs.uidObj.getUid()); pw.print(": "); printmAh(pw, bs.value); pw.println(); break; case USER: @@ -2152,6 +2204,23 @@ public abstract class BatteryStats implements Parcelable { pw.println(); } + sippers = helper.getMobilemsppList(); + if (sippers != null && sippers.size() > 0) { + pw.print(prefix); pw.println(" Per-app mobile ms per packet:"); + for (int i=0; i<sippers.size(); i++) { + BatterySipper bs = sippers.get(i); + sb.setLength(0); + sb.append(prefix); sb.append(" Uid "); + UserHandle.formatUid(sb, bs.uidObj.getUid()); + sb.append(": "); sb.append(BatteryStatsHelper.makemAh(bs.mobilemspp)); + sb.append(" ("); sb.append(bs.mobileRxPackets+bs.mobileTxPackets); + sb.append(" packets over "); formatTimeMsNoSpace(sb, bs.mobileActive); + sb.append(")"); + pw.println(sb.toString()); + } + pw.println(); + } + if (timers.size() > 0) { Collections.sort(timers, timerComparator); pw.print(prefix); pw.println(" All partial wake locks:"); @@ -2183,13 +2252,15 @@ public abstract class BatteryStats implements Parcelable { UserHandle.formatUid(pw, uid); pw.println(":"); boolean uidActivity = false; - + long mobileRxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which); long mobileTxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which); long wifiRxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which); long wifiTxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which); long mobileRxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which); long mobileTxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which); + long uidMobileActiveTime = u.getMobileRadioActiveTime(which); + int uidMobileActiveCount = u.getMobileRadioActiveCount(which); long wifiRxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which); long wifiTxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which); long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which); @@ -2204,6 +2275,23 @@ public abstract class BatteryStats implements Parcelable { pw.print(" sent (packets "); pw.print(mobileRxPackets); pw.print(" received, "); pw.print(mobileTxPackets); pw.println(" sent)"); } + if (uidMobileActiveTime > 0 || uidMobileActiveCount > 0) { + sb.setLength(0); + sb.append(prefix); sb.append(" Mobile radio active: "); + formatTimeMs(sb, uidMobileActiveTime / 1000); + sb.append("("); + sb.append(formatRatioLocked(uidMobileActiveTime, mobileActiveTime)); + sb.append(") "); sb.append(uidMobileActiveCount); sb.append("x"); + long packets = mobileRxPackets + mobileTxPackets; + if (packets == 0) { + packets = 1; + } + sb.append(" @ "); + sb.append(BatteryStatsHelper.makemAh(uidMobileActiveTime / 1000 / (double)packets)); + sb.append(" mspp"); + pw.println(sb.toString()); + } + if (wifiRxBytes > 0 || wifiTxBytes > 0 || wifiRxPackets > 0 || wifiTxPackets > 0) { pw.print(prefix); pw.print(" Wi-Fi network: "); pw.print(formatBytesLocked(wifiRxBytes)); pw.print(" received, "); @@ -2212,6 +2300,24 @@ public abstract class BatteryStats implements Parcelable { pw.print(" received, "); pw.print(wifiTxPackets); pw.println(" sent)"); } + if (fullWifiLockOnTime != 0 || wifiScanTime != 0 + || uidWifiRunningTime != 0) { + sb.setLength(0); + sb.append(prefix); sb.append(" Wifi Running: "); + formatTimeMs(sb, uidWifiRunningTime / 1000); + sb.append("("); sb.append(formatRatioLocked(uidWifiRunningTime, + whichBatteryRealtime)); sb.append(")\n"); + sb.append(prefix); sb.append(" Full Wifi Lock: "); + formatTimeMs(sb, fullWifiLockOnTime / 1000); + sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime, + whichBatteryRealtime)); sb.append(")\n"); + sb.append(prefix); sb.append(" Wifi Scan: "); + formatTimeMs(sb, wifiScanTime / 1000); + sb.append("("); sb.append(formatRatioLocked(wifiScanTime, + whichBatteryRealtime)); sb.append(")"); + pw.println(sb.toString()); + } + if (u.hasUserActivity()) { boolean hasData = false; for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) { @@ -2233,24 +2339,6 @@ public abstract class BatteryStats implements Parcelable { pw.println(sb.toString()); } } - - if (fullWifiLockOnTime != 0 || wifiScanTime != 0 - || uidWifiRunningTime != 0) { - sb.setLength(0); - sb.append(prefix); sb.append(" Wifi Running: "); - formatTimeMs(sb, uidWifiRunningTime / 1000); - sb.append("("); sb.append(formatRatioLocked(uidWifiRunningTime, - whichBatteryRealtime)); sb.append(")\n"); - sb.append(prefix); sb.append(" Full Wifi Lock: "); - formatTimeMs(sb, fullWifiLockOnTime / 1000); - sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime, - whichBatteryRealtime)); sb.append(")\n"); - sb.append(prefix); sb.append(" Wifi Scan: "); - formatTimeMs(sb, wifiScanTime / 1000); - sb.append("("); sb.append(formatRatioLocked(wifiScanTime, - whichBatteryRealtime)); sb.append(")"); - pw.println(sb.toString()); - } Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats(); if (wakelocks.size() > 0) { diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java index 9f1e72d..fd3f9b3 100644 --- a/core/java/android/transition/Transition.java +++ b/core/java/android/transition/Transition.java @@ -552,7 +552,8 @@ public abstract class Transition implements Cloneable { return false; } - private static ArrayMap<Animator, AnimationInfo> getRunningAnimators() { + /** @hide */ + public static ArrayMap<Animator, AnimationInfo> getRunningAnimators() { ArrayMap<Animator, AnimationInfo> runningAnimators = sRunningAnimators.get(); if (runningAnimators == null) { runningAnimators = new ArrayMap<Animator, AnimationInfo>(); @@ -1112,32 +1113,30 @@ public abstract class Transition implements Cloneable { } } } - if (view.getParent() instanceof ViewGroup) { - TransitionValues values = new TransitionValues(); - values.view = view; - if (start) { - captureStartValues(values); + TransitionValues values = new TransitionValues(); + values.view = view; + if (start) { + captureStartValues(values); + } else { + captureEndValues(values); + } + if (start) { + if (!isListViewItem) { + mStartValues.viewValues.put(view, values); + if (id >= 0) { + mStartValues.idValues.put((int) id, values); + } } else { - captureEndValues(values); + mStartValues.itemIdValues.put(itemId, values); } - if (start) { - if (!isListViewItem) { - mStartValues.viewValues.put(view, values); - if (id >= 0) { - mStartValues.idValues.put((int) id, values); - } - } else { - mStartValues.itemIdValues.put(itemId, values); + } else { + if (!isListViewItem) { + mEndValues.viewValues.put(view, values); + if (id >= 0) { + mEndValues.idValues.put((int) id, values); } } else { - if (!isListViewItem) { - mEndValues.viewValues.put(view, values); - if (id >= 0) { - mEndValues.idValues.put((int) id, values); - } - } else { - mEndValues.itemIdValues.put(itemId, values); - } + mEndValues.itemIdValues.put(itemId, values); } } if (view instanceof ViewGroup) { diff --git a/core/java/android/transition/TransitionInflater.java b/core/java/android/transition/TransitionInflater.java index 912f2ed..9fa554c 100644 --- a/core/java/android/transition/TransitionInflater.java +++ b/core/java/android/transition/TransitionInflater.java @@ -285,27 +285,46 @@ public class TransitionInflater { com.android.internal.R.styleable.TransitionManager); int transitionId = a.getResourceId( com.android.internal.R.styleable.TransitionManager_transition, -1); + Scene fromScene = null, toScene = null; int fromId = a.getResourceId( com.android.internal.R.styleable.TransitionManager_fromScene, -1); - Scene fromScene = (fromId < 0) ? null: Scene.getSceneForLayout(sceneRoot, fromId, mContext); + if (fromId >= 0) fromScene = Scene.getSceneForLayout(sceneRoot, fromId, mContext); int toId = a.getResourceId( com.android.internal.R.styleable.TransitionManager_toScene, -1); - Scene toScene = (toId < 0) ? null : Scene.getSceneForLayout(sceneRoot, toId, mContext); - + if (toId >= 0) toScene = Scene.getSceneForLayout(sceneRoot, toId, mContext); + String fromName = a.getString( + com.android.internal.R.styleable.TransitionManager_fromSceneName); + String toName = a.getString( + com.android.internal.R.styleable.TransitionManager_toSceneName); if (transitionId >= 0) { Transition transition = inflateTransition(transitionId); if (transition != null) { - if (fromScene == null) { - if (toScene == null) { - throw new RuntimeException("No matching fromScene or toScene " + - "for transition ID " + transitionId); + if (fromScene != null) { + boolean hasDest = false; + if (toScene != null) { + transitionManager.setTransition(fromScene, toScene, transition); + hasDest = true; + } + + if (!TextUtils.isEmpty(toName)) { + transitionManager.setTransition(fromScene, toName, transition); + hasDest = true; + } + + if (!hasDest) { + throw new RuntimeException("No matching toScene or toSceneName for given " + + "fromScene for transition ID " + transitionId); + } + } else if (toId >= 0) { + transitionManager.setTransition(toScene, transition); + } + if (fromName != null) { + if (toScene != null) { + transitionManager.setTransition(fromName, toScene, transition); } else { - transitionManager.setTransition(toScene, transition); + throw new RuntimeException("No matching toScene for given fromSceneName " + + "for transition ID " + transitionId); } - } else if (toScene == null) { - transitionManager.setExitTransition(fromScene, transition); - } else { - transitionManager.setTransition(fromScene, toScene, transition); } } } diff --git a/core/java/android/transition/TransitionManager.java b/core/java/android/transition/TransitionManager.java index f3abfb0..0106f7f 100644 --- a/core/java/android/transition/TransitionManager.java +++ b/core/java/android/transition/TransitionManager.java @@ -70,9 +70,12 @@ public class TransitionManager { private static final String[] EMPTY_STRINGS = new String[0]; ArrayMap<Scene, Transition> mSceneTransitions = new ArrayMap<Scene, Transition>(); - ArrayMap<Scene, Transition> mExitSceneTransitions = new ArrayMap<Scene, Transition>(); ArrayMap<Scene, ArrayMap<Scene, Transition>> mScenePairTransitions = new ArrayMap<Scene, ArrayMap<Scene, Transition>>(); + ArrayMap<Scene, ArrayMap<String, Transition>> mSceneNameTransitions = + new ArrayMap<Scene, ArrayMap<String, Transition>>(); + ArrayMap<String, ArrayMap<Scene, Transition>> mNameSceneTransitions = + new ArrayMap<String, ArrayMap<Scene, Transition>>(); private static ThreadLocal<WeakReference<ArrayMap<ViewGroup, ArrayList<Transition>>>> sRunningTransitions = new ThreadLocal<WeakReference<ArrayMap<ViewGroup, ArrayList<Transition>>>>(); @@ -119,21 +122,6 @@ public class TransitionManager { } /** - * Sets a specific transition to occur when the given scene is exited. This - * has the lowest priority -- if a Scene-to-Scene transition or - * Scene enter transition can be applied, it will. - * - * @param scene The scene which, when exited, will cause the given - * transition to run. - * @param transition The transition that will play when the given scene is - * exited. A value of null will result in the default behavior of - * using the default transition instead. - */ - public void setExitTransition(Scene scene, Transition transition) { - mExitSceneTransitions.put(scene, transition); - } - - /** * Sets a specific transition to occur when the given pair of scenes is * exited/entered. * @@ -181,9 +169,6 @@ public class TransitionManager { } } transition = mSceneTransitions.get(scene); - if (transition == null && sceneRoot != null) { - transition = mExitSceneTransitions.get(Scene.getCurrentScene(sceneRoot)); - } return (transition != null) ? transition : sDefaultTransition; } @@ -239,31 +224,138 @@ public class TransitionManager { } /** - * Retrieve the transition to a target defined scene if one has been + * Retrieve the transition from a named scene to a target defined scene if one has been * associated with this TransitionManager. * + * <p>A named scene is an indirect link for a transition. Fundamentally a named + * scene represents a potentially arbitrary intersection point of two otherwise independent + * transitions. Activity A may define a transition from scene X to "com.example.scene.FOO" + * while activity B may define a transition from scene "com.example.scene.FOO" to scene Y. + * In this way applications may define an API for more sophisticated transitions between + * caller and called activities very similar to the way that <code>Intent</code> extras + * define APIs for arguments and data propagation between activities.</p> + * + * @param fromName Named scene that this transition corresponds to * @param toScene Target scene that this transition will move to - * @return Transition corresponding to the given toScene or null + * @return Transition corresponding to the given fromName and toScene or null * if no association exists in this TransitionManager * - * @see #setTransition(Scene, Transition) - * @hide + * @see #setTransition(String, Scene, Transition) */ - public Transition getEnterTransition(Scene toScene) { - return mSceneTransitions.get(toScene); + public Transition getNamedTransition(String fromName, Scene toScene) { + ArrayMap<Scene, Transition> m = mNameSceneTransitions.get(fromName); + if (m != null) { + return m.get(toScene); + } + return null; } /** * Retrieve the transition from a defined scene to a target named scene if one has been * associated with this TransitionManager. * + * <p>A named scene is an indirect link for a transition. Fundamentally a named + * scene represents a potentially arbitrary intersection point of two otherwise independent + * transitions. Activity A may define a transition from scene X to "com.example.scene.FOO" + * while activity B may define a transition from scene "com.example.scene.FOO" to scene Y. + * In this way applications may define an API for more sophisticated transitions between + * caller and called activities very similar to the way that <code>Intent</code> extras + * define APIs for arguments and data propagation between activities.</p> + * * @param fromScene Scene that this transition starts from - * @return Transition corresponding to the given fromScene or null + * @param toName Name of the target scene + * @return Transition corresponding to the given fromScene and toName or null * if no association exists in this TransitionManager - * @hide */ - public Transition getExitTransition(Scene fromScene) { - return mExitSceneTransitions.get(fromScene); + public Transition getNamedTransition(Scene fromScene, String toName) { + ArrayMap<String, Transition> m = mSceneNameTransitions.get(fromScene); + if (m != null) { + return m.get(toName); + } + return null; + } + + /** + * Retrieve the supported target named scenes when transitioning away from the given scene. + * + * <p>A named scene is an indirect link for a transition. Fundamentally a named + * scene represents a potentially arbitrary intersection point of two otherwise independent + * transitions. Activity A may define a transition from scene X to "com.example.scene.FOO" + * while activity B may define a transition from scene "com.example.scene.FOO" to scene Y. + * In this way applications may define an API for more sophisticated transitions between + * caller and called activities very similar to the way that <code>Intent</code> extras + * define APIs for arguments and data propagation between activities.</p> + * + * @param fromScene Scene to transition from + * @return An array of Strings naming each supported transition starting from + * <code>fromScene</code>. If no transitions to a named scene from the given + * scene are supported this function will return a String[] of length 0. + * + * @see #setTransition(Scene, String, Transition) + */ + public String[] getTargetSceneNames(Scene fromScene) { + final ArrayMap<String, Transition> m = mSceneNameTransitions.get(fromScene); + if (m == null) { + return EMPTY_STRINGS; + } + final int count = m.size(); + final String[] result = new String[count]; + for (int i = 0; i < count; i++) { + result[i] = m.keyAt(i); + } + return result; + } + + /** + * Set a transition from a specific scene to a named scene. + * + * <p>A named scene is an indirect link for a transition. Fundamentally a named + * scene represents a potentially arbitrary intersection point of two otherwise independent + * transitions. Activity A may define a transition from scene X to "com.example.scene.FOO" + * while activity B may define a transition from scene "com.example.scene.FOO" to scene Y. + * In this way applications may define an API for more sophisticated transitions between + * caller and called activities very similar to the way that <code>Intent</code> extras + * define APIs for arguments and data propagation between activities.</p> + * + * @param fromScene Scene to transition from + * @param toName Named scene to transition to + * @param transition Transition to use + * + * @see #getTargetSceneNames(Scene) + */ + public void setTransition(Scene fromScene, String toName, Transition transition) { + ArrayMap<String, Transition> m = mSceneNameTransitions.get(fromScene); + if (m == null) { + m = new ArrayMap<String, Transition>(); + mSceneNameTransitions.put(fromScene, m); + } + m.put(toName, transition); + } + + /** + * Set a transition from a named scene to a concrete scene. + * + * <p>A named scene is an indirect link for a transition. Fundamentally a named + * scene represents a potentially arbitrary intersection point of two otherwise independent + * transitions. Activity A may define a transition from scene X to "com.example.scene.FOO" + * while activity B may define a transition from scene "com.example.scene.FOO" to scene Y. + * In this way applications may define an API for more sophisticated transitions between + * caller and called activities very similar to the way that <code>Intent</code> extras + * define APIs for arguments and data propagation between activities.</p> + * + * @param fromName Named scene to transition from + * @param toScene Scene to transition to + * @param transition Transition to use + * + * @see #getNamedTransition(String, Scene) + */ + public void setTransition(String fromName, Scene toScene, Transition transition) { + ArrayMap<Scene, Transition> m = mNameSceneTransitions.get(fromName); + if (m == null) { + m = new ArrayMap<Scene, Transition>(); + mNameSceneTransitions.put(fromName, m); + } + m.put(toScene, transition); } /** diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 5a8d2c8..e693b9e 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -167,6 +167,13 @@ public class SurfaceControl { public static final int FX_SURFACE_DIM = 0x00020000; /** + * Surface creation flag: Creates a video plane Surface. + * This surface is backed by a hardware video plane. It is an error to lock + * a video plane surface, since it doesn't have a backing store. + */ + public static final int FX_SURFACE_VIDEO_PLANE = 0x00040000; + + /** * Mask used for FX values above. * */ diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 65d3f6d..9b23b35 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -421,7 +421,10 @@ public class SurfaceView extends View { mWindowType = type; } - private void updateWindow(boolean force, boolean redrawNeeded) { + /** + * @hide + */ + protected void updateWindow(boolean force, boolean redrawNeeded) { if (!mHaveFrame) { return; } diff --git a/core/java/android/view/VideoPlaneView.java b/core/java/android/view/VideoPlaneView.java new file mode 100644 index 0000000..81dcf9d --- /dev/null +++ b/core/java/android/view/VideoPlaneView.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view; + +import android.content.Context; +import android.util.AttributeSet; + +/** + * Provides a dedicated surface embedded inside of a view hierarchy much like a + * {@link SurfaceView}, but the surface is actually backed by a hardware video + * plane. + * + * TODO: Eventually this should be separate from SurfaceView. + * + * @hide + */ +public class VideoPlaneView extends SurfaceView { + public VideoPlaneView(Context context) { + super(context); + } + + public VideoPlaneView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public VideoPlaneView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public VideoPlaneView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + @Override + protected void updateWindow(boolean force, boolean redrawNeeded) { + mLayout.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_VIDEO_PLANE; + super.updateWindow(force, redrawNeeded); + } +} diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 99aee29..e9082c3 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -101,9 +101,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; -import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicInteger; @@ -18844,33 +18842,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } } - /** - * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions. - * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and - * a normal View or a ViewGroup with - * {@link android.view.ViewGroup#isTransitionGroup()} true. - * @hide - */ - public void captureTransitioningViews(List<View> transitioningViews) { - if (getVisibility() == View.VISIBLE) { - transitioningViews.add(this); - } - } - - /** - * Adds all Views that have {@link #getSharedElementName()} non-null to sharedElements. - * @param sharedElements Will contain all Views in the hierarchy having a shared element name. - * @hide - */ - public void findSharedElements(Map<String, View> sharedElements) { - if (getVisibility() == VISIBLE) { - String sharedElementName = getSharedElementName(); - if (sharedElementName != null) { - sharedElements.put(sharedElementName, this); - } - } - } - // // Properties // diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index cf5e8cf..9cd3c9d 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -31,7 +31,6 @@ import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Region; import android.os.Build; -import android.os.Bundle; import android.os.Parcelable; import android.os.SystemClock; import android.util.AttributeSet; @@ -51,8 +50,6 @@ import com.android.internal.util.Predicate; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; -import java.util.List; -import java.util.Map; import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; @@ -2303,13 +2300,14 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * individually during the transition. * @return True if the ViewGroup should be acted on together during an Activity transition. * The default value is false when the background is null and true when the background - * is not null or if {@link #getSharedElementName()} is not null. + * is not null. + * @see android.app.ActivityOptions#makeSceneTransitionAnimation(android.os.Bundle) */ public boolean isTransitionGroup() { if ((mGroupFlags & FLAG_IS_TRANSITION_GROUP_SET) != 0) { return ((mGroupFlags & FLAG_IS_TRANSITION_GROUP) != 0); } else { - return getBackground() != null || getSharedElementName() != null; + return getBackground() != null; } } @@ -2320,6 +2318,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * in Activity transitions. If false, the ViewGroup won't transition, * only its children. If true, the entire ViewGroup will transition * together. + * @see android.app.ActivityOptions#makeSceneTransitionAnimation(android.os.Bundle) */ public void setTransitionGroup(boolean isTransitionGroup) { mGroupFlags |= FLAG_IS_TRANSITION_GROUP_SET; @@ -5881,37 +5880,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager protected void onSetLayoutParams(View child, LayoutParams layoutParams) { } - /** @hide */ - @Override - public void captureTransitioningViews(List<View> transitioningViews) { - if (getVisibility() != View.VISIBLE) { - return; - } - if (isTransitionGroup()) { - transitioningViews.add(this); - } else { - int count = getChildCount(); - for (int i = 0; i < count; i++) { - View child = getChildAt(i); - child.captureTransitioningViews(transitioningViews); - } - } - } - - /** @hide */ - @Override - public void findSharedElements(Map<String, View> sharedElements) { - if (getVisibility() != VISIBLE) { - return; - } - super.findSharedElements(sharedElements); - int count = getChildCount(); - for (int i = 0; i < count; i++) { - View child = getChildAt(i); - child.findSharedElements(sharedElements); - } - } - /** * LayoutParams are used by views to tell their parents how they want to be * laid out. See diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index 4943a40..11740ab 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -29,12 +29,9 @@ import android.os.Bundle; import android.os.IBinder; import android.os.SystemProperties; import android.transition.Scene; -import android.transition.Transition; import android.transition.TransitionManager; import android.view.accessibility.AccessibilityEvent; -import java.util.Map; - /** * Abstract base class for a top-level window look and behavior policy. An * instance of this class should be used as the top-level view added to the @@ -1389,43 +1386,30 @@ public abstract class Window { * @hide */ public interface SceneTransitionListener { + void enterSharedElement(Bundle transitionArgs); void nullPendingTransition(); void convertFromTranslucent(); void convertToTranslucent(); - void sharedElementStart(Transition transition); - void sharedElementEnd(); } /** - * Controls when the Activity enter scene is triggered and the background is faded in. If - * triggerEarly is true, the enter scene will begin as soon as possible and the background - * will fade in when all shared elements are ready to begin transitioning. If triggerEarly is - * false, the Activity enter scene and background fade will be triggered when the calling - * Activity's exit transition completes. + * Controls how the background fade is triggered. If fadeEarly is true, the Window background + * will fade in as soon as the shared elements are ready to switch. If fadeEarly is false, + * the background will fade only after the calling Activity's exit transition completes. + * By default, the Window will fade in when the calling Activity's exit transition completes. * - * @param triggerEarly Set to true to have the Activity enter scene transition in as early as - * possible or set to false to wait for the calling Activity to exit first. + * @param fadeEarly Set to true to fade out the exiting Activity as soon as the shared elements + * are transferred. Set to false to fade out the exiting Activity as soon as + * the shared element is transferred. + * @hide */ - public void setTriggerEarlyEnterTransition(boolean triggerEarly) { + public void setEarlyBackgroundTransition(boolean fadeEarly) { } /** * Start the exit transition. * @hide */ - public Bundle startExitTransition(Map<String, View> sharedElements) { - return null; - } - - /** - * On entering Activity Scene transitions, shared element names may be mapped from a - * source Activity's specified name to a unique shared element name in the View hierarchy. - * Under most circumstances, mapping is not necessary - a single View will have the - * shared element name given by the calling Activity. However, if there are several similar - * Views (e.g. in a ListView), the correct shared element must be mapped. - * @param sharedElementNames A mapping from the calling Activity's assigned shared element - * name to a unique shared element name in the View hierarchy. - */ - public void mapTransitionTargets(Map<String, String> sharedElementNames) { + public void startExitTransition(ActivityOptions activityOptions) { } } diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 53a4c0d0..55956bf 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -98,7 +98,7 @@ public interface WindowManager extends ViewManager { * the given view hierarchy's {@link View#onDetachedFromWindow() * View.onDetachedFromWindow()} methods before returning. This is not * for normal applications; using it correctly requires great care. - * + * * @param view The view to be removed. */ public void removeViewImmediate(View view); @@ -112,7 +112,7 @@ public interface WindowManager extends ViewManager { */ @ViewDebug.ExportedProperty public int x; - + /** * Y position for this window. With the default gravity it is ignored. * When using {@link Gravity#TOP} or {@link Gravity#BOTTOM} it provides @@ -161,7 +161,7 @@ public interface WindowManager extends ViewManager { * be used by applications, and a special permission is required * to use them. * </ul> - * + * * @see #TYPE_BASE_APPLICATION * @see #TYPE_APPLICATION * @see #TYPE_APPLICATION_STARTING @@ -223,12 +223,12 @@ public interface WindowManager extends ViewManager { @ViewDebug.IntToString(from = TYPE_PRIVATE_PRESENTATION, to = "TYPE_PRIVATE_PRESENTATION") }) public int type; - + /** * Start of window types that represent normal application windows. */ public static final int FIRST_APPLICATION_WINDOW = 1; - + /** * Window type: an application window that serves as the "base" window * of the overall application; all other application windows will @@ -236,14 +236,14 @@ public interface WindowManager extends ViewManager { * In multiuser systems shows only on the owning user's window. */ public static final int TYPE_BASE_APPLICATION = 1; - + /** * Window type: a normal application window. The {@link #token} must be * an Activity token identifying who the window belongs to. * In multiuser systems shows only on the owning user's window. */ public static final int TYPE_APPLICATION = 2; - + /** * Window type: special application window that is displayed while the * application is starting. Not for use by applications themselves; @@ -252,12 +252,12 @@ public interface WindowManager extends ViewManager { * In multiuser systems shows on all users' windows. */ public static final int TYPE_APPLICATION_STARTING = 3; - + /** * End of types of application windows. */ public static final int LAST_APPLICATION_WINDOW = 99; - + /** * Start of types of sub-windows. The {@link #token} of these windows * must be set to the window they are attached to. These types of @@ -265,19 +265,19 @@ public interface WindowManager extends ViewManager { * coordinate space is relative to their attached window. */ public static final int FIRST_SUB_WINDOW = 1000; - + /** * Window type: a panel on top of an application window. These windows * appear on top of their attached window. */ public static final int TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW; - + /** * Window type: window for showing media (such as video). These windows * are displayed behind their attached window. */ public static final int TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW+1; - + /** * Window type: a sub-panel on top of an application window. These * windows are displayed on top their attached window and any @@ -290,7 +290,7 @@ public interface WindowManager extends ViewManager { * as a child of its container. */ public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3; - + /** * Window type: window for showing overlays on top of media windows. * These windows are displayed between TYPE_APPLICATION_MEDIA and the @@ -299,18 +299,18 @@ public interface WindowManager extends ViewManager { * @hide */ public static final int TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW+4; - + /** * End of types of sub-windows. */ public static final int LAST_SUB_WINDOW = 1999; - + /** * Start of system-specific window types. These are not normally * created by applications. */ public static final int FIRST_SYSTEM_WINDOW = 2000; - + /** * Window type: the status bar. There can be only one status bar * window; it is placed at the top of the screen, and all other @@ -318,14 +318,14 @@ public interface WindowManager extends ViewManager { * In multiuser systems shows on all users' windows. */ public static final int TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW; - + /** * Window type: the search bar. There can be only one search bar * window; it is placed at the top of the screen. * In multiuser systems shows on all users' windows. */ public static final int TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1; - + /** * Window type: phone. These are non-application windows providing * user interaction with the phone (in particular incoming calls). @@ -334,26 +334,26 @@ public interface WindowManager extends ViewManager { * In multiuser systems shows on all users' windows. */ public static final int TYPE_PHONE = FIRST_SYSTEM_WINDOW+2; - + /** * Window type: system window, such as low power alert. These windows * are always on top of application windows. * In multiuser systems shows only on the owning user's window. */ public static final int TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3; - + /** * Window type: keyguard window. * In multiuser systems shows on all users' windows. */ public static final int TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4; - + /** * Window type: transient notifications. * In multiuser systems shows only on the owning user's window. */ public static final int TYPE_TOAST = FIRST_SYSTEM_WINDOW+5; - + /** * Window type: system overlay windows, which need to be displayed * on top of everything else. These windows must not take input @@ -361,7 +361,7 @@ public interface WindowManager extends ViewManager { * In multiuser systems shows only on the owning user's window. */ public static final int TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6; - + /** * Window type: priority phone UI, which needs to be displayed even if * the keyguard is active. These windows must not take input @@ -369,26 +369,26 @@ public interface WindowManager extends ViewManager { * In multiuser systems shows on all users' windows. */ public static final int TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7; - + /** * Window type: panel that slides out from the status bar * In multiuser systems shows on all users' windows. */ public static final int TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW+8; - + /** * Window type: dialogs that the keyguard shows * In multiuser systems shows on all users' windows. */ public static final int TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW+9; - + /** * Window type: internal system error windows, appear on top of * everything they can. * In multiuser systems shows only on the owning user's window. */ public static final int TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10; - + /** * Window type: internal input methods windows, which appear above * the normal UI. Application windows may be resized or panned to keep @@ -559,16 +559,16 @@ public interface WindowManager extends ViewManager { /** @deprecated this is ignored, this value is set automatically when needed. */ @Deprecated public static final int MEMORY_TYPE_PUSH_BUFFERS = 3; - + /** * @deprecated this is ignored */ @Deprecated public int memoryType; - + /** Window flag: as long as this window is visible to the user, allow - * the lock screen to activate while the screen is on. - * This can be used independently, or in combination with + * the lock screen to activate while the screen is on. + * This can be used independently, or in combination with * {@link #FLAG_KEEP_SCREEN_ON} and/or {@link #FLAG_SHOW_WHEN_LOCKED} */ public static final int FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001; @@ -586,47 +586,47 @@ public interface WindowManager extends ViewManager { * instead go to whatever focusable window is behind it. This flag * will also enable {@link #FLAG_NOT_TOUCH_MODAL} whether or not that * is explicitly set. - * + * * <p>Setting this flag also implies that the window will not need to * interact with - * a soft input method, so it will be Z-ordered and positioned + * a soft input method, so it will be Z-ordered and positioned * independently of any active input method (typically this means it * gets Z-ordered on top of the input method, so it can use the full * screen for its content and cover the input method if needed. You * can use {@link #FLAG_ALT_FOCUSABLE_IM} to modify this behavior. */ public static final int FLAG_NOT_FOCUSABLE = 0x00000008; - + /** Window flag: this window can never receive touch events. */ public static final int FLAG_NOT_TOUCHABLE = 0x00000010; - + /** Window flag: even when this window is focusable (its * {@link #FLAG_NOT_FOCUSABLE} is not set), allow any pointer events * outside of the window to be sent to the windows behind it. Otherwise * it will consume all pointer events itself, regardless of whether they * are inside of the window. */ public static final int FLAG_NOT_TOUCH_MODAL = 0x00000020; - + /** Window flag: when set, if the device is asleep when the touch * screen is pressed, you will receive this first touch event. Usually * the first touch event is consumed by the system since the user can * not see what they are pressing on. */ public static final int FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040; - + /** Window flag: as long as this window is visible to the user, keep * the device's screen turned on and bright. */ public static final int FLAG_KEEP_SCREEN_ON = 0x00000080; - + /** Window flag: place the window within the entire screen, ignoring * decorations around the border (such as the status bar). The * window must correctly position its contents to take the screen * decoration into account. This flag is normally set for you * by Window as described in {@link Window#setFlags}. */ public static final int FLAG_LAYOUT_IN_SCREEN = 0x00000100; - + /** Window flag: allow window to extend outside of the screen. */ public static final int FLAG_LAYOUT_NO_LIMITS = 0x00000200; - + /** * Window flag: hide all screen decorations (such as the status bar) while * this window is displayed. This allows the window to use the entire @@ -648,17 +648,17 @@ public interface WindowManager extends ViewManager { * {@link android.R.style#Theme_DeviceDefault_Light_NoActionBar_Fullscreen}.</p> */ public static final int FLAG_FULLSCREEN = 0x00000400; - + /** Window flag: override {@link #FLAG_FULLSCREEN} and force the * screen decorations (such as the status bar) to be shown. */ public static final int FLAG_FORCE_NOT_FULLSCREEN = 0x00000800; - + /** Window flag: turn on dithering when compositing this window to * the screen. * @deprecated This flag is no longer used. */ @Deprecated public static final int FLAG_DITHER = 0x00001000; - + /** Window flag: treat the content of the window as secure, preventing * it from appearing in screenshots or from being viewed on non-secure * displays. @@ -667,21 +667,21 @@ public interface WindowManager extends ViewManager { * secure surfaces and secure displays. */ public static final int FLAG_SECURE = 0x00002000; - + /** Window flag: a special mode where the layout parameters are used * to perform scaling of the surface when it is composited to the * screen. */ public static final int FLAG_SCALED = 0x00004000; - + /** Window flag: intended for windows that will often be used when the user is * holding the screen against their face, it will aggressively filter the event * stream to prevent unintended presses in this situation that may not be - * desired for a particular window, when such an event stream is detected, the + * desired for a particular window, when such an event stream is detected, the * application will receive a CANCEL motion event to indicate this so applications - * can handle this accordingly by taking no action on the event + * can handle this accordingly by taking no action on the event * until the finger is released. */ public static final int FLAG_IGNORE_CHEEK_PRESSES = 0x00008000; - + /** Window flag: a special option only for use in combination with * {@link #FLAG_LAYOUT_IN_SCREEN}. When requesting layout in the * screen your window may appear on top of or behind screen decorations @@ -690,7 +690,7 @@ public interface WindowManager extends ViewManager { * content is not covered by screen decorations. This flag is normally * set for you by Window as described in {@link Window#setFlags}.*/ public static final int FLAG_LAYOUT_INSET_DECOR = 0x00010000; - + /** Window flag: invert the state of {@link #FLAG_NOT_FOCUSABLE} with * respect to how this window interacts with the current method. That * is, if FLAG_NOT_FOCUSABLE is set and this flag is set, then the @@ -701,7 +701,7 @@ public interface WindowManager extends ViewManager { * to use more space and cover the input method. */ public static final int FLAG_ALT_FOCUSABLE_IM = 0x00020000; - + /** Window flag: if you have set {@link #FLAG_NOT_TOUCH_MODAL}, you * can set this flag to receive a single special MotionEvent with * the action @@ -711,7 +711,7 @@ public interface WindowManager extends ViewManager { * first down as an ACTION_OUTSIDE. */ public static final int FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000; - + /** Window flag: special flag to let windows be shown when the screen * is locked. This will let application windows take precedence over * key guard or any other lock screens. Can be used with @@ -741,13 +741,13 @@ public interface WindowManager extends ViewManager { * {@link android.R.style#Theme_DeviceDefault_Wallpaper_NoTitleBar}.</p> */ public static final int FLAG_SHOW_WALLPAPER = 0x00100000; - + /** Window flag: when set as a window is being added or made * visible, once the window has been shown then the system will * poke the power manager's user activity (as if the user had woken * up the device) to turn the screen on. */ public static final int FLAG_TURN_SCREEN_ON = 0x00200000; - + /** Window flag: when set the window will cause the keyguard to * be dismissed, only if it is not a secure lock keyguard. Because such * a keyguard is not needed for security, it will never re-appear if @@ -761,7 +761,7 @@ public interface WindowManager extends ViewManager { * also been set. */ public static final int FLAG_DISMISS_KEYGUARD = 0x00400000; - + /** Window flag: when set the window will accept for touch events * outside of its bounds to be sent to other windows that also * support split touch. When this flag is not set, the first pointer @@ -773,7 +773,7 @@ public interface WindowManager extends ViewManager { * to be split across multiple windows. */ public static final int FLAG_SPLIT_TOUCH = 0x00800000; - + /** * <p>Indicates whether this window should be hardware accelerated. * Requesting hardware acceleration does not guarantee it will happen.</p> @@ -916,7 +916,7 @@ public interface WindowManager extends ViewManager { /** * Various behavioral options/flags. Default is none. - * + * * @see #FLAG_ALLOW_LOCK_WHILE_SCREEN_ON * @see #FLAG_DIM_BEHIND * @see #FLAG_NOT_FOCUSABLE @@ -1014,10 +1014,10 @@ public interface WindowManager extends ViewManager { * 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 + * 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; @@ -1028,7 +1028,7 @@ public interface WindowManager extends ViewManager { * If certain parts of the UI that really do want to use hardware * acceleration, this flag can be set to force it. This is basically * for the lock screen. Anyone else using it, you are probably wrong. - * + * * @hide */ public static final int PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED = 0x00000002; @@ -1086,6 +1086,11 @@ public interface WindowManager extends ViewManager { * {@hide} */ public static final int PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR = 0x00000200; + /** Window flag: the window is backed by a video plane, instead of a + * regular surface. + * {@hide} */ + public static final int PRIVATE_FLAG_VIDEO_PLANE = 0x00000400; + /** * Control flags that are private to the platform. * @hide @@ -1100,9 +1105,9 @@ public interface WindowManager extends ViewManager { * flags and returns true if the combination of the two corresponds * to a window that needs to be behind the input method so that the * user can type into it. - * + * * @param flags The current window manager flags. - * + * * @return Returns true if such a window should be behind/interact * with an input method, false if not. */ @@ -1114,63 +1119,63 @@ public interface WindowManager extends ViewManager { } return false; } - + /** * Mask for {@link #softInputMode} of the bits that determine the * desired visibility state of the soft input area for this window. */ public static final int SOFT_INPUT_MASK_STATE = 0x0f; - + /** * Visibility state for {@link #softInputMode}: no state has been specified. */ public static final int SOFT_INPUT_STATE_UNSPECIFIED = 0; - + /** * Visibility state for {@link #softInputMode}: please don't change the state of * the soft input area. */ public static final int SOFT_INPUT_STATE_UNCHANGED = 1; - + /** * Visibility state for {@link #softInputMode}: please hide any soft input * area when normally appropriate (when the user is navigating * forward to your window). */ public static final int SOFT_INPUT_STATE_HIDDEN = 2; - + /** * Visibility state for {@link #softInputMode}: please always hide any * soft input area when this window receives focus. */ public static final int SOFT_INPUT_STATE_ALWAYS_HIDDEN = 3; - + /** * Visibility state for {@link #softInputMode}: please show the soft * input area when normally appropriate (when the user is navigating * forward to your window). */ public static final int SOFT_INPUT_STATE_VISIBLE = 4; - + /** * Visibility state for {@link #softInputMode}: please always make the * soft input area visible when this window receives input focus. */ public static final int SOFT_INPUT_STATE_ALWAYS_VISIBLE = 5; - + /** * Mask for {@link #softInputMode} of the bits that determine the * way that the window should be adjusted to accommodate the soft * input window. */ public static final int SOFT_INPUT_MASK_ADJUST = 0xf0; - + /** Adjustment option for {@link #softInputMode}: nothing specified. * The system will try to pick one or * the other depending on the contents of the window. */ public static final int SOFT_INPUT_ADJUST_UNSPECIFIED = 0x00; - + /** Adjustment option for {@link #softInputMode}: set to allow the * window to be resized when an input * method is shown, so that its contents are not covered by the input @@ -1183,7 +1188,7 @@ public interface WindowManager extends ViewManager { * not resize, but will stay fullscreen. */ public static final int SOFT_INPUT_ADJUST_RESIZE = 0x10; - + /** Adjustment option for {@link #softInputMode}: set to have a window * pan when an input method is * shown, so it doesn't need to deal with resizing but just panned @@ -1193,7 +1198,7 @@ public interface WindowManager extends ViewManager { * the other depending on the contents of the window. */ public static final int SOFT_INPUT_ADJUST_PAN = 0x20; - + /** Adjustment option for {@link #softInputMode}: set to have a window * not adjust for a shown input method. The window will not be resized, * and it will not be panned to make its focus visible. @@ -1212,7 +1217,7 @@ public interface WindowManager extends ViewManager { /** * Desired operating mode for any soft input area. May be any combination * of: - * + * * <ul> * <li> One of the visibility states * {@link #SOFT_INPUT_STATE_UNSPECIFIED}, {@link #SOFT_INPUT_STATE_UNCHANGED}, @@ -1229,7 +1234,7 @@ public interface WindowManager extends ViewManager { * {@link android.R.attr#windowSoftInputMode} attribute.</p> */ public int softInputMode; - + /** * Placement of window within the screen as per {@link Gravity}. Both * {@link Gravity#apply(int, int, int, android.graphics.Rect, int, int, @@ -1246,7 +1251,7 @@ public interface WindowManager extends ViewManager { * @see Gravity */ public int gravity; - + /** * The horizontal margin, as a percentage of the container's width, * between the container and the widget. See @@ -1255,7 +1260,7 @@ public interface WindowManager extends ViewManager { * field is added with {@link #x} to supply the <var>xAdj</var> parameter. */ public float horizontalMargin; - + /** * The vertical margin, as a percentage of the container's height, * between the container and the widget. See @@ -1264,26 +1269,26 @@ public interface WindowManager extends ViewManager { * field is added with {@link #y} to supply the <var>yAdj</var> parameter. */ public float verticalMargin; - + /** * The desired bitmap format. May be one of the constants in * {@link android.graphics.PixelFormat}. Default is OPAQUE. */ public int format; - + /** * A style resource defining the animations to use for this window. * This must be a system resource; it can not be an application resource * because the window manager does not have access to applications. */ public int windowAnimations; - + /** * An alpha value to apply to this entire window. * An alpha of 1.0 means fully opaque and 0.0 means fully transparent */ public float alpha = 1.0f; - + /** * When {@link #FLAG_DIM_BEHIND} is set, this is the amount of dimming * to apply. Range is from 1.0 for completely opaque to 0.0 for no @@ -1311,7 +1316,7 @@ public interface WindowManager extends ViewManager { * to the hightest value when this window is in front. */ public static final float BRIGHTNESS_OVERRIDE_FULL = 1.0f; - + /** * This can be used to override the user's preferred brightness of * the screen. A value of less than 0, the default, means to use the @@ -1319,7 +1324,7 @@ public interface WindowManager extends ViewManager { * dark to full bright. */ public float screenBrightness = BRIGHTNESS_OVERRIDE_NONE; - + /** * This can be used to override the standard behavior of the button and * keyboard backlights. A value of less than 0, the default, means to @@ -1353,7 +1358,7 @@ public interface WindowManager extends ViewManager { * opaque windows have the #FLAG_FULLSCREEN bit set and are not covered * by other windows. All other situations default to the * {@link #ROTATION_ANIMATION_ROTATE} behavior. - * + * * @see #ROTATION_ANIMATION_ROTATE * @see #ROTATION_ANIMATION_CROSSFADE * @see #ROTATION_ANIMATION_JUMPCUT @@ -1365,18 +1370,18 @@ public interface WindowManager extends ViewManager { * you. */ public IBinder token = null; - + /** * Name of the package owning this window. */ public String packageName = null; - + /** * Specific orientation value for a window. * May be any of the same values allowed - * for {@link android.content.pm.ActivityInfo#screenOrientation}. - * If not set, a default value of - * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} + * for {@link android.content.pm.ActivityInfo#screenOrientation}. + * If not set, a default value of + * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} * will be used. */ public int screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; @@ -1398,7 +1403,7 @@ public interface WindowManager extends ViewManager { /** * Get callbacks about the system ui visibility changing. - * + * * TODO: Maybe there should be a bitfield of optional callbacks that we need. * * @hide @@ -1464,34 +1469,34 @@ public interface WindowManager extends ViewManager { type = TYPE_APPLICATION; format = PixelFormat.OPAQUE; } - + public LayoutParams(int _type) { super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); type = _type; format = PixelFormat.OPAQUE; } - + public LayoutParams(int _type, int _flags) { super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); type = _type; flags = _flags; format = PixelFormat.OPAQUE; } - + public LayoutParams(int _type, int _flags, int _format) { super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); type = _type; flags = _flags; format = _format; } - + public LayoutParams(int w, int h, int _type, int _flags, int _format) { super(w, h); type = _type; flags = _flags; format = _format; } - + public LayoutParams(int w, int h, int xpos, int ypos, int _type, int _flags, int _format) { super(w, h); @@ -1501,18 +1506,18 @@ public interface WindowManager extends ViewManager { flags = _flags; format = _format; } - + public final void setTitle(CharSequence title) { if (null == title) title = ""; - + mTitle = TextUtils.stringOrSpannedString(title); } - + public final CharSequence getTitle() { return mTitle; } - + public int describeContents() { return 0; } @@ -1546,19 +1551,19 @@ public interface WindowManager extends ViewManager { out.writeInt(inputFeatures); out.writeLong(userActivityTimeout); } - + public static final Parcelable.Creator<LayoutParams> CREATOR = new Parcelable.Creator<LayoutParams>() { public LayoutParams createFromParcel(Parcel in) { return new LayoutParams(in); } - + public LayoutParams[] newArray(int size) { return new LayoutParams[size]; } }; - - + + public LayoutParams(Parcel in) { width = in.readInt(); height = in.readInt(); @@ -1588,7 +1593,7 @@ public interface WindowManager extends ViewManager { inputFeatures = in.readInt(); userActivityTimeout = in.readLong(); } - + @SuppressWarnings({"PointlessBitwiseExpression"}) public static final int LAYOUT_CHANGED = 1<<0; public static final int TYPE_CHANGED = 1<<1; @@ -1622,10 +1627,10 @@ public interface WindowManager extends ViewManager { // internal buffer to backup/restore parameters under compatibility mode. private int[] mCompatibilityParamsBackup = null; - + public final int copyFrom(LayoutParams o) { int changes = 0; - + if (width != o.width) { width = o.width; changes |= LAYOUT_CHANGED; @@ -1724,7 +1729,7 @@ public interface WindowManager extends ViewManager { rotationAnimation = o.rotationAnimation; changes |= ROTATION_ANIMATION_CHANGED; } - + if (screenOrientation != o.screenOrientation) { screenOrientation = o.screenOrientation; changes |= SCREEN_ORIENTATION_CHANGED; @@ -1754,7 +1759,7 @@ public interface WindowManager extends ViewManager { return changes; } - + @Override public String debug(String output) { output += "Contents of " + this + ":"; @@ -1765,7 +1770,7 @@ public interface WindowManager extends ViewManager { Log.d("Debug", "WindowManager.LayoutParams={title=" + mTitle + "}"); return ""; } - + @Override public String toString() { StringBuilder sb = new StringBuilder(256); diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 0b78e0a..66580f8 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -2313,6 +2313,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te // If we failed to re-bind the data, scrap the obtained view. if (updatedView != transientView) { + setItemViewLayoutParams(updatedView, position); mRecycler.addScrapView(updatedView, position); } } @@ -2343,19 +2344,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te child.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); } - if (mAdapterHasStableIds) { - final ViewGroup.LayoutParams vlp = child.getLayoutParams(); - LayoutParams lp; - if (vlp == null) { - lp = (LayoutParams) generateDefaultLayoutParams(); - } else if (!checkLayoutParams(vlp)) { - lp = (LayoutParams) generateLayoutParams(vlp); - } else { - lp = (LayoutParams) vlp; - } - lp.itemId = mAdapter.getItemId(position); - child.setLayoutParams(lp); - } + setItemViewLayoutParams(child, position); if (AccessibilityManager.getInstance(mContext).isEnabled()) { if (mAccessibilityDelegate == null) { @@ -2371,6 +2360,24 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te return child; } + private void setItemViewLayoutParams(View child, int position) { + final ViewGroup.LayoutParams vlp = child.getLayoutParams(); + LayoutParams lp; + if (vlp == null) { + lp = (LayoutParams) generateDefaultLayoutParams(); + } else if (!checkLayoutParams(vlp)) { + lp = (LayoutParams) generateLayoutParams(vlp); + } else { + lp = (LayoutParams) vlp; + } + + if (mAdapterHasStableIds) { + lp.itemId = mAdapter.getItemId(position); + } + lp.viewType = mAdapter.getItemViewType(position); + child.setLayoutParams(lp); + } + class ListItemAccessibilityDelegate extends AccessibilityDelegate { @Override public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) { diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java index af9e2f0..f7e81b8 100644 --- a/core/java/android/widget/ProgressBar.java +++ b/core/java/android/widget/ProgressBar.java @@ -346,19 +346,24 @@ public class ProgressBar extends View { return out; } else if (drawable instanceof BitmapDrawable) { - final Bitmap tileBitmap = ((BitmapDrawable) drawable).getBitmap(); + final BitmapDrawable bitmap = (BitmapDrawable) drawable; + final Bitmap tileBitmap = bitmap.getBitmap(); if (mSampleTile == null) { mSampleTile = tileBitmap; } - - final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape()); + final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape()); final BitmapShader bitmapShader = new BitmapShader(tileBitmap, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP); shapeDrawable.getPaint().setShader(bitmapShader); - return (clip) ? new ClipDrawable(shapeDrawable, Gravity.LEFT, - ClipDrawable.HORIZONTAL) : shapeDrawable; + // Ensure the color filter and tint are propagated. + shapeDrawable.setTint(bitmap.getTint()); + shapeDrawable.setTintMode(bitmap.getTintMode()); + shapeDrawable.setColorFilter(bitmap.getColorFilter()); + + return clip ? new ClipDrawable( + shapeDrawable, Gravity.LEFT, ClipDrawable.HORIZONTAL) : shapeDrawable; } return drawable; diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java index cc51a8b..0a80495 100644 --- a/core/java/com/android/internal/app/ActionBarImpl.java +++ b/core/java/com/android/internal/app/ActionBarImpl.java @@ -57,7 +57,6 @@ import android.widget.SpinnerAdapter; import java.lang.ref.WeakReference; import java.util.ArrayList; -import java.util.Map; /** * ActionBarImpl is the ActionBar implementation used @@ -356,10 +355,6 @@ public class ActionBarImpl extends ActionBar { setSubtitle(mContext.getString(resId)); } - public void captureSharedElements(Map<String, View> sharedElements) { - mContainerView.findSharedElements(sharedElements); - } - public void setSelectedNavigationItem(int position) { switch (mActionView.getNavigationMode()) { case NAVIGATION_MODE_TABS: diff --git a/core/java/com/android/internal/os/BatterySipper.java b/core/java/com/android/internal/os/BatterySipper.java index 4eff5ac..565cee4 100644 --- a/core/java/com/android/internal/os/BatterySipper.java +++ b/core/java/com/android/internal/os/BatterySipper.java @@ -34,6 +34,8 @@ public class BatterySipper implements Comparable<BatterySipper> { public long wakeLockTime; public long mobileRxPackets; public long mobileTxPackets; + public long mobileActive; + public double mobilemspp; // milliseconds per packet public long wifiRxPackets; public long wifiTxPackets; public long mobileRxBytes; @@ -69,6 +71,11 @@ public class BatterySipper implements Comparable<BatterySipper> { return values; } + public void computeMobilemspp() { + long packets = mobileRxPackets+mobileTxPackets; + mobilemspp = packets > 0 ? (mobileActive / (double)packets) : 0; + } + @Override public int compareTo(BatterySipper other) { // Return the flipped value because we want the items in descending order diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java index e0cf435..755530c 100644 --- a/core/java/com/android/internal/os/BatteryStatsHelper.java +++ b/core/java/com/android/internal/os/BatteryStatsHelper.java @@ -43,6 +43,7 @@ import com.android.internal.os.BatterySipper.DrainType; import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; import java.util.List; import java.util.Map; @@ -73,6 +74,8 @@ public class BatteryStatsHelper { = new SparseArray<List<BatterySipper>>(); private final SparseArray<Double> mUserPower = new SparseArray<Double>(); + private final List<BatterySipper> mMobilemsppList = new ArrayList<BatterySipper>(); + private int mStatsType = BatteryStats.STATS_SINCE_CHARGED; private int mAsUser = 0; @@ -90,6 +93,9 @@ public class BatteryStatsHelper { private double mMinDrainedPower; private double mMaxDrainedPower; + // How much the apps together have kept the mobile radio active. + private long mAppMobileActive; + // How much the apps together have left WIFI running. private long mAppWifiRunning; @@ -132,7 +138,7 @@ public class BatteryStatsHelper { } public static String makemAh(double power) { - if (power < .0001) return String.format("%.8f", power); + if (power < .00001) return String.format("%.8f", power); else if (power < .0001) return String.format("%.7f", power); else if (power < .001) return String.format("%.6f", power); else if (power < .01) return String.format("%.5f", power); @@ -160,6 +166,7 @@ public class BatteryStatsHelper { mTotalPower = 0; mWifiPower = 0; mBluetoothPower = 0; + mAppMobileActive = 0; mAppWifiRunning = 0; mUsageList.clear(); @@ -167,6 +174,7 @@ public class BatteryStatsHelper { mBluetoothSippers.clear(); mUserSippers.clear(); mUserPower.clear(); + mMobilemsppList.clear(); if (mStats == null) { return; @@ -193,6 +201,37 @@ public class BatteryStatsHelper { * mPowerProfile.getBatteryCapacity()) / 100; processAppUsage(); + + // Before aggregating apps in to users, collect all apps to sort by their ms per packet. + for (int i=0; i<mUsageList.size(); i++) { + BatterySipper bs = mUsageList.get(i); + bs.computeMobilemspp(); + if (bs.mobilemspp != 0) { + mMobilemsppList.add(bs); + } + } + for (int i=0; i<mUserSippers.size(); i++) { + List<BatterySipper> user = mUserSippers.valueAt(i); + for (int j=0; j<user.size(); j++) { + BatterySipper bs = user.get(j); + bs.computeMobilemspp(); + if (bs.mobilemspp != 0) { + mMobilemsppList.add(bs); + } + } + } + Collections.sort(mMobilemsppList, new Comparator<BatterySipper>() { + @Override + public int compare(BatterySipper lhs, BatterySipper rhs) { + if (lhs.mobilemspp < rhs.mobilemspp) { + return 1; + } else if (lhs.mobilemspp > rhs.mobilemspp) { + return -1; + } + return 0; + } + }); + processMiscUsage(); if (DEBUG) { @@ -225,6 +264,7 @@ public class BatteryStatsHelper { powerCpuNormal[p] = mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_ACTIVE, p); } final double mobilePowerPerPacket = getMobilePowerPerPacket(); + final double mobilePowerPerMs = getMobilePowerPerMs(); final double wifiPowerPerPacket = getWifiPowerPerPacket(); long appWakelockTime = 0; BatterySipper osApp = null; @@ -320,9 +360,20 @@ public class BatteryStatsHelper { final long mobileTx = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, mStatsType); final long mobileRxB = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, mStatsType); final long mobileTxB = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, mStatsType); - p = (mobileRx + mobileTx) * mobilePowerPerPacket; + final long mobileActive = u.getMobileRadioActiveTime(mStatsType); + if (mobileActive > 0) { + // We are tracking when the radio is up, so can use the active time to + // determine power use. + mAppMobileActive += mobileActive; + p = (mobilePowerPerMs * mobileActive) / 1000; + } else { + // We are not tracking when the radio is up, so must approximate power use + // based on the number of packets. + p = (mobileRx + mobileTx) * mobilePowerPerPacket; + } if (DEBUG && p != 0) Log.d(TAG, "UID " + u.getUid() + ": mobile packets " - + (mobileRx+mobileTx) + " power=" + makemAh(p)); + + (mobileRx+mobileTx) + " active time " + mobileActive + + " power=" + makemAh(p)); power += p; // Add cost of wifi traffic @@ -406,6 +457,7 @@ public class BatteryStatsHelper { app.wakeLockTime = wakelockTime; app.mobileRxPackets = mobileRx; app.mobileTxPackets = mobileTx; + app.mobileActive = mobileActive / 1000; app.wifiRxPackets = wifiRx; app.wifiTxPackets = wifiTx; app.mobileRxBytes = mobileRxB; @@ -474,7 +526,7 @@ public class BatteryStatsHelper { double phoneOnPower = mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE) * phoneOnTimeMs / (60*60*1000); if (phoneOnPower != 0) { - addEntry(BatterySipper.DrainType.PHONE, phoneOnTimeMs, phoneOnPower); + BatterySipper bs = addEntry(BatterySipper.DrainType.PHONE, phoneOnTimeMs, phoneOnPower); } } @@ -531,12 +583,18 @@ public class BatteryStatsHelper { Log.d(TAG, "Cell radio scanning: time=" + scanningTimeMs + " power=" + makemAh(p)); } power += p; + long radioActiveTimeUs = mStats.getMobileRadioActiveTime(mBatteryRealtime, mStatsType); + long remainingActiveTime = (radioActiveTimeUs - mAppMobileActive) / 1000; + if (remainingActiveTime > 0) { + power += getMobilePowerPerMs() * remainingActiveTime; + } if (power != 0) { BatterySipper bs = addEntry(BatterySipper.DrainType.CELL, signalTimeMs, power); if (signalTimeMs != 0) { bs.noCoveragePercent = noCoverageTimeMs * 100.0 / signalTimeMs; } + bs.mobileActive = remainingActiveTime; } } @@ -551,6 +609,7 @@ public class BatteryStatsHelper { bs.wakeLockTime += wbs.wakeLockTime; bs.mobileRxPackets += wbs.mobileRxPackets; bs.mobileTxPackets += wbs.mobileTxPackets; + bs.mobileActive += wbs.mobileActive; bs.wifiRxPackets += wbs.wifiRxPackets; bs.wifiTxPackets += wbs.wifiTxPackets; bs.mobileRxBytes += wbs.mobileRxBytes; @@ -558,6 +617,7 @@ public class BatteryStatsHelper { bs.wifiRxBytes += wbs.wifiRxBytes; bs.wifiTxBytes += wbs.wifiTxBytes; } + bs.computeMobilemspp(); } private void addWiFiUsage() { @@ -650,6 +710,13 @@ public class BatteryStatsHelper { } /** + * Return estimated power (in mAs) of keeping the radio up + */ + private double getMobilePowerPerMs() { + return mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE) / (60*60*1000); + } + + /** * Return estimated power (in mAs) of sending a byte with the Wi-Fi radio. */ private double getWifiPowerPerPacket() { @@ -691,6 +758,10 @@ public class BatteryStatsHelper { return mUsageList; } + public List<BatterySipper> getMobilemsppList() { + return mMobilemsppList; + } + public long getStatsPeriod() { return mStatsPeriod; } public int getStatsType() { return mStatsType; }; diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 8843500..46983ab 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -87,7 +87,7 @@ public final class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - private static final int VERSION = 85 + (USE_OLD_HISTORY ? 1000 : 0); + private static final int VERSION = 90 + (USE_OLD_HISTORY ? 1000 : 0); // Maximum number of items we will record in the history. private static final int MAX_HISTORY_ITEMS = 2000; @@ -283,6 +283,8 @@ public final class BatteryStatsImpl extends BatteryStats { boolean mMobileRadioActive; StopwatchTimer mMobileRadioActiveTimer; + LongSamplingCounter mMobileRadioActiveUnknownTime; + LongSamplingCounter mMobileRadioActiveUnknownCount; /** Bluetooth headset object */ BluetoothHeadset mBtHeadset; @@ -1176,11 +1178,12 @@ public final class BatteryStatsImpl extends BatteryStats { void startRunningLocked(BatteryStatsImpl stats, long elapsedRealtime) { if (mNesting++ == 0) { - mUpdateTime = stats.getBatteryRealtimeLocked(elapsedRealtime * 1000); + final long batteryRealtime = stats.getBatteryRealtimeLocked(elapsedRealtime * 1000); + mUpdateTime = batteryRealtime; if (mTimerPool != null) { // Accumulate time to all currently active timers before adding // this new one to the pool. - refreshTimersLocked(stats, mTimerPool); + refreshTimersLocked(stats, batteryRealtime, mTimerPool, null); // Add this timer to the active pool mTimerPool.add(this); } @@ -1199,21 +1202,35 @@ public final class BatteryStatsImpl extends BatteryStats { return mNesting > 0; } + long checkpointRunningLocked(BatteryStatsImpl stats, long elapsedRealtime) { + if (mNesting > 0) { + // We are running... + final long batteryRealtime = stats.getBatteryRealtimeLocked(elapsedRealtime * 1000); + if (mTimerPool != null) { + return refreshTimersLocked(stats, batteryRealtime, mTimerPool, this); + } + final long heldTime = batteryRealtime - mUpdateTime; + mUpdateTime = batteryRealtime; + mTotalTime += heldTime; + return heldTime; + } + return 0; + } + void stopRunningLocked(BatteryStatsImpl stats, long elapsedRealtime) { // Ignore attempt to stop a timer that isn't running if (mNesting == 0) { return; } if (--mNesting == 0) { + final long batteryRealtime = stats.getBatteryRealtimeLocked(elapsedRealtime * 1000); if (mTimerPool != null) { // Accumulate time to all active counters, scaled by the total // active in the pool, before taking this one out of the pool. - refreshTimersLocked(stats, mTimerPool); + refreshTimersLocked(stats, batteryRealtime, mTimerPool, null); // Remove this timer from the active pool mTimerPool.remove(this); } else { - final long batteryRealtime = stats.getBatteryRealtimeLocked( - elapsedRealtime * 1000); mNesting = 1; mTotalTime = computeRunTimeLocked(batteryRealtime); mNesting = 0; @@ -1235,19 +1252,23 @@ public final class BatteryStatsImpl extends BatteryStats { // Update the total time for all other running Timers with the same type as this Timer // due to a change in timer count - private static void refreshTimersLocked(final BatteryStatsImpl stats, - final ArrayList<StopwatchTimer> pool) { - final long realtime = SystemClock.elapsedRealtime() * 1000; - final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime); + private static long refreshTimersLocked(final BatteryStatsImpl stats, + long batteryRealtime, final ArrayList<StopwatchTimer> pool, StopwatchTimer self) { + long selfTime = 0; final int N = pool.size(); for (int i=N-1; i>= 0; i--) { final StopwatchTimer t = pool.get(i); long heldTime = batteryRealtime - t.mUpdateTime; if (heldTime > 0) { - t.mTotalTime += heldTime / N; + final long myTime = heldTime / N; + if (t == self) { + selfTime = myTime; + } + t.mTotalTime += myTime; } t.mUpdateTime = batteryRealtime; } + return selfTime; } @Override @@ -2368,8 +2389,12 @@ public final class BatteryStatsImpl extends BatteryStats { + Integer.toHexString(mHistoryCur.states)); addHistoryRecordLocked(elapsedRealtime); mMobileRadioActive = active; - if (active) mMobileRadioActiveTimer.startRunningLocked(this, elapsedRealtime); - else mMobileRadioActiveTimer.stopRunningLocked(this, elapsedRealtime); + if (active) { + mMobileRadioActiveTimer.startRunningLocked(this, elapsedRealtime); + } else { + updateNetworkActivityLocked(NET_UPDATE_MOBILE, elapsedRealtime); + mMobileRadioActiveTimer.stopRunningLocked(this, elapsedRealtime); + } } } } catch (NumberFormatException e) { @@ -3006,7 +3031,7 @@ public final class BatteryStatsImpl extends BatteryStats { // During device boot, qtaguid isn't enabled until after the inital // loading of battery stats. Now that they're enabled, take our initial // snapshot for future delta calculation. - updateNetworkActivityLocked(); + updateNetworkActivityLocked(NET_UPDATE_ALL, SystemClock.elapsedRealtime()); } @Override public long getScreenOnTime(long batteryRealtime, int which) { @@ -3057,6 +3082,18 @@ public final class BatteryStatsImpl extends BatteryStats { return mMobileRadioActiveTimer.getTotalTimeLocked(batteryRealtime, which); } + @Override public int getMobileRadioActiveCount(int which) { + return mMobileRadioActiveTimer.getCountLocked(which); + } + + @Override public long getMobileRadioActiveUnknownTime(int which) { + return mMobileRadioActiveUnknownTime.getCountLocked(which); + } + + @Override public int getMobileRadioActiveUnknownCount(int which) { + return (int)mMobileRadioActiveUnknownCount.getCountLocked(which); + } + @Override public long getWifiOnTime(long batteryRealtime, int which) { return mWifiOnTimer.getTotalTimeLocked(batteryRealtime, which); } @@ -3156,6 +3193,8 @@ public final class BatteryStatsImpl extends BatteryStats { LongSamplingCounter[] mNetworkByteActivityCounters; LongSamplingCounter[] mNetworkPacketActivityCounters; + LongSamplingCounter mMobileRadioActiveTime; + LongSamplingCounter mMobileRadioActiveCount; /** * The statistics we have collected for this uid's wake locks. @@ -3556,6 +3595,14 @@ public final class BatteryStatsImpl extends BatteryStats { } } + void noteMobileRadioActiveTimeLocked(long batteryUptime) { + if (mNetworkByteActivityCounters == null) { + initNetworkActivityLocked(); + } + mMobileRadioActiveTime.addCountLocked(batteryUptime); + mMobileRadioActiveCount.addCountLocked(1); + } + @Override public boolean hasNetworkActivity() { return mNetworkByteActivityCounters != null; @@ -3581,6 +3628,18 @@ public final class BatteryStatsImpl extends BatteryStats { } } + @Override + public long getMobileRadioActiveTime(int which) { + return mMobileRadioActiveTime != null + ? mMobileRadioActiveTime.getCountLocked(which) : 0; + } + + @Override + public int getMobileRadioActiveCount(int which) { + return mMobileRadioActiveCount != null + ? (int)mMobileRadioActiveCount.getCountLocked(which) : 0; + } + void initNetworkActivityLocked() { mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES]; mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES]; @@ -3588,6 +3647,8 @@ public final class BatteryStatsImpl extends BatteryStats { mNetworkByteActivityCounters[i] = new LongSamplingCounter(mUnpluggables); mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mUnpluggables); } + mMobileRadioActiveTime = new LongSamplingCounter(mUnpluggables); + mMobileRadioActiveCount = new LongSamplingCounter(mUnpluggables); } /** @@ -3652,6 +3713,8 @@ public final class BatteryStatsImpl extends BatteryStats { mNetworkByteActivityCounters[i].reset(false); mNetworkPacketActivityCounters[i].reset(false); } + mMobileRadioActiveTime.reset(false); + mMobileRadioActiveCount.reset(false); } if (mWakelockStats.size() > 0) { @@ -3859,6 +3922,8 @@ public final class BatteryStatsImpl extends BatteryStats { mNetworkByteActivityCounters[i].writeToParcel(out); mNetworkPacketActivityCounters[i].writeToParcel(out); } + mMobileRadioActiveTime.writeToParcel(out); + mMobileRadioActiveCount.writeToParcel(out); } else { out.writeInt(0); } @@ -3982,6 +4047,8 @@ public final class BatteryStatsImpl extends BatteryStats { mNetworkByteActivityCounters[i] = new LongSamplingCounter(mUnpluggables, in); mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mUnpluggables, in); } + mMobileRadioActiveTime = new LongSamplingCounter(mUnpluggables, in); + mMobileRadioActiveCount = new LongSamplingCounter(mUnpluggables, in); } else { mNetworkByteActivityCounters = null; mNetworkPacketActivityCounters = null; @@ -5076,6 +5143,8 @@ public final class BatteryStatsImpl extends BatteryStats { mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mUnpluggables); } mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mUnpluggables); + mMobileRadioActiveUnknownTime = new LongSamplingCounter(mUnpluggables); + mMobileRadioActiveUnknownCount = new LongSamplingCounter(mUnpluggables); mWifiOnTimer = new StopwatchTimer(null, -3, null, mUnpluggables); mGlobalWifiRunningTimer = new StopwatchTimer(null, -4, null, mUnpluggables); for (int i=0; i<NUM_WIFI_STATES; i++) { @@ -5342,6 +5411,8 @@ public final class BatteryStatsImpl extends BatteryStats { mNetworkPacketActivityCounters[i].reset(false); } mMobileRadioActiveTimer.reset(this, false); + mMobileRadioActiveUnknownTime.reset(false); + mMobileRadioActiveUnknownCount.reset(false); mWifiOnTimer.reset(this, false); mGlobalWifiRunningTimer.reset(this, false); for (int i=0; i<NUM_WIFI_STATES; i++) { @@ -5419,7 +5490,7 @@ public final class BatteryStatsImpl extends BatteryStats { public void pullPendingStateUpdatesLocked() { updateKernelWakelocksLocked(); - updateNetworkActivityLocked(); + updateNetworkActivityLocked(NET_UPDATE_ALL, SystemClock.elapsedRealtime()); } void setOnBatteryLocked(boolean onBattery, int oldStatus, int level) { @@ -5604,10 +5675,14 @@ public final class BatteryStatsImpl extends BatteryStats { } } - private void updateNetworkActivityLocked() { + static final int NET_UPDATE_MOBILE = 1<<0; + static final int NET_UPDATE_WIFI = 1<<1; + static final int NET_UPDATE_ALL = 0xffff; + + private void updateNetworkActivityLocked(int which, long elapsedRealtime) { if (!SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) return; - if (mMobileIfaces.length > 0) { + if ((which&NET_UPDATE_MOBILE) != 0 && mMobileIfaces.length > 0) { final NetworkStats snapshot; final NetworkStats last = mCurMobileSnapshot; try { @@ -5625,6 +5700,10 @@ public final class BatteryStatsImpl extends BatteryStats { null, null, mTmpNetworkStats); mTmpNetworkStats = delta; + long radioTime = mMobileRadioActiveTimer.checkpointRunningLocked(this, + elapsedRealtime); + long totalPackets = delta.getTotalPackets(); + final int size = delta.size(); for (int i = 0; i < size; i++) { final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry); @@ -5637,6 +5716,17 @@ public final class BatteryStatsImpl extends BatteryStats { u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes, entry.txPackets); + if (radioTime > 0) { + // Distribute total radio active time in to this app. + long appPackets = entry.rxPackets + entry.txPackets; + long appRadioTime = (radioTime*appPackets)/totalPackets; + u.noteMobileRadioActiveTimeLocked(appRadioTime); + // Remove this app from the totals, so that we don't lose any time + // due to rounding. + radioTime -= appRadioTime; + totalPackets -= appPackets; + } + mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(entry.rxBytes); mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(entry.txBytes); mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked( @@ -5644,9 +5734,15 @@ public final class BatteryStatsImpl extends BatteryStats { mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked( entry.txPackets); } + + if (radioTime > 0) { + // Whoops, there is some radio time we can't blame on an app! + mMobileRadioActiveUnknownTime.addCountLocked(radioTime); + mMobileRadioActiveUnknownCount.addCountLocked(1); + } } - if (mWifiIfaces.length > 0) { + if ((which&NET_UPDATE_WIFI) != 0 && mWifiIfaces.length > 0) { final NetworkStats snapshot; final NetworkStats last = mCurWifiSnapshot; try { @@ -6275,6 +6371,8 @@ public final class BatteryStatsImpl extends BatteryStats { } mMobileRadioActive = false; mMobileRadioActiveTimer.readSummaryFromParcelLocked(in); + mMobileRadioActiveUnknownTime.readSummaryFromParcelLocked(in); + mMobileRadioActiveUnknownCount.readSummaryFromParcelLocked(in); mWifiOn = false; mWifiOnTimer.readSummaryFromParcelLocked(in); mGlobalWifiRunning = false; @@ -6370,6 +6468,8 @@ public final class BatteryStatsImpl extends BatteryStats { u.mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in); u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in); } + u.mMobileRadioActiveTime.readSummaryFromParcelLocked(in); + u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in); } int NW = in.readInt(); @@ -6506,6 +6606,8 @@ public final class BatteryStatsImpl extends BatteryStats { mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out); } mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL); + mMobileRadioActiveUnknownTime.writeSummaryFromParcelLocked(out); + mMobileRadioActiveUnknownCount.writeSummaryFromParcelLocked(out); mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL); for (int i=0; i<NUM_WIFI_STATES; i++) { @@ -6609,6 +6711,8 @@ public final class BatteryStatsImpl extends BatteryStats { u.mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out); u.mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out); } + u.mMobileRadioActiveTime.writeSummaryFromParcelLocked(out); + u.mMobileRadioActiveCount.writeSummaryFromParcelLocked(out); } int NW = u.mWakelockStats.size(); @@ -6748,6 +6852,8 @@ public final class BatteryStatsImpl extends BatteryStats { } mMobileRadioActive = false; mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mUnpluggables, in); + mMobileRadioActiveUnknownTime = new LongSamplingCounter(mUnpluggables, in); + mMobileRadioActiveUnknownCount = new LongSamplingCounter(mUnpluggables, in); mWifiOn = false; mWifiOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in); mGlobalWifiRunning = false; @@ -6865,6 +6971,8 @@ public final class BatteryStatsImpl extends BatteryStats { mNetworkPacketActivityCounters[i].writeToParcel(out); } mMobileRadioActiveTimer.writeToParcel(out, batteryRealtime); + mMobileRadioActiveUnknownTime.writeToParcel(out); + mMobileRadioActiveUnknownCount.writeToParcel(out); mWifiOnTimer.writeToParcel(out, batteryRealtime); mGlobalWifiRunningTimer.writeToParcel(out, batteryRealtime); for (int i=0; i<NUM_WIFI_STATES; i++) { diff --git a/core/res/res/layout-xlarge/screen_action_bar.xml b/core/res/res/layout-xlarge/screen_action_bar.xml index d2fe9fa..e495e53 100644 --- a/core/res/res/layout-xlarge/screen_action_bar.xml +++ b/core/res/res/layout-xlarge/screen_action_bar.xml @@ -34,7 +34,6 @@ the Action Bar enabled overlaying application content. android:layout_height="wrap_content" android:layout_alignParentTop="true" style="?android:attr/actionBarStyle" - android:sharedElementName="android:action_bar" android:gravity="top"> <com.android.internal.widget.ActionBarView android:id="@+id/action_bar" diff --git a/core/res/res/layout/screen_action_bar.xml b/core/res/res/layout/screen_action_bar.xml index 7b9a20b..b1889a2 100644 --- a/core/res/res/layout/screen_action_bar.xml +++ b/core/res/res/layout/screen_action_bar.xml @@ -33,7 +33,6 @@ This is an optimized layout for a screen with the Action Bar enabled. android:layout_height="wrap_content" android:layout_alignParentTop="true" style="?android:attr/actionBarStyle" - android:sharedElementName="android:action_bar" android:gravity="top"> <com.android.internal.widget.ActionBarView android:id="@+id/action_bar" diff --git a/core/res/res/layout/screen_custom_title.xml b/core/res/res/layout/screen_custom_title.xml index d02cc8b..e3364d1 100644 --- a/core/res/res/layout/screen_custom_title.xml +++ b/core/res/res/layout/screen_custom_title.xml @@ -31,7 +31,6 @@ This is a custom layout for a screen. <FrameLayout android:id="@android:id/title_container" android:layout_width="match_parent" android:layout_height="?android:attr/windowTitleSize" - android:sharedElementName="android:title" style="?android:attr/windowTitleBackgroundStyle"> </FrameLayout> <FrameLayout android:id="@android:id/content" diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 1c5be42..bfd7565 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -4760,6 +4760,14 @@ <attr name="fromScene" format="reference" /> <!-- The destination scene in this scene change. --> <attr name="toScene" format="reference" /> + <!-- The name of the originating scene in this scene change. + Apps should treat this name as an API in the same sense + that an Intent action or extra key is. --> + <attr name="fromSceneName" format="string" /> + <!-- The name of the destination scene in this scene change. + Apps should treat this name as an API in the same sense + that an Intent action or extra key is. --> + <attr name="toSceneName" format="string" /> </declare-styleable> <!-- ========================== --> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 3106daa..c814d25 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2103,6 +2103,8 @@ <public type="attr" name="controlY1" /> <public type="attr" name="controlX2" /> <public type="attr" name="controlY2" /> + <public type="attr" name="fromSceneName" /> + <public type="attr" name="toSceneName" /> <public type="attr" name="sharedElementName" /> <public type="attr" name="transitionGroup" /> <public type="attr" name="castsShadow" /> diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk new file mode 100644 index 0000000..9f04228 --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk @@ -0,0 +1,41 @@ +# Copyright (C) 2014 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := tests + +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_SDK_VERSION := 9 + +LOCAL_PACKAGE_NAME := MultiDexLegacyVersionedTestApp_v1 + +LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex + +mainDexList:= \ + $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list + +LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex + +include $(BUILD_PACKAGE) + +$(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses + $(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@ + echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@ + +$(built_dex_intermediate): $(mainDexList) + diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/AndroidManifest.xml b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/AndroidManifest.xml new file mode 100644 index 0000000..c7b066d --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/AndroidManifest.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.framework.multidexlegacyversionedtestapp" + android:versionCode="1" + android:versionName="1.0" > + + <uses-sdk + android:minSdkVersion="9" + android:targetSdkVersion="18" /> + + <application + android:name="android.support.multidex.MultiDexApplication" + android:allowBackup="true" + android:label="MultiDexLegacyVersionedTestApp_v1"> + <activity + android:name="com.android.framework.multidexlegacyversionedtestapp.MainActivity" + android:label="MultiDexLegacyVersionedTestApp_v1" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + <uses-library android:name="android.test.runner" /> + </application> + + <instrumentation android:name="android.test.InstrumentationTestRunner" + android:targetPackage="com.android.framework.multidexlegacyversionedtestapp" + android:label="Test for MultiDexLegacyVersionedTestApp_v1" /> + +</manifest> diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/res/layout/activity_main.xml b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/res/layout/activity_main.xml new file mode 100644 index 0000000..58ae67a --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/res/layout/activity_main.xml @@ -0,0 +1,7 @@ +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context=".MainActivity" > + +</RelativeLayout> diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/src/com/android/framework/multidexlegacyversionedtestapp/ClassForMainDex.java b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/src/com/android/framework/multidexlegacyversionedtestapp/ClassForMainDex.java new file mode 100644 index 0000000..8662562 --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/src/com/android/framework/multidexlegacyversionedtestapp/ClassForMainDex.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.framework.multidexlegacyversionedtestapp; + +/** + * Class directly referenced from Activity, will be kept in main dex. The class is not referenced + * by <clinit> or <init>, its direct references are not kept in main dex. + */ +public class ClassForMainDex { + + public static int getVersion() { + return Version.getVersion(); + } + +} diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/src/com/android/framework/multidexlegacyversionedtestapp/MainActivity.java b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/src/com/android/framework/multidexlegacyversionedtestapp/MainActivity.java new file mode 100644 index 0000000..351d860 --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/src/com/android/framework/multidexlegacyversionedtestapp/MainActivity.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.framework.multidexlegacyversionedtestapp; + +import android.app.Activity; +import android.os.Bundle; + +public class MainActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + } + + public int getVersion() { + return ClassForMainDex.getVersion(); + } + +} diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/src/com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.java b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/src/com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.java new file mode 100644 index 0000000..24b4d69 --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/src/com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.framework.multidexlegacyversionedtestapp; + +import android.test.ActivityInstrumentationTestCase2; + +/** + * Run the tests with: <code>adb shell am instrument -w + com.android.framework.multidexlegacyversionedtestapp/android.test.InstrumentationTestRunner +</code> + */ +public class MultiDexUpdateTest extends ActivityInstrumentationTestCase2<MainActivity> +{ + public MultiDexUpdateTest() { + super(MainActivity.class); + } + + /** + * Tests that all classes of the application can be loaded. Verifies also that we load the + * correct version of {@link Version} ie the class is the secondary dex file. + */ + public void testAllClassAvailable() + { + assertEquals(1, getActivity().getVersion()); + } +} diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/src/com/android/framework/multidexlegacyversionedtestapp/Version.java b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/src/com/android/framework/multidexlegacyversionedtestapp/Version.java new file mode 100644 index 0000000..eb9827a --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/src/com/android/framework/multidexlegacyversionedtestapp/Version.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.framework.multidexlegacyversionedtestapp; + +/* can go in secondary dex */ +public class Version { + + public static int getVersion() { + return 1; + } +} diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk new file mode 100644 index 0000000..1b8da41 --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk @@ -0,0 +1,41 @@ +# Copyright (C) 2014 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := tests + +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_SDK_VERSION := 9 + +LOCAL_PACKAGE_NAME := MultiDexLegacyVersionedTestApp_v2 + +LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex + +mainDexList:= \ + $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list + +LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex + +include $(BUILD_PACKAGE) + +$(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses + $(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@ + echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@ + +$(built_dex_intermediate): $(mainDexList) + diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/AndroidManifest.xml b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/AndroidManifest.xml new file mode 100644 index 0000000..4d24793 --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/AndroidManifest.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.framework.multidexlegacyversionedtestapp" + android:versionCode="2" + android:versionName="2.0" > + + <uses-sdk + android:minSdkVersion="9" + android:targetSdkVersion="18" /> + + <application + android:name="android.support.multidex.MultiDexApplication" + android:allowBackup="true" + android:label="MultiDexLegacyVersionedTestApp_v2"> + <activity + android:name="com.android.framework.multidexlegacyversionedtestapp.MainActivity" + android:label="MultiDexLegacyVersionedTestApp_v2" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + <uses-library android:name="android.test.runner" /> + </application> + + <instrumentation android:name="android.test.InstrumentationTestRunner" + android:targetPackage="com.android.framework.multidexlegacyversionedtestapp" + android:label="Test for MultiDexLegacyVersionedTestApp_v2" /> + +</manifest> diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/res/layout/activity_main.xml b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/res/layout/activity_main.xml new file mode 100644 index 0000000..58ae67a --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/res/layout/activity_main.xml @@ -0,0 +1,7 @@ +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context=".MainActivity" > + +</RelativeLayout> diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/src/com/android/framework/multidexlegacyversionedtestapp/ClassForMainDex.java b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/src/com/android/framework/multidexlegacyversionedtestapp/ClassForMainDex.java new file mode 100644 index 0000000..8662562 --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/src/com/android/framework/multidexlegacyversionedtestapp/ClassForMainDex.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.framework.multidexlegacyversionedtestapp; + +/** + * Class directly referenced from Activity, will be kept in main dex. The class is not referenced + * by <clinit> or <init>, its direct references are not kept in main dex. + */ +public class ClassForMainDex { + + public static int getVersion() { + return Version.getVersion(); + } + +} diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/src/com/android/framework/multidexlegacyversionedtestapp/MainActivity.java b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/src/com/android/framework/multidexlegacyversionedtestapp/MainActivity.java new file mode 100644 index 0000000..351d860 --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/src/com/android/framework/multidexlegacyversionedtestapp/MainActivity.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.framework.multidexlegacyversionedtestapp; + +import android.app.Activity; +import android.os.Bundle; + +public class MainActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + } + + public int getVersion() { + return ClassForMainDex.getVersion(); + } + +} diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/src/com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.java b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/src/com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.java new file mode 100644 index 0000000..f130cb2 --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/src/com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.framework.multidexlegacyversionedtestapp; + +import android.test.ActivityInstrumentationTestCase2; + +/** + * Run the tests with: <code>adb shell am instrument -w + com.android.framework.multidexlegacyversionedtestapp/android.test.InstrumentationTestRunner +</code> + */ +public class MultiDexUpdateTest extends ActivityInstrumentationTestCase2<MainActivity> +{ + public MultiDexUpdateTest() { + super(MainActivity.class); + } + + /** + * Tests that all classes of the application can be loaded. Verifies also that we load the + * correct version of {@link Version} ie the class is the secondary dex file. + */ + public void testAllClassAvailable() + { + assertEquals(2, getActivity().getVersion()); + } +} diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/src/com/android/framework/multidexlegacyversionedtestapp/Version.java b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/src/com/android/framework/multidexlegacyversionedtestapp/Version.java new file mode 100644 index 0000000..1f2305f --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/src/com/android/framework/multidexlegacyversionedtestapp/Version.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.framework.multidexlegacyversionedtestapp; + +/* can go in secondary dex */ +public class Version { + + public static int getVersion() { + return 2; + } +} diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk new file mode 100644 index 0000000..945bfcc --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk @@ -0,0 +1,41 @@ +# Copyright (C) 2014 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := tests + +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_SDK_VERSION := 9 + +LOCAL_PACKAGE_NAME := MultiDexLegacyVersionedTestApp_v3 + +LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex + +mainDexList:= \ + $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list + +LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex + +include $(BUILD_PACKAGE) + +$(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses + $(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@ + echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@ + +$(built_dex_intermediate): $(mainDexList) + diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/AndroidManifest.xml b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/AndroidManifest.xml new file mode 100644 index 0000000..76c92dd --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/AndroidManifest.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.framework.multidexlegacyversionedtestapp" + android:versionCode="3" + android:versionName="3.0" > + + <uses-sdk + android:minSdkVersion="9" + android:targetSdkVersion="18" /> + + <application + android:name="android.support.multidex.MultiDexApplication" + android:allowBackup="true" + android:label="MultiDexLegacyVersionedTestApp_v3"> + <activity + android:name="com.android.framework.multidexlegacyversionedtestapp.MainActivity" + android:label="MultiDexLegacyVersionedTestApp_v3" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + <uses-library android:name="android.test.runner" /> + </application> + + <instrumentation android:name="android.test.InstrumentationTestRunner" + android:targetPackage="com.android.framework.multidexlegacyversionedtestapp" + android:label="Test for MultiDexLegacyVersionedTestApp_v3" /> + +</manifest> diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/res/layout/activity_main.xml b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/res/layout/activity_main.xml new file mode 100644 index 0000000..58ae67a --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/res/layout/activity_main.xml @@ -0,0 +1,7 @@ +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context=".MainActivity" > + +</RelativeLayout> diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/src/com/android/framework/multidexlegacyversionedtestapp/ClassForMainDex.java b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/src/com/android/framework/multidexlegacyversionedtestapp/ClassForMainDex.java new file mode 100644 index 0000000..8662562 --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/src/com/android/framework/multidexlegacyversionedtestapp/ClassForMainDex.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.framework.multidexlegacyversionedtestapp; + +/** + * Class directly referenced from Activity, will be kept in main dex. The class is not referenced + * by <clinit> or <init>, its direct references are not kept in main dex. + */ +public class ClassForMainDex { + + public static int getVersion() { + return Version.getVersion(); + } + +} diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/src/com/android/framework/multidexlegacyversionedtestapp/MainActivity.java b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/src/com/android/framework/multidexlegacyversionedtestapp/MainActivity.java new file mode 100644 index 0000000..351d860 --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/src/com/android/framework/multidexlegacyversionedtestapp/MainActivity.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.framework.multidexlegacyversionedtestapp; + +import android.app.Activity; +import android.os.Bundle; + +public class MainActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + } + + public int getVersion() { + return ClassForMainDex.getVersion(); + } + +} diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/src/com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.java b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/src/com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.java new file mode 100644 index 0000000..67aa478 --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/src/com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.framework.multidexlegacyversionedtestapp; + +import android.test.ActivityInstrumentationTestCase2; + +/** + * Run the tests with: <code>adb shell am instrument -w + com.android.framework.multidexlegacyversionedtestapp/android.test.InstrumentationTestRunner +</code> + */ +public class MultiDexUpdateTest extends ActivityInstrumentationTestCase2<MainActivity> +{ + public MultiDexUpdateTest() { + super(MainActivity.class); + } + + /** + * Tests that all classes of the application can be loaded. Verifies also that we load the + * correct version of {@link Version} ie the class is the secondary dex file. + */ + public void testAllClassAvailable() + { + assertEquals(3, getActivity().getVersion()); + } +} diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/src/com/android/framework/multidexlegacyversionedtestapp/Version.java b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/src/com/android/framework/multidexlegacyversionedtestapp/Version.java new file mode 100644 index 0000000..1c8ef3b --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/src/com/android/framework/multidexlegacyversionedtestapp/Version.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.framework.multidexlegacyversionedtestapp; + +/* can go in secondary dex */ +public class Version { + + public static int getVersion() { + return 3; + } +} |