diff options
35 files changed, 515 insertions, 181 deletions
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java index 5055b29..075f203 100644 --- a/core/java/android/animation/AnimatorSet.java +++ b/core/java/android/animation/AnimatorSet.java @@ -16,9 +16,10 @@ package android.animation; +import android.util.ArrayMap; + import java.util.ArrayList; import java.util.Collection; -import java.util.HashMap; import java.util.List; /** @@ -68,7 +69,7 @@ public final class AnimatorSet extends Animator { * to a single node representing that Animator, not create a new Node * if one already exists. */ - private HashMap<Animator, Node> mNodeMap = new HashMap<Animator, Node>(); + private ArrayMap<Animator, Node> mNodeMap = new ArrayMap<Animator, Node>(); /** * Set of all nodes created for this AnimatorSet. This list is used upon @@ -646,7 +647,7 @@ public final class AnimatorSet extends Animator { anim.mTerminated = false; anim.mStarted = false; anim.mPlayingSet = new ArrayList<Animator>(); - anim.mNodeMap = new HashMap<Animator, Node>(); + anim.mNodeMap = new ArrayMap<Animator, Node>(); anim.mNodes = new ArrayList<Node>(nodeCount); anim.mSortedNodes = new ArrayList<Node>(nodeCount); anim.mReversible = mReversible; diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java index a7864f4..3018fe2 100644 --- a/core/java/android/app/ActivityView.java +++ b/core/java/android/app/ActivityView.java @@ -24,7 +24,10 @@ import android.content.IIntentSender; import android.content.Intent; import android.content.IntentSender; import android.graphics.SurfaceTexture; +import android.os.Handler; +import android.os.HandlerThread; import android.os.IBinder; +import android.os.Message; import android.os.OperationCanceledException; import android.os.RemoteException; import android.util.AttributeSet; @@ -48,7 +51,9 @@ public class ActivityView extends ViewGroup { private static final String TAG = "ActivityView"; private static final boolean DEBUG = false; - DisplayMetrics mMetrics; + private static final int MSG_SET_SURFACE = 1; + + DisplayMetrics mMetrics = new DisplayMetrics(); private final TextureView mTextureView; private ActivityContainerWrapper mActivityContainer; private Activity mActivity; @@ -58,6 +63,9 @@ public class ActivityView extends ViewGroup { private int mLastVisibility; private ActivityViewCallback mActivityViewCallback; + private HandlerThread mThread = new HandlerThread("ActivityViewThread"); + private Handler mHandler; + public ActivityView(Context context) { this(context, null); } @@ -89,12 +97,27 @@ public class ActivityView extends ViewGroup { + e); } + mThread.start(); + mHandler = new Handler(mThread.getLooper()) { + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + if (msg.what == MSG_SET_SURFACE) { + try { + mActivityContainer.setSurface((Surface) msg.obj, msg.arg1, msg.arg2, + mMetrics.densityDpi); + } catch (RemoteException e) { + throw new RuntimeException( + "ActivityView: Unable to set surface of ActivityContainer. " + e); + } + } + } + }; mTextureView = new TextureView(context); mTextureView.setSurfaceTextureListener(new ActivityViewSurfaceTextureListener()); addView(mTextureView); WindowManager wm = (WindowManager)mActivity.getSystemService(Context.WINDOW_SERVICE); - mMetrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(mMetrics); mLastVisibility = getVisibility(); @@ -111,18 +134,12 @@ public class ActivityView extends ViewGroup { protected void onVisibilityChanged(View changedView, int visibility) { super.onVisibilityChanged(changedView, visibility); - if (mSurface != null) { - try { - if (visibility == View.GONE) { - mActivityContainer.setSurface(null, mWidth, mHeight, mMetrics.densityDpi); - } else if (mLastVisibility == View.GONE) { - // Don't change surface when going between View.VISIBLE and View.INVISIBLE. - mActivityContainer.setSurface(mSurface, mWidth, mHeight, mMetrics.densityDpi); - } - } catch (RemoteException e) { - throw new RuntimeException( - "ActivityView: Unable to set surface of ActivityContainer. " + e); - } + if (mSurface != null && (visibility == View.GONE || mLastVisibility == View.GONE)) { + Message msg = Message.obtain(mHandler, MSG_SET_SURFACE); + msg.obj = (visibility == View.GONE) ? null : mSurface; + msg.arg1 = mWidth; + msg.arg2 = mHeight; + mHandler.sendMessage(msg); } mLastVisibility = visibility; } diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java index c125544..c23e7b2 100644 --- a/core/java/android/database/DatabaseUtils.java +++ b/core/java/android/database/DatabaseUtils.java @@ -272,7 +272,7 @@ public class DatabaseUtils { window.setStartPosition(position); window.setNumColumns(numColumns); if (cursor.moveToPosition(position)) { - do { + rowloop: do { if (!window.allocRow()) { break; } @@ -309,7 +309,7 @@ public class DatabaseUtils { } if (!success) { window.freeLastRow(); - break; + break rowloop; } } position += 1; diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 016541f..5420cad 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -18,7 +18,6 @@ package android.service.wallpaper; import android.content.res.TypedArray; import android.graphics.Canvas; -import android.os.SystemProperties; import android.view.WindowInsets; import com.android.internal.R; @@ -161,9 +160,11 @@ public abstract class WallpaperService extends Service { final Rect mOverscanInsets = new Rect(); final Rect mContentInsets = new Rect(); final Rect mStableInsets = new Rect(); + final Rect mOutsets = new Rect(); final Rect mDispatchedOverscanInsets = new Rect(); final Rect mDispatchedContentInsets = new Rect(); final Rect mDispatchedStableInsets = new Rect(); + final Rect mDispatchedOutsets = new Rect(); final Rect mFinalSystemInsets = new Rect(); final Rect mFinalStableInsets = new Rect(); final Configuration mConfiguration = new Configuration(); @@ -270,7 +271,7 @@ public abstract class WallpaperService extends Service { final BaseIWindow mWindow = new BaseIWindow() { @Override public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, - Rect visibleInsets, Rect stableInsets, boolean reportDraw, + Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, Configuration newConfig) { Message msg = mCaller.obtainMessageI(MSG_WINDOW_RESIZED, reportDraw ? 1 : 0); @@ -661,30 +662,35 @@ public abstract class WallpaperService extends Service { mInputEventReceiver = new WallpaperInputEventReceiver( mInputChannel, Looper.myLooper()); } - + mSurfaceHolder.mSurfaceLock.lock(); mDrawingAllowed = true; if (!fixedSize) { mLayout.surfaceInsets.set(mIWallpaperEngine.mDisplayPadding); + mLayout.surfaceInsets.left += mOutsets.left; + mLayout.surfaceInsets.top += mOutsets.top; + mLayout.surfaceInsets.right += mOutsets.right; + mLayout.surfaceInsets.bottom += mOutsets.bottom; } else { mLayout.surfaceInsets.set(0, 0, 0, 0); } final int relayoutResult = mSession.relayout( mWindow, mWindow.mSeq, mLayout, mWidth, mHeight, View.VISIBLE, 0, mWinFrame, mOverscanInsets, mContentInsets, - mVisibleInsets, mStableInsets, mConfiguration, mSurfaceHolder.mSurface); + mVisibleInsets, mStableInsets, mOutsets, mConfiguration, + mSurfaceHolder.mSurface); if (DEBUG) Log.v(TAG, "New surface: " + mSurfaceHolder.mSurface + ", frame=" + mWinFrame); - + int w = mWinFrame.width(); int h = mWinFrame.height(); if (!fixedSize) { final Rect padding = mIWallpaperEngine.mDisplayPadding; - w += padding.left + padding.right; - h += padding.top + padding.bottom; + w += padding.left + padding.right + mOutsets.left + mOutsets.right; + h += padding.top + padding.bottom + mOutsets.top + mOutsets.bottom; mOverscanInsets.left += padding.left; mOverscanInsets.top += padding.top; mOverscanInsets.right += padding.right; @@ -708,9 +714,14 @@ public abstract class WallpaperService extends Service { mCurHeight = h; } + if (DEBUG) { + Log.v(TAG, "Wallpaper size has changed: (" + mCurWidth + ", " + mCurHeight); + } + insetsChanged |= !mDispatchedOverscanInsets.equals(mOverscanInsets); insetsChanged |= !mDispatchedContentInsets.equals(mContentInsets); insetsChanged |= !mDispatchedStableInsets.equals(mStableInsets); + insetsChanged |= !mDispatchedOutsets.equals(mOutsets); mSurfaceHolder.setSurfaceFrameSize(w, h); mSurfaceHolder.mSurfaceLock.unlock(); @@ -770,13 +781,20 @@ public abstract class WallpaperService extends Service { if (insetsChanged) { mDispatchedOverscanInsets.set(mOverscanInsets); + mDispatchedOverscanInsets.left += mOutsets.left; + mDispatchedOverscanInsets.top += mOutsets.top; + mDispatchedOverscanInsets.right += mOutsets.right; + mDispatchedOverscanInsets.bottom += mOutsets.bottom; mDispatchedContentInsets.set(mContentInsets); mDispatchedStableInsets.set(mStableInsets); + mDispatchedOutsets.set(mOutsets); mFinalSystemInsets.set(mDispatchedOverscanInsets); mFinalStableInsets.set(mDispatchedStableInsets); - mFinalSystemInsets.bottom = mIWallpaperEngine.mDisplayPadding.bottom; WindowInsets insets = new WindowInsets(mFinalSystemInsets, null, mFinalStableInsets, mWindowIsRound); + if (DEBUG) { + Log.v(TAG, "dispatching insets=" + insets); + } onApplyWindowInsets(insets); } diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl index 9fc80fc..b738ba0 100644 --- a/core/java/android/view/IWindow.aidl +++ b/core/java/android/view/IWindow.aidl @@ -46,7 +46,7 @@ oneway interface IWindow { void executeCommand(String command, String parameters, in ParcelFileDescriptor descriptor); void resized(in Rect frame, in Rect overscanInsets, in Rect contentInsets, - in Rect visibleInsets, in Rect stableInsets, boolean reportDraw, + in Rect visibleInsets, in Rect stableInsets, in Rect outsets, boolean reportDraw, in Configuration newConfig); void moved(int newX, int newY); void dispatchAppVisibility(boolean visible); diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index 63e1a85..ed60985 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -79,11 +79,13 @@ interface IWindowSession { * contents to make sure the user can see it. This is different than * <var>outContentInsets</var> in that these insets change transiently, * so complex relayout of the window should not happen based on them. + * @param outOutsets Rect in which is placed the dead area of the screen that we would like to + * treat as real display. Example of such area is a chin in some models of wearable devices. * @param outConfiguration New configuration of window, if it is now * becoming visible and the global configuration has changed since it * was last displayed. * @param outSurface Object in which is placed the new display surface. - * + * * @return int Result flags: {@link WindowManagerGlobal#RELAYOUT_SHOW_FOCUS}, * {@link WindowManagerGlobal#RELAYOUT_FIRST_TIME}. */ @@ -91,7 +93,7 @@ interface IWindowSession { int requestedWidth, int requestedHeight, int viewVisibility, int flags, out Rect outFrame, out Rect outOverscanInsets, out Rect outContentInsets, out Rect outVisibleInsets, out Rect outStableInsets, - out Configuration outConfig, out Surface outSurface); + out Rect outOutsets, out Configuration outConfig, out Surface outSurface); /** * If a call to relayout() asked to have the surface destroy deferred, diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java index 243a0fc..69287b1 100644 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -748,8 +748,21 @@ public class KeyEvent extends InputEvent implements Parcelable { public static final int KEYCODE_TV_TIMER_PROGRAMMING = 258; /** Key code constant: Help key. */ public static final int KEYCODE_HELP = 259; - - private static final int LAST_KEYCODE = KEYCODE_HELP; + /** Key code constant: Primary stem key for Wear + * Main power/reset button on watch. + * @hide */ + public static final int KEYCODE_STEM_PRIMARY = 264; + /** Key code constant: Generic stem key 1 for Wear + * @hide */ + public static final int KEYCODE_STEM_1 = 265; + /** Key code constant: Generic stem key 2 for Wear + * @hide */ + public static final int KEYCODE_STEM_2 = 266; + /** Key code constant: Generic stem key 3 for Wear + * @hide */ + public static final int KEYCODE_STEM_3 = 267; + + private static final int LAST_KEYCODE = KEYCODE_STEM_3; // NOTE: If you add a new keycode here you must also add it to: // isSystem() diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 49be57d..160c662 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -106,6 +106,7 @@ public class SurfaceView extends View { final Rect mOverscanInsets = new Rect(); final Rect mContentInsets = new Rect(); final Rect mStableInsets = new Rect(); + final Rect mOutsets = new Rect(); final Configuration mConfiguration = new Configuration(); static final int KEEP_SCREEN_ON_MSG = 1; @@ -519,7 +520,8 @@ public class SurfaceView extends View { visible ? VISIBLE : GONE, WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY, mWinFrame, mOverscanInsets, mContentInsets, - mVisibleInsets, mStableInsets, mConfiguration, mNewSurface); + mVisibleInsets, mStableInsets, mOutsets, mConfiguration, + mNewSurface); if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) { mReportDrawNeeded = true; } @@ -654,7 +656,7 @@ public class SurfaceView extends View { @Override public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, - Rect visibleInsets, Rect stableInsets, boolean reportDraw, + Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, Configuration newConfig) { SurfaceView surfaceView = mSurfaceView.get(); if (surfaceView != null) { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 3c05872..aeb4ac6 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -6667,6 +6667,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * Returns the outsets, which areas of the device that aren't a surface, but we would like to + * treat them as such. + * @hide + */ + public void getOutsets(Rect outOutsetRect) { + outOutsetRect.set(mAttachInfo.mOutsets); + } + + /** * Returns the visibility status for this view. * * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. @@ -20312,6 +20321,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, final Rect mStableInsets = new Rect(); /** + * For windows that include areas that are not covered by real surface these are the outsets + * for real surface. + */ + final Rect mOutsets = new Rect(); + + /** * The internal insets given by this window. This value is * supplied by the client (through * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 113ad8d..a182ef1 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -261,6 +261,7 @@ public final class ViewRootImpl implements ViewParent, final Rect mPendingVisibleInsets = new Rect(); final Rect mPendingStableInsets = new Rect(); final Rect mPendingContentInsets = new Rect(); + final Rect mPendingOutsets = new Rect(); final ViewTreeObserver.InternalInsetsInfo mLastGivenInsets = new ViewTreeObserver.InternalInsetsInfo(); @@ -1222,8 +1223,14 @@ public final class ViewRootImpl implements ViewParent, void dispatchApplyInsets(View host) { mDispatchContentInsets.set(mAttachInfo.mContentInsets); mDispatchStableInsets.set(mAttachInfo.mStableInsets); - host.dispatchApplyWindowInsets(new WindowInsets( - mDispatchContentInsets, null /* windowDecorInsets */, + Rect outsets = mAttachInfo.mOutsets; + Rect contentInsets = mDispatchContentInsets; + if (outsets.left > 0 || outsets.top > 0 || outsets.right > 0 || outsets.bottom > 0) { + contentInsets = new Rect(contentInsets.left + outsets.left, + contentInsets.top + outsets.top, contentInsets.right + outsets.right, + contentInsets.bottom + outsets.bottom); + } + host.dispatchApplyWindowInsets(new WindowInsets(contentInsets, null /* windowDecorInsets */, mDispatchStableInsets, mWindowIsRound)); } @@ -1369,6 +1376,9 @@ public final class ViewRootImpl implements ViewParent, if (DEBUG_LAYOUT) Log.v(TAG, "Visible insets changing to: " + mAttachInfo.mVisibleInsets); } + if (!mPendingOutsets.equals(mAttachInfo.mOutsets)) { + insetsChanged = true; + } if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT || lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) { windowSizeMayChange = true; @@ -1545,6 +1555,7 @@ public final class ViewRootImpl implements ViewParent, mAttachInfo.mVisibleInsets); final boolean stableInsetsChanged = !mPendingStableInsets.equals( mAttachInfo.mStableInsets); + final boolean outsetsChanged = !mPendingOutsets.equals(mAttachInfo.mOutsets); if (contentInsetsChanged) { if (mWidth > 0 && mHeight > 0 && lp != null && ((lp.systemUiVisibility|lp.subtreeSystemUiVisibility) @@ -1628,9 +1639,11 @@ public final class ViewRootImpl implements ViewParent, } if (contentInsetsChanged || mLastSystemUiVisibility != mAttachInfo.mSystemUiVisibility || mApplyInsetsRequested - || mLastOverscanRequested != mAttachInfo.mOverscanRequested) { + || mLastOverscanRequested != mAttachInfo.mOverscanRequested + || outsetsChanged) { mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility; mLastOverscanRequested = mAttachInfo.mOverscanRequested; + mAttachInfo.mOutsets.set(mPendingOutsets); mApplyInsetsRequested = false; dispatchApplyInsets(host); } @@ -3201,6 +3214,7 @@ public final class ViewRootImpl implements ViewParent, && mPendingContentInsets.equals(args.arg2) && mPendingStableInsets.equals(args.arg6) && mPendingVisibleInsets.equals(args.arg3) + && mPendingOutsets.equals(args.arg7) && args.arg4 == null) { break; } @@ -3219,6 +3233,7 @@ public final class ViewRootImpl implements ViewParent, mPendingContentInsets.set((Rect) args.arg2); mPendingStableInsets.set((Rect) args.arg6); mPendingVisibleInsets.set((Rect) args.arg3); + mPendingOutsets.set((Rect) args.arg7); args.recycle(); @@ -5317,7 +5332,7 @@ public final class ViewRootImpl implements ViewParent, (int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets, - mPendingStableInsets, mPendingConfiguration, mSurface); + mPendingStableInsets, mPendingOutsets, mPendingConfiguration, mSurface); //Log.d(TAG, "<<<<<< BACK FROM relayout"); if (restore) { params.restore(); @@ -5593,7 +5608,8 @@ public final class ViewRootImpl implements ViewParent, } public void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets, - Rect visibleInsets, Rect stableInsets, boolean reportDraw, Configuration newConfig) { + Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, + Configuration newConfig) { if (DEBUG_LAYOUT) Log.v(TAG, "Resizing " + this + ": frame=" + frame.toShortString() + " contentInsets=" + contentInsets.toShortString() + " visibleInsets=" + visibleInsets.toShortString() @@ -5613,6 +5629,7 @@ public final class ViewRootImpl implements ViewParent, args.arg4 = sameProcessCall && newConfig != null ? new Configuration(newConfig) : newConfig; args.arg5 = sameProcessCall ? new Rect(overscanInsets) : overscanInsets; args.arg6 = sameProcessCall ? new Rect(stableInsets) : stableInsets; + args.arg7 = sameProcessCall ? new Rect(outsets) : outsets; msg.obj = args; mHandler.sendMessage(msg); } @@ -6492,12 +6509,12 @@ public final class ViewRootImpl implements ViewParent, @Override public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, - Rect visibleInsets, Rect stableInsets, boolean reportDraw, + Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, Configuration newConfig) { final ViewRootImpl viewAncestor = mViewAncestor.get(); if (viewAncestor != null) { viewAncestor.dispatchResized(frame, overscanInsets, contentInsets, - visibleInsets, stableInsets, reportDraw, newConfig); + visibleInsets, stableInsets, outsets, reportDraw, newConfig); } } diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index 780ca99..71cb889 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -158,10 +158,12 @@ public interface WindowManagerPolicy { * @param decorFrame The decor frame specified by policy specific to this window, * to use for proper cropping during animation. * @param stableFrame The frame around which stable system decoration is positioned. + * @param outsetFrame The frame that includes areas that aren't part of the surface but we + * want to treat them as such. */ public void computeFrameLw(Rect parentFrame, Rect displayFrame, Rect overlayFrame, Rect contentFrame, Rect visibleFrame, Rect decorFrame, - Rect stableFrame); + Rect stableFrame, Rect outsetFrame); /** * Retrieve the current frame of the window that has been assigned by diff --git a/core/java/com/android/internal/os/SomeArgs.java b/core/java/com/android/internal/os/SomeArgs.java index c977997..b0d24fd 100644 --- a/core/java/com/android/internal/os/SomeArgs.java +++ b/core/java/com/android/internal/os/SomeArgs.java @@ -46,6 +46,7 @@ public final class SomeArgs { public Object arg4; public Object arg5; public Object arg6; + public Object arg7; public int argi1; public int argi2; public int argi3; @@ -97,6 +98,7 @@ public final class SomeArgs { arg4 = null; arg5 = null; arg6 = null; + arg7 = null; argi1 = 0; argi2 = 0; argi3 = 0; diff --git a/core/java/com/android/internal/util/ScreenShapeHelper.java b/core/java/com/android/internal/util/ScreenShapeHelper.java index 1bcc7a0..e06bec5 100644 --- a/core/java/com/android/internal/util/ScreenShapeHelper.java +++ b/core/java/com/android/internal/util/ScreenShapeHelper.java @@ -18,20 +18,14 @@ public class ScreenShapeHelper { /** * Return the bottom pixel window outset of a window given its style attributes. - * @param displayMetrics Display metrics of the current device - * @param windowStyle Window style attributes for the window. * @return An outset dimension in pixels or 0 if no outset should be applied. */ - public static int getWindowOutsetBottomPx(DisplayMetrics displayMetrics, - TypedArray windowStyle) { + public static int getWindowOutsetBottomPx(Resources resources) { if (IS_EMULATOR) { return SystemProperties.getInt(ViewRootImpl.PROPERTY_EMULATOR_WIN_OUTSET_BOTTOM_PX, 0); - } else if (windowStyle.hasValue(R.styleable.Window_windowOutsetBottom)) { - TypedValue outsetBottom = new TypedValue(); - windowStyle.getValue(R.styleable.Window_windowOutsetBottom, outsetBottom); - return (int) outsetBottom.getDimension(displayMetrics); + } else { + return resources.getInteger(com.android.internal.R.integer.config_windowOutsetBottom); } - return 0; } /** @@ -41,8 +35,7 @@ public class ScreenShapeHelper { if (IS_EMULATOR) { return SystemProperties.getBoolean(ViewRootImpl.PROPERTY_EMULATOR_CIRCULAR, false); } else { - return resources.getBoolean( - com.android.internal.R.bool.config_windowIsRound); + return resources.getBoolean(com.android.internal.R.bool.config_windowIsRound); } } } diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java index 993ab58..b55aabb 100644 --- a/core/java/com/android/internal/view/BaseIWindow.java +++ b/core/java/com/android/internal/view/BaseIWindow.java @@ -34,8 +34,8 @@ public class BaseIWindow extends IWindow.Stub { } @Override - public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, - Rect visibleInsets, Rect stableInsets, boolean reportDraw, Configuration newConfig) { + public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets, + Rect stableInsets, Rect outsets, boolean reportDraw, Configuration newConfig) { if (reportDraw) { try { mSession.finishDrawing(this); diff --git a/core/java/com/android/internal/widget/SwipeDismissLayout.java b/core/java/com/android/internal/widget/SwipeDismissLayout.java index 6d4e058..35ed63b 100644 --- a/core/java/com/android/internal/widget/SwipeDismissLayout.java +++ b/core/java/com/android/internal/widget/SwipeDismissLayout.java @@ -16,9 +16,11 @@ package com.android.internal.widget; -import android.animation.TimeInterpolator; import android.app.Activity; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.content.res.TypedArray; import android.util.AttributeSet; import android.util.Log; @@ -28,8 +30,6 @@ import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewTreeObserver; -import android.view.animation.AccelerateInterpolator; -import android.view.animation.DecelerateInterpolator; import android.widget.FrameLayout; /** @@ -62,10 +62,6 @@ public class SwipeDismissLayout extends FrameLayout { // Cached ViewConfiguration and system-wide constant values private int mSlop; private int mMinFlingVelocity; - private int mMaxFlingVelocity; - private long mAnimationTime; - private TimeInterpolator mCancelInterpolator; - private TimeInterpolator mDismissInterpolator; // Transient properties private int mActiveTouchId; @@ -92,6 +88,18 @@ public class SwipeDismissLayout extends FrameLayout { } } }; + private BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (mDismissed) { + dismiss(); + } else { + cancel(); + } + resetMembers(); + } + }; + private IntentFilter mScreenOffFilter = new IntentFilter(Intent.ACTION_SCREEN_OFF); private float mLastX; @@ -114,11 +122,6 @@ public class SwipeDismissLayout extends FrameLayout { ViewConfiguration vc = ViewConfiguration.get(context); mSlop = vc.getScaledTouchSlop(); mMinFlingVelocity = vc.getScaledMinimumFlingVelocity(); - mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity(); - mAnimationTime = getContext().getResources().getInteger( - android.R.integer.config_shortAnimTime); - mCancelInterpolator = new DecelerateInterpolator(1.5f); - mDismissInterpolator = new AccelerateInterpolator(1.5f); TypedArray a = context.getTheme().obtainStyledAttributes( com.android.internal.R.styleable.Theme); mUseDynamicTranslucency = !a.hasValue( @@ -141,15 +144,17 @@ public class SwipeDismissLayout extends FrameLayout { getViewTreeObserver().addOnEnterAnimationCompleteListener( mOnEnterAnimationCompleteListener); } + getContext().registerReceiver(mScreenOffReceiver, mScreenOffFilter); } @Override protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); + getContext().unregisterReceiver(mScreenOffReceiver); if (getContext() instanceof Activity) { getViewTreeObserver().removeOnEnterAnimationCompleteListener( mOnEnterAnimationCompleteListener); } + super.onDetachedFromWindow(); } @Override diff --git a/core/jni/android/graphics/Region.cpp b/core/jni/android/graphics/Region.cpp index ec4d8bf..5368503 100644 --- a/core/jni/android/graphics/Region.cpp +++ b/core/jni/android/graphics/Region.cpp @@ -212,11 +212,12 @@ static jlong Region_createFromParcel(JNIEnv* env, jobject clazz, jobject parcel) android::Parcel* p = android::parcelForJavaObject(env, parcel); - const size_t size = p->readInt32(); + size_t size = p->readInt32(); const void* regionData = p->readInplace(size); if (regionData == NULL) { return NULL; } + SkRegion* region = new SkRegion; size_t actualSize = region->readFromMemory(regionData, size); diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 8492eaa..ee6eef2 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -1778,6 +1778,10 @@ <enum name="KEYCODE_TV_MEDIA_CONTEXT_MENU" value="257" /> <enum name="KEYCODE_TV_TIMER_PROGRAMMING" value="258" /> <enum name="KEYCODE_HELP" value="259" /> + <enum name="KEYCODE_STEM_PRIMARY" value="264" /> + <enum name="KEYCODE_STEM_1" value="265" /> + <enum name="KEYCODE_STEM_2" value="266" /> + <enum name="KEYCODE_STEM_3" value="267" /> </attr> <!-- ***************************************************************** --> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index f923d50..251e3af 100755 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1826,6 +1826,11 @@ <!-- default window inset isRound property --> <bool name="config_windowIsRound">false</bool> + <!-- Override this value if the device has a chin, i.e. area that is not actual part of the + screen but you would like to be treated as a real display. The value is the height of the + chin. --> + <integer name="config_windowOutsetBottom">0</integer> + <!-- Package name for default network scorer app; overridden by product overlays. --> <string name="config_defaultNetworkScorerPackageName"></string> @@ -2100,6 +2105,10 @@ <!-- Keyguard component --> <string name="config_keyguardComponent" translatable="false">com.android.systemui/com.android.systemui.keyguard.KeyguardService</string> + <!-- This config is used to force VoiceInteractionService to start on certain low ram devices. + It declares the package name of VoiceInteractionService that should be started. --> + <string translatable="false" name="config_forceVoiceInteractionServicePackage"></string> + <!-- This config is ued to determine whether animations are allowed in low power mode. --> <bool name="config_allowAnimationsInLowPowerMode">false</bool> </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index f0e56e7..3049544 100755 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -374,6 +374,7 @@ <java-symbol type="integer" name="config_wifi_supplicant_scan_interval" /> <java-symbol type="integer" name="config_wifi_disconnected_scan_interval" /> <java-symbol type="integer" name="config_wifi_scan_interval_p2p_connected" /> + <java-symbol type="integer" name="config_windowOutsetBottom" /> <java-symbol type="integer" name="db_connection_pool_size" /> <java-symbol type="integer" name="db_journal_size_limit" /> <java-symbol type="integer" name="db_wal_autocheckpoint" /> @@ -552,6 +553,7 @@ <java-symbol type="string" name="chooseActivity" /> <java-symbol type="string" name="config_default_dns_server" /> <java-symbol type="string" name="config_ethernet_iface_regex" /> + <java-symbol type="string" name="config_forceVoiceInteractionServicePackage" /> <java-symbol type="string" name="config_mms_user_agent" /> <java-symbol type="string" name="config_mms_user_agent_profile_url" /> <java-symbol type="string" name="config_ntpServer" /> diff --git a/core/res/res/values/themes_micro.xml b/core/res/res/values/themes_micro.xml index 112afa6..8bf635e 100644 --- a/core/res/res/values/themes_micro.xml +++ b/core/res/res/values/themes_micro.xml @@ -14,7 +14,7 @@ limitations under the License. --> <resources> - <style name="Theme.Micro" parent="Theme.Material.NoActionBar"> + <style name="Theme.MicroBase" parent="Theme.Material.NoActionBar"> <item name="alertDialogTheme">@style/Theme.Micro.Dialog.Alert</item> <item name="alertDialogStyle">@style/AlertDialog.Micro</item> <item name="dialogTheme">@style/Theme.Micro.Dialog</item> @@ -29,7 +29,10 @@ <item name="windowOverscan">true</item> </style> - <style name="Theme.Micro.Light" parent="Theme.Material.Light.NoActionBar"> + <style name="Theme.Micro" parent="Theme.MicroBase"> + </style> + + <style name="Theme.Micro.LightBase" parent="Theme.Material.Light.NoActionBar"> <item name="alertDialogTheme">@style/Theme.Micro.Dialog.Alert</item> <item name="alertDialogStyle">@style/AlertDialog.Micro</item> <item name="dialogTheme">@style/Theme.Micro.Dialog</item> @@ -44,7 +47,11 @@ <item name="windowOverscan">true</item> </style> - <style name="Theme.Micro.Dialog" parent="Theme.Material.Light.Dialog"> + <!-- Indirection needed for overlays to make sure there is a common base parent --> + <style name="Theme.Micro.Light" parent="Theme.Micro.LightBase"> + </style> + + <style name="Theme.Micro.DialogBase" parent="Theme.Material.Light.Dialog"> <item name="windowTitleStyle">@android:style/DialogWindowTitle.Micro</item> <item name="windowIsFloating">false</item> <item name="windowFullscreen">true</item> @@ -54,6 +61,10 @@ <item name="windowOverscan">true</item> </style> + <!-- Indirection needed for overlays to make sure there is a common base parent --> + <style name="Theme.Micro.Dialog" parent="Theme.Micro.DialogBase"> + </style> + <style name="Theme.Micro.Dialog.Alert"> <item name="windowTitleStyle">@style/DialogWindowTitle.Micro</item> <item name="alertDialogStyle">@style/AlertDialog.Micro</item> diff --git a/packages/Shell/src/com/android/shell/BugreportReceiver.java b/packages/Shell/src/com/android/shell/BugreportReceiver.java index 48ecaa5..b3ba895 100644 --- a/packages/Shell/src/com/android/shell/BugreportReceiver.java +++ b/packages/Shell/src/com/android/shell/BugreportReceiver.java @@ -27,6 +27,7 @@ import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.res.Configuration; import android.net.Uri; import android.os.AsyncTask; import android.os.FileUtils; @@ -65,9 +66,35 @@ public class BugreportReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { + final Configuration conf = context.getResources().getConfiguration(); final File bugreportFile = getFileExtra(intent, EXTRA_BUGREPORT); final File screenshotFile = getFileExtra(intent, EXTRA_SCREENSHOT); + if ((conf.uiMode & Configuration.UI_MODE_TYPE_MASK) != Configuration.UI_MODE_TYPE_WATCH) { + triggerLocalNotification(context, bugreportFile, screenshotFile); + } + + // Clean up older bugreports in background + final PendingResult result = goAsync(); + new AsyncTask<Void, Void, Void>() { + @Override + protected Void doInBackground(Void... params) { + FileUtils.deleteOlderFiles( + bugreportFile.getParentFile(), MIN_KEEP_COUNT, MIN_KEEP_AGE); + result.finish(); + return null; + } + }.execute(); + } + + /** + * Responsible for triggering a notification that allows the user to start a + * "share" intent with the bug report. On watches we have other methods to allow the user to + * start this intent (usually by triggering it on another connected device); we don't need to + * display the notification in this case. + */ + private void triggerLocalNotification(final Context context, final File bugreportFile, + final File screenshotFile) { // Files are kept on private storage, so turn into Uris that we can // grant temporary permissions for. final Uri bugreportUri = FileProvider.getUriForFile(context, AUTHORITY, bugreportFile); @@ -97,18 +124,6 @@ public class BugreportReceiver extends BroadcastReceiver { com.android.internal.R.color.system_notification_accent_color)); NotificationManager.from(context).notify(TAG, 0, builder.build()); - - // Clean up older bugreports in background - final PendingResult result = goAsync(); - new AsyncTask<Void, Void, Void>() { - @Override - protected Void doInBackground(Void... params) { - FileUtils.deleteOlderFiles( - bugreportFile.getParentFile(), MIN_KEEP_COUNT, MIN_KEEP_AGE); - result.finish(); - return null; - } - }.execute(); } private static Intent buildWarningIntent(Context context, Intent sendIntent) { diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java index c9028c4..09766e4 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java @@ -25,7 +25,6 @@ import static android.view.WindowManager.LayoutParams.*; import android.app.SearchManager; import android.os.UserHandle; import com.android.internal.R; -import com.android.internal.util.ScreenShapeHelper; import com.android.internal.view.RootViewSurfaceTaker; import com.android.internal.view.StandaloneActionMode; import com.android.internal.view.menu.ContextMenuBuilder; @@ -62,7 +61,6 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; import android.os.ServiceManager; -import android.os.SystemProperties; import android.transition.Scene; import android.transition.Transition; import android.transition.TransitionInflater; @@ -76,7 +74,6 @@ import android.util.SparseArray; import android.util.TypedValue; import android.view.ActionMode; import android.view.ContextThemeWrapper; -import android.view.Display; import android.view.Gravity; import android.view.IRotationWatcher; import android.view.IWindowManager; @@ -280,6 +277,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { private Boolean mSharedElementsUseOverlay; private Rect mTempRect; + private Rect mOutsets = new Rect(); static class WindowManagerHolder { static final IWindowManager sWindowManager = IWindowManager.Stub.asInterface( @@ -2380,19 +2378,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } @Override - public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) { - if (mOutsetBottomPx != 0) { - WindowInsets newInsets = insets.replaceSystemWindowInsets( - insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(), - insets.getSystemWindowInsetRight(), mOutsetBottomPx); - return super.dispatchApplyWindowInsets(newInsets); - } else { - return super.dispatchApplyWindowInsets(insets); - } - } - - - @Override public boolean onTouchEvent(MotionEvent event) { return onInterceptTouchEvent(event); } @@ -2603,11 +2588,21 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } } - if (mOutsetBottomPx != 0) { + getOutsets(mOutsets); + if (mOutsets.top > 0 || mOutsets.bottom > 0) { int mode = MeasureSpec.getMode(heightMeasureSpec); if (mode != MeasureSpec.UNSPECIFIED) { int height = MeasureSpec.getSize(heightMeasureSpec); - heightMeasureSpec = MeasureSpec.makeMeasureSpec(height + mOutsetBottomPx, mode); + heightMeasureSpec = MeasureSpec.makeMeasureSpec( + height + mOutsets.top + mOutsets.bottom, mode); + } + } + if (mOutsets.left > 0 || mOutsets.right > 0) { + int mode = MeasureSpec.getMode(widthMeasureSpec); + if (mode != MeasureSpec.UNSPECIFIED) { + int width = MeasureSpec.getSize(widthMeasureSpec); + widthMeasureSpec = MeasureSpec.makeMeasureSpec( + width + mOutsets.left + mOutsets.right, mode); } } @@ -2645,6 +2640,18 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + getOutsets(mOutsets); + if (mOutsets.left > 0) { + offsetLeftAndRight(-mOutsets.left); + } + if (mOutsets.top > 0) { + offsetTopAndBottom(-mOutsets.top); + } + } + + @Override public void draw(Canvas canvas) { super.draw(canvas); @@ -3433,19 +3440,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { requestFeature(FEATURE_ACTIVITY_TRANSITIONS); } - final WindowManager windowService = (WindowManager) getContext().getSystemService( - Context.WINDOW_SERVICE); - if (windowService != null) { - final Display display = windowService.getDefaultDisplay(); - final boolean shouldUseBottomOutset = - display.getDisplayId() == Display.DEFAULT_DISPLAY - || (getForcedWindowFlags() & FLAG_FULLSCREEN) != 0; - if (shouldUseBottomOutset) { - mOutsetBottomPx = ScreenShapeHelper.getWindowOutsetBottomPx( - getContext().getResources().getDisplayMetrics(), a); - } - } - final Context context = getContext(); final int targetSdk = context.getApplicationInfo().targetSdkVersion; final boolean targetPreHoneycomb = targetSdk < android.os.Build.VERSION_CODES.HONEYCOMB; diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index a509706..00facf0 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -109,6 +109,7 @@ import com.android.internal.policy.PolicyManager; import com.android.internal.policy.impl.keyguard.KeyguardServiceDelegate; import com.android.internal.policy.impl.keyguard.KeyguardServiceDelegate.ShowListener; import com.android.internal.statusbar.IStatusBarService; +import com.android.internal.util.ScreenShapeHelper; import com.android.internal.widget.PointerLocationView; import com.android.server.LocalServices; @@ -459,6 +460,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { static final Rect mTmpDecorFrame = new Rect(); static final Rect mTmpStableFrame = new Rect(); static final Rect mTmpNavigationFrame = new Rect(); + static final Rect mTmpOutsetFrame = new Rect(); WindowState mTopFullscreenOpaqueWindowState; HashSet<IApplicationToken> mAppsToBeHidden = new HashSet<IApplicationToken>(); @@ -3328,6 +3330,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { final Rect of = mTmpOverscanFrame; final Rect vf = mTmpVisibleFrame; final Rect dcf = mTmpDecorFrame; + final Rect osf = mTmpOutsetFrame; pf.left = df.left = of.left = vf.left = mDockLeft; pf.top = df.top = of.top = vf.top = mDockTop; pf.right = df.right = of.right = vf.right = mDockRight; @@ -3439,7 +3442,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // And compute the final frame. mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf, - mTmpNavigationFrame); + mTmpNavigationFrame, mTmpNavigationFrame); if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame); if (mNavigationBarController.checkHiddenLw()) { updateSysUiVisibility = true; @@ -3464,7 +3467,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { mStatusBarLayer = mStatusBar.getSurfaceLayer(); // Let the status bar determine its size. - mStatusBar.computeFrameLw(pf, df, vf, vf, vf, dcf, vf); + mStatusBar.computeFrameLw(pf, df, vf, vf, vf, dcf, vf, osf); // For layout, the status bar is always at the top with our fixed height. mStableTop = mUnrestrictedScreenTop + mStatusBarHeight; @@ -3638,6 +3641,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { final Rect vf = mTmpVisibleFrame; final Rect dcf = mTmpDecorFrame; final Rect sf = mTmpStableFrame; + Rect osf = null; dcf.setEmpty(); final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar @@ -4022,6 +4026,37 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } + // If the device has a chin (e.g. some watches), a dead area at the bottom of the screen we + // need to provide information to the clients that want to pretend that you can draw there. + // We only want to apply outsets to certain types of windows. For example, we never want to + // apply the outsets to floating dialogs, because they wouldn't make sense there. + final boolean useOutsets = attrs.type == TYPE_WALLPAPER + || (fl & (WindowManager.LayoutParams.FLAG_FULLSCREEN + | WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN)) != 0; + if (isDefaultDisplay && useOutsets) { + osf = mTmpOutsetFrame; + osf.set(cf.left, cf.top, cf.right, cf.bottom); + int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources()); + if (outset > 0) { + int rotation = Surface.ROTATION_0; + try { + rotation = mWindowManager.getRotation(); + } catch (RemoteException e) { + } + if (rotation == Surface.ROTATION_0) { + osf.bottom += outset; + } else if (rotation == Surface.ROTATION_90) { + osf.right += outset; + } else if (rotation == Surface.ROTATION_180) { + osf.top -= outset; + } else if (rotation == Surface.ROTATION_270) { + osf.left -= outset; + } + if (DEBUG_LAYOUT) Slog.v(TAG, "applying bottom outset of " + outset + + " with rotation " + rotation + ", result: " + osf); + } + } + if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle() + ": sim=#" + Integer.toHexString(sim) + " attach=" + attached + " type=" + attrs.type @@ -4030,9 +4065,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { + " of=" + of.toShortString() + " cf=" + cf.toShortString() + " vf=" + vf.toShortString() + " dcf=" + dcf.toShortString() - + " sf=" + sf.toShortString()); + + " sf=" + sf.toShortString() + + " osf=" + (osf == null ? "null" : osf.toShortString())); - win.computeFrameLw(pf, df, of, cf, vf, dcf, sf); + win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf); // Dock windows carve out the bottom of the screen, so normal windows // can't appear underneath them. @@ -5138,10 +5174,16 @@ public class PhoneWindowManager implements WindowManagerPolicy { } private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode) { - if (!wakeInTheaterMode && isTheaterModeEnabled()) { + final boolean theaterModeEnabled = isTheaterModeEnabled(); + if (!wakeInTheaterMode && theaterModeEnabled) { return false; } + if (theaterModeEnabled) { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.THEATER_MODE_ON, 0); + } + mPowerManager.wakeUp(wakeTime); return true; } diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index 0c726f3..0631447 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -18,6 +18,7 @@ package com.android.server; import android.app.ActivityManager; import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.bluetooth.IBluetooth; import android.bluetooth.IBluetoothGatt; @@ -115,6 +116,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int SERVICE_IBLUETOOTH = 1; private static final int SERVICE_IBLUETOOTHGATT = 2; + private static final String[] DEVICE_TYPE_NAMES = new String[] { + "???", + "BR/EDR", + "LE", + "DUAL" + }; + private final Context mContext; // Locks are not provided for mName and mAddress. @@ -1530,12 +1538,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub { writer.println(" state: " + mState); writer.println(" address: " + mAddress); writer.println(" name: " + mName + "\n"); - writer.flush(); if (mBluetooth == null) { writer.println("Bluetooth Service not connected"); } else { try { + writer.println("Bonded devices:"); + for (BluetoothDevice device : mBluetooth.getBondedDevices()) { + writer.println(" " + device.getAddress() + + " [" + DEVICE_TYPE_NAMES[device.getType()] + "] " + + device.getName()); + } + writer.flush(); + ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(fd); mBluetooth.dump(pfd); pfd.close(); diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 0630cad..2b96f9c 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -831,8 +831,18 @@ public final class ActivityStackSupervisor implements DisplayListener { void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason) { moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason); - startActivityLocked(null, intent, null, aInfo, null, null, null, null, 0, 0, 0, null, - 0, 0, 0, null, false, null, null, null); + startActivityLocked(null /* caller */, intent, null /* resolvedType */, aInfo, + null /* voiceSession */, null /* voiceInteractor */, null /* resultTo */, + null /* resultWho */, 0 /* requestCode */, 0 /* callingPid */, 0 /* callingUid */, + null /* callingPackage */, 0 /* realCallingPid */, 0 /* realCallingUid */, + 0 /* startFlags */, null /* options */, false /* componentSpecified */, + null /* outActivity */, null /* container */, null /* inTask */); + if (inResumeTopActivity) { + // If we are in resume section already, home activity will be initialized, but not + // resumed (to avoid recursive resume) and will stay that way until something pokes it + // again. We need to schedule another resume. + scheduleResumeTopActivities(); + } } final int startActivityMayWait(IApplicationThread caller, int callingUid, diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java index 61631d4..0d5e6bc 100644 --- a/services/core/java/com/android/server/display/DisplayDevice.java +++ b/services/core/java/com/android/server/display/DisplayDevice.java @@ -47,6 +47,10 @@ abstract class DisplayDevice { // within a transaction from performTraversalInTransactionLocked. private Surface mCurrentSurface; + // DEBUG STATE: Last device info which was written to the log, or null if none. + // Do not use for any other purpose. + DisplayDeviceInfo mDebugLastLoggedDeviceInfo; + public DisplayDevice(DisplayAdapter displayAdapter, IBinder displayToken, String uniqueId) { mDisplayAdapter = displayAdapter; mDisplayToken = displayToken; diff --git a/services/core/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java index d1e73f0..ebf6e4e 100644 --- a/services/core/java/com/android/server/display/DisplayDeviceInfo.java +++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java @@ -104,6 +104,16 @@ final class DisplayDeviceInfo { public static final int TOUCH_EXTERNAL = 2; /** + * Diff result: The {@link #state} fields differ. + */ + public static final int DIFF_STATE = 1 << 0; + + /** + * Diff result: Other fields differ. + */ + public static final int DIFF_OTHER = 1 << 1; + + /** * Gets the name of the display device, which may be derived from EDID or * other sources. The name may be localized and displayed to the user. */ @@ -238,26 +248,39 @@ final class DisplayDeviceInfo { } public boolean equals(DisplayDeviceInfo other) { - return other != null - && Objects.equal(name, other.name) - && Objects.equal(uniqueId, other.uniqueId) - && width == other.width - && height == other.height - && refreshRate == other.refreshRate - && Arrays.equals(supportedRefreshRates, other.supportedRefreshRates) - && densityDpi == other.densityDpi - && xDpi == other.xDpi - && yDpi == other.yDpi - && appVsyncOffsetNanos == other.appVsyncOffsetNanos - && presentationDeadlineNanos == other.presentationDeadlineNanos - && flags == other.flags - && touch == other.touch - && rotation == other.rotation - && type == other.type - && Objects.equal(address, other.address) - && state == other.state - && ownerUid == other.ownerUid - && Objects.equal(ownerPackageName, other.ownerPackageName); + return other != null && diff(other) == 0; + } + + /** + * Computes the difference between display device infos. + * Assumes other is not null. + */ + public int diff(DisplayDeviceInfo other) { + int diff = 0; + if (state != other.state) { + diff |= DIFF_STATE; + } + if (!Objects.equal(name, other.name) + || !Objects.equal(uniqueId, other.uniqueId) + || width != other.width + || height != other.height + || refreshRate != other.refreshRate + || !Arrays.equals(supportedRefreshRates, other.supportedRefreshRates) + || densityDpi != other.densityDpi + || xDpi != other.xDpi + || yDpi != other.yDpi + || appVsyncOffsetNanos != other.appVsyncOffsetNanos + || presentationDeadlineNanos != other.presentationDeadlineNanos + || flags != other.flags + || touch != other.touch + || rotation != other.rotation + || type != other.type + || !Objects.equal(address, other.address) + || ownerUid != other.ownerUid + || !Objects.equal(ownerPackageName, other.ownerPackageName)) { + diff |= DIFF_OTHER; + } + return diff; } @Override diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index 5f0ad9f..96ff702 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -640,13 +640,14 @@ public final class DisplayManagerService extends SystemService { } private void handleDisplayDeviceAddedLocked(DisplayDevice device) { + DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); if (mDisplayDevices.contains(device)) { - Slog.w(TAG, "Attempted to add already added display device: " - + device.getDisplayDeviceInfoLocked()); + Slog.w(TAG, "Attempted to add already added display device: " + info); return; } - Slog.i(TAG, "Display device added: " + device.getDisplayDeviceInfoLocked()); + Slog.i(TAG, "Display device added: " + info); + device.mDebugLastLoggedDeviceInfo = info; mDisplayDevices.add(device); addLogicalDisplayLocked(device); @@ -659,13 +660,20 @@ public final class DisplayManagerService extends SystemService { private void handleDisplayDeviceChanged(DisplayDevice device) { synchronized (mSyncRoot) { + DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); if (!mDisplayDevices.contains(device)) { - Slog.w(TAG, "Attempted to change non-existent display device: " - + device.getDisplayDeviceInfoLocked()); + Slog.w(TAG, "Attempted to change non-existent display device: " + info); return; } - Slog.i(TAG, "Display device changed: " + device.getDisplayDeviceInfoLocked()); + int diff = device.mDebugLastLoggedDeviceInfo.diff(info); + if (diff == DisplayDeviceInfo.DIFF_STATE) { + Slog.i(TAG, "Display device changed state: \"" + info.name + + "\", " + Display.stateToString(info.state)); + } else if (diff != 0) { + Slog.i(TAG, "Display device changed: " + info); + } + device.mDebugLastLoggedDeviceInfo = info; device.applyPendingDisplayDeviceInfoChangesLocked(); if (updateLogicalDisplaysLocked()) { @@ -680,13 +688,14 @@ public final class DisplayManagerService extends SystemService { } } private void handleDisplayDeviceRemovedLocked(DisplayDevice device) { + DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); if (!mDisplayDevices.remove(device)) { - Slog.w(TAG, "Attempted to remove non-existent display device: " - + device.getDisplayDeviceInfoLocked()); + Slog.w(TAG, "Attempted to remove non-existent display device: " + info); return; } - Slog.i(TAG, "Display device removed: " + device.getDisplayDeviceInfoLocked()); + Slog.i(TAG, "Display device removed: " + info); + device.mDebugLastLoggedDeviceInfo = info; updateLogicalDisplaysLocked(); scheduleTraversalLocked(false); diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java index 621e1bd..ba72987 100644 --- a/services/core/java/com/android/server/location/GpsLocationProvider.java +++ b/services/core/java/com/android/server/location/GpsLocationProvider.java @@ -22,10 +22,8 @@ import com.android.internal.location.GpsNetInitiatedHandler; import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification; import com.android.internal.location.ProviderProperties; import com.android.internal.location.ProviderRequest; -import com.android.internal.R; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneConstants; -import com.android.internal.telephony.TelephonyIntents; import android.app.AlarmManager; import android.app.AppOpsManager; @@ -72,7 +70,6 @@ import android.provider.Settings; import android.provider.Telephony.Carriers; import android.provider.Telephony.Sms.Intents; import android.telephony.SmsMessage; -import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; import android.telephony.TelephonyManager; @@ -91,7 +88,6 @@ import java.io.StringReader; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Date; -import java.util.List; import java.util.Map.Entry; import java.util.Properties; @@ -283,8 +279,16 @@ public class GpsLocationProvider implements LocationProviderInterface { // current setting 24 hours private static final long NTP_INTERVAL = 24*60*60*1000; // how long to wait if we have a network error in NTP or XTRA downloading + // the initial value of the exponential backoff // current setting - 5 minutes private static final long RETRY_INTERVAL = 5*60*1000; + // how long to wait if we have a network error in NTP or XTRA downloading + // the max value of the exponential backoff + // current setting - 4 hours + private static final long MAX_RETRY_INTERVAL = 4*60*60*1000; + + private BackOff mNtpBackOff = new BackOff(RETRY_INTERVAL, MAX_RETRY_INTERVAL); + private BackOff mXtraBackOff = new BackOff(RETRY_INTERVAL, MAX_RETRY_INTERVAL); // true if we are enabled, protected by this private boolean mEnabled; @@ -877,9 +881,10 @@ public class GpsLocationProvider implements LocationProviderInterface { native_inject_time(time, timeReference, (int) certainty); delay = NTP_INTERVAL; + mNtpBackOff.reset(); } else { if (DEBUG) Log.d(TAG, "requestTime failed"); - delay = RETRY_INTERVAL; + delay = mNtpBackOff.nextBackoffMillis(); } sendMessage(INJECT_NTP_TIME_FINISHED, 0, null); @@ -920,6 +925,7 @@ public class GpsLocationProvider implements LocationProviderInterface { Log.d(TAG, "calling native_inject_xtra_data"); } native_inject_xtra_data(data, data.length); + mXtraBackOff.reset(); } sendMessage(DOWNLOAD_XTRA_DATA_FINISHED, 0, null); @@ -927,7 +933,8 @@ public class GpsLocationProvider implements LocationProviderInterface { if (data == null) { // try again later // since this is delayed and not urgent we do not hold a wake lock here - mHandler.sendEmptyMessageDelayed(DOWNLOAD_XTRA_DATA, RETRY_INTERVAL); + mHandler.sendEmptyMessageDelayed(DOWNLOAD_XTRA_DATA, + mXtraBackOff.nextBackoffMillis()); } // release wake lock held by task @@ -2147,6 +2154,36 @@ public class GpsLocationProvider implements LocationProviderInterface { pw.append(s); } + /** + * A simple implementation of exponential backoff. + */ + private static final class BackOff { + private static final int MULTIPLIER = 2; + private final long mInitIntervalMillis; + private final long mMaxIntervalMillis; + private long mCurrentIntervalMillis; + + public BackOff(long initIntervalMillis, long maxIntervalMillis) { + mInitIntervalMillis = initIntervalMillis; + mMaxIntervalMillis = maxIntervalMillis; + + mCurrentIntervalMillis = mInitIntervalMillis / MULTIPLIER; + } + + public long nextBackoffMillis() { + if (mCurrentIntervalMillis > mMaxIntervalMillis) { + return mMaxIntervalMillis; + } + + mCurrentIntervalMillis *= MULTIPLIER; + return mCurrentIntervalMillis; + } + + public void reset() { + mCurrentIntervalMillis = mInitIntervalMillis / MULTIPLIER; + } + } + // for GPS SV statistics private static final int MAX_SVS = 32; private static final int EPHEMERIS_MASK = 0; diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index a1d145c..40e6d58 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -190,14 +190,15 @@ final class Session extends IWindowSession.Stub public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewFlags, int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, - Rect outVisibleInsets, Rect outStableInsets, Configuration outConfig, + Rect outVisibleInsets, Rect outStableInsets, Rect outsets, Configuration + outConfig, Surface outSurface) { if (false) Slog.d(WindowManagerService.TAG, ">>>>>> ENTERED relayout from " + Binder.getCallingPid()); int res = mService.relayoutWindow(this, window, seq, attrs, requestedWidth, requestedHeight, viewFlags, flags, outFrame, outOverscanInsets, outContentInsets, outVisibleInsets, - outStableInsets, outConfig, outSurface); + outStableInsets, outsets, outConfig, outSurface); if (false) Slog.d(WindowManagerService.TAG, "<<<<<< EXITING relayout to " + Binder.getCallingPid()); return res; @@ -536,4 +537,4 @@ final class Session extends IWindowSession.Stub public String toString() { return mStringName; } -}
\ No newline at end of file +} diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index ad6aa75..b75622b 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -3012,7 +3012,7 @@ public class WindowManagerService extends IWindowManager.Stub WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewVisibility, int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, - Rect outVisibleInsets, Rect outStableInsets, Configuration outConfig, + Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Configuration outConfig, Surface outSurface) { boolean toBeDisplayed = false; boolean inTouchMode; @@ -3293,6 +3293,7 @@ public class WindowManagerService extends IWindowManager.Stub outContentInsets.set(win.mContentInsets); outVisibleInsets.set(win.mVisibleInsets); outStableInsets.set(win.mStableInsets); + outOutsets.set(win.mOutsets); if (localLOGV) Slog.v( TAG, "Relayout given client " + client.asBinder() + ", requestedWidth=" + requestedWidth @@ -9456,6 +9457,7 @@ public class WindowManagerService extends IWindowManager.Stub w.mLastContentInsets.set(w.mContentInsets); w.mLastVisibleInsets.set(w.mVisibleInsets); w.mLastStableInsets.set(w.mStableInsets); + w.mLastOutsets.set(w.mOutsets); makeWindowFreezingScreenIfNeededLocked(w); // If the orientation is changing, then we need to // hold off on unfreezing the display until this diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index b621c52..dff79a8 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -179,6 +179,14 @@ final class WindowState implements WindowManagerPolicy.WindowState { boolean mStableInsetsChanged; /** + * Outsets determine the area outside of the surface where we want to pretend that it's possible + * to draw anyway. + */ + final Rect mOutsets = new Rect(); + final Rect mLastOutsets = new Rect(); + boolean mOutsetsChanged = false; + + /** * Set to true if we are waiting for this window to receive its * given internal insets before laying out other windows based on it. */ @@ -259,6 +267,10 @@ final class WindowState implements WindowManagerPolicy.WindowState { // displays hint text. final Rect mVisibleFrame = new Rect(); + // Frame that includes dead area outside of the surface but where we want to pretend that it's + // possible to draw. + final Rect mOutsetFrame = new Rect(); + boolean mContentChanged; // If a window showing a wallpaper: the requested offset for the @@ -517,7 +529,8 @@ final class WindowState implements WindowManagerPolicy.WindowState { } @Override - public void computeFrameLw(Rect pf, Rect df, Rect of, Rect cf, Rect vf, Rect dcf, Rect sf) { + public void computeFrameLw(Rect pf, Rect df, Rect of, Rect cf, Rect vf, Rect dcf, Rect sf, + Rect osf) { mHaveFrame = true; TaskStack stack = mAppToken != null ? getStack() : null; @@ -585,6 +598,10 @@ final class WindowState implements WindowManagerPolicy.WindowState { mVisibleFrame.set(vf); mDecorFrame.set(dcf); mStableFrame.set(sf); + final boolean hasOutsets = osf != null; + if (hasOutsets) { + mOutsetFrame.set(osf); + } final int fw = mFrame.width(); final int fh = mFrame.height(); @@ -610,6 +627,16 @@ final class WindowState implements WindowManagerPolicy.WindowState { // Now make sure the window fits in the overall display. Gravity.applyDisplay(mAttrs.gravity, df, mFrame); + // Calculate the outsets before the content frame gets shrinked to the window frame. + if (hasOutsets) { + mOutsets.set(Math.max(mContentFrame.left - mOutsetFrame.left, 0), + Math.max(mContentFrame.top - mOutsetFrame.top, 0), + Math.max(mOutsetFrame.right - mContentFrame.right, 0), + Math.max(mOutsetFrame.bottom - mContentFrame.bottom, 0)); + } else { + mOutsets.set(0, 0, 0, 0); + } + // Make sure the content and visible frames are inside of the // final window frame. mContentFrame.set(Math.max(mContentFrame.left, mFrame.left), @@ -656,6 +683,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { mContentInsets.scale(mInvGlobalScale); mVisibleInsets.scale(mInvGlobalScale); mStableInsets.scale(mInvGlobalScale); + mOutsets.scale(mInvGlobalScale); // Also the scaled frame that we report to the app needs to be // adjusted to be in its coordinate space. @@ -678,7 +706,8 @@ final class WindowState implements WindowManagerPolicy.WindowState { + "): frame=" + mFrame.toShortString() + " ci=" + mContentInsets.toShortString() + " vi=" + mVisibleInsets.toShortString() - + " vi=" + mStableInsets.toShortString()); + + " vi=" + mStableInsets.toShortString() + + " of=" + mOutsets.toShortString()); } @Override @@ -784,7 +813,9 @@ final class WindowState implements WindowManagerPolicy.WindowState { mContentInsetsChanged |= !mLastContentInsets.equals(mContentInsets); mVisibleInsetsChanged |= !mLastVisibleInsets.equals(mVisibleInsets); mStableInsetsChanged |= !mLastStableInsets.equals(mStableInsets); - return mOverscanInsetsChanged || mContentInsetsChanged || mVisibleInsetsChanged; + mOutsetsChanged |= !mLastOutsets.equals(mOutsets); + return mOverscanInsetsChanged || mContentInsetsChanged || mVisibleInsetsChanged + || mOutsetsChanged; } public DisplayContent getDisplayContent() { @@ -1329,7 +1360,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { } return displayContent.isDefaultDisplay; } - + public void setShowToOwnerOnlyLocked(boolean showToOwnerOnly) { mShowToOwnerOnly = showToOwnerOnly; } @@ -1439,6 +1470,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { final Rect contentInsets = mLastContentInsets; final Rect visibleInsets = mLastVisibleInsets; final Rect stableInsets = mLastStableInsets; + final Rect outsets = mLastOutsets; final boolean reportDraw = mWinAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING; final Configuration newConfig = configChanged ? mConfiguration : null; if (mAttrs.type != WindowManager.LayoutParams.TYPE_APPLICATION_STARTING @@ -1449,7 +1481,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { public void run() { try { mClient.resized(frame, overscanInsets, contentInsets, - visibleInsets, stableInsets, reportDraw, newConfig); + visibleInsets, stableInsets, outsets, reportDraw, newConfig); } catch (RemoteException e) { // Not a remote call, RemoteException won't be raised. } @@ -1457,7 +1489,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { }); } else { mClient.resized(frame, overscanInsets, contentInsets, visibleInsets, stableInsets, - reportDraw, newConfig); + outsets, reportDraw, newConfig); } //TODO (multidisplay): Accessibility supported only for the default display. @@ -1470,6 +1502,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { mContentInsetsChanged = false; mVisibleInsetsChanged = false; mStableInsetsChanged = false; + mOutsetsChanged = false; mWinAnimator.mSurfaceResized = false; } catch (RemoteException e) { mOrientationChanging = false; @@ -1615,17 +1648,22 @@ final class WindowState implements WindowManagerPolicy.WindowState { pw.println(); pw.print(prefix); pw.print(" decor="); mDecorFrame.printShortString(pw); pw.println(); + pw.print(prefix); pw.print(" outset="); mOutsetFrame.printShortString(pw); + pw.println(); pw.print(prefix); pw.print("Cur insets: overscan="); mOverscanInsets.printShortString(pw); pw.print(" content="); mContentInsets.printShortString(pw); pw.print(" visible="); mVisibleInsets.printShortString(pw); pw.print(" stable="); mStableInsets.printShortString(pw); + pw.print(" outsets="); mOutsets.printShortString(pw); pw.println(); pw.print(prefix); pw.print("Lst insets: overscan="); mLastOverscanInsets.printShortString(pw); pw.print(" content="); mLastContentInsets.printShortString(pw); pw.print(" visible="); mLastVisibleInsets.printShortString(pw); pw.print(" stable="); mLastStableInsets.printShortString(pw); + pw.print(" physical="); mLastOutsets.printShortString(pw); + pw.print(" outset="); mLastOutsets.printShortString(pw); pw.println(); } pw.print(prefix); pw.print(mWinAnimator); pw.println(":"); diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java index f5d4867..2fe3670 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java @@ -28,6 +28,7 @@ import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; +import android.content.res.Resources; import android.database.ContentObserver; import android.hardware.soundtrigger.IRecognitionStatusCallback; import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel; @@ -79,6 +80,7 @@ public class VoiceInteractionManagerService extends SystemService { mResolver = context.getContentResolver(); mDbHelper = new DatabaseHelper(context); mSoundTriggerHelper = new SoundTriggerHelper(context); + mServiceStub = new VoiceInteractionManagerServiceStub(); } @Override @@ -104,8 +106,7 @@ public class VoiceInteractionManagerService extends SystemService { } // implementation entry point and binder service - private final VoiceInteractionManagerServiceStub mServiceStub - = new VoiceInteractionManagerServiceStub(); + private final VoiceInteractionManagerServiceStub mServiceStub; class VoiceInteractionManagerServiceStub extends IVoiceInteractionManagerService.Stub { @@ -113,6 +114,11 @@ public class VoiceInteractionManagerService extends SystemService { private boolean mSafeMode; private int mCurUser; + private final boolean mEnableService; + + VoiceInteractionManagerServiceStub() { + mEnableService = shouldEnableService(mContext.getResources()); + } @Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) @@ -136,15 +142,14 @@ public class VoiceInteractionManagerService extends SystemService { Settings.Secure.VOICE_INTERACTION_SERVICE, userHandle); ComponentName curRecognizer = getCurRecognizer(userHandle); VoiceInteractionServiceInfo curInteractorInfo = null; - if (curInteractorStr == null && curRecognizer != null - && !ActivityManager.isLowRamDeviceStatic()) { + if (curInteractorStr == null && curRecognizer != null && mEnableService) { // If there is no interactor setting, that means we are upgrading // from an older platform version. If the current recognizer is not // set or matches the preferred recognizer, then we want to upgrade // the user to have the default voice interaction service enabled. // Note that we don't do this for low-RAM devices, since we aren't // supporting voice interaction services there. - curInteractorInfo = findAvailInteractor(userHandle, curRecognizer); + curInteractorInfo = findAvailInteractor(userHandle, curRecognizer.getPackageName()); if (curInteractorInfo != null) { // Looks good! We'll apply this one. To make it happen, we clear the // recognizer so that we don't think we have anything set and will @@ -153,9 +158,21 @@ public class VoiceInteractionManagerService extends SystemService { } } + // If forceInteractorPackage exists, try to apply the interactor from this package if + // possible and ignore the regular interactor setting. + String forceInteractorPackage = + getForceVoiceInteractionServicePackage(mContext.getResources()); + if (forceInteractorPackage != null) { + curInteractorInfo = findAvailInteractor(userHandle, forceInteractorPackage); + if (curInteractorInfo != null) { + // We'll apply this one. Clear the recognizer and re-apply the settings. + curRecognizer = null; + } + } + // If we are on a svelte device, make sure an interactor is not currently // enabled; if it is, turn it off. - if (ActivityManager.isLowRamDeviceStatic() && curInteractorStr != null) { + if (!mEnableService && curInteractorStr != null) { if (!TextUtils.isEmpty(curInteractorStr)) { setCurInteractor(null, userHandle); curInteractorStr = ""; @@ -184,7 +201,7 @@ public class VoiceInteractionManagerService extends SystemService { } // Initializing settings, look for an interactor first (but only on non-svelte). - if (curInteractorInfo == null && !ActivityManager.isLowRamDeviceStatic()) { + if (curInteractorInfo == null && mEnableService) { curInteractorInfo = findAvailInteractor(userHandle, null); } @@ -210,6 +227,18 @@ public class VoiceInteractionManagerService extends SystemService { } } + private boolean shouldEnableService(Resources res) { + // VoiceInteractionService should not be enabled on low ram devices unless it has the config flag. + return !ActivityManager.isLowRamDeviceStatic() || + getForceVoiceInteractionServicePackage(res) != null; + } + + private String getForceVoiceInteractionServicePackage(Resources res) { + String interactorPackage = + res.getString(com.android.internal.R.string.config_forceVoiceInteractionServicePackage); + return TextUtils.isEmpty(interactorPackage) ? null : interactorPackage; + } + public void systemRunning(boolean safeMode) { mSafeMode = safeMode; @@ -260,7 +289,7 @@ public class VoiceInteractionManagerService extends SystemService { } } - VoiceInteractionServiceInfo findAvailInteractor(int userHandle, ComponentName recognizer) { + VoiceInteractionServiceInfo findAvailInteractor(int userHandle, String packageName) { List<ResolveInfo> available = mContext.getPackageManager().queryIntentServicesAsUser( new Intent(VoiceInteractionService.SERVICE_INTERFACE), 0, userHandle); @@ -281,8 +310,8 @@ public class VoiceInteractionManagerService extends SystemService { VoiceInteractionServiceInfo info = new VoiceInteractionServiceInfo( mContext.getPackageManager(), comp, userHandle); if (info.getParseError() == null) { - if (recognizer == null || info.getServiceInfo().packageName.equals( - recognizer.getPackageName())) { + if (packageName == null || info.getServiceInfo().packageName.equals( + packageName)) { if (foundInfo == null) { foundInfo = info; } else { @@ -659,6 +688,7 @@ public class VoiceInteractionManagerService extends SystemService { } synchronized (this) { pw.println("VOICE INTERACTION MANAGER (dumpsys voiceinteraction)\n"); + pw.println(" mEnableService: " + mEnableService); if (mImpl == null) { pw.println(" (No active implementation)"); return; diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java index 4c4454d..fb5d44f 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java @@ -47,8 +47,8 @@ public final class BridgeWindow implements IWindow { } @Override - public void resized(Rect rect, Rect rect2, Rect rect3, Rect rect4, Rect rect5, boolean b, - Configuration configuration) throws RemoteException { + public void resized(Rect rect, Rect rect2, Rect rect3, Rect rect4, Rect rect5, Rect rect6, + boolean b, Configuration configuration) throws RemoteException { // pass for now. } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java index 25f7078..8575839 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java @@ -89,7 +89,7 @@ public final class BridgeWindowSession implements IWindowSession { @Override public int relayout(IWindow iWindow, int i, LayoutParams layoutParams, int i2, int i3, int i4, int i5, Rect rect, Rect rect2, Rect rect3, Rect rect4, Rect rect5, - Configuration configuration, Surface surface) throws RemoteException { + Rect rect6, Configuration configuration, Surface surface) throws RemoteException { // pass for now. return 0; } |