From e2ac5207f204ee26ba43c033d9ffb51f7daee2bd Mon Sep 17 00:00:00 2001 From: John Spurlock Date: Tue, 30 Oct 2012 11:05:55 -0400 Subject: [PATCH 01/14] Disable lockscreen window anim when launching camera. Prevent the exit animation from running when exiting the lockscreen due to launching the camera from the camera widget. Bug:7429770 Change-Id: I2a0148d84158fca11dda4c4a563fe5ab3236be81 --- .../policy/impl/keyguard/CameraWidgetFrame.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java b/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java index b38a9ed2934ce..66b8c7fd42fec 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java @@ -27,6 +27,7 @@ import android.util.Log; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; +import android.view.WindowManager; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.ImageView.ScaleType; @@ -47,6 +48,7 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli private final Handler mHandler = new Handler(); private final KeyguardActivityLauncher mActivityLauncher; private final Callbacks mCallbacks; + private final WindowManager mWindowManager; private View mWidgetView; private long mLaunchCameraStart; @@ -81,6 +83,7 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli mCallbacks = callbacks; mActivityLauncher = activityLauncher; + mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); } public static CameraWidgetFrame create(Context context, Callbacks callbacks, @@ -200,6 +203,7 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli scaleX, scaleY, startCenter, finishCenter)); + enableWindowExitAnimation(false); animate() .scaleX(scale) .scaleY(scale) @@ -305,6 +309,7 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli setScaleX(1); setScaleY(1); setTranslationY(0); + enableWindowExitAnimation(true); } @Override @@ -312,4 +317,14 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli super.onAttachedToWindow(); mHandler.post(mRenderRunnable); } + + private void enableWindowExitAnimation(boolean isEnabled) { + View root = getRootView(); + WindowManager.LayoutParams lp = (WindowManager.LayoutParams) root.getLayoutParams(); + int newWindowAnimations = isEnabled ? com.android.internal.R.style.Animation_LockScreen : 0; + if (newWindowAnimations != lp.windowAnimations) { + lp.windowAnimations = newWindowAnimations; + mWindowManager.updateViewLayout(root, lp); + } + } } From 70aa528b73fc54fe7896ac1ae349569d83caba59 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Tue, 30 Oct 2012 10:56:37 -0700 Subject: [PATCH 02/14] Fixing some regressions in tablet reordering/deleting. Change-Id: Ib3e48fa2606c0259603f6daf3b2ef72e1c8e292d --- .../impl/keyguard/KeyguardViewStateManager.java | 7 +++++++ .../policy/impl/keyguard/KeyguardWidgetPager.java | 4 +++- .../internal/policy/impl/keyguard/PagedView.java | 14 ++++++++------ 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java index 85245ba439b1c..14fd1f9d48ba5 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java @@ -58,6 +58,13 @@ public class KeyguardViewStateManager implements SlidingChallengeLayout.OnChalle return false; } + public boolean isChallengeOverlapping() { + if (mChallengeLayout != null) { + return mChallengeLayout.isChallengeOverlapping(); + } + return false; + } + public void setSecurityViewContainer(KeyguardSecurityView container) { mKeyguardSecurityContainer = container; } diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java index 800ccc08671b8..0a2f1aaa48a4f 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java @@ -589,7 +589,9 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit @Override public boolean onLongClick(View v) { // Disallow long pressing to reorder if the challenge is showing - if (!mViewStateManager.isChallengeShowing() && startReordering()) { + boolean isChallengeOverlapping = mViewStateManager.isChallengeShowing() && + mViewStateManager.isChallengeOverlapping(); + if (!isChallengeOverlapping && startReordering()) { return true; } return false; diff --git a/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java b/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java index 657a31f3d38c5..099ea079577a7 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java @@ -2072,15 +2072,15 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc // If we haven't flung-to-delete the current child, then we just animate the drag view // back into position + final Runnable onCompleteRunnable = new Runnable() { + @Override + public void run() { + onEndReordering(); + } + }; if (!mIsFlingingToDelete) { mPostReorderingPreZoomInRunnable = new Runnable() { public void run() { - Runnable onCompleteRunnable = new Runnable() { - @Override - public void run() { - onEndReordering(); - } - }; zoomIn(onCompleteRunnable); }; }; @@ -2091,6 +2091,8 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc snapToPage(indexOfChild(mDragView), 0); // Animate the drag view back to the front position animateDragViewToOriginalPosition(); + } else { + zoomIn(onCompleteRunnable); } } From 8a26bf5aea45650a14215d398c7d0909fcf80c43 Mon Sep 17 00:00:00 2001 From: Daniel Sandler Date: Tue, 30 Oct 2012 13:29:50 -0400 Subject: [PATCH 03/14] Impose a height & width downward on challenge views. This means that challenges may no longer wrap_content, even vertically. But it's the only way to rationalize across different challenges, some of which want to be a fixed size, some match_parent, and some wrap_content. This change also fixes some problems with the password view as well as PIN view (usable again on sw360 devices like Galaxy Nexus). Bug: 7427586 Change-Id: I648e68c5159fef7cf594d4bfe8f6d4bdd5da6b6a Proto-Id: I280b4875a9deee5dfb7409bdfa8ed0b96fbd0cff --- .../res/layout-land/keyguard_host_view.xml | 8 +- .../res/layout-port/keyguard_host_view.xml | 8 +- .../res/res/layout/keyguard_password_view.xml | 104 ++++++++---------- core/res/res/layout/keyguard_pin_view.xml | 26 ++--- core/res/res/values-sw380dp/dimens.xml | 23 ++++ core/res/res/values-sw720dp/dimens.xml | 5 + core/res/res/values/dimens.xml | 6 + core/res/res/values/symbols.xml | 1 + .../keyguard/KeyguardAbsKeyInputView.java | 3 +- .../policy/impl/keyguard/KeyguardPINView.java | 5 + .../impl/keyguard/KeyguardPasswordView.java | 5 + 11 files changed, 114 insertions(+), 80 deletions(-) create mode 100644 core/res/res/values-sw380dp/dimens.xml diff --git a/core/res/res/layout-land/keyguard_host_view.xml b/core/res/res/layout-land/keyguard_host_view.xml index bb455bdecbba0..67ac1d5298c0d 100644 --- a/core/res/res/layout-land/keyguard_host_view.xml +++ b/core/res/res/layout-land/keyguard_host_view.xml @@ -50,14 +50,14 @@ + android:gravity="bottom" + > - + android:layout_weight="1" + /> - + - + + + - + - - - + - - - - - - - + - @@ -112,7 +112,7 @@ android:layout_width="0px" android:layout_height="match_parent" android:layout_weight="1" - androidprv:textView="@+id/passwordEntry" + androidprv:textView="@+id/pinEntry" androidprv:digit="4" /> @@ -146,7 +146,7 @@ android:layout_width="0px" android:layout_height="match_parent" android:layout_weight="1" - androidprv:textView="@+id/passwordEntry" + androidprv:textView="@+id/pinEntry" androidprv:digit="7" /> @@ -185,7 +185,7 @@ android:layout_width="0px" android:layout_height="match_parent" android:layout_weight="1" - androidprv:textView="@+id/passwordEntry" + androidprv:textView="@+id/pinEntry" androidprv:digit="0" /> + + + + + 340dp + \ No newline at end of file diff --git a/core/res/res/values-sw720dp/dimens.xml b/core/res/res/values-sw720dp/dimens.xml index d6d2b6621a0df..ffb4e1152a820 100644 --- a/core/res/res/values-sw720dp/dimens.xml +++ b/core/res/res/values-sw720dp/dimens.xml @@ -112,4 +112,9 @@ 12sp + + 420dp + + + 420dp diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index b830e798f613d..c0b2b1fb4a783 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -303,6 +303,12 @@ 80dip + + 320dp + + + 400dp + 8dp diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 7ebf7e7bfd6b7..5a0088c7b9264 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1269,6 +1269,7 @@ + diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAbsKeyInputView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAbsKeyInputView.java index 9c21830cf710c..eabf5e026254d 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAbsKeyInputView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAbsKeyInputView.java @@ -87,13 +87,14 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout } } + protected abstract int getPasswordTextViewId(); protected abstract void resetState(); @Override protected void onFinishInflate() { mLockPatternUtils = new LockPatternUtils(mContext); - mPasswordEntry = (TextView) findViewById(R.id.passwordEntry); + mPasswordEntry = (TextView) findViewById(getPasswordTextViewId()); mPasswordEntry.setOnEditorActionListener(this); mPasswordEntry.addTextChangedListener(this); diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPINView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPINView.java index bea9aec13ed59..852240116c468 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPINView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPINView.java @@ -46,6 +46,11 @@ public class KeyguardPINView extends KeyguardAbsKeyInputView mPasswordEntry.setEnabled(true); } + @Override + protected int getPasswordTextViewId() { + return R.id.pinEntry; + } + @Override protected void onFinishInflate() { super.onFinishInflate(); diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java index b6334f0c83cc7..b35450cb4b71b 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java @@ -59,6 +59,11 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView mPasswordEntry.setEnabled(true); } + @Override + protected int getPasswordTextViewId() { + return R.id.passwordEntry; + } + @Override public boolean needsInput() { return true; From 5be14ded6762bc51fabbbecb1b2ec01a8c758631 Mon Sep 17 00:00:00 2001 From: Adam Cohen Date: Tue, 30 Oct 2012 11:19:48 -0700 Subject: [PATCH 04/14] Addressing a couple comments on previous CL Change-Id: I6ee066a5e6c2dadff921bb2ed7e91ea2601eec05 --- .../internal/policy/impl/keyguard/KeyguardWidgetFrame.java | 2 +- .../policy/impl/keyguard/SlidingChallengeLayout.java | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java index e9c90a77b55b5..b1ff049a1961e 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java @@ -62,7 +62,7 @@ public class KeyguardWidgetFrame extends FrameLayout { private float mBackgroundAlphaMultiplier = 1.0f; private Drawable mBackgroundDrawable; private Rect mBackgroundRect = new Rect(); - private static int mSmallWidgetHeight; + private int mSmallWidgetHeight; // Multiple callers may try and adjust the alpha of the frame. When a caller shows // the outlines, we give that caller control, and nobody else can fade them out. diff --git a/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java b/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java index 35eccbb1e8052..74b05dde38a34 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java @@ -702,11 +702,13 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout } else if (lp.childType == LayoutParams.CHILD_TYPE_SCRIM) { setScrimView(child); } + if (child.getVisibility() == GONE) continue; } - // We want to measure the challenge view first, for various reasons that I'd rather - // not get into here. + // We want to measure the challenge view first, since the KeyguardWidgetPager + // needs to do things its measure pass that are dependent on the challenge view + // having been measured. if (mChallengeView != null) { measureChildWithMargins(mChallengeView, widthSpec, 0, heightSpec, 0); } From 68d257d788f5154922cd605ab8079a5c0815dffc Mon Sep 17 00:00:00 2001 From: Brian Colonna Date: Tue, 30 Oct 2012 14:48:55 -0400 Subject: [PATCH 05/14] FUL uses square aspect ratio for all layouts fixes b/7426399 When the referenced bug was filed, face unlock was only showing as a tiny sliver on tablet layouts. Due to other changes in the lockscreen branch, it was no longer a sliver, but was still an incorrect layout, with a width much greater than height. This change makes face unlock square for all layouts. The face unlock RelativeLayout was replaced with a custom FaceUnlockView derived from RelativeLayout. The new view forces a square layout using the same technique used by LockPatternView. Note that there is still a bug where the pattern view covers the widget area on portrait tablet layouts. The face unlock view has this same issue, but may resolve itself when the pattern bug is fixed. Also note there are two other Face Unlock tablet bugs that existed before this change (and therefore are not caused by this change): - flash during transition from spotlight animation to camera preview - PIN backup is upper-left instead of centered Change-Id: I550eccfa3924f230a9dc43f0a9b59f1ea55a9273 --- .../internal/widget/FaceUnlockView.java | 67 +++++++++++++++++++ .../res/layout/keyguard_face_unlock_view.xml | 7 +- 2 files changed, 70 insertions(+), 4 deletions(-) create mode 100644 core/java/com/android/internal/widget/FaceUnlockView.java diff --git a/core/java/com/android/internal/widget/FaceUnlockView.java b/core/java/com/android/internal/widget/FaceUnlockView.java new file mode 100644 index 0000000000000..c8d65fcc56e0f --- /dev/null +++ b/core/java/com/android/internal/widget/FaceUnlockView.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.util.Log; +import android.view.View; +import android.widget.RelativeLayout; + +public class FaceUnlockView extends RelativeLayout { + private static final String TAG = "FaceUnlockView"; + + public FaceUnlockView(Context context) { + this(context, null); + } + + public FaceUnlockView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + private int resolveMeasured(int measureSpec, int desired) + { + int result = 0; + int specSize = MeasureSpec.getSize(measureSpec); + switch (MeasureSpec.getMode(measureSpec)) { + case MeasureSpec.UNSPECIFIED: + result = desired; + break; + case MeasureSpec.AT_MOST: + result = Math.max(specSize, desired); + break; + case MeasureSpec.EXACTLY: + default: + result = specSize; + } + return result; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + + final int minimumWidth = getSuggestedMinimumWidth(); + final int minimumHeight = getSuggestedMinimumHeight(); + int viewWidth = resolveMeasured(widthMeasureSpec, minimumWidth); + int viewHeight = resolveMeasured(heightMeasureSpec, minimumHeight); + + viewWidth = viewHeight = Math.min(viewWidth, viewHeight); + Log.v(TAG, "FaceUnlockView dimensions: " + viewWidth + "x" + viewHeight); + setMeasuredDimension(viewWidth, viewHeight); + } +} diff --git a/core/res/res/layout/keyguard_face_unlock_view.xml b/core/res/res/layout/keyguard_face_unlock_view.xml index ae7984c783337..976d0c6e5d840 100644 --- a/core/res/res/layout/keyguard_face_unlock_view.xml +++ b/core/res/res/layout/keyguard_face_unlock_view.xml @@ -30,10 +30,10 @@ android:layout_height="wrap_content" /> - @@ -55,8 +55,7 @@ android:background="#00000000" android:src="@*android:drawable/ic_facial_backup" /> - - + Date: Tue, 30 Oct 2012 12:03:18 -0700 Subject: [PATCH 06/14] Moving persistence calls to background. Change-Id: Ief3b0862dfd24d520ec88afb5bbb9954ee90f2ac --- .../impl/keyguard/KeyguardWidgetPager.java | 35 ++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java index 800ccc08671b8..c326a5aac244a 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java @@ -24,6 +24,8 @@ import android.animation.TimeInterpolator; import android.appwidget.AppWidgetHostView; import android.content.Context; import android.content.res.Resources; +import android.os.Handler; +import android.os.HandlerThread; import android.util.AttributeSet; import android.view.Gravity; import android.view.MotionEvent; @@ -33,7 +35,6 @@ import android.view.ViewGroup; import android.widget.FrameLayout; import com.android.internal.R; - import com.android.internal.widget.LockPatternUtils; import java.util.ArrayList; @@ -67,6 +68,10 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit private boolean mCameraWidgetEnabled; + // Background threads to deal with persistence + private HandlerThread mBgPersistenceWorkerThread; + private Handler mBgPersistenceWorkerHandler; + public KeyguardWidgetPager(Context context, AttributeSet attrs) { this(context, attrs, 0); } @@ -85,6 +90,9 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit Resources r = getResources(); mCameraWidgetEnabled = r.getBoolean(R.bool.kg_enable_camera_default_widget); + mBgPersistenceWorkerThread = new HandlerThread("KeyguardWidgetPager Persistence"); + mBgPersistenceWorkerThread.start(); + mBgPersistenceWorkerHandler = new Handler(mBgPersistenceWorkerThread.getLooper()); } public void setViewStateManager(KeyguardViewStateManager viewStateManager) { @@ -179,17 +187,28 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit public void onRemoveView(View v) { - int appWidgetId = ((KeyguardWidgetFrame) v).getContentAppWidgetId(); - mLockPatternUtils.removeAppWidget(appWidgetId); + final int appWidgetId = ((KeyguardWidgetFrame) v).getContentAppWidgetId(); + mBgPersistenceWorkerHandler.post(new Runnable() { + @Override + public void run() { + mLockPatternUtils.removeAppWidget(appWidgetId); + } + }); } - public void onAddView(View v, int index) { - int appWidgetId = ((KeyguardWidgetFrame) v).getContentAppWidgetId(); - getVisiblePages(mTempVisiblePagesRange); - boundByReorderablePages(true, mTempVisiblePagesRange); + public void onAddView(View v, final int index) { + final int appWidgetId = ((KeyguardWidgetFrame) v).getContentAppWidgetId(); + final int[] pagesRange = new int[mTempVisiblePagesRange.length]; + getVisiblePages(pagesRange); + boundByReorderablePages(true, pagesRange); // Subtract from the index to take into account pages before the reorderable // pages (e.g. the "add widget" page) - mLockPatternUtils.addAppWidget(appWidgetId, index - mTempVisiblePagesRange[0]); + mBgPersistenceWorkerHandler.post(new Runnable() { + @Override + public void run() { + mLockPatternUtils.addAppWidget(appWidgetId, index - pagesRange[0]); + } + }); } /* From 737798271e6e5b9466acef26ead061ecf6d0f292 Mon Sep 17 00:00:00 2001 From: John Spurlock Date: Tue, 30 Oct 2012 11:47:23 -0400 Subject: [PATCH 07/14] Render camera widget correctly after shell restart. Bug: 7440304 Change-Id: I1ad8573cc843142d77436fd8361d7fc613b09f21 --- .../impl/keyguard/CameraWidgetFrame.java | 37 +++++++++++++------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java b/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java index 66b8c7fd42fec..3dd0a8f3c2bbd 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java @@ -21,12 +21,14 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.Point; import android.os.Handler; import android.os.SystemClock; import android.util.Log; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; +import android.view.ViewGroup; import android.view.WindowManager; import android.widget.FrameLayout; import android.widget.ImageView; @@ -49,10 +51,10 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli private final KeyguardActivityLauncher mActivityLauncher; private final Callbacks mCallbacks; private final WindowManager mWindowManager; + private final Point mRenderedSize = new Point(); private View mWidgetView; private long mLaunchCameraStart; - private boolean mRendered; private boolean mActive; private boolean mChallengeActive; private boolean mTransitioning; @@ -144,16 +146,22 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli } public void render() { - if (mRendered) return; - try { int width = getRootView().getWidth(); int height = getRootView().getHeight(); - if (DEBUG) Log.d(TAG, String.format("render [%sx%s] %s", - width, height, Integer.toHexString(hashCode()))); + if (mRenderedSize.x == width && mRenderedSize.y == height) { + if (DEBUG) Log.d(TAG, String.format("already rendered at size=%sx%s", + width, height)); + return; + } if (width == 0 || height == 0) { return; } + if (DEBUG) Log.d(TAG, String.format("render size=%sx%s instance=%s at %s", + width, height, + Integer.toHexString(hashCode()), + SystemClock.uptimeMillis())); + Bitmap offscreen = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Canvas c = new Canvas(offscreen); mWidgetView.measure( @@ -162,7 +170,7 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli mWidgetView.layout(0, 0, width, height); mWidgetView.draw(c); ((ImageView)getChildAt(0)).setImageBitmap(offscreen); - mRendered = true; + mRenderedSize.set(width, height); } catch (Throwable t) { Log.w(TAG, "Error rendering camera widget", t); removeAllViews(); @@ -313,18 +321,23 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli } @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + if (DEBUG) Log.d(TAG, String.format("onSizeChanged new=%sx%s old=%sx%s at %s", + w, h, oldw, oldh, SystemClock.uptimeMillis())); mHandler.post(mRenderRunnable); + super.onSizeChanged(w, h, oldw, oldh); } private void enableWindowExitAnimation(boolean isEnabled) { View root = getRootView(); - WindowManager.LayoutParams lp = (WindowManager.LayoutParams) root.getLayoutParams(); + ViewGroup.LayoutParams lp = root.getLayoutParams(); + if (!(lp instanceof WindowManager.LayoutParams)) + return; + WindowManager.LayoutParams wlp = (WindowManager.LayoutParams) lp; int newWindowAnimations = isEnabled ? com.android.internal.R.style.Animation_LockScreen : 0; - if (newWindowAnimations != lp.windowAnimations) { - lp.windowAnimations = newWindowAnimations; - mWindowManager.updateViewLayout(root, lp); + if (newWindowAnimations != wlp.windowAnimations) { + wlp.windowAnimations = newWindowAnimations; + mWindowManager.updateViewLayout(root, wlp); } } } From bdca3c0a21ba15e8bb6d7ef0ca1b7e8024f98f19 Mon Sep 17 00:00:00 2001 From: Jim Miller Date: Mon, 29 Oct 2012 19:11:50 -0700 Subject: [PATCH 08/14] Implement correct music widget positioning in keyguard This always inserts the music widget to the left of the camera widget if it exists or as the right-most widget when music is playing. Fixes bug 7425361 Change-Id: Ida992fbdde254a2de0ab12c63e003ccfeab7a94a --- .../impl/keyguard/KeyguardHostView.java | 54 ++++++++++++------- .../KeyguardTransportControlView.java | 12 +---- .../impl/keyguard/KeyguardWidgetPager.java | 45 +++++++++++++++- 3 files changed, 82 insertions(+), 29 deletions(-) diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java index 3a01e64ff537d..c772f07078680 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java @@ -48,7 +48,6 @@ import android.view.View; import android.view.WindowManager; import android.view.animation.AnimationUtils; import android.widget.RemoteViews.OnClickHandler; -import android.widget.TextView; import com.android.internal.R; import com.android.internal.policy.impl.keyguard.KeyguardSecurityModel.SecurityMode; @@ -144,7 +143,7 @@ public class KeyguardHostView extends KeyguardViewBase { private int getWidgetPosition(int id) { final int children = mAppWidgetContainer.getChildCount(); for (int i = 0; i < children; i++) { - if (mAppWidgetContainer.getChildAt(i).getId() == id) { + if (mAppWidgetContainer.getWidgetPageAt(i).getContent().getId() == id) { return i; } } @@ -864,7 +863,8 @@ public class KeyguardHostView extends KeyguardViewBase { @Override LockPatternUtils getLockPatternUtils() { return mLockPatternUtils; - }}; + } + }; private void addDefaultWidgets() { LayoutInflater inflater = LayoutInflater.from(mContext); @@ -906,6 +906,33 @@ public class KeyguardHostView extends KeyguardViewBase { initializeTransportControl(); } + private void removeTransportFromWidgetPager() { + int page = getWidgetPosition(R.id.keyguard_transport_control); + if (page != -1) { + mAppWidgetContainer.removeWidget(mTransportControl); + + // XXX keep view attached so we still get show/hide events from AudioManager + KeyguardHostView.this.addView(mTransportControl); + mTransportControl.setVisibility(View.GONE); + mTransportState = TRANSPORT_GONE; + mTransportControl.post(mSwitchPageRunnable); + } + } + + private void addTransportToWidgetPager() { + if (getWidgetPosition(R.id.keyguard_transport_control) == -1) { + KeyguardHostView.this.removeView(mTransportControl); + // insert to left of camera if it exists, otherwise after right-most widget + int lastWidget = mAppWidgetContainer.getChildCount() - 1; + int position = 0; // handle no widget case + if (lastWidget >= 0) { + position = isCameraPage(lastWidget) ? lastWidget : lastWidget + 1; + } + mAppWidgetContainer.addWidget(mTransportControl, position); + mTransportControl.setVisibility(View.VISIBLE); + } + } + private void initializeTransportControl() { mTransportControl = (KeyguardTransportControlView) findViewById(R.id.keyguard_transport_control); @@ -917,24 +944,14 @@ public class KeyguardHostView extends KeyguardViewBase { mTransportControl.setKeyguardCallback(new TransportCallback() { @Override public void onListenerDetached() { - int page = getWidgetPosition(R.id.keyguard_transport_control); - if (page != -1) { - mAppWidgetContainer.removeView(mTransportControl); - // XXX keep view attached so we still get show/hide events from AudioManager - KeyguardHostView.this.addView(mTransportControl); - mTransportControl.setVisibility(View.GONE); - mTransportState = TRANSPORT_GONE; - mTransportControl.post(mSwitchPageRunnable); - } + removeTransportFromWidgetPager(); + mTransportControl.post(mSwitchPageRunnable); } @Override public void onListenerAttached() { - if (getWidgetPosition(R.id.keyguard_transport_control) == -1) { - KeyguardHostView.this.removeView(mTransportControl); - mAppWidgetContainer.addView(mTransportControl, 0); - mTransportControl.setVisibility(View.VISIBLE); - } + // Transport will be added when playstate changes... + mTransportControl.post(mSwitchPageRunnable); } @Override @@ -1058,6 +1075,7 @@ public class KeyguardHostView extends KeyguardViewBase { mTransportControl.isMusicPlaying() || mTransportState == TRANSPORT_VISIBLE; if (isMusicPlaying) { mTransportState = TRANSPORT_VISIBLE; + addTransportToWidgetPager(); } else if (mTransportState == TRANSPORT_VISIBLE) { mTransportState = TRANSPORT_INVISIBLE; } @@ -1081,7 +1099,7 @@ public class KeyguardHostView extends KeyguardViewBase { // if music playing, show transport if (isMusicPlaying) { if (DEBUG) Log.d(TAG, "Music playing, show transport"); - return mAppWidgetContainer.indexOfChild(mTransportControl); + return mAppWidgetContainer.getWidgetPageIndex(mTransportControl); } // if we have a valid sticky widget, show it diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardTransportControlView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardTransportControlView.java index 89f220a0cf2d0..d2846026324af 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardTransportControlView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardTransportControlView.java @@ -40,6 +40,7 @@ import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.view.View.OnClickListener; +import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; @@ -49,14 +50,13 @@ import java.lang.ref.WeakReference; /** * This is the widget responsible for showing music controls in keyguard. */ -public class KeyguardTransportControlView extends KeyguardWidgetFrame implements OnClickListener { +public class KeyguardTransportControlView extends FrameLayout implements OnClickListener { private static final int MSG_UPDATE_STATE = 100; private static final int MSG_SET_METADATA = 101; private static final int MSG_SET_TRANSPORT_CONTROLS = 102; private static final int MSG_SET_ARTWORK = 103; private static final int MSG_SET_GENERATION_ID = 104; - private static final int MAXDIM = 512; private static final int DISPLAY_TIMEOUT_MS = 5000; // 5s protected static final boolean DEBUG = false; protected static final String TAG = "TransportControlView"; @@ -260,14 +260,6 @@ public class KeyguardTransportControlView extends KeyguardWidgetFrame implements mAttached = false; } - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); -// int dim = Math.min(MAXDIM, Math.max(getWidth(), getHeight())); -// Log.v(TAG, "setting max bitmap size: " + dim + "x" + dim); -// mAudioManager.remoteControlDisplayUsesBitmapSize(mIRCD, dim, dim); - } - class Metadata { private String artist; private String trackTitle; diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java index 0a2f1aaa48a4f..4d8824668529b 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java @@ -25,6 +25,7 @@ import android.appwidget.AppWidgetHostView; import android.content.Context; import android.content.res.Resources; import android.util.AttributeSet; +import android.util.Slog; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; @@ -61,6 +62,7 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit private boolean mShowHintsOnLayout = false; private static final long CUSTOM_WIDGET_USER_ACTIVITY_TIMEOUT = 30000; + private static final String TAG = "KeyguardWidgetPager"; private int mPage = 0; private Callbacks mCallbacks; @@ -226,25 +228,40 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit } } - // We enforce that all children are KeyguardWidgetFrames + /** + * Use addWidget() instead. + * @deprecated + */ @Override public void addView(View child, int index) { enforceKeyguardWidgetFrame(child); super.addView(child, index); } + /** + * Use addWidget() instead. + * @deprecated + */ @Override public void addView(View child, int width, int height) { enforceKeyguardWidgetFrame(child); super.addView(child, width, height); } + /** + * Use addWidget() instead. + * @deprecated + */ @Override public void addView(View child, LayoutParams params) { enforceKeyguardWidgetFrame(child); super.addView(child, params); } + /** + * Use addWidget() instead. + * @deprecated + */ @Override public void addView(View child, int index, LayoutParams params) { enforceKeyguardWidgetFrame(child); @@ -596,4 +613,30 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit } return false; } + + public void removeWidget(View view) { + if (view instanceof KeyguardWidgetFrame) { + removeView(view); + } else { + // Assume view was wrapped by a KeyguardWidgetFrame in KeyguardWidgetPager#addWidget(). + // This supports legacy hard-coded "widgets" like KeyguardTransportControlView. + int pos = getWidgetPageIndex(view); + if (pos != -1) { + KeyguardWidgetFrame frame = (KeyguardWidgetFrame) getChildAt(pos); + frame.removeView(view); + removeView(frame); + } else { + Slog.w(TAG, "removeWidget() can't find:" + view); + } + } + } + + public int getWidgetPageIndex(View view) { + if (view instanceof KeyguardWidgetFrame) { + return indexOfChild(view); + } else { + // View was wrapped by a KeyguardWidgetFrame by KeyguardWidgetPager#addWidget() + return indexOfChild((KeyguardWidgetFrame)view.getParent()); + } + } } From 26e6c2e44235428717d7152b9e6398649452f1d2 Mon Sep 17 00:00:00 2001 From: Jim Miller Date: Tue, 30 Oct 2012 14:12:22 -0700 Subject: [PATCH 09/14] Attempt to fix bug on devices where multi-user support is disabled. Bug 7437751 Change-Id: Iff9f6a5a91fb9dd69b7176a5febb1d6e158d90b6 --- .../internal/policy/impl/keyguard/KeyguardHostView.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java index 3a01e64ff537d..a5f1ab2f45a99 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java @@ -1119,6 +1119,10 @@ public class KeyguardHostView extends KeyguardViewBase { } private void enableUserSelectorIfNecessary() { + if (!UserManager.supportsMultipleUsers()) { + return; // device doesn't support multi-user mode + } + // if there are multiple users, we need to enable to multi-user switcher UserManager mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE); List users = mUm.getUsers(true); From e0566da2dab8c3b9ddca43131f21ef58b79049c8 Mon Sep 17 00:00:00 2001 From: Jim Miller Date: Tue, 30 Oct 2012 14:57:29 -0700 Subject: [PATCH 10/14] Fill in logic in WidgetPager to ignore music when reordering. This moves music state management into KeyguardViewStateManager to allow KeyguardWidgetPager access to it. Fixes bug 7442977 Change-Id: I113b6d1c8848d60ae53b99e697b33e1e33d67853 --- .../impl/keyguard/KeyguardHostView.java | 23 ++++++++----------- .../keyguard/KeyguardViewStateManager.java | 15 ++++++++++++ .../impl/keyguard/KeyguardWidgetPager.java | 3 +-- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java index c772f07078680..3df83ecefe071 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java @@ -65,11 +65,6 @@ public class KeyguardHostView extends KeyguardViewBase { // also referenced in SecuritySettings.java static final int APPWIDGET_HOST_ID = 0x4B455947; - // transport control states - private static final int TRANSPORT_GONE = 0; - private static final int TRANSPORT_INVISIBLE = 1; - private static final int TRANSPORT_VISIBLE = 2; - private AppWidgetHost mAppWidgetHost; private KeyguardWidgetPager mAppWidgetContainer; private KeyguardSecurityViewFlipper mSecurityViewContainer; @@ -89,7 +84,6 @@ public class KeyguardHostView extends KeyguardViewBase { private KeyguardViewStateManager mViewStateManager; private Rect mTempRect = new Rect(); - private int mTransportState = TRANSPORT_GONE; /*package*/ interface TransportCallback { void onListenerDetached(); @@ -914,7 +908,7 @@ public class KeyguardHostView extends KeyguardViewBase { // XXX keep view attached so we still get show/hide events from AudioManager KeyguardHostView.this.addView(mTransportControl); mTransportControl.setVisibility(View.GONE); - mTransportState = TRANSPORT_GONE; + mViewStateManager.setTransportState(KeyguardViewStateManager.TRANSPORT_GONE); mTransportControl.post(mSwitchPageRunnable); } } @@ -1044,7 +1038,7 @@ public class KeyguardHostView extends KeyguardViewBase { saveStickyWidgetIndex(); Parcelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); - ss.transportState = mTransportState; + ss.transportState = mViewStateManager.getTransportState(); return ss; } @@ -1057,7 +1051,7 @@ public class KeyguardHostView extends KeyguardViewBase { } SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); - mTransportState = ss.transportState; + mViewStateManager.setTransportState(ss.transportState); post(mSwitchPageRunnable); } @@ -1071,13 +1065,14 @@ public class KeyguardHostView extends KeyguardViewBase { } private void showAppropriateWidgetPage() { - boolean isMusicPlaying = - mTransportControl.isMusicPlaying() || mTransportState == TRANSPORT_VISIBLE; + int state = mViewStateManager.getTransportState(); + boolean isMusicPlaying = mTransportControl.isMusicPlaying() + || state == KeyguardViewStateManager.TRANSPORT_VISIBLE; if (isMusicPlaying) { - mTransportState = TRANSPORT_VISIBLE; + mViewStateManager.setTransportState(KeyguardViewStateManager.TRANSPORT_VISIBLE); addTransportToWidgetPager(); - } else if (mTransportState == TRANSPORT_VISIBLE) { - mTransportState = TRANSPORT_INVISIBLE; + } else if (state == KeyguardViewStateManager.TRANSPORT_VISIBLE) { + mViewStateManager.setTransportState(KeyguardViewStateManager.TRANSPORT_INVISIBLE); } int pageToShow = getAppropriateWidgetPage(isMusicPlaying); mAppWidgetContainer.setCurrentPage(pageToShow); diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java index 14fd1f9d48ba5..e42cf1de55c0e 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java @@ -32,6 +32,13 @@ public class KeyguardViewStateManager implements SlidingChallengeLayout.OnChalle private static final int SCREEN_ON_RING_HINT_DELAY = 300; Handler mMainQueue = new Handler(Looper.myLooper()); + // transport control states + static final int TRANSPORT_GONE = 0; + static final int TRANSPORT_INVISIBLE = 1; + static final int TRANSPORT_VISIBLE = 2; + + private int mTransportState = TRANSPORT_GONE; + int mLastScrollState = SlidingChallengeLayout.SCROLL_STATE_IDLE; // Paged view state @@ -214,4 +221,12 @@ public class KeyguardViewStateManager implements SlidingChallengeLayout.OnChalle mMainQueue.postDelayed(mHideHintsRunnable, SCREEN_ON_HINT_DURATION); } + + public void setTransportState(int state) { + mTransportState = state; + } + + public int getTransportState() { + return mTransportState; + } } diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java index 4d8824668529b..ad898b38d13cf 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java @@ -431,8 +431,7 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit return true; } boolean isMusicWidgetVisible() { - // TODO: Make proper test once we have music in the list - return false; + return mViewStateManager.getTransportState() != KeyguardViewStateManager.TRANSPORT_GONE; } boolean isCameraWidgetVisible() { return mCameraWidgetEnabled; From ddbf138d11d9ad4fa9ec871b2fc5862dad20f02c Mon Sep 17 00:00:00 2001 From: Brian Colonna Date: Tue, 30 Oct 2012 18:34:39 -0400 Subject: [PATCH 11/14] Fixed misplacement of cancel(X) button for Face Unlock Before the FUL service started, the FUL cancel button was positioned off of the right side of the window. This was because the FaceUnlockView (derived from RelativeLayout) was calling super.onMeasure() incorrectly, preventing it from using the new 'square' size when laying out child views. Change-Id: I2f1e86617da5c8f37123febab2e433288bdea062 --- .../com/android/internal/widget/FaceUnlockView.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/core/java/com/android/internal/widget/FaceUnlockView.java b/core/java/com/android/internal/widget/FaceUnlockView.java index c8d65fcc56e0f..e3c124730ae54 100644 --- a/core/java/com/android/internal/widget/FaceUnlockView.java +++ b/core/java/com/android/internal/widget/FaceUnlockView.java @@ -53,15 +53,17 @@ public class FaceUnlockView extends RelativeLayout { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - final int minimumWidth = getSuggestedMinimumWidth(); final int minimumHeight = getSuggestedMinimumHeight(); int viewWidth = resolveMeasured(widthMeasureSpec, minimumWidth); int viewHeight = resolveMeasured(heightMeasureSpec, minimumHeight); - viewWidth = viewHeight = Math.min(viewWidth, viewHeight); - Log.v(TAG, "FaceUnlockView dimensions: " + viewWidth + "x" + viewHeight); - setMeasuredDimension(viewWidth, viewHeight); + final int chosenSize = Math.min(viewWidth, viewHeight); + final int newWidthMeasureSpec = + MeasureSpec.makeMeasureSpec(chosenSize, MeasureSpec.AT_MOST); + final int newHeightMeasureSpec = + MeasureSpec.makeMeasureSpec(chosenSize, MeasureSpec.AT_MOST); + + super.onMeasure(newWidthMeasureSpec, newHeightMeasureSpec); } } From 70009e426a39cc2940d264c4fb87a4402c60b0ff Mon Sep 17 00:00:00 2001 From: Adam Cohen Date: Tue, 30 Oct 2012 16:48:22 -0700 Subject: [PATCH 12/14] Making the reordering play nice with the 3D widget carousel -> Ensuring that transforms, hidden side pages, alphas all transition and fade seamlessly to and from the carousel Change-Id: I6197f17899135a9e551ff1691c63ad5a2bb1d0f7 --- .../impl/keyguard/KeyguardHostView.java | 2 +- .../keyguard/KeyguardViewStateManager.java | 8 + .../impl/keyguard/KeyguardWidgetCarousel.java | 160 +++++++++++++++++- .../impl/keyguard/KeyguardWidgetPager.java | 51 ++++-- .../policy/impl/keyguard/PagedView.java | 4 +- 5 files changed, 201 insertions(+), 24 deletions(-) diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java index a5f1ab2f45a99..a182ec39205e1 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java @@ -162,6 +162,7 @@ public class KeyguardHostView extends KeyguardViewBase { addDefaultWidgets(); addWidgetsFromSettings(); + mSwitchPageRunnable.run(); mViewStateManager = new KeyguardViewStateManager(); SlidingChallengeLayout slider = @@ -217,7 +218,6 @@ public class KeyguardHostView extends KeyguardViewBase { protected void onAttachedToWindow() { super.onAttachedToWindow(); mAppWidgetHost.startListening(); - post(mSwitchPageRunnable); } @Override diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java index 14fd1f9d48ba5..eed8104864731 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java @@ -86,6 +86,14 @@ public class KeyguardViewStateManager implements SlidingChallengeLayout.OnChalle mChallengeLayout.showBouncer(); } + public void fadeOutSecurity(int duration) { + ((View) mKeyguardSecurityContainer).animate().alpha(0).setDuration(duration); + } + + public void fadeInSecurity(int duration) { + ((View) mKeyguardSecurityContainer).animate().alpha(1f).setDuration(duration); + } + public void onPageSwitch(View newPage, int newPageIndex) { // Reset the previous page size and ensure the current page is sized appropriately. // We only modify the page state if it is not currently under control by the slider. diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java index cf16ef2a715de..bcba96cbc451f 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java @@ -15,9 +15,19 @@ */ package com.android.internal.policy.impl.keyguard; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.animation.PropertyValuesHolder; import android.content.Context; import android.util.AttributeSet; import android.view.View; +import android.view.animation.AccelerateInterpolator; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.Interpolator; + +import java.util.ArrayList; import com.android.internal.R; @@ -26,6 +36,8 @@ public class KeyguardWidgetCarousel extends KeyguardWidgetPager { private float mAdjacentPagesAngle; private static float MAX_SCROLL_PROGRESS = 1.3f; private static float CAMERA_DISTANCE = 10000; + protected AnimatorSet mChildrenTransformsAnimator; + float[] mTmpTransform = new float[3]; public KeyguardWidgetCarousel(Context context, AttributeSet attrs) { this(context, attrs, 0); @@ -48,13 +60,15 @@ public class KeyguardWidgetCarousel extends KeyguardWidgetPager { View child = getChildAt(index); if (child == null) return 0f; + float maxAlpha = KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER; + float scrollProgress = getScrollProgress(screenCenter, child, index); if (!isOverScrollChild(index, scrollProgress)) { scrollProgress = getBoundedScrollProgress(screenCenter, child, index); - float alpha = 1 - Math.abs(scrollProgress / MAX_SCROLL_PROGRESS); + float alpha = maxAlpha - maxAlpha * Math.abs(scrollProgress / MAX_SCROLL_PROGRESS); return alpha; } else { - return 1f; + return maxAlpha; } } @@ -73,16 +87,17 @@ public class KeyguardWidgetCarousel extends KeyguardWidgetPager { } } } - } @Override protected void screenScrolled(int screenCenter) { mScreenCenter = screenCenter; updatePageAlphaValues(screenCenter); + if (isReordering(false)) return; for (int i = 0; i < getChildCount(); i++) { KeyguardWidgetFrame v = getWidgetPageAt(i); float scrollProgress = getScrollProgress(screenCenter, v, i); + float boundedProgress = getBoundedScrollProgress(screenCenter, v, i); if (v == mDragView || v == null) continue; v.setCameraDistance(CAMERA_DISTANCE); @@ -90,17 +105,15 @@ public class KeyguardWidgetCarousel extends KeyguardWidgetPager { v.setRotationY(- OVERSCROLL_MAX_ROTATION * scrollProgress); v.setOverScrollAmount(Math.abs(scrollProgress), scrollProgress < 0); } else { - scrollProgress = getBoundedScrollProgress(screenCenter, v, i); int width = v.getMeasuredWidth(); - float pivotX = (width / 2f) + scrollProgress * (width / 2f); + float pivotX = (width / 2f) + boundedProgress * (width / 2f); float pivotY = v.getMeasuredHeight() / 2; - float rotationY = - mAdjacentPagesAngle * scrollProgress; + float rotationY = - mAdjacentPagesAngle * boundedProgress; v.setPivotX(pivotX); v.setPivotY(pivotY); v.setRotationY(rotationY); v.setOverScrollAmount(0f, false); } - float alpha = v.getAlpha(); // If the view has 0 alpha, we set it to be invisible so as to prevent // it from accepting touches @@ -111,4 +124,137 @@ public class KeyguardWidgetCarousel extends KeyguardWidgetPager { } } } + + void animatePagesToNeutral() { + if (mChildrenTransformsAnimator != null) { + mChildrenTransformsAnimator.cancel(); + mChildrenTransformsAnimator = null; + } + + int count = getChildCount(); + PropertyValuesHolder alpha; + PropertyValuesHolder outlineAlpha; + PropertyValuesHolder rotationY; + ArrayList anims = new ArrayList(); + + for (int i = 0; i < count; i++) { + KeyguardWidgetFrame child = getWidgetPageAt(i); + boolean inVisibleRange = (i >= mCurrentPage - 1 && i <= mCurrentPage + 1); + if (!inVisibleRange) { + child.setRotationY(0f); + } + alpha = PropertyValuesHolder.ofFloat("contentAlpha", 1.0f); + outlineAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha", 1.0f); + rotationY = PropertyValuesHolder.ofFloat("rotationY", 0f); + ObjectAnimator a = ObjectAnimator.ofPropertyValuesHolder(child, alpha, outlineAlpha, rotationY); + child.setVisibility(VISIBLE); + if (!inVisibleRange) { + a.setInterpolator(mSlowFadeInterpolator); + } + anims.add(a); + } + + int duration = REORDERING_ZOOM_IN_OUT_DURATION; + mChildrenTransformsAnimator = new AnimatorSet(); + mChildrenTransformsAnimator.playTogether(anims); + + mChildrenTransformsAnimator.setDuration(duration); + mChildrenTransformsAnimator.start(); + } + + private void getTransformForPage(int screenCenter, int index, float[] transform) { + View child = getChildAt(index); + float boundedProgress = getBoundedScrollProgress(screenCenter, child, index); + float rotationY = - mAdjacentPagesAngle * boundedProgress; + int width = child.getMeasuredWidth(); + float pivotX = (width / 2f) + boundedProgress * (width / 2f); + float pivotY = child.getMeasuredHeight() / 2; + + transform[0] = pivotX; + transform[1] = pivotY; + transform[2] = rotationY; + } + + Interpolator mFastFadeInterpolator = new Interpolator() { + Interpolator mInternal = new DecelerateInterpolator(1.5f); + float mFactor = 2.5f; + @Override + public float getInterpolation(float input) { + return mInternal.getInterpolation(Math.min(mFactor * input, 1f)); + } + }; + + Interpolator mSlowFadeInterpolator = new Interpolator() { + Interpolator mInternal = new AccelerateInterpolator(1.5f); + float mFactor = 1.3f; + @Override + public float getInterpolation(float input) { + input -= (1 - 1 / mFactor); + input = mFactor * Math.max(input, 0f); + return mInternal.getInterpolation(input); + } + }; + + void animatePagesToCarousel() { + if (mChildrenTransformsAnimator != null) { + mChildrenTransformsAnimator.cancel(); + mChildrenTransformsAnimator = null; + } + + int count = getChildCount(); + PropertyValuesHolder alpha; + PropertyValuesHolder outlineAlpha; + PropertyValuesHolder rotationY; + PropertyValuesHolder pivotX; + PropertyValuesHolder pivotY; + ArrayList anims = new ArrayList(); + + for (int i = 0; i < count; i++) { + KeyguardWidgetFrame child = getWidgetPageAt(i); + float finalAlpha = getAlphaForPage(mScreenCenter, i); + getTransformForPage(mScreenCenter, i, mTmpTransform); + + boolean inVisibleRange = (i >= mCurrentPage - 1 && i <= mCurrentPage + 1); + + ObjectAnimator a; + alpha = PropertyValuesHolder.ofFloat("contentAlpha", finalAlpha); + outlineAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha", finalAlpha); + pivotX = PropertyValuesHolder.ofFloat("pivotX", mTmpTransform[0]); + pivotY = PropertyValuesHolder.ofFloat("pivotY", mTmpTransform[1]); + rotationY = PropertyValuesHolder.ofFloat("rotationY", mTmpTransform[2]); + + if (inVisibleRange) { + // for the central pages we animate into a rotated state + a = ObjectAnimator.ofPropertyValuesHolder(child, alpha, outlineAlpha, + pivotX, pivotY, rotationY); + } else { + a = ObjectAnimator.ofPropertyValuesHolder(child, alpha, outlineAlpha); + a.setInterpolator(mFastFadeInterpolator); + } + anims.add(a); + } + + int duration = REORDERING_ZOOM_IN_OUT_DURATION; + mChildrenTransformsAnimator = new AnimatorSet(); + mChildrenTransformsAnimator.playTogether(anims); + + mChildrenTransformsAnimator.setDuration(duration); + mChildrenTransformsAnimator.start(); + } + + protected void reorderStarting() { + mViewStateManager.fadeOutSecurity(REORDERING_ZOOM_IN_OUT_DURATION); + animatePagesToNeutral(); + } + + protected boolean zoomIn(final Runnable onCompleteRunnable) { + animatePagesToCarousel(); + return super.zoomIn(onCompleteRunnable); + } + + @Override + protected void onEndReordering() { + super.onEndReordering(); + mViewStateManager.fadeInSecurity(REORDERING_ZOOM_IN_OUT_DURATION); + } } diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java index 738df1d3caf8e..bddd6edc7586f 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java @@ -47,7 +47,7 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit protected static float OVERSCROLL_MAX_ROTATION = 30; private static final boolean PERFORM_OVERSCROLL_ROTATION = true; - private KeyguardViewStateManager mViewStateManager; + protected KeyguardViewStateManager mViewStateManager; private LockPatternUtils mLockPatternUtils; // Related to the fading in / out background outlines @@ -59,7 +59,7 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit protected int mScreenCenter; private boolean mHasLayout = false; private boolean mHasMeasure = false; - private boolean mShowHintsOnLayout = false; + boolean showHintsAfterLayout = false; private static final long CUSTOM_WIDGET_USER_ACTIVITY_TIMEOUT = 30000; @@ -291,7 +291,9 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit if (mViewStateManager != null) { mViewStateManager.onPageBeginMoving(); } - showOutlinesAndSidePages(); + if (!isReordering(false)) { + showOutlinesAndSidePages(); + } userActivity(); } @@ -300,17 +302,22 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit if (mViewStateManager != null) { mViewStateManager.onPageEndMoving(); } - hideOutlinesAndSidePages(); + + // In the reordering case, the pages will be faded appropriately on completion + // of the zoom in animation. + if (!isReordering(false)) { + hideOutlinesAndSidePages(); + } } - private void enablePageLayers() { + protected void enablePageLayers() { int children = getChildCount(); for (int i = 0; i < children; i++) { getWidgetPageAt(i).enableHardwareLayersForContent(); } } - private void disablePageLayers() { + protected void disablePageLayers() { int children = getChildCount(); for (int i = 0; i < children; i++) { getWidgetPageAt(i).disableHardwareLayersForContent(); @@ -440,10 +447,15 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit return mCameraWidgetEnabled; } + protected void reorderStarting() { + showOutlinesAndSidePages(); + } + @Override protected void onStartReordering() { super.onStartReordering(); - showOutlinesAndSidePages(); + enablePageLayers(); + reorderStarting(); } @Override @@ -453,7 +465,6 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit } void showOutlinesAndSidePages() { - enablePageLayers(); animateOutlinesAndSidePages(true); } @@ -466,7 +477,7 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit showOutlinesAndSidePages(); } else { // The layout hints depend on layout being run once - mShowHintsOnLayout = true; + showHintsAfterLayout = true; } } @@ -477,16 +488,17 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit mHasLayout = false; } + @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); - if (mShowHintsOnLayout) { + if (showHintsAfterLayout) { post(new Runnable() { @Override public void run() { showOutlinesAndSidePages(); } }); - mShowHintsOnLayout = false; + showHintsAfterLayout = false; } mHasLayout = true; } @@ -523,17 +535,22 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit } void animateOutlinesAndSidePages(final boolean show) { + animateOutlinesAndSidePages(show, -1); + } + + void animateOutlinesAndSidePages(final boolean show, int duration) { if (mChildrenOutlineFadeAnimation != null) { mChildrenOutlineFadeAnimation.cancel(); mChildrenOutlineFadeAnimation = null; } - int count = getChildCount(); PropertyValuesHolder alpha; ArrayList anims = new ArrayList(); - int duration = show ? CHILDREN_OUTLINE_FADE_IN_DURATION : - CHILDREN_OUTLINE_FADE_OUT_DURATION; + if (duration == -1) { + duration = show ? CHILDREN_OUTLINE_FADE_IN_DURATION : + CHILDREN_OUTLINE_FADE_OUT_DURATION; + } int curPage = getNextPage(); for (int i = 0; i < count; i++) { @@ -559,6 +576,12 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit mChildrenOutlineFadeAnimation.setDuration(duration); mChildrenOutlineFadeAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + if (show) { + enablePageLayers(); + } + } @Override public void onAnimationEnd(Animator animation) { if (!show) { diff --git a/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java b/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java index 099ea079577a7..c93b11af89da8 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java @@ -1995,7 +1995,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc } // "Zooms out" the PagedView to reveal more side pages - boolean zoomOut() { + protected boolean zoomOut() { if (mZoomInOutAnim != null && mZoomInOutAnim.isRunning()) { mZoomInOutAnim.cancel(); } @@ -2097,7 +2097,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc } // "Zooms in" the PagedView to highlight the current page - boolean zoomIn(final Runnable onCompleteRunnable) { + protected boolean zoomIn(final Runnable onCompleteRunnable) { if (mZoomInOutAnim != null && mZoomInOutAnim.isRunning()) { mZoomInOutAnim.cancel(); } From 54d181db0e7a4335918b4c38f4418430ca99b6c1 Mon Sep 17 00:00:00 2001 From: Danielle Millett Date: Tue, 30 Oct 2012 20:18:44 -0400 Subject: [PATCH 13/14] Removed makeInvisible() function This is now being done inside stopUI instead of its own separate call since it needs to be done on the UI thread inside FaceLockService. Change-Id: Iaf3a203f7f201ba4dde4c878f457e765f11e6c0e --- .../com/android/internal/policy/IFaceLockInterface.aidl | 1 - .../android/internal/policy/impl/keyguard/FaceUnlock.java | 7 ------- 2 files changed, 8 deletions(-) diff --git a/core/java/com/android/internal/policy/IFaceLockInterface.aidl b/core/java/com/android/internal/policy/IFaceLockInterface.aidl index a017722439d4f..017801bbf8869 100644 --- a/core/java/com/android/internal/policy/IFaceLockInterface.aidl +++ b/core/java/com/android/internal/policy/IFaceLockInterface.aidl @@ -23,7 +23,6 @@ interface IFaceLockInterface { void startUi(IBinder containingWindowToken, int x, int y, int width, int height, boolean useLiveliness); void stopUi(); - void makeInvisible(); void registerCallback(IFaceLockCallback cb); void unregisterCallback(IFaceLockCallback cb); } diff --git a/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java b/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java index cae598cc7d99e..faf0ca0c0fd07 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java @@ -151,13 +151,6 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback { } boolean mWasRunning = mIsRunning; - try { - if (mService != null) { - mService.makeInvisible(); - } - } catch (RemoteException e) { - Log.e(TAG, "Caught exception making Face Unlock invisible: " + e.toString()); - } stopUi(); From ab8635d179124e379385aa02020ca3a216944a25 Mon Sep 17 00:00:00 2001 From: Adam Cohen Date: Tue, 30 Oct 2012 17:31:32 -0700 Subject: [PATCH 14/14] Fix content alpha Change-Id: I13e8ad73baf768976240c1c7c5a2cb05d5d62061 --- .../impl/keyguard/KeyguardWidgetCarousel.java | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java index bcba96cbc451f..2e83b42b0e4c2 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java @@ -60,15 +60,13 @@ public class KeyguardWidgetCarousel extends KeyguardWidgetPager { View child = getChildAt(index); if (child == null) return 0f; - float maxAlpha = KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER; - float scrollProgress = getScrollProgress(screenCenter, child, index); if (!isOverScrollChild(index, scrollProgress)) { scrollProgress = getBoundedScrollProgress(screenCenter, child, index); - float alpha = maxAlpha - maxAlpha * Math.abs(scrollProgress / MAX_SCROLL_PROGRESS); + float alpha = 1.0f - 1.0f * Math.abs(scrollProgress / MAX_SCROLL_PROGRESS); return alpha; } else { - return maxAlpha; + return 1.0f; } } @@ -81,9 +79,8 @@ public class KeyguardWidgetCarousel extends KeyguardWidgetPager { for (int i = 0; i < getChildCount(); i++) { KeyguardWidgetFrame child = getWidgetPageAt(i); if (child != null) { - float alpha = getAlphaForPage(screenCenter, i); - child.setBackgroundAlpha(alpha); - child.setContentAlpha(alpha); + child.setBackgroundAlpha(getOutlineAlphaForPage(screenCenter, i)); + child.setContentAlpha(getAlphaForPage(screenCenter, i)); } } } @@ -144,7 +141,8 @@ public class KeyguardWidgetCarousel extends KeyguardWidgetPager { child.setRotationY(0f); } alpha = PropertyValuesHolder.ofFloat("contentAlpha", 1.0f); - outlineAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha", 1.0f); + outlineAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha", + KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER); rotationY = PropertyValuesHolder.ofFloat("rotationY", 0f); ObjectAnimator a = ObjectAnimator.ofPropertyValuesHolder(child, alpha, outlineAlpha, rotationY); child.setVisibility(VISIBLE); @@ -212,13 +210,14 @@ public class KeyguardWidgetCarousel extends KeyguardWidgetPager { for (int i = 0; i < count; i++) { KeyguardWidgetFrame child = getWidgetPageAt(i); float finalAlpha = getAlphaForPage(mScreenCenter, i); + float finalOutlineAlpha = getOutlineAlphaForPage(mScreenCenter, i); getTransformForPage(mScreenCenter, i, mTmpTransform); boolean inVisibleRange = (i >= mCurrentPage - 1 && i <= mCurrentPage + 1); ObjectAnimator a; alpha = PropertyValuesHolder.ofFloat("contentAlpha", finalAlpha); - outlineAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha", finalAlpha); + outlineAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha", finalOutlineAlpha); pivotX = PropertyValuesHolder.ofFloat("pivotX", mTmpTransform[0]); pivotY = PropertyValuesHolder.ofFloat("pivotY", mTmpTransform[1]); rotationY = PropertyValuesHolder.ofFloat("rotationY", mTmpTransform[2]);