diff options
| author | 2012-10-30 18:04:31 -0700 | |
|---|---|---|
| committer | 2012-10-30 18:04:31 -0700 | |
| commit | 5c12bc5851056f114893f3d381f9fc8785e2cdb0 (patch) | |
| tree | 17878b3d5f64c9de966c154fcabf0c86d5e98349 | |
| parent | 20329dcb37fffca1de3ded6b58341e87cc43c4a9 (diff) | |
| parent | a371e5315ea2f632c80b56e1f8665765414df980 (diff) | |
Merge remote-tracking branch 'goog/jb-mr1-lockscreen-dev' into jb-mr1-dev
26 files changed, 589 insertions, 193 deletions
diff --git a/core/java/com/android/internal/policy/IFaceLockInterface.aidl b/core/java/com/android/internal/policy/IFaceLockInterface.aidl index a017722439d4..017801bbf886 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/core/java/com/android/internal/widget/FaceUnlockView.java b/core/java/com/android/internal/widget/FaceUnlockView.java new file mode 100644 index 000000000000..e3c124730ae5 --- /dev/null +++ b/core/java/com/android/internal/widget/FaceUnlockView.java @@ -0,0 +1,69 @@ +/* + * 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) { + final int minimumWidth = getSuggestedMinimumWidth(); + final int minimumHeight = getSuggestedMinimumHeight(); + int viewWidth = resolveMeasured(widthMeasureSpec, minimumWidth); + int viewHeight = resolveMeasured(heightMeasureSpec, minimumHeight); + + 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); + } +} diff --git a/core/res/res/layout-land/keyguard_host_view.xml b/core/res/res/layout-land/keyguard_host_view.xml index bb455bdecbba..67ac1d5298c0 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 @@ <com.android.internal.policy.impl.keyguard.KeyguardSecurityContainer android:id="@+id/keyguard_security_container" - android:layout_width="wrap_content" - android:layout_height="wrap_content" + android:layout_width="@dimen/keyguard_security_width" + android:layout_height="@dimen/keyguard_security_height" androidprv:layout_childType="challenge" androidprv:layout_centerWithinArea="0.55"> <com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper android:id="@+id/view_flipper" - android:layout_width="wrap_content" - android:layout_height="wrap_content" + android:layout_width="match_parent" + android:layout_height="match_parent" android:clipChildren="false" android:clipToPadding="false" android:paddingLeft="@dimen/keyguard_security_view_margin" diff --git a/core/res/res/layout-port/keyguard_host_view.xml b/core/res/res/layout-port/keyguard_host_view.xml index ed55e61ce5b2..544447149eb8 100644 --- a/core/res/res/layout-port/keyguard_host_view.xml +++ b/core/res/res/layout-port/keyguard_host_view.xml @@ -51,8 +51,8 @@ <com.android.internal.policy.impl.keyguard.KeyguardSecurityContainer android:id="@+id/keyguard_security_container" - android:layout_width="wrap_content" - android:layout_height="wrap_content" + android:layout_width="@dimen/keyguard_security_width" + android:layout_height="@dimen/keyguard_security_height" androidprv:layout_childType="challenge" android:layout_marginLeft="@dimen/kg_edge_swipe_region_size" android:layout_marginRight="@dimen/kg_edge_swipe_region_size" @@ -60,8 +60,8 @@ android:gravity="bottom|center_horizontal"> <com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper android:id="@+id/view_flipper" - android:layout_width="wrap_content" - android:layout_height="wrap_content" + android:layout_width="match_parent" + android:layout_height="match_parent" android:clipChildren="false" android:clipToPadding="false" android:paddingLeft="@dimen/keyguard_security_view_margin" diff --git a/core/res/res/layout/keyguard_face_unlock_view.xml b/core/res/res/layout/keyguard_face_unlock_view.xml index ae7984c78333..976d0c6e5d84 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" /> - <RelativeLayout + <com.android.internal.widget.FaceUnlockView android:id="@+id/face_unlock_area_view" android:layout_width="match_parent" - android:layout_height="@*android:dimen/face_unlock_height" + android:layout_height="0dp" android:background="@*android:drawable/intro_bg" android:gravity="center" android:layout_weight="1"> @@ -55,8 +55,7 @@ android:background="#00000000" android:src="@*android:drawable/ic_facial_backup" /> - - </RelativeLayout> + </com.android.internal.widget.FaceUnlockView> <include layout="@layout/keyguard_emergency_carrier_area" android:id="@+id/keyguard_selector_fade_container" diff --git a/core/res/res/layout/keyguard_password_view.xml b/core/res/res/layout/keyguard_password_view.xml index a184415919f6..b6faf5be123c 100644 --- a/core/res/res/layout/keyguard_password_view.xml +++ b/core/res/res/layout/keyguard_password_view.xml @@ -22,73 +22,61 @@ android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_gravity="center"> + android:gravity="bottom" + > - <FrameLayout + <Space android:layout_width="match_parent" android:layout_height="0dp" - android:layout_weight="1"> + android:layout_weight="1" + /> - <include layout="@layout/keyguard_message_area" - android:layout_width="match_parent" - android:layout_height="wrap_content" - /> - - <LinearLayout - android:layout_height="wrap_content" - android:layout_width="match_parent" - android:orientation="vertical" - android:layout_gravity="center"> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical"> + <include layout="@layout/keyguard_message_area" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> - <!-- Password entry field --> - <!-- Note: the entire container is styled to look like the edit field, - since the backspace/IME switcher looks better inside --> - <LinearLayout - android:layout_gravity="center_vertical|fill_horizontal" - android:layout_height="wrap_content" - android:layout_width="match_parent" - android:orientation="horizontal" - android:background="#70000000" - android:layout_marginStart="4dip" - android:layout_marginEnd="4dip"> + <!-- Password entry field --> + <!-- Note: the entire container is styled to look like the edit field, + since the backspace/IME switcher looks better inside --> + <LinearLayout + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:orientation="horizontal" + android:background="#70000000" + android:layout_marginTop="8dp" + android:layout_marginBottom="8dp" + > - <EditText android:id="@+id/passwordEntry" - android:layout_width="0dip" - android:layout_height="wrap_content" - android:layout_weight="1" - android:gravity="center_horizontal" - android:layout_gravity="center_vertical" - android:layout_marginStart="@*android:dimen/keyguard_lockscreen_pin_margin_left" - android:singleLine="true" - android:textStyle="normal" - android:inputType="textPassword" - android:textSize="36sp" - android:background="@null" - android:textAppearance="?android:attr/textAppearanceMedium" - android:textColor="#ffffffff" - android:imeOptions="flagForceAscii|actionDone" - /> + <EditText android:id="@+id/passwordEntry" + android:layout_width="0dip" + android:layout_height="wrap_content" + android:layout_weight="1" + android:gravity="center_horizontal" + android:layout_gravity="center_vertical" + android:layout_marginStart="@*android:dimen/keyguard_lockscreen_pin_margin_left" + android:singleLine="true" + android:textStyle="normal" + android:inputType="textPassword" + android:textSize="36sp" + android:background="@null" + android:textAppearance="?android:attr/textAppearanceMedium" + android:textColor="#ffffffff" + android:imeOptions="flagForceAscii|actionDone" + /> - <ImageView android:id="@+id/switch_ime_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:src="@*android:drawable/ic_lockscreen_ime" - android:clickable="true" - android:padding="8dip" - android:layout_gravity="center" - android:background="?android:attr/selectableItemBackground" - android:visibility="gone" - /> + <ImageView android:id="@+id/switch_ime_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:src="@*android:drawable/ic_lockscreen_ime" + android:clickable="true" + android:padding="8dip" + android:layout_gravity="center" + android:background="?android:attr/selectableItemBackground" + android:visibility="gone" + /> - </LinearLayout> - </LinearLayout> </LinearLayout> - </FrameLayout> + <include layout="@layout/keyguard_emergency_carrier_area" android:id="@+id/keyguard_selector_fade_container" android:layout_width="match_parent" diff --git a/core/res/res/layout/keyguard_pin_view.xml b/core/res/res/layout/keyguard_pin_view.xml index d62570b4a857..19e0a27c30d3 100644 --- a/core/res/res/layout/keyguard_pin_view.xml +++ b/core/res/res/layout/keyguard_pin_view.xml @@ -21,8 +21,8 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:androidprv="http://schemas.android.com/apk/res/android" android:id="@+id/keyguard_pin_view" - android:layout_width="350dp" - android:layout_height="350dp" + android:layout_width="match_parent" + android:layout_height="match_parent" android:orientation="vertical" > <include layout="@layout/keyguard_message_area" @@ -35,7 +35,7 @@ android:orientation="horizontal" android:layout_weight="1" > - <TextView android:id="@+id/passwordEntry" + <TextView android:id="@+id/pinEntry" android:editable="true" android:layout_width="0dip" android:layout_height="match_parent" @@ -78,7 +78,7 @@ android:layout_width="0px" android:layout_height="match_parent" android:layout_weight="1" - androidprv:textView="@+id/passwordEntry" + androidprv:textView="@+id/pinEntry" androidprv:digit="1" /> <view class="com.android.internal.policy.impl.keyguard.NumPadKey" @@ -87,7 +87,7 @@ android:layout_width="0px" android:layout_height="match_parent" android:layout_weight="1" - androidprv:textView="@+id/passwordEntry" + androidprv:textView="@+id/pinEntry" androidprv:digit="2" /> <view class="com.android.internal.policy.impl.keyguard.NumPadKey" @@ -96,7 +96,7 @@ android:layout_width="0px" android:layout_height="match_parent" android:layout_weight="1" - androidprv:textView="@+id/passwordEntry" + androidprv:textView="@+id/pinEntry" androidprv:digit="3" /> </LinearLayout> @@ -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" /> <view class="com.android.internal.policy.impl.keyguard.NumPadKey" @@ -121,7 +121,7 @@ android:layout_width="0px" android:layout_height="match_parent" android:layout_weight="1" - androidprv:textView="@+id/passwordEntry" + androidprv:textView="@+id/pinEntry" androidprv:digit="5" /> <view class="com.android.internal.policy.impl.keyguard.NumPadKey" @@ -130,7 +130,7 @@ android:layout_width="0px" android:layout_height="match_parent" android:layout_weight="1" - androidprv:textView="@+id/passwordEntry" + androidprv:textView="@+id/pinEntry" androidprv:digit="6" /> </LinearLayout> @@ -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" /> <view class="com.android.internal.policy.impl.keyguard.NumPadKey" @@ -155,7 +155,7 @@ android:layout_width="0px" android:layout_height="match_parent" android:layout_weight="1" - androidprv:textView="@+id/passwordEntry" + androidprv:textView="@+id/pinEntry" androidprv:digit="8" /> <view class="com.android.internal.policy.impl.keyguard.NumPadKey" @@ -164,7 +164,7 @@ android:layout_width="0px" android:layout_height="match_parent" android:layout_weight="1" - androidprv:textView="@+id/passwordEntry" + androidprv:textView="@+id/pinEntry" androidprv:digit="9" /> </LinearLayout> @@ -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" /> <ImageButton diff --git a/core/res/res/values-sw380dp/dimens.xml b/core/res/res/values-sw380dp/dimens.xml new file mode 100644 index 000000000000..fc0e85d26bae --- /dev/null +++ b/core/res/res/values-sw380dp/dimens.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +** +** Copyright 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. +*/ +--> + +<resources> + <!-- Width of the sliding KeyguardSecurityContainer (includes 2x keyguard_security_view_margin) --> + <dimen name="keyguard_security_width">340dp</dimen> +</resources>
\ 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 d6d2b6621a0d..ffb4e1152a82 100644 --- a/core/res/res/values-sw720dp/dimens.xml +++ b/core/res/res/values-sw720dp/dimens.xml @@ -112,4 +112,9 @@ <!-- Size of the text under the avator on the multiuser lockscreen. --> <dimen name="keyguard_avatar_name_size">12sp</dimen> + <!-- Width of the sliding KeyguardSecurityContainer (includes 2x keyguard_security_view_margin) --> + <dimen name="keyguard_security_width">420dp</dimen> + + <!-- Height of the sliding KeyguardSecurityContainer (includes 2x keyguard_security_view_margin) --> + <dimen name="keyguard_security_height">420dp</dimen> </resources> diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index b830e798f613..c0b2b1fb4a78 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -303,6 +303,12 @@ <!-- Touch slop for the global toggle accessibility gesture --> <dimen name="accessibility_touch_slop">80dip</dimen> + <!-- Width of the sliding KeyguardSecurityContainer (includes 2x keyguard_security_view_margin) --> + <dimen name="keyguard_security_width">320dp</dimen> + + <!-- Height of the sliding KeyguardSecurityContainer (includes 2x keyguard_security_view_margin) --> + <dimen name="keyguard_security_height">400dp</dimen> + <!-- Margin around the various security views --> <dimen name="keyguard_security_view_margin">8dp</dimen> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 7ebf7e7bfd6b..5a0088c7b926 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1269,6 +1269,7 @@ <java-symbol type="id" name="option3" /> <java-symbol type="id" name="password" /> <java-symbol type="id" name="passwordEntry" /> + <java-symbol type="id" name="pinEntry" /> <java-symbol type="id" name="pinDel" /> <java-symbol type="id" name="pinDisplay" /> <java-symbol type="id" name="owner_info" /> diff --git a/location/java/android/location/Geofence.java b/location/java/android/location/Geofence.java index e0e11be44279..b3e4a88982d4 100644 --- a/location/java/android/location/Geofence.java +++ b/location/java/android/location/Geofence.java @@ -36,8 +36,8 @@ public final class Geofence implements Parcelable { /** * Create a horizontal, circular geofence. * - * @param latitude latitude in degrees, between -90 and +90 inclusive - * @param longitude longitude in degrees, between -180 and +180 inclusive + * @param latitude latitude in degrees + * @param longitude longitude in degrees * @param radius radius in meters * @return a new geofence * @throws IllegalArgumentException if any parameters are out of range diff --git a/location/java/android/location/LocationProvider.java b/location/java/android/location/LocationProvider.java index 8e0061d8dd9e..737e17f378dc 100644 --- a/location/java/android/location/LocationProvider.java +++ b/location/java/android/location/LocationProvider.java @@ -33,8 +33,8 @@ import com.android.internal.location.ProviderProperties; * Criteria} class allows providers to be selected based on * user-specified criteria. * - * @deprecated Use the {@link LocationRequest} class to request location - * instead of enumerating providers. + * @deprecated Use the {@link Criteria} class to request location instead of + * enumerating providers. */ @Deprecated public class LocationProvider { 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 b38a9ed2934c..3dd0a8f3c2bb 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,15 @@ 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; import android.widget.ImageView.ScaleType; @@ -47,10 +50,11 @@ 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 final Point mRenderedSize = new Point(); private View mWidgetView; private long mLaunchCameraStart; - private boolean mRendered; private boolean mActive; private boolean mChallengeActive; private boolean mTransitioning; @@ -81,6 +85,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, @@ -141,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( @@ -159,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(); @@ -200,6 +211,7 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli scaleX, scaleY, startCenter, finishCenter)); + enableWindowExitAnimation(false); animate() .scaleX(scale) .scaleY(scale) @@ -305,11 +317,27 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli setScaleX(1); setScaleY(1); setTranslationY(0); + enableWindowExitAnimation(true); } @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(); + 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 != wlp.windowAnimations) { + wlp.windowAnimations = newWindowAnimations; + mWindowManager.updateViewLayout(root, wlp); + } } } 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 cae598cc7d99..faf0ca0c0fd0 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(); 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 9c21830cf710..eabf5e026254 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/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java index ec89da25840a..748e0dfdcd22 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; @@ -66,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; @@ -90,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(); @@ -144,7 +137,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; } } @@ -162,6 +155,7 @@ public class KeyguardHostView extends KeyguardViewBase { addDefaultWidgets(); addWidgetsFromSettings(); + mSwitchPageRunnable.run(); mViewStateManager = new KeyguardViewStateManager(); SlidingChallengeLayout slider = @@ -217,7 +211,6 @@ public class KeyguardHostView extends KeyguardViewBase { protected void onAttachedToWindow() { super.onAttachedToWindow(); mAppWidgetHost.startListening(); - post(mSwitchPageRunnable); } @Override @@ -864,7 +857,8 @@ public class KeyguardHostView extends KeyguardViewBase { @Override LockPatternUtils getLockPatternUtils() { return mLockPatternUtils; - }}; + } + }; private void addDefaultWidgets() { LayoutInflater inflater = LayoutInflater.from(mContext); @@ -906,6 +900,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); + mViewStateManager.setTransportState(KeyguardViewStateManager.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 +938,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 @@ -1027,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; } @@ -1040,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); } @@ -1054,12 +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; - } else if (mTransportState == TRANSPORT_VISIBLE) { - mTransportState = TRANSPORT_INVISIBLE; + mViewStateManager.setTransportState(KeyguardViewStateManager.TRANSPORT_VISIBLE); + addTransportToWidgetPager(); + } else if (state == KeyguardViewStateManager.TRANSPORT_VISIBLE) { + mViewStateManager.setTransportState(KeyguardViewStateManager.TRANSPORT_INVISIBLE); } int pageToShow = getAppropriateWidgetPage(isMusicPlaying); mAppWidgetContainer.setCurrentPage(pageToShow); @@ -1081,7 +1094,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 @@ -1119,6 +1132,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<UserInfo> users = mUm.getUsers(true); 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 bea9aec13ed5..852240116c46 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPINView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPINView.java @@ -47,6 +47,11 @@ public class KeyguardPINView extends KeyguardAbsKeyInputView } @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 b6334f0c83cc..b35450cb4b71 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java @@ -60,6 +60,11 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView } @Override + protected int getPasswordTextViewId() { + return R.id.passwordEntry; + } + + @Override public boolean needsInput() { return true; } 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 89f220a0cf2d..d2846026324a 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/KeyguardViewStateManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java index 85245ba439b1..c89e8800f6cd 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 @@ -58,6 +65,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; } @@ -79,6 +93,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. @@ -207,4 +229,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/KeyguardWidgetCarousel.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java index cf16ef2a715d..2e83b42b0e4c 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); @@ -51,10 +63,10 @@ public class KeyguardWidgetCarousel extends KeyguardWidgetPager { 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 = 1.0f - 1.0f * Math.abs(scrollProgress / MAX_SCROLL_PROGRESS); return alpha; } else { - return 1f; + return 1.0f; } } @@ -67,22 +79,22 @@ 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)); } } } - } @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 +102,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 +121,139 @@ public class KeyguardWidgetCarousel extends KeyguardWidgetPager { } } } + + void animatePagesToNeutral() { + if (mChildrenTransformsAnimator != null) { + mChildrenTransformsAnimator.cancel(); + mChildrenTransformsAnimator = null; + } + + int count = getChildCount(); + PropertyValuesHolder alpha; + PropertyValuesHolder outlineAlpha; + PropertyValuesHolder rotationY; + ArrayList<Animator> anims = new ArrayList<Animator>(); + + 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", + KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER); + 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<Animator> anims = new ArrayList<Animator>(); + + 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", finalOutlineAlpha); + 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/KeyguardWidgetFrame.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java index e9c90a77b55b..b1ff049a1961 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/KeyguardWidgetPager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java index 800ccc08671b..667b2d63b262 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java @@ -24,7 +24,10 @@ 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.util.Slog; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; @@ -33,7 +36,6 @@ import android.view.ViewGroup; import android.widget.FrameLayout; import com.android.internal.R; - import com.android.internal.widget.LockPatternUtils; import java.util.ArrayList; @@ -46,7 +48,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 @@ -58,15 +60,20 @@ 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; + private static final String TAG = "KeyguardWidgetPager"; private int mPage = 0; private Callbacks mCallbacks; 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 +92,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 +189,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]); + } + }); } /* @@ -226,25 +247,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); @@ -272,7 +308,9 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit if (mViewStateManager != null) { mViewStateManager.onPageBeginMoving(); } - showOutlinesAndSidePages(); + if (!isReordering(false)) { + showOutlinesAndSidePages(); + } userActivity(); } @@ -281,17 +319,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(); @@ -414,17 +457,21 @@ 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; } + protected void reorderStarting() { + showOutlinesAndSidePages(); + } + @Override protected void onStartReordering() { super.onStartReordering(); - showOutlinesAndSidePages(); + enablePageLayers(); + reorderStarting(); } @Override @@ -434,7 +481,6 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit } void showOutlinesAndSidePages() { - enablePageLayers(); animateOutlinesAndSidePages(true); } @@ -447,7 +493,7 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit showOutlinesAndSidePages(); } else { // The layout hints depend on layout being run once - mShowHintsOnLayout = true; + showHintsAfterLayout = true; } } @@ -458,16 +504,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; } @@ -504,17 +551,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<Animator> anims = new ArrayList<Animator>(); - 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++) { @@ -541,6 +593,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) { disablePageLayers(); @@ -589,9 +647,37 @@ 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; } + + 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()); + } + } } 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 657a31f3d38c..c93b11af89da 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(); } @@ -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,11 +2091,13 @@ 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); } } // "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(); } 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 35eccbb1e805..74b05dde38a3 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); } |