diff options
67 files changed, 853 insertions, 356 deletions
diff --git a/Android.mk b/Android.mk index a0187165cb52..a1d91c363b0b 100644 --- a/Android.mk +++ b/Android.mk @@ -231,6 +231,7 @@ LOCAL_SRC_FILES += \ core/java/android/view/IWindowId.aidl \ core/java/android/view/IWindowManager.aidl \ core/java/android/view/IWindowSession.aidl \ + core/java/android/view/IWindowSessionCallback.aidl \ core/java/android/speech/IRecognitionListener.aidl \ core/java/android/speech/IRecognitionService.aidl \ core/java/android/speech/tts/ITextToSpeechCallback.aidl \ diff --git a/api/current.txt b/api/current.txt index 18824832dd46..eb63f90e0d37 100644 --- a/api/current.txt +++ b/api/current.txt @@ -490,6 +490,7 @@ package android { field public static final int editTextStyle = 16842862; // 0x101006e field public static final deprecated int editable = 16843115; // 0x101016b field public static final int editorExtras = 16843300; // 0x1010224 + field public static final int elegantTextHeight = 16843867; // 0x101045b field public static final int elevation = 16843843; // 0x1010443 field public static final int ellipsize = 16842923; // 0x10100ab field public static final int ems = 16843096; // 0x1010158 @@ -11901,7 +11902,6 @@ package android.hardware { method public int getMinDelay(); method public java.lang.String getName(); method public float getPower(); - method public java.lang.String getRequiredPermission(); method public float getResolution(); method public java.lang.String getStringType(); method public int getType(); @@ -12668,6 +12668,7 @@ package android.hardware.camera2.params { } public final class TonemapCurve { + ctor public TonemapCurve(float[], float[], float[]); method public void copyColorCurve(int, float[], int); method public android.graphics.PointF getPoint(int, int); method public int getPointCount(int); @@ -15922,35 +15923,18 @@ package android.media.tv { public final class TvInputInfo implements android.os.Parcelable { method public int describeContents(); - method public android.content.ComponentName getComponent(); method public java.lang.String getId(); method public android.content.Intent getIntentForSettingsActivity(); method public android.content.Intent getIntentForSetupActivity(); - method public java.lang.String getPackageName(); - method public java.lang.String getServiceName(); + method public android.content.pm.ServiceInfo getServiceInfo(); method public java.lang.CharSequence loadLabel(android.content.pm.PackageManager); method public void writeToParcel(android.os.Parcel, int); field public static final java.lang.String EXTRA_SERVICE_NAME = "serviceName"; } public final class TvInputManager { - method public void createSession(java.lang.String, android.media.tv.TvInputManager.SessionCallback, android.os.Handler); method public boolean getAvailability(java.lang.String); method public java.util.List<android.media.tv.TvInputInfo> getTvInputList(); - method public void registerListener(java.lang.String, android.media.tv.TvInputManager.TvInputListener, android.os.Handler); - method public void unregisterListener(java.lang.String, android.media.tv.TvInputManager.TvInputListener); - } - - public static final class TvInputManager.Session { - method public void release(); - method public void setVolume(float); - method public void tune(android.net.Uri); - } - - public static abstract class TvInputManager.SessionCallback { - ctor public TvInputManager.SessionCallback(); - method public void onSessionCreated(android.media.tv.TvInputManager.Session); - method public void onSessionReleased(android.media.tv.TvInputManager.Session); } public static abstract class TvInputManager.TvInputListener { @@ -15961,14 +15945,13 @@ package android.media.tv { public abstract class TvInputService extends android.app.Service { ctor public TvInputService(); method public final android.os.IBinder onBind(android.content.Intent); - method public abstract android.media.tv.TvInputService.TvInputSessionImpl onCreateSession(); - method public final void setAvailable(boolean); + method public abstract android.media.tv.TvInputService.Session onCreateSession(); field public static final java.lang.String SERVICE_INTERFACE = "android.media.tv.TvInputService"; field public static final java.lang.String SERVICE_META_DATA = "android.media.tv.input"; } - public abstract class TvInputService.TvInputSessionImpl implements android.view.KeyEvent.Callback { - ctor public TvInputService.TvInputSessionImpl(); + public abstract class TvInputService.Session implements android.view.KeyEvent.Callback { + ctor public TvInputService.Session(); method public android.view.View onCreateOverlayView(); method public boolean onGenericMotionEvent(android.view.MotionEvent); method public boolean onKeyDown(int, android.view.KeyEvent); @@ -15976,8 +15959,8 @@ package android.media.tv { method public boolean onKeyMultiple(int, int, android.view.KeyEvent); method public boolean onKeyUp(int, android.view.KeyEvent); method public abstract void onRelease(); + method public abstract void onSetStreamVolume(float); method public abstract boolean onSetSurface(android.view.Surface); - method public abstract void onSetVolume(float); method public boolean onTouchEvent(android.view.MotionEvent); method public boolean onTrackballEvent(android.view.MotionEvent); method public abstract boolean onTune(android.net.Uri); @@ -15988,17 +15971,26 @@ package android.media.tv { ctor public TvView(android.content.Context); ctor public TvView(android.content.Context, android.util.AttributeSet); ctor public TvView(android.content.Context, android.util.AttributeSet, int); - method public void bindTvInput(java.lang.String, android.media.tv.TvInputManager.SessionCallback); method public boolean dispatchUnhandledInputEvent(android.view.InputEvent); method public boolean onUnhandledInputEvent(android.view.InputEvent); + method public void reset(); method public void setOnUnhandledInputEventListener(android.media.tv.TvView.OnUnhandledInputEventListener); - method public void unbindTvInput(); + method public void setStreamVolume(float); + method public void setTvInputListener(android.media.tv.TvView.TvInputListener); + method public void tune(java.lang.String, android.net.Uri); + field public static final int ERROR_BUSY = 0; // 0x0 + field public static final int ERROR_TV_INPUT_DISCONNECTED = 1; // 0x1 } public static abstract interface TvView.OnUnhandledInputEventListener { method public abstract boolean onUnhandledInputEvent(android.view.InputEvent); } + public static abstract class TvView.TvInputListener { + ctor public TvView.TvInputListener(); + method public void onError(java.lang.String, int); + } + } package android.mtp { @@ -21331,12 +21323,14 @@ package android.os { public final class PowerManager { method public void goToSleep(long); method public boolean isInteractive(); + method public boolean isPowerSaveMode(); method public deprecated boolean isScreenOn(); method public android.os.PowerManager.WakeLock newWakeLock(int, java.lang.String); method public void reboot(java.lang.String); method public void userActivity(long, boolean); method public void wakeUp(long); field public static final int ACQUIRE_CAUSES_WAKEUP = 268435456; // 0x10000000 + field public static final java.lang.String ACTION_POWER_SAVE_MODE_CHANGED = "android.os.action.POWER_SAVE_MODE_CHANGED"; field public static final deprecated int FULL_WAKE_LOCK = 26; // 0x1a field public static final int ON_AFTER_RELEASE = 536870912; // 0x20000000 field public static final int PARTIAL_WAKE_LOCK = 1; // 0x1 @@ -29860,20 +29854,12 @@ package android.transition { method public long getStartDelay(android.view.ViewGroup, android.transition.Transition, android.transition.TransitionValues, android.transition.TransitionValues); method public void setPropagationSpeed(float); method public void setSide(int); - field public static final int BOTTOM = 3; // 0x3 - field public static final int LEFT = 0; // 0x0 - field public static final int RIGHT = 2; // 0x2 - field public static final int TOP = 1; // 0x1 } public class Slide extends android.transition.Visibility { ctor public Slide(); ctor public Slide(int); method public void setSlideEdge(int); - field public static final int BOTTOM = 3; // 0x3 - field public static final int LEFT = 0; // 0x0 - field public static final int RIGHT = 2; // 0x2 - field public static final int TOP = 1; // 0x1 } public abstract class Transition implements java.lang.Cloneable { @@ -29927,7 +29913,7 @@ package android.transition { public static abstract class Transition.EpicenterCallback { ctor public Transition.EpicenterCallback(); - method public abstract android.graphics.Rect getEpicenter(android.transition.Transition); + method public abstract android.graphics.Rect onGetEpicenter(android.transition.Transition); } public static abstract interface Transition.TransitionListener { diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java index b739387a76c3..b658597b494e 100644 --- a/core/java/android/app/ActivityTransitionCoordinator.java +++ b/core/java/android/app/ActivityTransitionCoordinator.java @@ -563,7 +563,7 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { public void setEpicenter(Rect epicenter) { mEpicenter = epicenter; } @Override - public Rect getEpicenter(Transition transition) { + public Rect onGetEpicenter(Transition transition) { return mEpicenter; } } diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 8dba1dcc778c..5ac2a3393855 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -21,7 +21,10 @@ import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; import android.media.AudioManager; import android.media.session.MediaSessionToken; import android.net.Uri; @@ -32,6 +35,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; import android.os.UserHandle; +import android.os.UserManager; import android.text.TextUtils; import android.util.Log; import android.util.TypedValue; @@ -2305,7 +2309,23 @@ public class Notification implements Parcelable return this; } + private Bitmap getProfileBadge() { + UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); + Drawable badge = userManager.getBadgeForUser(android.os.Process.myUserHandle()); + if (badge == null) { + return null; + } + final int width = badge.getIntrinsicWidth(); + final int height = badge.getIntrinsicHeight(); + Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + badge.setBounds(0, 0, width, height); + badge.draw(canvas); + return bitmap; + } + private RemoteViews applyStandardTemplate(int resId, boolean fitIn1U) { + Bitmap profileIcon = getProfileBadge(); RemoteViews contentView = new RemoteViews(mContext.getPackageName(), resId); boolean showLine3 = false; boolean showLine2 = false; @@ -2313,6 +2333,12 @@ public class Notification implements Parcelable if (mPriority < PRIORITY_LOW) { // TODO: Low priority presentation } + if (profileIcon != null) { + contentView.setImageViewBitmap(R.id.profile_icon, profileIcon); + contentView.setViewVisibility(R.id.profile_icon, View.VISIBLE); + } else { + contentView.setViewVisibility(R.id.profile_icon, View.GONE); + } if (mLargeIcon != null) { contentView.setImageViewBitmap(R.id.icon, mLargeIcon); processLargeIcon(mLargeIcon, contentView); diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java index 86208fc96229..c593e9ef19e9 100644 --- a/core/java/android/hardware/Sensor.java +++ b/core/java/android/hardware/Sensor.java @@ -613,6 +613,7 @@ public final class Sensor { } /** + * @hide * @return The permission required to access this sensor. If empty, no permission is required. */ public String getRequiredPermission() { diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java index f74fbaa7ced4..c3e042eb4d61 100644 --- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java @@ -446,7 +446,12 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession { @Override public void onUnconfigured(CameraDevice camera) { - mUnconfigureDrainer.taskFinished(); + synchronized (session) { + // Ignore #onUnconfigured before #close is called + if (mClosed) { + mUnconfigureDrainer.taskFinished(); + } + } } }; diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java index 97950827b688..d4adae1bb6b8 100644 --- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java @@ -101,11 +101,11 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { @Override public void run() { if (!CameraDeviceImpl.this.isClosed()) { - mDeviceListener.onOpened(CameraDeviceImpl.this); StateListener sessionListener = mSessionStateListener; if (sessionListener != null) { sessionListener.onOpened(CameraDeviceImpl.this); } + mDeviceListener.onOpened(CameraDeviceImpl.this); } } }; @@ -114,11 +114,11 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { @Override public void run() { if (!CameraDeviceImpl.this.isClosed()) { - mDeviceListener.onUnconfigured(CameraDeviceImpl.this); StateListener sessionListener = mSessionStateListener; if (sessionListener != null) { sessionListener.onUnconfigured(CameraDeviceImpl.this); } + mDeviceListener.onUnconfigured(CameraDeviceImpl.this); } } }; @@ -127,11 +127,11 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { @Override public void run() { if (!CameraDeviceImpl.this.isClosed()) { - mDeviceListener.onActive(CameraDeviceImpl.this); StateListener sessionListener = mSessionStateListener; if (sessionListener != null) { sessionListener.onActive(CameraDeviceImpl.this); } + mDeviceListener.onActive(CameraDeviceImpl.this); } } }; @@ -140,11 +140,11 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { @Override public void run() { if (!CameraDeviceImpl.this.isClosed()) { - mDeviceListener.onBusy(CameraDeviceImpl.this); StateListener sessionListener = mSessionStateListener; if (sessionListener != null) { sessionListener.onBusy(CameraDeviceImpl.this); } + mDeviceListener.onBusy(CameraDeviceImpl.this); } } }; @@ -152,11 +152,11 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { private final Runnable mCallOnClosed = new Runnable() { @Override public void run() { - mDeviceListener.onClosed(CameraDeviceImpl.this); StateListener sessionListener = mSessionStateListener; if (sessionListener != null) { sessionListener.onClosed(CameraDeviceImpl.this); } + mDeviceListener.onClosed(CameraDeviceImpl.this); } }; @@ -164,11 +164,11 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { @Override public void run() { if (!CameraDeviceImpl.this.isClosed()) { - mDeviceListener.onIdle(CameraDeviceImpl.this); StateListener sessionListener = mSessionStateListener; if (sessionListener != null) { sessionListener.onIdle(CameraDeviceImpl.this); } + mDeviceListener.onIdle(CameraDeviceImpl.this); } } }; @@ -177,11 +177,11 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice { @Override public void run() { if (!CameraDeviceImpl.this.isClosed()) { - mDeviceListener.onDisconnected(CameraDeviceImpl.this); StateListener sessionListener = mSessionStateListener; if (sessionListener != null) { sessionListener.onDisconnected(CameraDeviceImpl.this); } + mDeviceListener.onDisconnected(CameraDeviceImpl.this); } } }; diff --git a/core/java/android/hardware/camera2/params/TonemapCurve.java b/core/java/android/hardware/camera2/params/TonemapCurve.java index 0fcffac060d6..481d67a3880a 100644 --- a/core/java/android/hardware/camera2/params/TonemapCurve.java +++ b/core/java/android/hardware/camera2/params/TonemapCurve.java @@ -78,7 +78,7 @@ public final class TonemapCurve { /** * Create a new immutable TonemapCurve instance. * - * <p>Values are stored as a contiguous {@code (Pin, Pout}) point.</p> + * <p>Values are stored as a contiguous array of {@code (Pin, Pout)} points.</p> * * <p>All parameters may have independent length but should have at most * {@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS} * {@value #POINT_SIZE} elements.</p> @@ -88,15 +88,16 @@ public final class TonemapCurve { * * <p>This constructor copies the array contents and does not retain ownership of the array.</p> * - * @param elements An array of elements whose length is {@code CHANNEL_COUNT * rows * columns} + * @param red An array of elements whose length is divisible by {@value #POINT_SIZE} + * @param green An array of elements whose length is divisible by {@value #POINT_SIZE} + * @param blue An array of elements whose length is divisible by {@value #POINT_SIZE} * * @throws IllegalArgumentException - * if the {@code elements} array length is invalid, - * if any of the subelems are not finite + * if any of input array length is invalid, + * or if any of the elements in the array are not in the range of + * [{@value #LEVEL_BLACK}, {@value #LEVEL_WHITE}] * @throws NullPointerException - * if any of the parameters is {@code null} - * - * @hide + * if any of the parameters are {@code null} */ public TonemapCurve(float[] red, float[] green, float[] blue) { // TODO: maxCurvePoints check? diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl index 61194e96c7f1..658180b21342 100644 --- a/core/java/android/os/IPowerManager.aidl +++ b/core/java/android/os/IPowerManager.aidl @@ -41,6 +41,7 @@ interface IPowerManager void goToSleep(long time, int reason, int flags); void nap(long time); boolean isInteractive(); + boolean isPowerSaveMode(); void reboot(boolean confirm, String reason, boolean wait); void shutdown(boolean confirm, boolean wait); diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index d5177e808e12..92e80a5afd1a 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -16,6 +16,7 @@ package android.os; +import android.annotation.SdkConstant; import android.content.Context; import android.util.Log; @@ -685,6 +686,30 @@ public final class PowerManager { } /** + * Returns true if the device is currently in power save mode. When in this mode, + * applications should reduce their functionality in order to conserve battery as + * much as possible. You can monitor for changes to this state with + * {@link #ACTION_POWER_SAVE_MODE_CHANGED}. + * + * @return Returns true if currently in low power mode, else false. + */ + public boolean isPowerSaveMode() { + try { + return mService.isPowerSaveMode(); + } catch (RemoteException e) { + return false; + } + } + + /** + * Intent that is broadcast when the state of {@link #isPowerSaveMode()} changes. + * This broadcast is only sent to registered receivers. + */ + @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_POWER_SAVE_MODE_CHANGED + = "android.os.action.POWER_SAVE_MODE_CHANGED"; + + /** * A wake lock is a mechanism to indicate that your application needs * to have the device stay on. * <p> diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index ee219e3d5d36..f7a89ba5452c 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -690,16 +690,45 @@ public class UserManager { } } + /** + * If the target user is a managed profile of the calling user or the caller + * is itself a managed profile, then this returns a drawable to use as a small + * icon to include in a view to distinguish it from the original icon. + * + * @param user The target user. + * @return the drawable or null if no drawable is required. + * @hide + */ + public Drawable getBadgeForUser(UserHandle user) { + UserInfo userInfo = getUserIfProfile(user.getIdentifier()); + if (userInfo != null && userInfo.isManagedProfile()) { + return Resources.getSystem().getDrawable( + com.android.internal.R.drawable.ic_corp_badge); + } + return null; + } + private int getBadgeResIdForUser(int userHandle) { // Return the framework-provided badge. + UserInfo userInfo = getUserIfProfile(userHandle); + if (userInfo != null && userInfo.isManagedProfile()) { + return com.android.internal.R.drawable.ic_corp_icon_badge; + } + return 0; + } + + /** + * @return UserInfo for userHandle if it exists and is a profile of the current + * user or null. + */ + private UserInfo getUserIfProfile(int userHandle) { List<UserInfo> userProfiles = getProfiles(getUserHandle()); for (UserInfo user : userProfiles) { - if (user.id == userHandle - && user.isManagedProfile()) { - return com.android.internal.R.drawable.ic_corp_badge; + if (user.id == userHandle) { + return user; } } - return 0; + return null; } private Drawable getMergedDrawable(Drawable icon, Drawable badge) { diff --git a/core/java/android/transition/SidePropagation.java b/core/java/android/transition/SidePropagation.java index 5d38ac85f699..623cdd18ee44 100644 --- a/core/java/android/transition/SidePropagation.java +++ b/core/java/android/transition/SidePropagation.java @@ -18,6 +18,7 @@ package android.transition; import android.graphics.Rect; import android.util.FloatMath; import android.util.Log; +import android.view.Gravity; import android.view.View; import android.view.ViewGroup; @@ -32,38 +33,19 @@ import android.view.ViewGroup; public class SidePropagation extends VisibilityPropagation { private static final String TAG = "SlidePropagation"; - /** - * Transition propagates relative to the distance of the left side of the scene. - */ - public static final int LEFT = Slide.LEFT; - - /** - * Transition propagates relative to the distance of the top of the scene. - */ - public static final int TOP = Slide.TOP; - - /** - * Transition propagates relative to the distance of the right side of the scene. - */ - public static final int RIGHT = Slide.RIGHT; - - /** - * Transition propagates relative to the distance of the bottom of the scene. - */ - public static final int BOTTOM = Slide.BOTTOM; - private float mPropagationSpeed = 3.0f; - private int mSide = BOTTOM; + private int mSide = Gravity.BOTTOM; /** * Sets the side that is used to calculate the transition propagation. If the transitioning * View is visible in the start of the transition, then it will transition sooner when * closer to the side and later when farther. If the view is not visible in the start of * the transition, then it will transition later when closer to the side and sooner when - * farther from the edge. The default is {@link #BOTTOM}. + * farther from the edge. The default is {@link Gravity#BOTTOM}. * * @param side The side that is used to calculate the transition propagation. Must be one of - * {@link #LEFT}, {@link #TOP}, {@link #RIGHT}, or {@link #BOTTOM}. + * {@link Gravity#LEFT}, {@link Gravity#TOP}, {@link Gravity#RIGHT}, or + * {@link Gravity#BOTTOM}. */ public void setSide(int side) { mSide = side; @@ -141,16 +123,16 @@ public class SidePropagation extends VisibilityPropagation { int left, int top, int right, int bottom) { int distance = 0; switch (mSide) { - case LEFT: + case Gravity.LEFT: distance = right - viewX + Math.abs(epicenterY - viewY); break; - case TOP: + case Gravity.TOP: distance = bottom - viewY + Math.abs(epicenterX - viewX); break; - case RIGHT: + case Gravity.RIGHT: distance = viewX - left + Math.abs(epicenterY - viewY); break; - case BOTTOM: + case Gravity.BOTTOM: distance = viewY - top + Math.abs(epicenterX - viewX); break; } @@ -159,8 +141,8 @@ public class SidePropagation extends VisibilityPropagation { private int getMaxDistance(ViewGroup sceneRoot) { switch (mSide) { - case LEFT: - case RIGHT: + case Gravity.LEFT: + case Gravity.RIGHT: return sceneRoot.getWidth(); default: return sceneRoot.getHeight(); diff --git a/core/java/android/transition/Slide.java b/core/java/android/transition/Slide.java index 0ff8ddd4d1f9..8269258eaad8 100644 --- a/core/java/android/transition/Slide.java +++ b/core/java/android/transition/Slide.java @@ -24,6 +24,7 @@ import android.animation.ValueAnimator; import android.graphics.Rect; import android.util.Log; import android.util.Property; +import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.view.animation.AccelerateInterpolator; @@ -41,35 +42,9 @@ import android.view.animation.DecelerateInterpolator; public class Slide extends Visibility { private static final String TAG = "Slide"; - /** - * Move Views in or out of the left edge of the scene. - * @see #setSlideEdge(int) - */ - public static final int LEFT = 0; - - /** - * Move Views in or out of the top edge of the scene. - * @see #setSlideEdge(int) - */ - public static final int TOP = 1; - - /** - * Move Views in or out of the right edge of the scene. - * @see #setSlideEdge(int) - */ - public static final int RIGHT = 2; - - /** - * Move Views in or out of the bottom edge of the scene. This is the - * default slide direction. - * @see #setSlideEdge(int) - */ - public static final int BOTTOM = 3; - private static final TimeInterpolator sDecelerate = new DecelerateInterpolator(); private static final TimeInterpolator sAccelerate = new AccelerateInterpolator(); - private int[] mTempLoc = new int[2]; private CalculateSlide mSlideCalculator = sCalculateBottom; private interface CalculateSlide { @@ -136,11 +111,11 @@ public class Slide extends Visibility { }; /** - * Constructor using the default {@link android.transition.Slide#BOTTOM} + * Constructor using the default {@link Gravity#BOTTOM} * slide edge direction. */ public Slide() { - setSlideEdge(BOTTOM); + setSlideEdge(Gravity.BOTTOM); } /** @@ -152,20 +127,22 @@ public class Slide extends Visibility { /** * Change the edge that Views appear and disappear from. - * @param slideEdge The edge of the scene to use for Views appearing and disappearing. + * @param slideEdge The edge of the scene to use for Views appearing and disappearing. One of + * {@link android.view.Gravity#LEFT}, {@link android.view.Gravity#TOP}, + * {@link android.view.Gravity#RIGHT}, {@link android.view.Gravity#BOTTOM}. */ public void setSlideEdge(int slideEdge) { switch (slideEdge) { - case LEFT: + case Gravity.LEFT: mSlideCalculator = sCalculateLeft; break; - case TOP: + case Gravity.TOP: mSlideCalculator = sCalculateTop; break; - case RIGHT: + case Gravity.RIGHT: mSlideCalculator = sCalculateRight; break; - case BOTTOM: + case Gravity.BOTTOM: mSlideCalculator = sCalculateBottom; break; default: diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java index 9a7009928186..e9c2bba0c3a7 100644 --- a/core/java/android/transition/Transition.java +++ b/core/java/android/transition/Transition.java @@ -1763,7 +1763,7 @@ public abstract class Transition implements Cloneable { /** * Sets the callback to use to find the epicenter of a Transition. A null value indicates - * that there is no epicenter in the Transition and getEpicenter() will return null. + * that there is no epicenter in the Transition and onGetEpicenter() will return null. * Transitions like {@link android.transition.Explode} use a point or Rect to orient * the direction of travel. This is called the epicenter of the Transition and is * typically centered on a touched View. The @@ -1799,7 +1799,7 @@ public abstract class Transition implements Cloneable { if (mEpicenterCallback == null) { return null; } - return mEpicenterCallback.getEpicenter(this); + return mEpicenterCallback.onGetEpicenter(this); } /** @@ -2112,6 +2112,6 @@ public abstract class Transition implements Cloneable { * @return The Rect region of the epicenter of <code>transition</code> or null if * there is no epicenter. */ - public abstract Rect getEpicenter(Transition transition); + public abstract Rect onGetEpicenter(Transition transition); } } diff --git a/core/java/android/transition/TransitionInflater.java b/core/java/android/transition/TransitionInflater.java index f4b562f58808..5b7c7379d093 100644 --- a/core/java/android/transition/TransitionInflater.java +++ b/core/java/android/transition/TransitionInflater.java @@ -22,6 +22,7 @@ import android.content.res.TypedArray; import android.content.res.XmlResourceParser; import android.util.AttributeSet; import android.util.Xml; +import android.view.Gravity; import android.view.InflateException; import android.view.ViewGroup; import android.view.animation.AnimationUtils; @@ -208,7 +209,7 @@ public class TransitionInflater { private Slide createSlideTransition(AttributeSet attrs) { TypedArray a = mContext.obtainStyledAttributes(attrs, com.android.internal.R.styleable.Slide); - int edge = a.getInt(com.android.internal.R.styleable.Slide_slideEdge, Slide.BOTTOM); + int edge = a.getInt(com.android.internal.R.styleable.Slide_slideEdge, Gravity.BOTTOM); Slide slide = new Slide(edge); a.recycle(); return slide; diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index a52ccdfef13e..ae59bbc636ff 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -30,6 +30,7 @@ import android.view.IApplicationToken; import android.view.IOnKeyguardExitResult; import android.view.IRotationWatcher; import android.view.IWindowSession; +import android.view.IWindowSessionCallback; import android.view.KeyEvent; import android.view.InputEvent; import android.view.MagnificationSpec; @@ -56,7 +57,7 @@ interface IWindowManager boolean stopViewServer(); // Transaction #2 boolean isViewServerRunning(); // Transaction #3 - IWindowSession openSession(in IInputMethodClient client, + IWindowSession openSession(in IWindowSessionCallback callback, in IInputMethodClient client, in IInputContext inputContext); boolean inputMethodClientHasFocus(IInputMethodClient client); @@ -130,6 +131,8 @@ interface IWindowManager void setAnimationScale(int which, float scale); void setAnimationScales(in float[] scales); + float getCurrentAnimatorScale(); + // For testing void setInTouchMode(boolean showFocus); diff --git a/core/java/android/view/IWindowSessionCallback.aidl b/core/java/android/view/IWindowSessionCallback.aidl new file mode 100644 index 000000000000..88931ce000a5 --- /dev/null +++ b/core/java/android/view/IWindowSessionCallback.aidl @@ -0,0 +1,27 @@ +/* +** Copyright 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; + +/** + * Callback to active sessions of the window manager + * + * {@hide} + */ +oneway interface IWindowSessionCallback +{ + void onAnimatorScaleChanged(float scale); +} diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java index b4779f4d91d6..0ebf2e18f184 100644 --- a/core/java/android/view/WindowManagerGlobal.java +++ b/core/java/android/view/WindowManagerGlobal.java @@ -147,9 +147,14 @@ public final class WindowManagerGlobal { InputMethodManager imm = InputMethodManager.getInstance(); IWindowManager windowManager = getWindowManagerService(); sWindowSession = windowManager.openSession( + new IWindowSessionCallback.Stub() { + @Override + public void onAnimatorScaleChanged(float scale) { + ValueAnimator.setDurationScale(scale); + } + }, imm.getClient(), imm.getInputContext()); - float animatorScale = windowManager.getAnimationScale(2); - ValueAnimator.setDurationScale(animatorScale); + ValueAnimator.setDurationScale(windowManager.getCurrentAnimatorScale()); } catch (RemoteException e) { Log.e(TAG, "Failed to open window session", e); } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index a4a9680e0995..43c8ddeab253 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -222,6 +222,7 @@ import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; * @attr ref android.R.styleable#TextView_imeActionLabel * @attr ref android.R.styleable#TextView_imeActionId * @attr ref android.R.styleable#TextView_editorExtras + * @attr ref android.R.styleable#TextView_elegantTextHeight */ @RemoteView public class TextView extends View implements ViewTreeObserver.OnPreDrawListener { @@ -2637,6 +2638,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * metrics, and also increases top and bottom bounds to provide more space. * * @param elegant set the paint's elegant metrics flag. + * + * @attr ref android.R.styleable#TextView_elegantTextHeight */ public void setElegantTextHeight(boolean elegant) { mTextPaint.setElegantTextHeight(elegant); diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index d844818cb506..f57c3a0d8365 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -74,6 +74,8 @@ <protected-broadcast android:name="android.intent.action.USER_FOREGROUND" /> <protected-broadcast android:name="android.intent.action.USER_SWITCHED" /> + <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGED" /> + <protected-broadcast android:name="android.app.action.ENTER_CAR_MODE" /> <protected-broadcast android:name="android.app.action.EXIT_CAR_MODE" /> <protected-broadcast android:name="android.app.action.ENTER_DESK_MODE" /> diff --git a/core/res/res/drawable-hdpi/ic_corp_badge.png b/core/res/res/drawable-hdpi/ic_corp_badge.png Binary files differdeleted file mode 100644 index f6473757242f..000000000000 --- a/core/res/res/drawable-hdpi/ic_corp_badge.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/ic_corp_badge.png b/core/res/res/drawable-xhdpi/ic_corp_badge.png Binary files differdeleted file mode 100644 index 80d848df9912..000000000000 --- a/core/res/res/drawable-xhdpi/ic_corp_badge.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/ic_corp_badge.png b/core/res/res/drawable-xxhdpi/ic_corp_badge.png Binary files differdeleted file mode 100644 index 885e2ac76cfb..000000000000 --- a/core/res/res/drawable-xxhdpi/ic_corp_badge.png +++ /dev/null diff --git a/core/res/res/drawable/ic_corp_badge.xml b/core/res/res/drawable/ic_corp_badge.xml new file mode 100644 index 000000000000..532571245d55 --- /dev/null +++ b/core/res/res/drawable/ic_corp_badge.xml @@ -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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > + <size + android:width="19.0dp" + android:height="19.0dp"/> + + <viewport + android:viewportWidth="19.0" + android:viewportHeight="19.0"/> + + <path + android:pathData="M9.5,9.5m-9.5,0.0a9.5,9.5 0.0,1.0 1.0,19.0 0.0a9.5,9.5 0.0,1.0 1.0,-19.0 0.0" + android:fill="#FF5722"/> + <path + android:pathData="M12.667,7.125l-1.583,0.0L11.084,6.333l-0.792,-0.792L8.708,5.5410004L7.917,6.333l0.0,0.792L6.333,7.125c-0.438,0.0 -0.788,0.354 -0.788,0.792l-0.004,4.354c0.0,0.438 0.354,0.792 0.792,0.792l6.333,0.0c0.438,0.0 0.792,-0.354 0.792,-0.792L13.458,7.917C13.458,7.479 13.104,7.125 12.667,7.125zM10.094,10.687L8.906,10.687L8.906,9.5l1.188,0.0L10.094,10.687zM10.292,7.125L8.708,7.125L8.708,6.333l1.583,0.0L10.291,7.125z" + android:fill="#FFFFFF"/> + <path + android:pathData="M4.75,4.75 h9.5 v9.5 h-9.5z" + android:fill="#00000000"/> +</vector> diff --git a/core/res/res/drawable/ic_corp_icon_badge.xml b/core/res/res/drawable/ic_corp_icon_badge.xml new file mode 100644 index 000000000000..7bfab4c55a0d --- /dev/null +++ b/core/res/res/drawable/ic_corp_icon_badge.xml @@ -0,0 +1,40 @@ +<!-- +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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > + <size + android:width="64.0dp" + android:height="64.0dp"/> + + <viewport + android:viewportWidth="64.0" + android:viewportHeight="64.0"/> + + <path + android:fill="#FF000000" + android:pathData="M49.062,50.0m-14.0,0.0a14.0,14.0 0.0,1.0 1.0,28.0 0.0a14.0,14.0 0.0,1.0 1.0,-28.0 0.0"/> + <path + android:fill="#FF000000" + android:pathData="M49.0,49.5m-14.0,0.0a14.0,14.0 0.0,1.0 1.0,28.0 0.0a14.0,14.0 0.0,1.0 1.0,-28.0 0.0"/> + <path + android:pathData="M49.0,49.0m-14.0,0.0a14.0,14.0 0.0,1.0 1.0,28.0 0.0a14.0,14.0 0.0,1.0 1.0,-28.0 0.0" + android:fill="#FF5722"/> + <path + android:pathData="M53.667,45.5l-2.333,0.0l0.0,-1.167l-1.167,-1.167l-2.333,0.0l-1.167,1.167L46.667,45.5l-2.333,0.0c-0.645,0.0 -1.161,0.522 -1.161,1.167l-0.006,6.417c0.0,0.645 0.522,1.167 1.167,1.167l9.333,0.0c0.645,0.0 1.167,-0.522 1.167,-1.167l0.0,-6.417C54.833,46.022 54.311,45.5 53.667,45.5zM49.875,50.75l-1.75,0.0L48.125,49.0l1.75,0.0L49.875,50.75zM50.167,45.5l-2.333,0.0l0.0,-1.167l2.333,0.0L50.167,45.5z" + android:fill="#FFFFFF"/> + <path + android:pathData="M42.0,42.0 h14.0 v14.0 h-14.0z" + android:fill="#00000000"/> +</vector> diff --git a/core/res/res/layout/notification_template_quantum_base.xml b/core/res/res/layout/notification_template_quantum_base.xml index 789bf32e33f7..4265f9da9d34 100644 --- a/core/res/res/layout/notification_template_quantum_base.xml +++ b/core/res/res/layout/notification_template_quantum_base.xml @@ -120,6 +120,15 @@ android:gravity="center" android:paddingStart="8dp" /> + <ImageView android:id="@+id/profile_icon" + android:layout_width="24dp" + android:layout_height="24dp" + android:layout_gravity="center" + android:layout_weight="0" + android:layout_marginStart="8dp" + android:scaleType="centerInside" + android:visibility="gone" + /> </LinearLayout> </LinearLayout> </FrameLayout> diff --git a/core/res/res/layout/notification_template_quantum_big_base.xml b/core/res/res/layout/notification_template_quantum_big_base.xml index 8cb55494d48c..95a4c82774cd 100644 --- a/core/res/res/layout/notification_template_quantum_big_base.xml +++ b/core/res/res/layout/notification_template_quantum_big_base.xml @@ -127,6 +127,15 @@ android:gravity="center" android:paddingStart="8dp" /> + <ImageView android:id="@+id/profile_icon" + android:layout_width="24dp" + android:layout_height="24dp" + android:layout_gravity="center" + android:layout_weight="0" + android:layout_marginStart="8dp" + android:scaleType="centerInside" + android:visibility="gone" + /> </LinearLayout> <ProgressBar android:id="@android:id/progress" diff --git a/core/res/res/layout/notification_template_quantum_big_text.xml b/core/res/res/layout/notification_template_quantum_big_text.xml index bbd1071c1fd0..45811fc187d1 100644 --- a/core/res/res/layout/notification_template_quantum_big_text.xml +++ b/core/res/res/layout/notification_template_quantum_big_text.xml @@ -165,6 +165,15 @@ android:gravity="center" android:paddingStart="8dp" /> + <ImageView android:id="@+id/profile_icon" + android:layout_width="24dp" + android:layout_height="24dp" + android:layout_gravity="center" + android:layout_weight="0" + android:layout_marginStart="8dp" + android:scaleType="centerInside" + android:visibility="gone" + /> </LinearLayout> </LinearLayout> </FrameLayout> diff --git a/core/res/res/layout/notification_template_quantum_inbox.xml b/core/res/res/layout/notification_template_quantum_inbox.xml index a071d59fa596..3851dd3624d4 100644 --- a/core/res/res/layout/notification_template_quantum_inbox.xml +++ b/core/res/res/layout/notification_template_quantum_inbox.xml @@ -249,6 +249,15 @@ android:gravity="center" android:paddingStart="8dp" /> + <ImageView android:id="@+id/profile_icon" + android:layout_width="24dp" + android:layout_height="24dp" + android:layout_gravity="center" + android:layout_weight="0" + android:layout_marginStart="8dp" + android:scaleType="centerInside" + android:visibility="gone" + /> </LinearLayout> </LinearLayout> </FrameLayout> diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml index c966a12b7c9b..639091e14284 100644 --- a/core/res/res/values/ids.xml +++ b/core/res/res/values/ids.xml @@ -23,6 +23,7 @@ <item type="id" name="empty" /> <item type="id" name="hint" /> <item type="id" name="icon" /> + <item type="id" name="icon_badge" /> <item type="id" name="icon1" /> <item type="id" name="icon2" /> <item type="id" name="input" /> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 88e1cda837d8..5d9f3e5d078f 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2179,6 +2179,7 @@ <public type="attr" name="contentInsetRight" /> <public type="attr" name="paddingMode" /> <public type="attr" name="selectableItemBackgroundBorderless" /> + <public type="attr" name="elegantTextHeight" /> <public-padding type="dimen" name="l_resource_pad" end="0x01050010" /> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 61b6a0d92c76..80eceb5ecd66 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -217,6 +217,7 @@ <java-symbol type="id" name="pin_confirm_text" /> <java-symbol type="id" name="pin_error_message" /> <java-symbol type="id" name="timePickerLayout" /> + <java-symbol type="id" name="profile_icon" /> <java-symbol type="attr" name="actionModeShareDrawable" /> <java-symbol type="attr" name="alertDialogCenterButtons" /> @@ -1119,6 +1120,7 @@ <java-symbol type="drawable" name="cling_arrow_up" /> <java-symbol type="drawable" name="cling_bg" /> <java-symbol type="drawable" name="ic_corp_badge" /> + <java-symbol type="drawable" name="ic_corp_icon_badge" /> <java-symbol type="layout" name="action_bar_home" /> <java-symbol type="layout" name="action_bar_title_item" /> diff --git a/core/res/res/values/themes_quantum.xml b/core/res/res/values/themes_quantum.xml index eda7174d8d5c..1eeaaeb2ba85 100644 --- a/core/res/res/values/themes_quantum.xml +++ b/core/res/res/values/themes_quantum.xml @@ -733,6 +733,9 @@ please see themes_device_defaults.xml. <style name="Theme.Quantum.Light.DarkActionBar"> <item name="actionBarWidgetTheme">@null</item> <item name="actionBarTheme">@style/ThemeOverlay.Quantum.Dark.ActionBar</item> + + <item name="colorPrimaryDark">@color/quantum_blue_grey_900</item> + <item name="colorPrimary">@color/quantum_blue_grey_800</item> </style> <style name="ThemeOverlay" /> diff --git a/media/java/android/media/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java index 975e3917037b..d20ee0e00491 100644 --- a/media/java/android/media/tv/ITvInputSessionWrapper.java +++ b/media/java/android/media/tv/ITvInputSessionWrapper.java @@ -18,8 +18,6 @@ package android.media.tv; import android.content.Context; import android.graphics.Rect; -import android.media.tv.TvInputManager.Session; -import android.media.tv.TvInputService.TvInputSessionImpl; import android.net.Uri; import android.os.IBinder; import android.os.Looper; @@ -52,11 +50,11 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand private final HandlerCaller mCaller; - private TvInputSessionImpl mTvInputSessionImpl; + private TvInputService.Session mTvInputSessionImpl; private InputChannel mChannel; private TvInputEventReceiver mReceiver; - public ITvInputSessionWrapper(Context context, TvInputSessionImpl sessionImpl, + public ITvInputSessionWrapper(Context context, TvInputService.Session sessionImpl, InputChannel channel) { mCaller = new HandlerCaller(context, null, this, true /* asyncHandler */); mTvInputSessionImpl = sessionImpl; @@ -169,8 +167,8 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand } int handled = mTvInputSessionImpl.dispatchInputEvent(event, this); - if (handled != Session.DISPATCH_IN_PROGRESS) { - finishInputEvent(event, handled == Session.DISPATCH_HANDLED); + if (handled != TvInputManager.Session.DISPATCH_IN_PROGRESS) { + finishInputEvent(event, handled == TvInputManager.Session.DISPATCH_HANDLED); } } } diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java index ed599edc99e3..9525c081bec6 100644 --- a/media/java/android/media/tv/TvInputInfo.java +++ b/media/java/android/media/tv/TvInputInfo.java @@ -138,21 +138,15 @@ public final class TvInputInfo implements Parcelable { } /** - * Returns the .apk package that implements this TV input service. + * Returns the information of the service that implements this TV input. */ - public String getPackageName() { - return mService.serviceInfo.packageName; - } - - /** - * Returns the class name of the service component that implements this TV input service. - */ - public String getServiceName() { - return mService.serviceInfo.name; + public ServiceInfo getServiceInfo() { + return mService.serviceInfo; } /** * Returns the component of the service that implements this TV input. + * @hide */ public ComponentName getComponent() { return new ComponentName(mService.serviceInfo.packageName, mService.serviceInfo.name); @@ -164,8 +158,8 @@ public final class TvInputInfo implements Parcelable { public Intent getIntentForSetupActivity() { if (!TextUtils.isEmpty(mSetupActivity)) { Intent intent = new Intent(Intent.ACTION_MAIN); - intent.setClassName(getPackageName(), mSetupActivity); - intent.putExtra(EXTRA_SERVICE_NAME, getServiceName()); + intent.setClassName(mService.serviceInfo.packageName, mSetupActivity); + intent.putExtra(EXTRA_SERVICE_NAME, mService.serviceInfo.name); return intent; } return null; @@ -177,8 +171,8 @@ public final class TvInputInfo implements Parcelable { public Intent getIntentForSettingsActivity() { if (!TextUtils.isEmpty(mSettingsActivity)) { Intent intent = new Intent(Intent.ACTION_MAIN); - intent.setClassName(getPackageName(), mSettingsActivity); - intent.putExtra(EXTRA_SERVICE_NAME, getServiceName()); + intent.setClassName(mService.serviceInfo.packageName, mSettingsActivity); + intent.putExtra(EXTRA_SERVICE_NAME, mService.serviceInfo.name); return intent; } return null; diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java index 698a861fc721..edfdd60defc6 100644 --- a/media/java/android/media/tv/TvInputManager.java +++ b/media/java/android/media/tv/TvInputManager.java @@ -67,6 +67,7 @@ public final class TvInputManager { /** * Interface used to receive the created session. + * @hide */ public abstract static class SessionCallback { /** @@ -390,6 +391,7 @@ public final class TvInputManager { * @param listener a listener used to monitor status of the given TV input. * @param handler a {@link Handler} that the status change will be delivered to. * @throws IllegalArgumentException if any of the arguments is {@code null}. + * @hide */ public void registerListener(String inputId, TvInputListener listener, Handler handler) { if (inputId == null) { @@ -422,6 +424,7 @@ public final class TvInputManager { * @param inputId the id of the TV input. * @param listener the existing listener to remove for the given TV input. * @throws IllegalArgumentException if any of the arguments is {@code null}. + * @hide */ public void unregisterListener(String inputId, final TvInputListener listener) { if (inputId == null) { @@ -465,6 +468,7 @@ public final class TvInputManager { * @param callback a callback used to receive the created session. * @param handler a {@link Handler} that the session creation will be delivered to. * @throws IllegalArgumentException if any of the arguments is {@code null}. + * @hide */ public void createSession(String inputId, final SessionCallback callback, Handler handler) { @@ -489,7 +493,10 @@ public final class TvInputManager { } } - /** The Session provides the per-session functionality of TV inputs. */ + /** + * The Session provides the per-session functionality of TV inputs. + * @hide + */ public static final class Session { static final int DISPATCH_IN_PROGRESS = -1; static final int DISPATCH_NOT_HANDLED = 0; @@ -562,13 +569,13 @@ public final class TvInputManager { } /** - * Sets the relative volume of this session to handle a change of audio focus. + * Sets the relative stream volume of this session to handle a change of audio focus. * * @param volume A volume value between 0.0f to 1.0f. * @throws IllegalArgumentException if the volume value is out of range. * @throws IllegalStateException if the session has been already released. */ - public void setVolume(float volume) { + public void setStreamVolume(float volume) { if (mToken == null) { throw new IllegalStateException("the session has been already released"); } diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java index 8ba0e2078a78..409a33c7a25b 100644 --- a/media/java/android/media/tv/TvInputService.java +++ b/media/java/android/media/tv/TvInputService.java @@ -22,8 +22,6 @@ import android.content.Context; import android.content.Intent; import android.graphics.PixelFormat; import android.graphics.Rect; -import android.media.tv.ITvInputService; -import android.media.tv.TvInputManager.Session; import android.net.Uri; import android.os.Bundle; import android.os.Handler; @@ -47,7 +45,17 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.SomeArgs; /** - * A base class for implementing television input service. + * The TvInputService class represents a TV input or source such as HDMI or built-in tuner which + * provides pass-through video or broadcast TV programs. + * <p> + * Applications will not normally use this service themselves, instead relying on the standard + * interaction provided by {@link TvView}. Those implementing TV input services should normally do + * so by deriving from this class and providing their own session implementation based on + * {@link TvInputService.Session}. All TV input services must require that clients hold the + * {@link android.Manifest.permission#BIND_TV_INPUT} in order to interact with the service; if this + * permission is not specified in the manifest, the system will refuse to bind to that TV input + * service. + * </p> */ public abstract class TvInputService extends Service { // STOPSHIP: Turn debugging off. @@ -74,7 +82,9 @@ public abstract class TvInputService extends Service { private final Handler mHandler = new ServiceHandler(); private final RemoteCallbackList<ITvInputServiceCallback> mCallbacks = new RemoteCallbackList<ITvInputServiceCallback>(); - private boolean mAvailable; + // STOPSHIP: Redesign the API around the availability change. For now, the service will be + // always available. + private final boolean mAvailable = true; @Override public void onCreate() { @@ -124,19 +134,6 @@ public abstract class TvInputService extends Service { } /** - * Convenience method to notify an availability change of this TV input service. - * - * @param available {@code true} if the input service is available to show TV programs. - */ - public final void setAvailable(boolean available) { - if (available != mAvailable) { - mAvailable = available; - mHandler.obtainMessage(ServiceHandler.DO_BROADCAST_AVAILABILITY_CHANGE, available) - .sendToTarget(); - } - } - - /** * Get the number of callbacks that are registered. * * @hide @@ -147,17 +144,17 @@ public abstract class TvInputService extends Service { } /** - * Returns a concrete implementation of {@link TvInputSessionImpl}. + * Returns a concrete implementation of {@link Session}. * <p> * May return {@code null} if this TV input service fails to create a session for some reason. * </p> */ - public abstract TvInputSessionImpl onCreateSession(); + public abstract Session onCreateSession(); /** - * Base class for derived classes to implement to provide {@link TvInputManager.Session}. + * Base class for derived classes to implement to provide a TV input session. */ - public abstract class TvInputSessionImpl implements KeyEvent.Callback { + public abstract class Session implements KeyEvent.Callback { private final KeyEvent.DispatcherState mDispatcherState = new KeyEvent.DispatcherState(); private final WindowManager mWindowManager; private WindowManager.LayoutParams mWindowParams; @@ -168,7 +165,7 @@ public abstract class TvInputService extends Service { private Rect mOverlayFrame; private ITvInputSessionCallback mSessionCallback; - public TvInputSessionImpl() { + public Session() { mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); } @@ -303,12 +300,12 @@ public abstract class TvInputService extends Service { public abstract boolean onSetSurface(Surface surface); /** - * Sets the relative volume of the current TV input session to handle the change of audio - * focus by setting. + * Sets the relative stream volume of the current TV input session to handle the change of + * audio focus by setting. * * @param volume Volume scale from 0.0 to 1.0. */ - public abstract void onSetVolume(float volume); + public abstract void onSetStreamVolume(float volume); /** * Tunes to a given channel. @@ -469,10 +466,10 @@ public abstract class TvInputService extends Service { } /** - * Calls {@link #onSetVolume}. + * Calls {@link #onSetStreamVolume}. */ void setVolume(float volume) { - onSetVolume(volume); + onSetStreamVolume(volume); } /** @@ -565,33 +562,33 @@ public abstract class TvInputService extends Service { if (DEBUG) Log.d(TAG, "dispatchInputEvent(" + event + ")"); if (event instanceof KeyEvent) { if (((KeyEvent) event).dispatch(this, mDispatcherState, this)) { - return Session.DISPATCH_HANDLED; + return TvInputManager.Session.DISPATCH_HANDLED; } } else if (event instanceof MotionEvent) { MotionEvent motionEvent = (MotionEvent) event; final int source = motionEvent.getSource(); if (motionEvent.isTouchEvent()) { if (onTouchEvent(motionEvent)) { - return Session.DISPATCH_HANDLED; + return TvInputManager.Session.DISPATCH_HANDLED; } } else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) { if (onTrackballEvent(motionEvent)) { - return Session.DISPATCH_HANDLED; + return TvInputManager.Session.DISPATCH_HANDLED; } } else { if (onGenericMotionEvent(motionEvent)) { - return Session.DISPATCH_HANDLED; + return TvInputManager.Session.DISPATCH_HANDLED; } } } if (mOverlayView == null || !mOverlayView.isAttachedToWindow()) { - return Session.DISPATCH_NOT_HANDLED; + return TvInputManager.Session.DISPATCH_NOT_HANDLED; } if (!mOverlayView.hasWindowFocus()) { mOverlayView.getViewRootImpl().windowFocusChanged(true, true); } mOverlayView.getViewRootImpl().dispatchInputEvent(event, receiver); - return Session.DISPATCH_IN_PROGRESS; + return TvInputManager.Session.DISPATCH_IN_PROGRESS; } private void setSessionCallback(ITvInputSessionCallback callback) { @@ -611,7 +608,7 @@ public abstract class TvInputService extends Service { InputChannel channel = (InputChannel) args.arg1; ITvInputSessionCallback cb = (ITvInputSessionCallback) args.arg2; try { - TvInputSessionImpl sessionImpl = onCreateSession(); + Session sessionImpl = onCreateSession(); if (sessionImpl == null) { // Failed to create a session. cb.onSessionCreated(null); diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java index d8b362d41328..c2459a64d44f 100644 --- a/media/java/android/media/tv/TvView.java +++ b/media/java/android/media/tv/TvView.java @@ -21,6 +21,7 @@ import android.graphics.Rect; import android.media.tv.TvInputManager.Session; import android.media.tv.TvInputManager.Session.FinishedInputEventCallback; import android.media.tv.TvInputManager.SessionCallback; +import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.text.TextUtils; @@ -38,9 +39,21 @@ import android.view.ViewRootImpl; * View playing TV */ public class TvView extends SurfaceView { + private static final String TAG = "TvView"; // STOPSHIP: Turn debugging off. private static final boolean DEBUG = true; - private static final String TAG = "TvView"; + + /** + * Passed with {@link TvInputListener#onError(String, int)}. Indicates that the requested TV + * input is busy and unable to handle the request. + */ + public static final int ERROR_BUSY = 0; + + /** + * Passed with {@link TvInputListener#onError(String, int)}. Indicates that the underlying TV + * input has been disconnected. + */ + public static final int ERROR_TV_INPUT_DISCONNECTED = 1; private final Handler mHandler = new Handler(); private TvInputManager.Session mSession; @@ -48,7 +61,8 @@ public class TvView extends SurfaceView { private boolean mOverlayViewCreated; private Rect mOverlayViewFrame; private final TvInputManager mTvInputManager; - private SessionCallback mSessionCallback; + private MySessionCallback mSessionCallback; + private TvInputListener mListener; private OnUnhandledInputEventListener mOnUnhandledInputEventListener; private final SurfaceHolder.Callback mSurfaceHolderCallback = new SurfaceHolder.Callback() { @@ -113,44 +127,70 @@ public class TvView extends SurfaceView { } /** - * Binds a TV input to this view. {@link SessionCallback#onSessionCreated} will be - * called to send the result of this binding with {@link TvInputManager.Session}. - * If a TV input is already bound, the input will be unbound from this view and its session - * will be released. + * Sets a listener for events in this TvView. * - * @param inputId the id of TV input which will be bound to this view. - * @param callback called when TV input is bound. The callback sends - * {@link TvInputManager.Session} - * @throws IllegalArgumentException if any of the arguments is {@code null}. + * @param listener The listener to be called with events. A value of {@code null} removes any + * existing listener. */ - public void bindTvInput(String inputId, SessionCallback callback) { + public void setTvInputListener(TvInputListener listener) { + mListener = listener; + } + + /** + * Sets the relative stream volume of this session to handle a change of audio focus. + * + * @param volume A volume value between 0.0f to 1.0f. + */ + public void setStreamVolume(float volume) { + if (DEBUG) Log.d(TAG, "setStreamVolume(" + volume + ")"); + if (mSession == null) { + return; + } + mSession.setStreamVolume(volume); + } + + /** + * Tunes to a given channel. + * + * @param inputId the id of TV input which will play the given channel. + * @param channelUri The URI of a channel. + */ + public void tune(String inputId, Uri channelUri) { + if (DEBUG) Log.d(TAG, "tune(" + channelUri + ")"); if (TextUtils.isEmpty(inputId)) { throw new IllegalArgumentException("inputId cannot be null or an empty string"); } - if (callback == null) { - throw new IllegalArgumentException("callback cannot be null"); - } - if (mSession != null) { - release(); + if (mSessionCallback != null && mSessionCallback.mInputId.equals(inputId)) { + if (mSession != null) { + mSession.tune(channelUri); + } else { + // Session is not created yet. Replace the channel which will be set once the + // session is made. + mSessionCallback.mChannelUri = channelUri; + } + } else { + if (mSession != null) { + release(); + } + // When createSession() is called multiple times before the callback is called, + // only the callback of the last createSession() call will be actually called back. + // The previous callbacks will be ignored. For the logic, mSessionCallback + // is newly assigned for every createSession request and compared with + // MySessionCreateCallback.this. + mSessionCallback = new MySessionCallback(inputId, channelUri); + mTvInputManager.createSession(inputId, mSessionCallback, mHandler); } - // When bindTvInput is called multiple times before the callback is called, - // only the callback of the last bindTvInput call will be actually called back. - // The previous callbacks will be ignored. For the logic, mSessionCallback - // is newly assigned for every bindTvInput call and compared with - // MySessionCreateCallback.this. - mSessionCallback = new MySessionCallback(callback); - mTvInputManager.createSession(inputId, mSessionCallback, mHandler); } /** - * Unbinds a TV input currently bound. Its corresponding {@link TvInputManager.Session} - * is released. + * Resets this TvView. + * <p> + * This method is primarily used to un-tune the current TvView. */ - public void unbindTvInput() { + public void reset() { if (mSession != null) { release(); } - mSessionCallback = null; } /** @@ -277,6 +317,7 @@ public class TvView extends SurfaceView { removeSessionOverlayView(); mSession.release(); mSession = null; + mSessionCallback = null; } private void setSessionSurface(Surface surface) { @@ -326,6 +367,71 @@ public class TvView extends SurfaceView { } /** + * Interface used to receive various status updates on the {@link TvView}. + */ + public abstract static class TvInputListener { + + /** + * This is invoked when an error occurred while handling requested operation. + * + * @param inputId The ID of the TV input bound to this view. + * @param errorCode The error code. For the details of error code, please see + * {@link TvView}. + */ + public void onError(String inputId, int errorCode) { + } + + /** + * This is invoked when the view is tuned to a specific channel and starts decoding video + * stream from there. It is also called later when the video format is changed. + * + * @param inputId The ID of the TV input bound to this view. + * @param width The width of the video. + * @param height The height of the video. + * @param interlaced {@code true} if the video is interlaced, {@code false} if the video is + * progressive. + * @hide + */ + public void onVideoStreamChanged(String inputId, int width, int height, + boolean interlaced) { + } + + /** + * This is invoked when the view is tuned to a specific channel and starts decoding audio + * stream from there. It is also called later when the audio format is changed. + * + * @param inputId The ID of the TV input bound to this view. + * @param channelCount The number of channels in the audio stream. + * @hide + */ + public void onAudioStreamChanged(String inputId, int channelCount) { + } + + /** + * This is invoked when the view is tuned to a specific channel and starts decoding data + * stream that includes subtitle information from the channel. It is also called later when + * the information disappears or appears. + * + * @param inputId The ID of the TV input bound to this view. + * @param hasClosedCaption {@code true} if the stream contains closed caption, {@code false} + * otherwise. + * @hide + */ + public void onClosedCaptionStreamChanged(String inputId, boolean hasClosedCaption) { + } + + /** + * This is invoked when a custom event from the bound TV input is sent to this view. + * + * @param eventType The type of the event. + * @param eventArgs Optional arguments of the event. + * @hide + */ + public void onEvent(String inputId, String eventType, Bundle eventArgs) { + } + } + + /** * Interface definition for a callback to be invoked when the unhandled input event is received. */ public interface OnUnhandledInputEventListener { @@ -343,10 +449,12 @@ public class TvView extends SurfaceView { } private class MySessionCallback extends SessionCallback { - final SessionCallback mExternalCallback; + final String mInputId; + Uri mChannelUri; - MySessionCallback(SessionCallback externalCallback) { - mExternalCallback = externalCallback; + MySessionCallback(String inputId, Uri channelUri) { + mInputId = inputId; + mChannelUri = channelUri; } @Override @@ -367,17 +475,20 @@ public class TvView extends SurfaceView { setSessionSurface(mSurface); } createSessionOverlayView(); - } - if (mExternalCallback != null) { - mExternalCallback.onSessionCreated(session); + mSession.tune(mChannelUri); + } else { + if (mListener != null) { + mListener.onError(mInputId, ERROR_BUSY); + } } } @Override public void onSessionReleased(Session session) { mSession = null; - if (mExternalCallback != null) { - mExternalCallback.onSessionReleased(session); + mSessionCallback = null; + if (mListener != null) { + mListener.onError(mInputId, ERROR_TV_INPUT_DISCONNECTED); } } @@ -387,8 +498,8 @@ public class TvView extends SurfaceView { if (DEBUG) { Log.d(TAG, "onVideoSizeChanged(" + width + ", " + height + ")"); } - if (mExternalCallback != null) { - mExternalCallback.onVideoStreamChanged(session, width, height, interlaced); + if (mListener != null) { + mListener.onVideoStreamChanged(mInputId, width, height, interlaced); } } @@ -397,8 +508,8 @@ public class TvView extends SurfaceView { if (DEBUG) { Log.d(TAG, "onAudioStreamChanged(" + channelCount + ")"); } - if (mExternalCallback != null) { - mExternalCallback.onAudioStreamChanged(session, channelCount); + if (mListener != null) { + mListener.onAudioStreamChanged(mInputId, channelCount); } } @@ -407,16 +518,16 @@ public class TvView extends SurfaceView { if (DEBUG) { Log.d(TAG, "onClosedCaptionStreamChanged(" + hasClosedCaption + ")"); } - if (mExternalCallback != null) { - mExternalCallback.onClosedCaptionStreamChanged(session, hasClosedCaption); + if (mListener != null) { + mListener.onClosedCaptionStreamChanged(mInputId, hasClosedCaption); } } @Override public void onSessionEvent(TvInputManager.Session session, String eventType, Bundle eventArgs) { - if (mExternalCallback != null) { - mExternalCallback.onSessionEvent(session, eventType, eventArgs); + if (mListener != null) { + mListener.onEvent(mInputId, eventType, eventArgs); } } } diff --git a/native/android/sensor.cpp b/native/android/sensor.cpp index acfcd836bbb8..3f37ed15435a 100644 --- a/native/android/sensor.cpp +++ b/native/android/sensor.cpp @@ -171,8 +171,3 @@ const char* ASensor_getStringType(ASensor const* sensor) { return static_cast<Sensor const*>(sensor)->getStringType().string(); } - -const char* ASensor_getRequiredPermission(ASensor const* sensor) -{ - return static_cast<Sensor const*>(sensor)->getRequiredPermission().string(); -} diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth.png Binary files differdeleted file mode 100644 index 7ed4c78de97c..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth_connected.png Binary files differdeleted file mode 100644 index 08c07b2bf5b1..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth_connected.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth.png Binary files differdeleted file mode 100644 index bd4e1ae0dfad..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth_connected.png Binary files differdeleted file mode 100644 index e82c6e43babc..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth_connected.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth.png Binary files differdeleted file mode 100644 index 757dbf3be7c5..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth_connected.png Binary files differdeleted file mode 100644 index d431dc2779aa..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth_connected.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_bluetooth.png Binary files differdeleted file mode 100644 index 17ffdb9a4128..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_bluetooth.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_bluetooth_connected.png Binary files differdeleted file mode 100644 index 6ec234eb8a0f..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_bluetooth_connected.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable/stat_sys_data_bluetooth.xml b/packages/SystemUI/res/drawable/stat_sys_data_bluetooth.xml new file mode 100644 index 000000000000..e28490bfb890 --- /dev/null +++ b/packages/SystemUI/res/drawable/stat_sys_data_bluetooth.xml @@ -0,0 +1,28 @@ +<!-- +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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > + <size + android:width="18dp" + android:height="18dp"/> + + <viewport + android:viewportWidth="48.0" + android:viewportHeight="48.0"/> + + <path + android:fill="#FFFFFFFF" + android:pathData="M35.4,15.4L24.0,4.0l-2.0,0.0l0.0,15.2L12.8,10.0L10.0,12.8L21.2,24.0L10.0,35.2l2.8,2.8l9.2,-9.2L22.0,44.0l2.0,0.0l11.4,-11.4L26.8,24.0L35.4,15.4zM26.0,11.7l3.8,3.8L26.0,19.2L26.0,11.7zM29.8,32.6L26.0,36.3l0.0,-7.5L29.8,32.6z"/> +</vector> diff --git a/packages/SystemUI/res/drawable/stat_sys_data_bluetooth_connected.xml b/packages/SystemUI/res/drawable/stat_sys_data_bluetooth_connected.xml new file mode 100644 index 000000000000..c012d14a7fba --- /dev/null +++ b/packages/SystemUI/res/drawable/stat_sys_data_bluetooth_connected.xml @@ -0,0 +1,28 @@ +<!-- +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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > + <size + android:width="18dp" + android:height="18dp"/> + + <viewport + android:viewportWidth="48.0" + android:viewportHeight="48.0"/> + + <path + android:fill="#FFFFFFFF" + android:pathData="M14.0,24.0l-4.0,-4.0l-4.0,4.0l4.0,4.0L14.0,24.0zM35.4,15.4L24.0,4.0l-2.0,0.0l0.0,15.2L12.8,10.0L10.0,12.8L21.2,24.0L10.0,35.2l2.8,2.8l9.2,-9.2L22.0,44.0l2.0,0.0l11.4,-11.4L26.8,24.0L35.4,15.4zM26.0,11.7l3.8,3.8L26.0,19.2L26.0,11.7zM29.8,32.6L26.0,36.3l0.0,-7.5L29.8,32.6zM38.0,20.0l-4.0,4.0l4.0,4.0l4.0,-4.0L38.0,20.0z"/> +</vector> diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java index 20ed62992d05..7431e6941e51 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java @@ -84,7 +84,7 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> { } else if (connecting) { state.iconId = R.drawable.ic_qs_bluetooth_connecting; stateContentDescription = mContext.getString(R.string.accessibility_desc_connecting); - state.label = mController.getLastDeviceName(); + state.label = mContext.getString(R.string.quick_settings_bluetooth_label); } else { state.iconId = R.drawable.ic_qs_bluetooth_on; stateContentDescription = mContext.getString(R.string.accessibility_desc_on); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index 06cc476d0295..d1484e130bda 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -992,7 +992,10 @@ public abstract class BaseStatusBar extends SystemUI implements title.setText(entry.notification.getPackageName()); } - final ImageView icon = (ImageView) publicViewLocal.findViewById(com.android.internal.R.id.icon); + final ImageView icon = (ImageView) publicViewLocal.findViewById( + com.android.internal.R.id.icon); + final ImageView profileIcon = (ImageView) publicViewLocal.findViewById( + com.android.internal.R.id.profile_icon); final StatusBarIcon ic = new StatusBarIcon(entry.notification.getPackageName(), entry.notification.getUser(), @@ -1008,7 +1011,19 @@ public abstract class BaseStatusBar extends SystemUI implements com.android.internal.R.drawable.notification_icon_legacy_bg_inset); } - final TextView text = (TextView) publicViewLocal.findViewById(com.android.internal.R.id.text); + if (profileIcon != null) { + Drawable profileDrawable + = mUserManager.getBadgeForUser(entry.notification.getUser()); + if (profileDrawable != null) { + profileIcon.setImageDrawable(profileDrawable); + profileIcon.setVisibility(View.VISIBLE); + } else { + profileIcon.setVisibility(View.GONE); + } + } + + final TextView text = (TextView) publicViewLocal.findViewById( + com.android.internal.R.id.text); text.setText("Unlock your device to see this notification."); // TODO: fill out "time" as well diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 227304c2e30b..ac9866cadfaa 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -87,6 +87,8 @@ import android.view.animation.AccelerateInterpolator; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.view.animation.DecelerateInterpolator; +import android.view.animation.Interpolator; +import android.view.animation.PathInterpolator; import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.TextView; @@ -400,6 +402,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, private boolean mSettingsClosing; private boolean mVisible; + private Interpolator mAlphaOut = new PathInterpolator(0f, 0.4f, 1f, 1f); + private Interpolator mAlphaIn = new PathInterpolator(0f, 0f, 0.8f, 1f); + private final OnChildLocationsChangedListener mOnChildLocationsChangedListener = new OnChildLocationsChangedListener() { @Override @@ -408,6 +413,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } }; + private int mDisabledUnmodified; + public void setOnFlipRunnable(Runnable onFlipRunnable) { mOnFlipRunnable = onFlipRunnable; } @@ -677,10 +684,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mDateTimeView.setEnabled(true); } - mNotificationPanel.setSystemUiVisibility( - View.STATUS_BAR_DISABLE_NOTIFICATION_ICONS | - View.STATUS_BAR_DISABLE_CLOCK); - mTicker = new MyTicker(context, mStatusBarView); TickerView tickerView = (TickerView)mStatusBarView.findViewById(R.id.tickerText); @@ -1187,7 +1190,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, Entry ent = mNotificationData.get(i); if (!(provisioned || showNotificationEvenIfUnprovisioned(ent.notification))) continue; - // TODO How do we want to badge notifcations from profiles. if (!notificationIsForCurrentProfiles(ent.notification)) continue; final int vis = ent.notification.getNotification().visibility; @@ -1416,10 +1418,20 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } } + private int adjustDisableFlags(int state) { + if (mExpandedVisible) { + state |= StatusBarManager.DISABLE_NOTIFICATION_ICONS; + state |= StatusBarManager.DISABLE_SYSTEM_INFO; + } + return state; + } + /** * State is one or more of the DISABLE constants from StatusBarManager. */ public void disable(int state) { + mDisabledUnmodified = state; + state = adjustDisableFlags(state); final int old = mDisabled; final int diff = state ^ old; mDisabled = state; @@ -1457,20 +1469,17 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if ((state & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) { mSystemIconArea.animate() .alpha(0f) - .translationY(mNaturalBarHeight*0.5f) - .setDuration(175) - .setInterpolator(new DecelerateInterpolator(1.5f)) - .setListener(mMakeIconsInvisible) - .start(); + .withLayer() + .setDuration(160) + .setInterpolator(mAlphaIn) + .setListener(mMakeIconsInvisible); } else { mSystemIconArea.setVisibility(View.VISIBLE); mSystemIconArea.animate() .alpha(1f) - .translationY(0) - .setStartDelay(0) - .setInterpolator(new DecelerateInterpolator(1.5f)) - .setDuration(175) - .start(); + .withLayer() + .setInterpolator(mAlphaOut) + .setDuration(320); } } @@ -1506,20 +1515,18 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mNotificationIcons.animate() .alpha(0f) - .translationY(mNaturalBarHeight*0.5f) - .setDuration(175) - .setInterpolator(new DecelerateInterpolator(1.5f)) + .withLayer() + .setDuration(160) + .setInterpolator(mAlphaIn) .setListener(mMakeIconsInvisible) .start(); } else { mNotificationIcons.setVisibility(View.VISIBLE); mNotificationIcons.animate() .alpha(1f) - .translationY(0) - .setStartDelay(0) - .setInterpolator(new DecelerateInterpolator(1.5f)) - .setDuration(175) - .start(); + .withLayer() + .setInterpolator(mAlphaOut) + .setDuration(320); } } } @@ -1619,7 +1626,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mStatusBarWindowManager.setStatusBarExpanded(true); visibilityChanged(true); - + disable(mDisabledUnmodified); setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true); } @@ -1770,10 +1777,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mStatusBarView.collapseAllPanels(true); } - void makeExpandedInvisibleSoon() { - mHandler.postDelayed(new Runnable() { public void run() { makeExpandedInvisible(); }}, 50); - } - void makeExpandedInvisible() { if (SPEW) Log.d(TAG, "makeExpandedInvisible: mExpandedVisible=" + mExpandedVisible + " mExpandedVisible=" + mExpandedVisible); @@ -1817,7 +1820,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false); - + disable(mDisabledUnmodified); showBouncer(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java index 910d88ca5707..3a17177720d5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java @@ -111,8 +111,7 @@ public class PhoneStatusBarView extends PanelBar { @Override public void onAllPanelsCollapsed() { super.onAllPanelsCollapsed(); - // give animations time to settle - mBar.makeExpandedInvisibleSoon(); + mBar.makeExpandedInvisible(); mLastFullyOpenedPanel = null; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java index 117bf61ccf57..379b509d1083 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java @@ -45,6 +45,7 @@ public class BluetoothControllerImpl extends BroadcastReceiver implements Blueto filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); + filter.addAction(BluetoothDevice.ACTION_ALIAS_CHANGED); context.registerReceiver(this, filter); final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); @@ -104,8 +105,8 @@ public class BluetoothControllerImpl extends BroadcastReceiver implements Blueto @Override public String getLastDeviceName() { - return mLastDevice != null ? mLastDevice.getName() - : mBondedDevices.size() == 1 ? mBondedDevices.iterator().next().getName() + return mLastDevice != null ? mLastDevice.getAliasName() + : mBondedDevices.size() == 1 ? mBondedDevices.iterator().next().getAliasName() : null; } @@ -122,6 +123,9 @@ public class BluetoothControllerImpl extends BroadcastReceiver implements Blueto == BluetoothAdapter.STATE_CONNECTING; mLastDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); } + if (action.equals(BluetoothDevice.ACTION_ALIAS_CHANGED)) { + mLastDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); + } fireCallbacks(); updateBondedBluetoothDevices(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java index 4d862139b5e3..20caed8cc850 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -264,6 +264,13 @@ public class NotificationStackScrollLayout extends ViewGroup : mPaddingBetweenElementsNormal; mBottomStackSlowDownHeight = mStackScrollAlgorithm.getBottomStackSlowDownLength(); updateContentHeight(); + notifyHeightChangeListener(null); + } + + private void notifyHeightChangeListener(ExpandableView view) { + if (mOnHeightChangedListener != null) { + mOnHeightChangedListener.onHeightChanged(view); + } } @Override @@ -402,9 +409,7 @@ public class NotificationStackScrollLayout extends ViewGroup mNeedsAnimation = true; } requestChildrenUpdate(); - if (mOnHeightChangedListener != null) { - mOnHeightChangedListener.onHeightChanged(null); - } + notifyHeightChangeListener(null); } } @@ -1725,9 +1730,7 @@ public class NotificationStackScrollLayout extends ViewGroup public void onHeightChanged(ExpandableView view) { updateContentHeight(); updateScrollPositionIfNecessary(); - if (mOnHeightChangedListener != null) { - mOnHeightChangedListener.onHeightChanged(view); - } + notifyHeightChangeListener(view); requestChildrenUpdate(); } diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java index 80a14b3511f3..1cab7ea426bf 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java @@ -333,6 +333,7 @@ public class VolumePanel extends Handler { public void onDismiss(DialogInterface dialog) { mActiveStreamType = -1; mAudioManager.forceVolumeControlStream(mActiveStreamType); + collapse(); } }); @@ -651,12 +652,8 @@ public class VolumePanel extends Handler { mExpandDivider.setVisibility(show ? View.VISIBLE : View.GONE); mExpandButton.setImageResource(zen ? com.android.systemui.R.drawable.ic_vol_zen_on : com.android.systemui.R.drawable.ic_vol_zen_off); - if (show) { - if (zen) { - expand(); - } else { - collapse(); - } + if (show && !zen) { + collapse(); } } else { mExpandButton.setVisibility(View.GONE); diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java index 1000352f6933..798e7fa43228 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java +++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java @@ -323,10 +323,6 @@ public class ZenModePanel extends LinearLayout { button1.setVisibility(View.GONE); button2.setVisibility(View.GONE); } - if (mExitConditionId != null && mExitConditionId.equals(tag.conditionId)) { - if (DEBUG) Log.d(mTag, "Auto-selecting row with mExitConditionId=" + mExitConditionId); - tag.rb.setChecked(true); - } } private void onClickTimeButton(View row, ConditionTag tag, boolean up) { diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java index cb5946afacaa..fe5c2ef3ad06 100644 --- a/services/core/java/com/android/server/BatteryService.java +++ b/services/core/java/com/android/server/BatteryService.java @@ -128,6 +128,8 @@ public final class BatteryService extends Binder { private int mPlugType; private int mLastPlugType = -1; // Extra state so we can detect first run + private boolean mBatteryLevelLow; + private long mDischargeStartTime; private int mDischargeStartLevel; @@ -222,14 +224,30 @@ public final class BatteryService extends Binder { } /** - * Returns true if battery level is below the first warning threshold. + * Returns whether we currently consider the battery level to be low. */ - public boolean isBatteryLow() { + public boolean getBatteryLevelLow() { synchronized (mLock) { - return mBatteryProps.batteryPresent && mBatteryProps.batteryLevel <= mLowBatteryWarningLevel; + return mBatteryLevelLow; } } + public boolean isBatteryLowLocked() { + final boolean plugged = mPlugType != BATTERY_PLUGGED_NONE; + final boolean oldPlugged = mLastPlugType != BATTERY_PLUGGED_NONE; + + /* The ACTION_BATTERY_LOW broadcast is sent in these situations: + * - is just un-plugged (previously was plugged) and battery level is + * less than or equal to WARNING, or + * - is not plugged and battery level falls to WARNING boundary + * (becomes <= mLowBatteryWarningLevel). + */ + return !plugged + && mBatteryProps.batteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN + && mBatteryProps.batteryLevel <= mLowBatteryWarningLevel + && (oldPlugged || mLastBatteryLevel > mLowBatteryWarningLevel); + } + /** * Returns a non-zero value if an unsupported charger is attached. */ @@ -382,19 +400,7 @@ public final class BatteryService extends Binder { logOutlier = true; } - final boolean plugged = mPlugType != BATTERY_PLUGGED_NONE; - final boolean oldPlugged = mLastPlugType != BATTERY_PLUGGED_NONE; - - /* The ACTION_BATTERY_LOW broadcast is sent in these situations: - * - is just un-plugged (previously was plugged) and battery level is - * less than or equal to WARNING, or - * - is not plugged and battery level falls to WARNING boundary - * (becomes <= mLowBatteryWarningLevel). - */ - final boolean sendBatteryLow = !plugged - && mBatteryProps.batteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN - && mBatteryProps.batteryLevel <= mLowBatteryWarningLevel - && (oldPlugged || mLastBatteryLevel > mLowBatteryWarningLevel); + mBatteryLevelLow = isBatteryLowLocked(); sendIntentLocked(); @@ -422,7 +428,7 @@ public final class BatteryService extends Binder { }); } - if (sendBatteryLow) { + if (mBatteryLevelLow) { mSentLowBatteryBroadcast = true; mHandler.post(new Runnable() { @Override diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java index 06dd3edb3015..fdaf55e4f9a4 100644 --- a/services/core/java/com/android/server/VibratorService.java +++ b/services/core/java/com/android/server/VibratorService.java @@ -28,6 +28,7 @@ import android.os.BatteryStats; import android.os.Handler; import android.os.IVibratorService; import android.os.PowerManager; +import android.os.PowerManagerInternal; import android.os.Process; import android.os.RemoteException; import android.os.IBinder; @@ -64,6 +65,7 @@ public class VibratorService extends IVibratorService.Stub private final PowerManager.WakeLock mWakeLock; private final IAppOpsService mAppOpsService; private final IBatteryStats mBatteryStatsService; + private PowerManagerInternal mPowerManagerInternal; private InputManager mIm; volatile VibrateThread mThread; @@ -169,14 +171,19 @@ public class VibratorService extends IVibratorService.Stub mIm = (InputManager)mContext.getSystemService(Context.INPUT_SERVICE); mSettingObserver = new SettingsObserver(mH); + mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); + mPowerManagerInternal.registerLowPowerModeObserver( + new PowerManagerInternal.LowPowerModeListener() { + @Override + public void onLowPowerModeChanged(boolean enabled) { + updateInputDeviceVibrators(); + } + }); + mContext.getContentResolver().registerContentObserver( Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES), true, mSettingObserver, UserHandle.USER_ALL); - mContext.getContentResolver().registerContentObserver( - Settings.Global.getUriFor(Settings.Global.LOW_POWER_MODE), false, - mSettingObserver, UserHandle.USER_ALL); - mContext.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -448,8 +455,7 @@ public class VibratorService extends IVibratorService.Stub } catch (SettingNotFoundException snfe) { } - mLowPowerMode = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.LOW_POWER_MODE, 0) != 0; + mLowPowerMode = mPowerManagerInternal.getLowPowerModeEnabled(); if (mVibrateInputDevicesSetting) { if (!mInputDeviceListenerRegistered) { diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index aca17bff6a96..d8671d9535e7 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -406,6 +406,12 @@ public final class PowerManagerService extends com.android.server.SystemService // If true, the device is in low power mode. private boolean mLowPowerModeEnabled; + // Current state of the low power mode setting. + private boolean mLowPowerModeSetting; + + // True if the battery level is currently considered low. + private boolean mBatteryLevelLow; + private final ArrayList<PowerManagerInternal.LowPowerModeListener> mLowPowerModeListeners = new ArrayList<PowerManagerInternal.LowPowerModeListener>(); @@ -502,6 +508,7 @@ public final class PowerManagerService extends com.android.server.SystemService // Register for broadcasts from other components of the system. IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_BATTERY_CHANGED); + filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); mContext.registerReceiver(new BatteryReceiver(), filter, null, mHandler); filter = new IntentFilter(); @@ -638,7 +645,18 @@ public final class PowerManagerService extends com.android.server.SystemService final boolean lowPowerModeEnabled = Settings.Global.getInt(resolver, Settings.Global.LOW_POWER_MODE, 0) != 0; - if (lowPowerModeEnabled != mLowPowerModeEnabled) { + if (lowPowerModeEnabled != mLowPowerModeSetting) { + mLowPowerModeSetting = lowPowerModeEnabled; + updateLowPowerModeLocked(); + } + + mDirty |= DIRTY_SETTINGS; + } + + void updateLowPowerModeLocked() { + final boolean lowPowerModeEnabled = mLowPowerModeSetting || mBatteryLevelLow; + if (mLowPowerModeEnabled != lowPowerModeEnabled) { + mLowPowerModeEnabled = lowPowerModeEnabled; powerHintInternal(POWER_HINT_LOW_POWER_MODE, lowPowerModeEnabled ? 1 : 0); mLowPowerModeEnabled = lowPowerModeEnabled; BackgroundThread.getHandler().post(new Runnable() { @@ -652,11 +670,12 @@ public final class PowerManagerService extends com.android.server.SystemService for (int i=0; i<listeners.size(); i++) { listeners.get(i).onLowPowerModeChanged(lowPowerModeEnabled); } + Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); + mContext.sendBroadcast(intent); } }); } - - mDirty |= DIRTY_SETTINGS; } private void handleSettingsChangedLocked() { @@ -1137,9 +1156,11 @@ public final class PowerManagerService extends com.android.server.SystemService if ((dirty & DIRTY_BATTERY_STATE) != 0) { final boolean wasPowered = mIsPowered; final int oldPlugType = mPlugType; + final boolean oldLevelLow = mBatteryLevelLow; mIsPowered = mBatteryService.isPowered(BatteryManager.BATTERY_PLUGGED_ANY); mPlugType = mBatteryService.getPlugType(); mBatteryLevel = mBatteryService.getBatteryLevel(); + mBatteryLevelLow = mBatteryService.getBatteryLevelLow(); if (DEBUG_SPEW) { Slog.d(TAG, "updateIsPoweredLocked: wasPowered=" + wasPowered @@ -1175,6 +1196,10 @@ public final class PowerManagerService extends com.android.server.SystemService mNotifier.onWirelessChargingStarted(); } } + + if (oldLevelLow != mBatteryLevelLow) { + updateLowPowerModeLocked(); + } } } @@ -1896,6 +1921,12 @@ public final class PowerManagerService extends com.android.server.SystemService } } + private boolean isLowPowerModeInternal() { + synchronized (mLock) { + return mLowPowerModeEnabled; + } + } + private void handleBatteryStateChangedLocked() { mDirty |= DIRTY_BATTERY_STATE; updatePowerStateLocked(); @@ -2764,6 +2795,16 @@ public final class PowerManagerService extends com.android.server.SystemService } } + @Override // Binder call + public boolean isPowerSaveMode() { + final long ident = Binder.clearCallingIdentity(); + try { + return isLowPowerModeInternal(); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + /** * Reboots the device. * diff --git a/services/core/java/com/android/server/task/controllers/BatteryController.java b/services/core/java/com/android/server/task/controllers/BatteryController.java index 585b41fce23b..4727e9a6b831 100644 --- a/services/core/java/com/android/server/task/controllers/BatteryController.java +++ b/services/core/java/com/android/server/task/controllers/BatteryController.java @@ -151,7 +151,7 @@ public class BatteryController extends StateController { // Initialise tracker state. BatteryService batteryService = (BatteryService) ServiceManager.getService("battery"); if (batteryService != null) { - mBatteryHealthy = !batteryService.isBatteryLow(); + mBatteryHealthy = !batteryService.getBatteryLevelLow(); mCharging = batteryService.isPowered(BatteryManager.BATTERY_PLUGGED_ANY); } else { // Unavailable for some reason, we default to false and let ACTION_BATTERY_[OK,LOW] diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java index 35b7f99d8813..cfd09e5c8e17 100644 --- a/services/core/java/com/android/server/wm/AccessibilityController.java +++ b/services/core/java/com/android/server/wm/AccessibilityController.java @@ -541,7 +541,7 @@ final class AccessibilityController { if (isMagnifyingLocked()) { setMagnifiedRegionBorderShownLocked(false, false); final long delay = (long) (mLongAnimationDuration - * mWindowManagerService.mWindowAnimationScale); + * mWindowManagerService.getWindowAnimationScaleLocked()); Message message = mHandler.obtainMessage( MyHandler.MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED); mHandler.sendMessageDelayed(message, delay); diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java index 7fe895b57a90..63ae98e444a5 100644 --- a/services/core/java/com/android/server/wm/AppWindowAnimator.java +++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java @@ -87,7 +87,7 @@ public class AppWindowAnimator { anim.initialize(width, height, width, height); } anim.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION); - anim.scaleCurrentDuration(mService.mTransitionAnimationScale); + anim.scaleCurrentDuration(mService.getTransitionAnimationScaleLocked()); int zorder = anim.getZAdjustment(); int adj = 0; if (zorder == Animation.ZORDER_TOP) { @@ -227,7 +227,8 @@ public class AppWindowAnimator { if (!animating) { if (WindowManagerService.DEBUG_ANIM) Slog.v( TAG, "Starting animation in " + mAppToken + - " @ " + currentTime + " scale=" + mService.mTransitionAnimationScale + " @ " + currentTime + " scale=" + + mService.getTransitionAnimationScaleLocked() + " allDrawn=" + mAppToken.allDrawn + " animating=" + animating); animation.setStartTime(currentTime); animating = true; diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index ca9076f51496..3200b54f5c5d 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -17,6 +17,7 @@ package com.android.server.wm; import android.view.IWindowId; +import android.view.IWindowSessionCallback; import com.android.internal.view.IInputContext; import com.android.internal.view.IInputMethodClient; import com.android.internal.view.IInputMethodManager; @@ -54,6 +55,7 @@ import java.io.PrintWriter; final class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { final WindowManagerService mService; + final IWindowSessionCallback mCallback; final IInputMethodClient mClient; final IInputContext mInputContext; final int mUid; @@ -62,14 +64,17 @@ final class Session extends IWindowSession.Stub SurfaceSession mSurfaceSession; int mNumWindow = 0; boolean mClientDead = false; + float mLastReportedAnimatorScale; - public Session(WindowManagerService service, IInputMethodClient client, - IInputContext inputContext) { + public Session(WindowManagerService service, IWindowSessionCallback callback, + IInputMethodClient client, IInputContext inputContext) { mService = service; + mCallback = callback; mClient = client; mInputContext = inputContext; mUid = Binder.getCallingUid(); mPid = Binder.getCallingPid(); + mLastReportedAnimatorScale = service.getCurrentAnimatorScale(); StringBuilder sb = new StringBuilder(); sb.append("Session{"); sb.append(Integer.toHexString(System.identityHashCode(this))); @@ -464,6 +469,9 @@ final class Session extends IWindowSession.Stub if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i( WindowManagerService.TAG, " NEW SURFACE SESSION " + mSurfaceSession); mService.mSessions.add(this); + if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) { + mService.dispatchNewAnimatorScaleLocked(this); + } } mNumWindow++; } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index da584d8ef59a..1db8b55196b6 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -24,6 +24,7 @@ import android.util.ArraySet; import android.util.TimeUtils; import android.view.IWindowId; +import android.view.IWindowSessionCallback; import android.view.WindowContentFrameStats; import com.android.internal.app.IBatteryStats; import com.android.internal.policy.PolicyManager; @@ -339,7 +340,7 @@ public class WindowManagerService extends IWindowManager.Stub /** * All currently active sessions with clients. */ - final HashSet<Session> mSessions = new HashSet<Session>(); + final ArraySet<Session> mSessions = new ArraySet<Session>(); /** * Mapping from an IWindow IBinder to the server's Window object. @@ -562,9 +563,10 @@ public class WindowManagerService extends IWindowManager.Stub PowerManager mPowerManager; PowerManagerInternal mPowerManagerInternal; - float mWindowAnimationScale = 1.0f; - float mTransitionAnimationScale = 1.0f; - float mAnimatorDurationScale = 1.0f; + float mWindowAnimationScaleSetting = 1.0f; + float mTransitionAnimationScaleSetting = 1.0f; + float mAnimatorDurationScaleSetting = 1.0f; + boolean mAnimationsDisabled = false; final InputManagerService mInputManager; final DisplayManagerInternal mDisplayManagerInternal; @@ -780,6 +782,19 @@ public class WindowManagerService extends IWindowManager.Stub mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); mPowerManagerInternal.setPolicy(mPolicy); // TODO: register as local service instead + mPowerManagerInternal.registerLowPowerModeObserver( + new PowerManagerInternal.LowPowerModeListener() { + @Override + public void onLowPowerModeChanged(boolean enabled) { + synchronized (mWindowMap) { + if (mAnimationsDisabled != enabled) { + mAnimationsDisabled = enabled; + dispatchNewAnimatorScaleLocked(null); + } + } + } + }); + mAnimationsDisabled = mPowerManagerInternal.getLowPowerModeEnabled(); mScreenFrozenLock = mPowerManager.newWakeLock( PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN"); mScreenFrozenLock.setReferenceCounted(false); @@ -799,12 +814,12 @@ public class WindowManagerService extends IWindowManager.Stub ); // Get persisted window scale setting - mWindowAnimationScale = Settings.Global.getFloat(context.getContentResolver(), - Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScale); - mTransitionAnimationScale = Settings.Global.getFloat(context.getContentResolver(), - Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale); + mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(), + Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting); + mTransitionAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(), + Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScaleSetting); setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(), - Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale)); + Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting)); // Track changes to DevicePolicyManager state so we can enable/disable keyguard. IntentFilter filter = new IntentFilter(); @@ -5188,9 +5203,9 @@ public class WindowManagerService extends IWindowManager.Stub scale = fixScale(scale); switch (which) { - case 0: mWindowAnimationScale = scale; break; - case 1: mTransitionAnimationScale = scale; break; - case 2: mAnimatorDurationScale = scale; break; + case 0: mWindowAnimationScaleSetting = scale; break; + case 1: mTransitionAnimationScaleSetting = scale; break; + case 2: mAnimatorDurationScaleSetting = scale; break; } // Persist setting @@ -5206,13 +5221,14 @@ public class WindowManagerService extends IWindowManager.Stub if (scales != null) { if (scales.length >= 1) { - mWindowAnimationScale = fixScale(scales[0]); + mWindowAnimationScaleSetting = fixScale(scales[0]); } if (scales.length >= 2) { - mTransitionAnimationScale = fixScale(scales[1]); + mTransitionAnimationScaleSetting = fixScale(scales[1]); } if (scales.length >= 3) { - setAnimatorDurationScale(fixScale(scales[2])); + mAnimatorDurationScaleSetting = fixScale(scales[2]); + dispatchNewAnimatorScaleLocked(null); } } @@ -5221,24 +5237,43 @@ public class WindowManagerService extends IWindowManager.Stub } private void setAnimatorDurationScale(float scale) { - mAnimatorDurationScale = scale; + mAnimatorDurationScaleSetting = scale; ValueAnimator.setDurationScale(scale); } + public float getWindowAnimationScaleLocked() { + return mAnimationsDisabled ? 0 : mWindowAnimationScaleSetting; + } + + public float getTransitionAnimationScaleLocked() { + return mAnimationsDisabled ? 0 : mTransitionAnimationScaleSetting; + } + @Override public float getAnimationScale(int which) { switch (which) { - case 0: return mWindowAnimationScale; - case 1: return mTransitionAnimationScale; - case 2: return mAnimatorDurationScale; + case 0: return mWindowAnimationScaleSetting; + case 1: return mTransitionAnimationScaleSetting; + case 2: return mAnimatorDurationScaleSetting; } return 0; } @Override public float[] getAnimationScales() { - return new float[] { mWindowAnimationScale, mTransitionAnimationScale, - mAnimatorDurationScale }; + return new float[] { mWindowAnimationScaleSetting, mTransitionAnimationScaleSetting, + mAnimatorDurationScaleSetting }; + } + + @Override + public float getCurrentAnimatorScale() { + synchronized(mWindowMap) { + return mAnimationsDisabled ? 0 : mAnimatorDurationScaleSetting; + } + } + + void dispatchNewAnimatorScaleLocked(Session session) { + mH.obtainMessage(H.NEW_ANIMATOR_SCALE, session).sendToTarget(); } @Override @@ -6094,7 +6129,7 @@ public class WindowManagerService extends IWindowManager.Stub && screenRotationAnimation.hasScreenshot()) { if (screenRotationAnimation.setRotationInTransaction( rotation, mFxSession, - MAX_ANIMATION_DURATION, mTransitionAnimationScale, + MAX_ANIMATION_DURATION, getTransitionAnimationScaleLocked(), displayInfo.logicalWidth, displayInfo.logicalHeight)) { scheduleAnimationLocked(); } @@ -7179,6 +7214,8 @@ public class WindowManagerService extends IWindowManager.Stub public static final int SHOW_DISPLAY_MASK = 33; public static final int ALL_WINDOWS_DRAWN = 34; + public static final int NEW_ANIMATOR_SCALE = 35; + @Override public void handleMessage(Message msg) { if (DEBUG_WINDOW_TRACE) { @@ -7429,11 +7466,12 @@ public class WindowManagerService extends IWindowManager.Stub case PERSIST_ANIMATION_SCALE: { Settings.Global.putFloat(mContext.getContentResolver(), - Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScale); + Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting); Settings.Global.putFloat(mContext.getContentResolver(), - Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale); + Settings.Global.TRANSITION_ANIMATION_SCALE, + mTransitionAnimationScaleSetting); Settings.Global.putFloat(mContext.getContentResolver(), - Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale); + Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting); break; } @@ -7636,6 +7674,33 @@ public class WindowManagerService extends IWindowManager.Stub } } } + case NEW_ANIMATOR_SCALE: { + float scale = getCurrentAnimatorScale(); + ValueAnimator.setDurationScale(scale); + Session session = (Session)msg.obj; + if (session != null) { + try { + session.mCallback.onAnimatorScaleChanged(scale); + } catch (RemoteException e) { + } + } else { + ArrayList<IWindowSessionCallback> callbacks + = new ArrayList<IWindowSessionCallback>(); + synchronized (mWindowMap) { + for (int i=0; i<mSessions.size(); i++) { + callbacks.add(mSessions.valueAt(i).mCallback); + } + + } + for (int i=0; i<callbacks.size(); i++) { + try { + callbacks.get(i).onAnimatorScaleChanged(scale); + } catch (RemoteException e) { + } + } + } + } + break; } if (DEBUG_WINDOW_TRACE) { Slog.v(TAG, "handleMessage: exit"); @@ -7648,11 +7713,11 @@ public class WindowManagerService extends IWindowManager.Stub // ------------------------------------------------------------- @Override - public IWindowSession openSession(IInputMethodClient client, + public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client, IInputContext inputContext) { if (client == null) throw new IllegalArgumentException("null client"); if (inputContext == null) throw new IllegalArgumentException("null inputContext"); - Session session = new Session(this, client, inputContext); + Session session = new Session(this, callback, client, inputContext); return session; } @@ -8762,7 +8827,7 @@ public class WindowManagerService extends IWindowManager.Stub displayInfo.appWidth, displayInfo.appHeight, transit); appAnimator.thumbnailAnimation = anim; anim.restrictDuration(MAX_ANIMATION_DURATION); - anim.scaleCurrentDuration(mTransitionAnimationScale); + anim.scaleCurrentDuration(getTransitionAnimationScaleLocked()); Point p = new Point(); mAppTransition.getStartingPoint(p); appAnimator.thumbnailX = p.x; @@ -10070,7 +10135,7 @@ public class WindowManagerService extends IWindowManager.Stub mExitAnimId = mEnterAnimId = 0; } if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, - mTransitionAnimationScale, displayInfo.logicalWidth, + getTransitionAnimationScaleLocked(), displayInfo.logicalWidth, displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) { scheduleAnimationLocked(); } else { @@ -10405,13 +10470,10 @@ public class WindowManagerService extends IWindowManager.Stub void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) { pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); - if (mSessions.size() > 0) { - Iterator<Session> it = mSessions.iterator(); - while (it.hasNext()) { - Session s = it.next(); - pw.print(" Session "); pw.print(s); pw.println(':'); - s.dump(pw, " "); - } + for (int i=0; i<mSessions.size(); i++) { + Session s = mSessions.valueAt(i); + pw.print(" Session "); pw.print(s); pw.println(':'); + s.dump(pw, " "); } } @@ -10615,9 +10677,10 @@ public class WindowManagerService extends IWindowManager.Stub pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation); pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation); pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); - pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale); - pw.print(" mTransitionWindowAnimationScale="); pw.print(mTransitionAnimationScale); - pw.print(" mAnimatorDurationScale="); pw.println(mAnimatorDurationScale); + pw.print(" Animation settings: disabled="); pw.print(mAnimationsDisabled); + pw.print(" window="); pw.print(mWindowAnimationScaleSetting); + pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting); + pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting); pw.print(" mTraversalScheduled="); pw.println(mTraversalScheduled); pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index e257ebc90b48..bda10de01df0 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -207,7 +207,7 @@ class WindowStateAnimator { mLocalAnimating = false; mAnimation = anim; mAnimation.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION); - mAnimation.scaleCurrentDuration(mService.mWindowAnimationScale); + mAnimation.scaleCurrentDuration(mService.getWindowAnimationScaleLocked()); // Start out animation gone if window is gone, or visible if window is visible. mTransformation.clear(); mTransformation.setAlpha(mLastHidden ? 0 : 1); @@ -283,7 +283,7 @@ class WindowStateAnimator { " @ " + currentTime + ": ww=" + mWin.mFrame.width() + " wh=" + mWin.mFrame.height() + " dw=" + mAnimDw + " dh=" + mAnimDh + - " scale=" + mService.mWindowAnimationScale); + " scale=" + mService.getWindowAnimationScaleLocked()); mAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(), mAnimDw, mAnimDh); final DisplayInfo displayInfo = displayContent.getDisplayInfo(); diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java index cfe8e1580851..2f40003cc784 100644 --- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java +++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java @@ -195,8 +195,8 @@ public class IWindowManagerImpl implements IWindowManager { } @Override - public IWindowSession openSession(IInputMethodClient arg0, IInputContext arg1) - throws RemoteException { + public IWindowSession openSession(IWindowSessionCallback argn1, IInputMethodClient arg0, + IInputContext arg1) throws RemoteException { // TODO Auto-generated method stub return null; } @@ -276,6 +276,11 @@ public class IWindowManagerImpl implements IWindowManager { } @Override + public float getCurrentAnimatorScale() throws RemoteException { + return 0; + } + + @Override public void setAppGroupId(IBinder arg0, int arg1) throws RemoteException { // TODO Auto-generated method stub |