am 841ce670: Merge commit \'81af21e67cd842d16d4b45e8a2d1ec56ff8d764f\' into jb-mr1-dev
* commit '841ce670b29180a157a084a9c0e803b13e92020c': (26 commits) hide the correct text, and more text, on bounce Improve PIN key layouts. Obscure speech for PIN password keys when no headset plugged in. Initial changes to allow dropping on delete target to remove widget. hide multiuser selector when IME is up. Block swipe up gesture if challenge non-interactive. Properly disable challenge handle. Disable disable back if using an alternate back icon. Disable security handle when swiping into camera widget. Import translations. DO NOT MERGE Fix small issue with previous CL Widget size policy, size callbacks Don't show security method until we actually return from the camera Fix whitespace problem and sync with prototype. PUK support. Fix build. SIM PIN support. Use clock's widget as the default keyguard widget Add configurable em-dash separator for all concatenated keyguard strings Cleaning up keyguard persistence threads when the pager is detached. (Bug 7460991) ...
This commit is contained in:
@@ -244,14 +244,22 @@ public class AppWidgetHostView extends FrameLayout {
|
||||
*
|
||||
* @param newOptions The bundle of options, in addition to the size information,
|
||||
* can be null.
|
||||
* @param minWidth The minimum width that the widget will be displayed at.
|
||||
* @param minHeight The maximum height that the widget will be displayed at.
|
||||
* @param maxWidth The maximum width that the widget will be displayed at.
|
||||
* @param maxHeight The maximum height that the widget will be displayed at.
|
||||
* @param minWidth The minimum width in dips that the widget will be displayed at.
|
||||
* @param minHeight The maximum height in dips that the widget will be displayed at.
|
||||
* @param maxWidth The maximum width in dips that the widget will be displayed at.
|
||||
* @param maxHeight The maximum height in dips that the widget will be displayed at.
|
||||
*
|
||||
*/
|
||||
public void updateAppWidgetSize(Bundle newOptions, int minWidth, int minHeight, int maxWidth,
|
||||
int maxHeight) {
|
||||
updateAppWidgetSize(newOptions, minWidth, minHeight, maxWidth, maxHeight, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public void updateAppWidgetSize(Bundle newOptions, int minWidth, int minHeight, int maxWidth,
|
||||
int maxHeight, boolean ignorePadding) {
|
||||
if (newOptions == null) {
|
||||
newOptions = new Bundle();
|
||||
}
|
||||
@@ -265,10 +273,10 @@ public class AppWidgetHostView extends FrameLayout {
|
||||
int xPaddingDips = (int) ((padding.left + padding.right) / density);
|
||||
int yPaddingDips = (int) ((padding.top + padding.bottom) / density);
|
||||
|
||||
int newMinWidth = minWidth - xPaddingDips;
|
||||
int newMinHeight = minHeight - yPaddingDips;
|
||||
int newMaxWidth = maxWidth - xPaddingDips;
|
||||
int newMaxHeight = maxHeight - yPaddingDips;
|
||||
int newMinWidth = minWidth - (ignorePadding ? 0 : xPaddingDips);
|
||||
int newMinHeight = minHeight - (ignorePadding ? 0 : yPaddingDips);
|
||||
int newMaxWidth = maxWidth - (ignorePadding ? 0 : xPaddingDips);
|
||||
int newMaxHeight = maxHeight - (ignorePadding ? 0 : yPaddingDips);
|
||||
|
||||
AppWidgetManager widgetManager = AppWidgetManager.getInstance(mContext);
|
||||
|
||||
|
||||
@@ -1073,11 +1073,7 @@ public class LockPatternUtils {
|
||||
}
|
||||
return appWidgetIds;
|
||||
}
|
||||
if (appWidgetIdString == null) {
|
||||
return new int[] { LockPatternUtils.ID_DEFAULT_STATUS_WIDGET };
|
||||
} else {
|
||||
return new int[0];
|
||||
}
|
||||
return new int[0];
|
||||
}
|
||||
|
||||
private static String combineStrings(int[] list, String separator) {
|
||||
|
||||
BIN
core/res/res/drawable-hdpi/kg_widget_delete_drop_target.png
Normal file
BIN
core/res/res/drawable-hdpi/kg_widget_delete_drop_target.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1003 B |
BIN
core/res/res/drawable-mdpi/kg_widget_delete_drop_target.png
Normal file
BIN
core/res/res/drawable-mdpi/kg_widget_delete_drop_target.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 802 B |
BIN
core/res/res/drawable-xhdpi/kg_widget_delete_drop_target.png
Normal file
BIN
core/res/res/drawable-xhdpi/kg_widget_delete_drop_target.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
@@ -33,6 +33,12 @@
|
||||
android:layout_height="match_parent"
|
||||
android:clipChildren="false">
|
||||
|
||||
<include layout="@layout/keyguard_widget_remove_drop_target"
|
||||
android:id="@+id/keyguard_widget_pager_delete_target"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top|center_horizontal" />
|
||||
|
||||
<include layout="@layout/keyguard_widget_pager"
|
||||
android:id="@+id/app_widget_container"
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
android:paddingRight="25dp"
|
||||
android:paddingTop="25dp"
|
||||
android:paddingBottom="25dp"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
androidprv:pageSpacing="10dp">
|
||||
</com.android.internal.policy.impl.keyguard.KeyguardWidgetCarousel>
|
||||
@@ -33,6 +33,16 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<include layout="@layout/keyguard_widget_remove_drop_target"
|
||||
android:id="@+id/keyguard_widget_pager_delete_target"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top|center_horizontal" />
|
||||
</FrameLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
android:paddingRight="25dp"
|
||||
android:paddingTop="25dp"
|
||||
android:paddingBottom="@dimen/kg_widget_pager_bottom_padding"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
androidprv:pageSpacing="10dp">
|
||||
</com.android.internal.policy.impl.keyguard.KeyguardWidgetPager>
|
||||
|
||||
@@ -34,6 +34,12 @@
|
||||
android:clipChildren="false"
|
||||
android:orientation="vertical">
|
||||
|
||||
<include layout="@layout/keyguard_widget_remove_drop_target"
|
||||
android:id="@+id/keyguard_widget_pager_delete_target"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top|center_horizontal" />
|
||||
|
||||
<include layout="@layout/keyguard_widget_pager"
|
||||
android:id="@+id/app_widget_container"
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -193,10 +193,10 @@
|
||||
<ImageButton
|
||||
android:id="@+id/key_enter"
|
||||
style="@style/Widget.Button.NumPadKey"
|
||||
android:gravity="center"
|
||||
android:layout_width="0px"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:paddingRight="30dp"
|
||||
android:src="@drawable/sym_keyboard_return_holo"
|
||||
android:contentDescription="@string/keyboardview_keycode_enter"
|
||||
/>
|
||||
|
||||
@@ -19,98 +19,200 @@
|
||||
<!-- This is the SIM PIN view that allows the user to enter a SIM PIN to unlock the device. -->
|
||||
<com.android.internal.policy.impl.keyguard.KeyguardSimPinView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:androidprv="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/keyguard_sim_pin_view"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_horizontal">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_lockscreen_sim"/>
|
||||
|
||||
<include layout="@layout/keyguard_message_area"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
/>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:orientation="horizontal"
|
||||
android:layout_weight="1"
|
||||
>
|
||||
<TextView android:id="@+id/pinEntry"
|
||||
android:editable="true"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:layout_marginStart="@*android:dimen/keyguard_lockscreen_pin_margin_left"
|
||||
android:singleLine="true"
|
||||
android:cursorVisible="false"
|
||||
android:background="@null"
|
||||
android:textAppearance="@style/TextAppearance.NumPadKey"
|
||||
android:imeOptions="flagForceAscii|actionDone"
|
||||
/>
|
||||
<ImageButton android:id="@+id/delete_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:src="@*android:drawable/ic_input_delete"
|
||||
android:clickable="true"
|
||||
android:paddingTop="8dip"
|
||||
android:paddingBottom="8dip"
|
||||
android:paddingLeft="24dp"
|
||||
android:paddingRight="24dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:contentDescription="@string/keyboardview_keycode_delete"
|
||||
/>
|
||||
</LinearLayout>
|
||||
<View
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="1dp"
|
||||
android:background="#55FFFFFF"
|
||||
/>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_height="0dip"
|
||||
android:layout_width="match_parent"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
<view class="com.android.internal.policy.impl.keyguard.NumPadKey"
|
||||
android:id="@+id/key1"
|
||||
style="@style/Widget.Button.NumPadKey"
|
||||
android:layout_width="0px"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_lockscreen_sim"/>
|
||||
|
||||
<include layout="@layout/keyguard_message_area_large"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 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_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginEnd="4dip"
|
||||
android:layout_marginStart="4dip"
|
||||
android:gravity="center_vertical"
|
||||
android:background="#70000000">
|
||||
|
||||
<!-- displays dots as user enters pin -->
|
||||
<EditText android:id="@+id/sim_pin_entry"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true"
|
||||
android:gravity="center_horizontal"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="@*android:dimen/keyguard_lockscreen_pin_margin_left"
|
||||
android:textStyle="normal"
|
||||
android:inputType="textPassword"
|
||||
android:textSize="36sp"
|
||||
android:background="@null"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textColor="#ffffffff"
|
||||
android:imeOptions="flagForceAscii|actionDone"
|
||||
androidprv:textView="@+id/pinEntry"
|
||||
androidprv:digit="1"
|
||||
/>
|
||||
|
||||
<ImageButton android:id="@+id/delete_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:src="@android:drawable/ic_input_delete"
|
||||
android:clickable="true"
|
||||
android:padding="8dip"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
<view class="com.android.internal.policy.impl.keyguard.NumPadKey"
|
||||
android:id="@+id/key2"
|
||||
style="@style/Widget.Button.NumPadKey"
|
||||
android:layout_width="0px"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
androidprv:textView="@+id/pinEntry"
|
||||
androidprv:digit="2"
|
||||
/>
|
||||
<view class="com.android.internal.policy.impl.keyguard.NumPadKey"
|
||||
android:id="@+id/key3"
|
||||
style="@style/Widget.Button.NumPadKey"
|
||||
android:layout_width="0px"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
androidprv:textView="@+id/pinEntry"
|
||||
androidprv:digit="3"
|
||||
/>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
<view class="com.android.internal.policy.impl.keyguard.NumPadKey"
|
||||
android:id="@+id/key4"
|
||||
style="@style/Widget.Button.NumPadKey"
|
||||
android:layout_width="0px"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
androidprv:textView="@+id/pinEntry"
|
||||
androidprv:digit="4"
|
||||
/>
|
||||
<view class="com.android.internal.policy.impl.keyguard.NumPadKey"
|
||||
android:id="@+id/key5"
|
||||
style="@style/Widget.Button.NumPadKey"
|
||||
android:layout_width="0px"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
androidprv:textView="@+id/pinEntry"
|
||||
androidprv:digit="5"
|
||||
/>
|
||||
<view class="com.android.internal.policy.impl.keyguard.NumPadKey"
|
||||
android:id="@+id/key6"
|
||||
style="@style/Widget.Button.NumPadKey"
|
||||
android:layout_width="0px"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
androidprv:textView="@+id/pinEntry"
|
||||
androidprv:digit="6"
|
||||
/>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:orientation="horizontal"
|
||||
android:layout_weight="1"
|
||||
>
|
||||
<view class="com.android.internal.policy.impl.keyguard.NumPadKey"
|
||||
android:id="@+id/key7"
|
||||
style="@style/Widget.Button.NumPadKey"
|
||||
android:layout_width="0px"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
androidprv:textView="@+id/pinEntry"
|
||||
androidprv:digit="7"
|
||||
/>
|
||||
<view class="com.android.internal.policy.impl.keyguard.NumPadKey"
|
||||
android:id="@+id/key8"
|
||||
style="@style/Widget.Button.NumPadKey"
|
||||
android:layout_width="0px"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
androidprv:textView="@+id/pinEntry"
|
||||
androidprv:digit="8"
|
||||
/>
|
||||
<view class="com.android.internal.policy.impl.keyguard.NumPadKey"
|
||||
android:id="@+id/key9"
|
||||
style="@style/Widget.Button.NumPadKey"
|
||||
android:layout_width="0px"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
androidprv:textView="@+id/pinEntry"
|
||||
androidprv:digit="9"
|
||||
/>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
<Space
|
||||
android:layout_width="0px"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
/>
|
||||
<view class="com.android.internal.policy.impl.keyguard.NumPadKey"
|
||||
android:id="@+id/key0"
|
||||
style="@style/Widget.Button.NumPadKey"
|
||||
android:layout_width="0px"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
androidprv:textView="@+id/pinEntry"
|
||||
androidprv:digit="0"
|
||||
/>
|
||||
<ImageButton
|
||||
android:id="@+id/key_enter"
|
||||
style="@style/Widget.Button.NumPadKey"
|
||||
android:layout_width="0px"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:paddingRight="30dp"
|
||||
android:src="@drawable/sym_keyboard_return_holo"
|
||||
android:contentDescription="@string/keyboardview_keycode_enter"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Numeric keyboard -->
|
||||
<com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dip"
|
||||
android:layout_marginEnd="4dip"
|
||||
android:paddingTop="4dip"
|
||||
android:paddingBottom="4dip"
|
||||
android:background="#40000000"
|
||||
android:keyBackground="@*android:drawable/btn_keyboard_key_ics"
|
||||
android:clickable="true"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
<include layout="@layout/keyguard_emergency_carrier_area"
|
||||
android:id="@+id/keyguard_selector_fade_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_gravity="bottom|center_horizontal"
|
||||
android:gravity="center_horizontal" />
|
||||
android:id="@+id/keyguard_selector_fade_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_gravity="bottom|center_horizontal"
|
||||
android:gravity="center_horizontal" />
|
||||
|
||||
</com.android.internal.policy.impl.keyguard.KeyguardSimPinView>
|
||||
|
||||
@@ -20,97 +20,199 @@
|
||||
carrier-provided PUK code and entering a new SIM PIN for it. -->
|
||||
<com.android.internal.policy.impl.keyguard.KeyguardSimPukView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:androidprv="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/keyguard_sim_puk_view"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center_horizontal">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_lockscreen_sim"/>
|
||||
|
||||
<include layout="@layout/keyguard_message_area"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
/>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:orientation="horizontal"
|
||||
android:layout_weight="1"
|
||||
>
|
||||
<TextView android:id="@+id/pinEntry"
|
||||
android:editable="true"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:layout_marginStart="@*android:dimen/keyguard_lockscreen_pin_margin_left"
|
||||
android:singleLine="true"
|
||||
android:cursorVisible="false"
|
||||
android:background="@null"
|
||||
android:textAppearance="@style/TextAppearance.NumPadKey"
|
||||
android:imeOptions="flagForceAscii|actionDone"
|
||||
/>
|
||||
<ImageButton android:id="@+id/delete_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:src="@*android:drawable/ic_input_delete"
|
||||
android:clickable="true"
|
||||
android:paddingTop="8dip"
|
||||
android:paddingBottom="8dip"
|
||||
android:paddingLeft="24dp"
|
||||
android:paddingRight="24dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:contentDescription="@string/keyboardview_keycode_delete"
|
||||
/>
|
||||
</LinearLayout>
|
||||
<View
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="1dp"
|
||||
android:background="#55FFFFFF"
|
||||
/>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_height="0dip"
|
||||
android:layout_width="match_parent"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
<view class="com.android.internal.policy.impl.keyguard.NumPadKey"
|
||||
android:id="@+id/key1"
|
||||
style="@style/Widget.Button.NumPadKey"
|
||||
android:layout_width="0px"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_lockscreen_sim"/>
|
||||
|
||||
<include layout="@layout/keyguard_message_area_large"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 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_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginEnd="4dip"
|
||||
android:layout_marginStart="4dip"
|
||||
android:gravity="center_vertical"
|
||||
android:background="#70000000">
|
||||
|
||||
<!-- displays dots as user enters pin -->
|
||||
<EditText android:id="@+id/sim_pin_entry"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true"
|
||||
android:gravity="center_horizontal"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="@*android:dimen/keyguard_lockscreen_pin_margin_left"
|
||||
android:textStyle="normal"
|
||||
android:inputType="textPassword"
|
||||
android:textSize="36sp"
|
||||
android:background="@null"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textColor="#ffffffff"
|
||||
android:imeOptions="flagForceAscii|actionDone"
|
||||
androidprv:textView="@+id/pinEntry"
|
||||
androidprv:digit="1"
|
||||
/>
|
||||
|
||||
<ImageButton android:id="@+id/delete_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:src="@android:drawable/ic_input_delete"
|
||||
android:clickable="true"
|
||||
android:padding="8dip"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
<view class="com.android.internal.policy.impl.keyguard.NumPadKey"
|
||||
android:id="@+id/key2"
|
||||
style="@style/Widget.Button.NumPadKey"
|
||||
android:layout_width="0px"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
androidprv:textView="@+id/pinEntry"
|
||||
androidprv:digit="2"
|
||||
/>
|
||||
<view class="com.android.internal.policy.impl.keyguard.NumPadKey"
|
||||
android:id="@+id/key3"
|
||||
style="@style/Widget.Button.NumPadKey"
|
||||
android:layout_width="0px"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
androidprv:textView="@+id/pinEntry"
|
||||
androidprv:digit="3"
|
||||
/>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
<view class="com.android.internal.policy.impl.keyguard.NumPadKey"
|
||||
android:id="@+id/key4"
|
||||
style="@style/Widget.Button.NumPadKey"
|
||||
android:layout_width="0px"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
androidprv:textView="@+id/pinEntry"
|
||||
androidprv:digit="4"
|
||||
/>
|
||||
<view class="com.android.internal.policy.impl.keyguard.NumPadKey"
|
||||
android:id="@+id/key5"
|
||||
style="@style/Widget.Button.NumPadKey"
|
||||
android:layout_width="0px"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
androidprv:textView="@+id/pinEntry"
|
||||
androidprv:digit="5"
|
||||
/>
|
||||
<view class="com.android.internal.policy.impl.keyguard.NumPadKey"
|
||||
android:id="@+id/key6"
|
||||
style="@style/Widget.Button.NumPadKey"
|
||||
android:layout_width="0px"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
androidprv:textView="@+id/pinEntry"
|
||||
androidprv:digit="6"
|
||||
/>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:orientation="horizontal"
|
||||
android:layout_weight="1"
|
||||
>
|
||||
<view class="com.android.internal.policy.impl.keyguard.NumPadKey"
|
||||
android:id="@+id/key7"
|
||||
style="@style/Widget.Button.NumPadKey"
|
||||
android:layout_width="0px"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
androidprv:textView="@+id/pinEntry"
|
||||
androidprv:digit="7"
|
||||
/>
|
||||
<view class="com.android.internal.policy.impl.keyguard.NumPadKey"
|
||||
android:id="@+id/key8"
|
||||
style="@style/Widget.Button.NumPadKey"
|
||||
android:layout_width="0px"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
androidprv:textView="@+id/pinEntry"
|
||||
androidprv:digit="8"
|
||||
/>
|
||||
<view class="com.android.internal.policy.impl.keyguard.NumPadKey"
|
||||
android:id="@+id/key9"
|
||||
style="@style/Widget.Button.NumPadKey"
|
||||
android:layout_width="0px"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
androidprv:textView="@+id/pinEntry"
|
||||
androidprv:digit="9"
|
||||
/>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
<Space
|
||||
android:layout_width="0px"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
/>
|
||||
<view class="com.android.internal.policy.impl.keyguard.NumPadKey"
|
||||
android:id="@+id/key0"
|
||||
style="@style/Widget.Button.NumPadKey"
|
||||
android:layout_width="0px"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
androidprv:textView="@+id/pinEntry"
|
||||
androidprv:digit="0"
|
||||
/>
|
||||
<ImageButton
|
||||
android:id="@+id/key_enter"
|
||||
style="@style/Widget.Button.NumPadKey"
|
||||
android:layout_width="0px"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:paddingRight="30dp"
|
||||
android:src="@drawable/sym_keyboard_return_holo"
|
||||
android:contentDescription="@string/keyboardview_keycode_enter"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Numeric keyboard -->
|
||||
<com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dip"
|
||||
android:layout_marginEnd="4dip"
|
||||
android:paddingTop="4dip"
|
||||
android:paddingBottom="4dip"
|
||||
android:background="#40000000"
|
||||
android:keyBackground="@*android:drawable/btn_keyboard_key_ics"
|
||||
android:clickable="true"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
<include layout="@layout/keyguard_emergency_carrier_area"
|
||||
android:id="@+id/keyguard_selector_fade_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_gravity="bottom|center_horizontal"
|
||||
android:gravity="center_horizontal" />
|
||||
android:id="@+id/keyguard_selector_fade_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_gravity="bottom|center_horizontal"
|
||||
android:gravity="center_horizontal" />
|
||||
</com.android.internal.policy.impl.keyguard.KeyguardSimPukView>
|
||||
|
||||
32
core/res/res/layout/keyguard_widget_remove_drop_target.xml
Normal file
32
core/res/res/layout/keyguard_widget_remove_drop_target.xml
Normal file
@@ -0,0 +1,32 @@
|
||||
<?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.
|
||||
*/
|
||||
-->
|
||||
<TextView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:gravity="center"
|
||||
android:padding="20dp"
|
||||
android:paddingLeft="40dp"
|
||||
android:paddingRight="40dp"
|
||||
android:drawableLeft="@drawable/kg_widget_delete_drop_target"
|
||||
android:drawablePadding="4dp"
|
||||
android:textColor="#FFF"
|
||||
android:textSize="13sp"
|
||||
android:shadowColor="#000"
|
||||
android:shadowDy="1.0"
|
||||
android:shadowRadius="1.0"
|
||||
android:visibility="gone" />
|
||||
@@ -56,4 +56,9 @@
|
||||
<!-- Bottom padding for the widget pager -->
|
||||
<dimen name="kg_widget_pager_bottom_padding">0dp</dimen>
|
||||
|
||||
<!-- If the height if keyguard drops below this threshold (most likely
|
||||
due to the appearance of the IME), then drop the multiuser selector.
|
||||
Landscape's layout allows this to be smaller than for portrait. -->
|
||||
<dimen name="kg_squashed_layout_threshold">400dp</dimen>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -404,6 +404,12 @@
|
||||
-->
|
||||
<integer name="config_longPressOnPowerBehavior">1</integer>
|
||||
|
||||
<!-- Package name for default keyguard appwidget [DO NOT TRANSLATE] -->
|
||||
<string name="widget_default_package_name"></string>
|
||||
|
||||
<!-- Class name for default keyguard appwidget [DO NOT TRANSLATE] -->
|
||||
<string name="widget_default_class_name"></string>
|
||||
|
||||
<!-- Indicate whether the SD card is accessible without removing the battery. -->
|
||||
<bool name="config_batterySdCardAccessibility">false</bool>
|
||||
|
||||
|
||||
@@ -330,4 +330,9 @@
|
||||
<!-- Size of the region along the edge of the screen that will accept
|
||||
swipes to scroll the widget area. -->
|
||||
<dimen name="kg_edge_swipe_region_size">24dp</dimen>
|
||||
|
||||
<!-- If the height if keyguard drops below this threshold (most likely
|
||||
due to the appearance of the IME), then drop the multiuser selector. -->
|
||||
<dimen name="kg_squashed_layout_threshold">600dp</dimen>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -2065,15 +2065,6 @@
|
||||
<!-- This can be used in any application wanting to disable the text "Emergency number" -->
|
||||
<string name="emergency_call_dialog_number_for_display">Emergency number</string>
|
||||
|
||||
<!-- String to display if the clock status widget is selected (it is the default) [CHAR LIMIT=22] -->
|
||||
<string name="widget_default" msgid="8269383575996003796">Clock</string>
|
||||
|
||||
<!-- Package name for default widget [DO NOT TRANSLATE] -->
|
||||
<string name="widget_default_package_name">com.android.deskclock</string>
|
||||
|
||||
<!-- Class name for default widget [DO NOT TRANSLATE] -->
|
||||
<string name="widget_default_class_name">com.android.deskclock.DeskClock</string>
|
||||
|
||||
<!--
|
||||
*** touch based lock / unlock ***
|
||||
--> <skip />
|
||||
@@ -3976,6 +3967,9 @@
|
||||
you will be asked to unlock your phone using an email account.\n\n
|
||||
Try again in <xliff:g id="number">%d</xliff:g> seconds.
|
||||
</string>
|
||||
<!-- Sequence of characters used to separate message strings in keyguard. Typically just em-dash
|
||||
with spaces on either side. [CHAR LIMIT=3] -->
|
||||
<string name="kg_text_message_separator" product="default"> \u2014 </string>
|
||||
|
||||
<!-- Message shown in dialog when user is attempting to set the music volume above the
|
||||
recommended maximum level for headphones -->
|
||||
|
||||
@@ -2482,13 +2482,14 @@ please see styles_device_defaults.xml.
|
||||
<style name="Widget.Button.NumPadKey"
|
||||
parent="@android:style/Widget.Button">
|
||||
<item name="android:singleLine">true</item>
|
||||
<item name="android:padding">6dip</item>
|
||||
<item name="android:gravity">left|center_vertical</item>
|
||||
<item name="android:background">?android:attr/selectableItemBackground</item>
|
||||
<item name="android:textSize">34dp</item>
|
||||
<item name="android:fontFamily">sans-serif</item>
|
||||
<item name="android:textStyle">normal</item>
|
||||
<item name="android:textColor">#ffffff</item>
|
||||
<item name="android:paddingBottom">10dp</item>
|
||||
<item name="android:paddingLeft">20dp</item>
|
||||
</style>
|
||||
<style name="TextAppearance.NumPadKey"
|
||||
parent="@android:style/TextAppearance">
|
||||
|
||||
@@ -479,7 +479,6 @@
|
||||
<java-symbol type="string" name="emailTypeOther" />
|
||||
<java-symbol type="string" name="emailTypeWork" />
|
||||
<java-symbol type="string" name="emergency_call_dialog_number_for_display" />
|
||||
<java-symbol type="string" name="widget_default" />
|
||||
<java-symbol type="string" name="widget_default_package_name" />
|
||||
<java-symbol type="string" name="widget_default_class_name" />
|
||||
<java-symbol type="string" name="emergency_calls_only" />
|
||||
@@ -1235,6 +1234,7 @@
|
||||
<java-symbol type="dimen" name="keyguard_avatar_frame_stroke_width" />
|
||||
<java-symbol type="dimen" name="keyguard_avatar_frame_shadow_radius" />
|
||||
<java-symbol type="dimen" name="kg_edge_swipe_region_size" />
|
||||
<java-symbol type="dimen" name="kg_squashed_layout_threshold" />
|
||||
<java-symbol type="drawable" name="ic_jog_dial_sound_off" />
|
||||
<java-symbol type="drawable" name="ic_jog_dial_sound_on" />
|
||||
<java-symbol type="drawable" name="ic_jog_dial_unlock" />
|
||||
@@ -1319,6 +1319,7 @@
|
||||
<java-symbol type="id" name="keyguard_sim_puk_view" />
|
||||
<java-symbol type="id" name="keyguard_account_view" />
|
||||
<java-symbol type="id" name="keyguard_selector_fade_container" />
|
||||
<java-symbol type="id" name="keyguard_widget_pager_delete_target" />
|
||||
<java-symbol type="id" name="app_widget_container" />
|
||||
<java-symbol type="id" name="view_flipper" />
|
||||
<java-symbol type="id" name="emergency_call_button" />
|
||||
@@ -1327,9 +1328,7 @@
|
||||
<java-symbol type="id" name="lockPatternView" />
|
||||
<java-symbol type="id" name="forgot_password_button" />
|
||||
<java-symbol type="id" name="glow_pad_view" />
|
||||
<java-symbol type="id" name="sim_pin_entry" />
|
||||
<java-symbol type="id" name="delete_button" />
|
||||
<java-symbol type="id" name="sim_pin_entry" />
|
||||
<java-symbol type="id" name="keyguard_user_avatar" />
|
||||
<java-symbol type="id" name="keyguard_user_name" />
|
||||
<java-symbol type="id" name="keyguard_transport_control" />
|
||||
@@ -1478,6 +1477,7 @@
|
||||
<java-symbol type="string" name="kg_failed_attempts_almost_at_login" />
|
||||
<java-symbol type="string" name="kg_enter_confirm_pin_hint" />
|
||||
<java-symbol type="string" name="kg_invalid_confirm_pin_hint" />
|
||||
<java-symbol type="string" name="kg_text_message_separator" />
|
||||
|
||||
<!-- From services -->
|
||||
<java-symbol type="anim" name="screen_rotate_0_enter" />
|
||||
|
||||
@@ -224,6 +224,8 @@ public class NavigationBarView extends LinearLayout {
|
||||
(0 != (hints & StatusBarManager.NAVIGATION_HINT_BACK_ALT))
|
||||
? (mVertical ? mBackAltLandIcon : mBackAltIcon)
|
||||
: (mVertical ? mBackLandIcon : mBackIcon));
|
||||
|
||||
setDisabledFlags(mDisabledFlags, true);
|
||||
}
|
||||
|
||||
public void setDisabledFlags(int disabledFlags) {
|
||||
@@ -237,7 +239,8 @@ public class NavigationBarView extends LinearLayout {
|
||||
|
||||
final boolean disableHome = ((disabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);
|
||||
final boolean disableRecent = ((disabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0);
|
||||
final boolean disableBack = ((disabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0);
|
||||
final boolean disableBack = ((disabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0)
|
||||
&& ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) == 0);
|
||||
final boolean disableSearch = ((disabledFlags & View.STATUS_BAR_DISABLE_SEARCH) != 0);
|
||||
|
||||
if (SLIPPERY_WHEN_DISABLED) {
|
||||
|
||||
@@ -53,13 +53,14 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli
|
||||
private final Callbacks mCallbacks;
|
||||
private final WindowManager mWindowManager;
|
||||
private final Point mRenderedSize = new Point();
|
||||
private final int[] mScreenLocation = new int[2];
|
||||
|
||||
private View mWidgetView;
|
||||
private long mLaunchCameraStart;
|
||||
private boolean mActive;
|
||||
private boolean mChallengeActive;
|
||||
private boolean mTransitioning;
|
||||
private boolean mDown;
|
||||
private boolean mWindowFocused;
|
||||
|
||||
private final Runnable mLaunchCameraRunnable = new Runnable() {
|
||||
@Override
|
||||
@@ -186,7 +187,7 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli
|
||||
}
|
||||
|
||||
private void transitionToCamera() {
|
||||
if (mTransitioning || mChallengeActive || mDown) return;
|
||||
if (mTransitioning || mDown) return;
|
||||
|
||||
mTransitioning = true;
|
||||
|
||||
@@ -233,7 +234,7 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli
|
||||
public void onClick(View v) {
|
||||
if (DEBUG) Log.d(TAG, "clicked");
|
||||
if (mTransitioning) return;
|
||||
if (mActive && !mChallengeActive) {
|
||||
if (mActive) {
|
||||
cancelTransitionToCamera();
|
||||
transitionToCamera();
|
||||
}
|
||||
@@ -242,6 +243,7 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasWindowFocus) {
|
||||
super.onWindowFocusChanged(hasWindowFocus);
|
||||
mWindowFocused = hasWindowFocus;
|
||||
if (DEBUG) Log.d(TAG, "onWindowFocusChanged: " + hasWindowFocus);
|
||||
if (!hasWindowFocus) {
|
||||
mTransitioning = false;
|
||||
@@ -265,13 +267,29 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onUserInteraction(int action) {
|
||||
if (mTransitioning) return true;
|
||||
if (DEBUG) Log.d(TAG, "onUserInteraction " + action);
|
||||
public boolean onUserInteraction(MotionEvent event) {
|
||||
if (!mWindowFocused) {
|
||||
if (DEBUG) Log.d(TAG, "onUserInteraction eaten: !mWindowFocused");
|
||||
return true;
|
||||
}
|
||||
if (mTransitioning) {
|
||||
if (DEBUG) Log.d(TAG, "onUserInteraction eaten: mTransitioning");
|
||||
return true;
|
||||
}
|
||||
|
||||
getLocationOnScreen(mScreenLocation);
|
||||
int rawBottom = mScreenLocation[1] + getHeight();
|
||||
if (event.getRawY() > rawBottom) {
|
||||
if (DEBUG) Log.d(TAG, "onUserInteraction eaten: below widget");
|
||||
return true;
|
||||
}
|
||||
|
||||
int action = event.getAction();
|
||||
mDown = action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_MOVE;
|
||||
if (mActive && !mChallengeActive) {
|
||||
if (mActive) {
|
||||
rescheduleTransitionToCamera();
|
||||
}
|
||||
if (DEBUG) Log.d(TAG, "onUserInteraction observed, not eaten");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -282,20 +300,6 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli
|
||||
super.onFocusLost();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChallengeActive(boolean challengeActive) {
|
||||
if (DEBUG) Log.d(TAG, "onChallengeActive: " + challengeActive);
|
||||
mChallengeActive = challengeActive;
|
||||
if (mTransitioning) return;
|
||||
if (mActive) {
|
||||
if (mChallengeActive) {
|
||||
cancelTransitionToCamera();
|
||||
} else {
|
||||
rescheduleTransitionToCamera();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onScreenTurnedOff() {
|
||||
if (DEBUG) Log.d(TAG, "onScreenTurnedOff");
|
||||
reset();
|
||||
@@ -321,7 +325,6 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli
|
||||
if (DEBUG) Log.d(TAG, "reset");
|
||||
mLaunchCameraStart = 0;
|
||||
mTransitioning = false;
|
||||
mChallengeActive = false;
|
||||
mDown = false;
|
||||
cancelTransitionToCamera();
|
||||
animate().cancel();
|
||||
@@ -347,6 +350,7 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli
|
||||
WindowManager.LayoutParams wlp = (WindowManager.LayoutParams) lp;
|
||||
int newWindowAnimations = isEnabled ? com.android.internal.R.style.Animation_LockScreen : 0;
|
||||
if (newWindowAnimations != wlp.windowAnimations) {
|
||||
if (DEBUG) Log.d(TAG, "setting windowAnimations to: " + newWindowAnimations);
|
||||
wlp.windowAnimations = newWindowAnimations;
|
||||
mWindowManager.updateViewLayout(root, wlp);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ import com.android.internal.telephony.IccCardConstants.State;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
|
||||
public class CarrierText extends TextView {
|
||||
private static CharSequence mSeparator;
|
||||
|
||||
private LockPatternUtils mLockPatternUtils;
|
||||
|
||||
private KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
|
||||
@@ -82,6 +84,7 @@ public class CarrierText extends TextView {
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
mSeparator = getResources().getString(R.string.kg_text_message_separator);
|
||||
KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mCallback);
|
||||
setSelected(true); // Allow marquee to work.
|
||||
}
|
||||
@@ -202,7 +205,7 @@ public class CarrierText extends TextView {
|
||||
final boolean plmnValid = !TextUtils.isEmpty(plmn);
|
||||
final boolean spnValid = !TextUtils.isEmpty(spn);
|
||||
if (plmnValid && spnValid) {
|
||||
return plmn + "|" + spn;
|
||||
return new StringBuilder().append(plmn).append(mSeparator).append(spn).toString();
|
||||
} else if (plmnValid) {
|
||||
return plmn;
|
||||
} else if (spnValid) {
|
||||
|
||||
@@ -130,6 +130,15 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout
|
||||
return mPasswordEntry.requestFocus(direction, previouslyFocusedRect);
|
||||
}
|
||||
|
||||
/*
|
||||
* Override this if you have a different string for "wrong password"
|
||||
*
|
||||
* Note that PIN/PUK have their own implementation of verifyPasswordAndUnlock and so don't need this
|
||||
*/
|
||||
protected int getWrongPasswordStringId() {
|
||||
return R.string.kg_wrong_password;
|
||||
}
|
||||
|
||||
protected void verifyPasswordAndUnlock() {
|
||||
String entry = mPasswordEntry.getText().toString();
|
||||
if (mLockPatternUtils.checkPassword(entry)) {
|
||||
@@ -144,7 +153,7 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout
|
||||
long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
|
||||
handleAttemptLockout(deadline);
|
||||
}
|
||||
mSecurityMessageDisplay.setMessage(R.string.kg_wrong_pin, true);
|
||||
mSecurityMessageDisplay.setMessage(getWrongPasswordStringId(), true);
|
||||
}
|
||||
mPasswordEntry.setText("");
|
||||
}
|
||||
@@ -164,6 +173,7 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
mSecurityMessageDisplay.setMessage("", false);
|
||||
resetState();
|
||||
}
|
||||
}.start();
|
||||
|
||||
@@ -29,8 +29,6 @@ import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentSender;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
@@ -50,7 +48,6 @@ import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.RemoteViews.OnClickHandler;
|
||||
|
||||
@@ -59,7 +56,6 @@ import com.android.internal.policy.impl.keyguard.KeyguardSecurityModel.SecurityM
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class KeyguardHostView extends KeyguardViewBase {
|
||||
@@ -68,10 +64,10 @@ public class KeyguardHostView extends KeyguardViewBase {
|
||||
// Use this to debug all of keyguard
|
||||
public static boolean DEBUG = KeyguardViewMediator.DEBUG;
|
||||
|
||||
// also referenced in SecuritySettings.java
|
||||
static final int APPWIDGET_HOST_ID = 0x4B455947;
|
||||
|
||||
private AppWidgetHost mAppWidgetHost;
|
||||
private AppWidgetManager mAppWidgetManager;
|
||||
private KeyguardWidgetPager mAppWidgetContainer;
|
||||
private KeyguardSecurityViewFlipper mSecurityViewContainer;
|
||||
private KeyguardSelectorView mKeyguardSelectorView;
|
||||
@@ -113,6 +109,7 @@ public class KeyguardHostView extends KeyguardViewBase {
|
||||
mLockPatternUtils = new LockPatternUtils(context);
|
||||
mAppWidgetHost = new AppWidgetHost(
|
||||
context, APPWIDGET_HOST_ID, mOnClickHandler, Looper.myLooper());
|
||||
mAppWidgetManager = AppWidgetManager.getInstance(mContext);
|
||||
mSecurityModel = new KeyguardSecurityModel(context);
|
||||
|
||||
// The following enables the MENU key to work for testing automation
|
||||
@@ -153,15 +150,13 @@ public class KeyguardHostView extends KeyguardViewBase {
|
||||
protected void onFinishInflate() {
|
||||
// Grab instances of and make any necessary changes to the main layouts. Create
|
||||
// view state manager and wire up necessary listeners / callbacks.
|
||||
View deleteDropTarget = findViewById(R.id.keyguard_widget_pager_delete_target);
|
||||
mAppWidgetContainer = (KeyguardWidgetPager) findViewById(R.id.app_widget_container);
|
||||
mAppWidgetContainer.setVisibility(VISIBLE);
|
||||
mAppWidgetContainer.setCallbacks(mWidgetCallbacks);
|
||||
mAppWidgetContainer.setDeleteDropTarget(deleteDropTarget);
|
||||
mAppWidgetContainer.setMinScale(0.5f);
|
||||
|
||||
addDefaultWidgets();
|
||||
addWidgetsFromSettings();
|
||||
mSwitchPageRunnable.run();
|
||||
|
||||
SlidingChallengeLayout slider =
|
||||
(SlidingChallengeLayout) findViewById(R.id.sliding_layout);
|
||||
if (slider != null) {
|
||||
@@ -183,8 +178,11 @@ public class KeyguardHostView extends KeyguardViewBase {
|
||||
setSystemUiVisibility(getSystemUiVisibility() | View.STATUS_BAR_DISABLE_BACK);
|
||||
}
|
||||
|
||||
showPrimarySecurityScreen(false);
|
||||
addDefaultWidgets();
|
||||
addWidgetsFromSettings();
|
||||
mSwitchPageRunnable.run();
|
||||
|
||||
showPrimarySecurityScreen(false);
|
||||
updateSecurityViews();
|
||||
}
|
||||
|
||||
@@ -549,8 +547,6 @@ public class KeyguardHostView extends KeyguardViewBase {
|
||||
};
|
||||
};
|
||||
|
||||
private KeyguardStatusViewManager mKeyguardStatusViewManager;
|
||||
|
||||
// Used to ignore callbacks from methods that are no longer current (e.g. face unlock).
|
||||
// This avoids unwanted asynchronous events from messing with the state.
|
||||
private KeyguardSecurityCallback mNullCallback = new KeyguardSecurityCallback() {
|
||||
@@ -590,6 +586,8 @@ public class KeyguardHostView extends KeyguardViewBase {
|
||||
}
|
||||
};
|
||||
|
||||
protected boolean mShowSecurityWhenReturn;
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
mIsVerifyUnlockOnly = false;
|
||||
@@ -715,6 +713,7 @@ public class KeyguardHostView extends KeyguardViewBase {
|
||||
// biometric unlock to start next time keyguard is shown.
|
||||
KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true);
|
||||
saveStickyWidgetIndex();
|
||||
checkAppWidgetConsistency();
|
||||
showPrimarySecurityScreen(true);
|
||||
getSecurityView(mCurrentSecuritySelection).onPause();
|
||||
CameraWidgetFrame cameraPage = findCameraPage();
|
||||
@@ -812,15 +811,16 @@ public class KeyguardHostView extends KeyguardViewBase {
|
||||
}
|
||||
}
|
||||
|
||||
private void addWidget(int appId, int pageIndex) {
|
||||
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext);
|
||||
AppWidgetProviderInfo appWidgetInfo = appWidgetManager.getAppWidgetInfo(appId);
|
||||
private boolean addWidget(int appId, int pageIndex) {
|
||||
AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appId);
|
||||
if (appWidgetInfo != null) {
|
||||
AppWidgetHostView view = getAppWidgetHost().createView(mContext, appId, appWidgetInfo);
|
||||
addWidget(view, pageIndex);
|
||||
return true;
|
||||
} else {
|
||||
Log.w(TAG, "AppWidgetInfo for app widget id " + appId + " was null, deleting");
|
||||
mLockPatternUtils.removeAppWidget(appId);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -842,11 +842,11 @@ public class KeyguardHostView extends KeyguardViewBase {
|
||||
SlidingChallengeLayout slider = locateSlider();
|
||||
if (slider != null) {
|
||||
slider.setHandleAlpha(1);
|
||||
slider.showChallenge(true);
|
||||
}
|
||||
mShowSecurityWhenReturn = true;
|
||||
}
|
||||
|
||||
private SlidingChallengeLayout locateSlider() {
|
||||
public SlidingChallengeLayout locateSlider() {
|
||||
return (SlidingChallengeLayout) findViewById(R.id.sliding_layout);
|
||||
}
|
||||
};
|
||||
@@ -890,22 +890,7 @@ public class KeyguardHostView extends KeyguardViewBase {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
int defaultIconId = 0;
|
||||
Resources res = KeyguardHostView.this.getContext().getResources();
|
||||
ComponentName clock = new ComponentName(
|
||||
res.getString(R.string.widget_default_package_name),
|
||||
res.getString(R.string.widget_default_class_name));
|
||||
try {
|
||||
ActivityInfo activityInfo =
|
||||
mContext.getPackageManager().getActivityInfo(clock, 0);
|
||||
if (activityInfo != null) {
|
||||
defaultIconId = activityInfo.icon;
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
defaultIconId = 0;
|
||||
}
|
||||
launchPickActivityIntent(R.string.widget_default, defaultIconId, clock,
|
||||
LockPatternUtils.EXTRA_DEFAULT_WIDGET);
|
||||
launchPickActivityIntent();
|
||||
}
|
||||
});
|
||||
mCallback.dismiss(false);
|
||||
@@ -916,8 +901,7 @@ public class KeyguardHostView extends KeyguardViewBase {
|
||||
initializeTransportControl();
|
||||
}
|
||||
|
||||
private void launchPickActivityIntent(int defaultLabelId, int defaultIconId,
|
||||
ComponentName defaultComponentName, String defaultTag) {
|
||||
private void launchPickActivityIntent() {
|
||||
// Create intent to pick widget
|
||||
Intent pickIntent = new Intent(AppWidgetManager.ACTION_KEYGUARD_APPWIDGET_PICK);
|
||||
|
||||
@@ -928,22 +912,6 @@ public class KeyguardHostView extends KeyguardViewBase {
|
||||
pickIntent.putExtra(AppWidgetManager.EXTRA_CATEGORY_FILTER,
|
||||
AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD);
|
||||
|
||||
// Add an custom entry for the default
|
||||
AppWidgetProviderInfo defaultInfo = new AppWidgetProviderInfo();
|
||||
ArrayList<AppWidgetProviderInfo> extraInfos = new ArrayList<AppWidgetProviderInfo>();
|
||||
defaultInfo.label = getResources().getString(defaultLabelId);
|
||||
defaultInfo.icon = defaultIconId;
|
||||
defaultInfo.provider = defaultComponentName;
|
||||
extraInfos.add(defaultInfo);
|
||||
|
||||
ArrayList<Bundle> extraExtras = new ArrayList<Bundle>();
|
||||
Bundle b = new Bundle();
|
||||
b.putBoolean(defaultTag, true);
|
||||
extraExtras.add(b);
|
||||
|
||||
// Launch the widget picker
|
||||
pickIntent.putExtra(AppWidgetManager.EXTRA_CUSTOM_INFO, extraInfos);
|
||||
pickIntent.putExtra(AppWidgetManager.EXTRA_CUSTOM_EXTRAS, extraExtras);
|
||||
pickIntent.putExtra(Intent.EXTRA_INTENT, getBaseIntent());
|
||||
pickIntent.addFlags(
|
||||
Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
@@ -1024,6 +992,22 @@ public class KeyguardHostView extends KeyguardViewBase {
|
||||
}
|
||||
}
|
||||
|
||||
private int getAddPageIndex() {
|
||||
View addWidget = mAppWidgetContainer.findViewById(R.id.keyguard_add_widget);
|
||||
int addPageIndex = mAppWidgetContainer.indexOfChild(addWidget);
|
||||
// This shouldn't happen, but just to be safe!
|
||||
if (addPageIndex < 0) {
|
||||
addPageIndex = 0;
|
||||
}
|
||||
return addPageIndex;
|
||||
}
|
||||
|
||||
private void addDefaultStatusWidget(int index) {
|
||||
LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
View statusWidget = inflater.inflate(R.layout.keyguard_status_view, null, true);
|
||||
mAppWidgetContainer.addWidget(statusWidget, index);
|
||||
}
|
||||
|
||||
private void addWidgetsFromSettings() {
|
||||
DevicePolicyManager dpm =
|
||||
(DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
|
||||
@@ -1036,23 +1020,17 @@ public class KeyguardHostView extends KeyguardViewBase {
|
||||
}
|
||||
}
|
||||
|
||||
View addWidget = mAppWidgetContainer.findViewById(R.id.keyguard_add_widget);
|
||||
int addPageIndex = mAppWidgetContainer.indexOfChild(addWidget);
|
||||
// This shouldn't happen, but just to be safe!
|
||||
if (addPageIndex < 0) {
|
||||
addPageIndex = 0;
|
||||
}
|
||||
int addPageIndex = getAddPageIndex();
|
||||
|
||||
// Add user-selected widget
|
||||
final int[] widgets = mLockPatternUtils.getAppWidgets();
|
||||
|
||||
if (widgets == null) {
|
||||
Log.d(TAG, "Problem reading widgets");
|
||||
} else {
|
||||
for (int i = widgets.length -1; i >= 0; i--) {
|
||||
if (widgets[i] == LockPatternUtils.ID_DEFAULT_STATUS_WIDGET) {
|
||||
LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
View statusWidget = inflater.inflate(R.layout.keyguard_status_view, null, true);
|
||||
mAppWidgetContainer.addWidget(statusWidget, addPageIndex + 1);
|
||||
addDefaultStatusWidget(addPageIndex + 1);
|
||||
} else {
|
||||
// We add the widgets from left to right, starting after the first page after
|
||||
// the add page. We count down, since the order will be persisted from right
|
||||
@@ -1061,6 +1039,42 @@ public class KeyguardHostView extends KeyguardViewBase {
|
||||
}
|
||||
}
|
||||
}
|
||||
checkAppWidgetConsistency();
|
||||
}
|
||||
|
||||
public void checkAppWidgetConsistency() {
|
||||
final int childCount = mAppWidgetContainer.getChildCount();
|
||||
boolean widgetPageExists = false;
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
if (isWidgetPage(i)) {
|
||||
widgetPageExists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!widgetPageExists) {
|
||||
final int addPageIndex = getAddPageIndex();
|
||||
|
||||
Resources res = getContext().getResources();
|
||||
ComponentName defaultAppWidget = new ComponentName(
|
||||
res.getString(R.string.widget_default_package_name),
|
||||
res.getString(R.string.widget_default_class_name));
|
||||
|
||||
// Note: we don't support configuring the widget
|
||||
int appWidgetId = mAppWidgetHost.allocateAppWidgetId();
|
||||
boolean bindSuccessful = false;
|
||||
try {
|
||||
mAppWidgetManager.bindAppWidgetId(appWidgetId, defaultAppWidget);
|
||||
bindSuccessful = true;
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.e(TAG, "Error when trying to bind default AppWidget: " + e);
|
||||
}
|
||||
// Use the built-in status/clock view if we can't inflate the default widget
|
||||
if (!(bindSuccessful && addWidget(appWidgetId, addPageIndex + 1))) {
|
||||
addDefaultStatusWidget(addPageIndex + 1);
|
||||
}
|
||||
mAppWidgetContainer.onAddView(
|
||||
mAppWidgetContainer.getChildAt(addPageIndex + 1), addPageIndex + 1);
|
||||
}
|
||||
}
|
||||
|
||||
Runnable mSwitchPageRunnable = new Runnable() {
|
||||
@@ -1129,6 +1143,14 @@ public class KeyguardHostView extends KeyguardViewBase {
|
||||
if (DEBUG) Log.d(TAG, "Window is " + (hasWindowFocus ? "focused" : "unfocused"));
|
||||
if (!hasWindowFocus) {
|
||||
saveStickyWidgetIndex();
|
||||
} else if (mShowSecurityWhenReturn) {
|
||||
SlidingChallengeLayout slider =
|
||||
(SlidingChallengeLayout) findViewById(R.id.sliding_layout);
|
||||
if (slider != null) {
|
||||
slider.setHandleAlpha(1);
|
||||
slider.showChallenge(true);
|
||||
}
|
||||
mShowSecurityWhenReturn = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1155,6 +1177,15 @@ public class KeyguardHostView extends KeyguardViewBase {
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isWidgetPage(int pageIndex) {
|
||||
View v = mAppWidgetContainer.getChildAt(pageIndex);
|
||||
if (v != null && v instanceof KeyguardWidgetFrame) {
|
||||
KeyguardWidgetFrame kwf = (KeyguardWidgetFrame) v;
|
||||
return kwf.getContentAppWidgetId() != AppWidgetManager.INVALID_APPWIDGET_ID;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isCameraPage(int pageIndex) {
|
||||
View v = mAppWidgetContainer.getChildAt(pageIndex);
|
||||
return v != null && v instanceof CameraWidgetFrame;
|
||||
|
||||
@@ -43,7 +43,6 @@ class KeyguardMessageArea extends TextView {
|
||||
|
||||
static final int SECURITY_MESSAGE_DURATION = 5000;
|
||||
protected static final int FADE_DURATION = 750;
|
||||
static final String SEPARATOR = " ";
|
||||
|
||||
// are we showing battery information?
|
||||
boolean mShowingBatteryInfo = false;
|
||||
@@ -143,6 +142,8 @@ class KeyguardMessageArea extends TextView {
|
||||
}
|
||||
};
|
||||
|
||||
private CharSequence mSeparator;
|
||||
|
||||
public KeyguardMessageArea(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
@@ -158,6 +159,8 @@ class KeyguardMessageArea extends TextView {
|
||||
mUpdateMonitor.registerCallback(mInfoCallback);
|
||||
mHandler = new Handler(Looper.myLooper());
|
||||
|
||||
mSeparator = getResources().getString(R.string.kg_text_message_separator);
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
@@ -186,23 +189,23 @@ class KeyguardMessageArea extends TextView {
|
||||
setText(status);
|
||||
}
|
||||
|
||||
|
||||
private CharSequence concat(Object... args) {
|
||||
private CharSequence concat(CharSequence... args) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
final Object arg = args[i];
|
||||
if (arg instanceof CharSequence) {
|
||||
b.append((CharSequence)args[i]);
|
||||
b.append(SEPARATOR);
|
||||
} else if (arg instanceof String) {
|
||||
b.append((String)args[i]);
|
||||
b.append(SEPARATOR);
|
||||
if (!TextUtils.isEmpty(args[0])) {
|
||||
b.append(args[0]);
|
||||
}
|
||||
for (int i = 1; i < args.length; i++) {
|
||||
CharSequence text = args[i];
|
||||
if (!TextUtils.isEmpty(text)) {
|
||||
if (b.length() > 0) {
|
||||
b.append(mSeparator);
|
||||
}
|
||||
b.append(text);
|
||||
}
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
|
||||
CharSequence getCurrentMessage() {
|
||||
return mShowingMessage ? mMessage : null;
|
||||
}
|
||||
|
||||
@@ -65,10 +65,12 @@ public class KeyguardPINView extends KeyguardAbsKeyInputView
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
doHapticKeyClick();
|
||||
verifyPasswordAndUnlock();
|
||||
if (mPasswordEntry.isEnabled()) {
|
||||
verifyPasswordAndUnlock();
|
||||
}
|
||||
}
|
||||
});
|
||||
ok.setOnHoverListener(new NumPadKey.LiftToActivateListener(getContext()));
|
||||
ok.setOnHoverListener(new LiftToActivateListener(getContext()));
|
||||
}
|
||||
|
||||
// The delete button is of the PIN keyboard itself in some (e.g. tablet) layouts,
|
||||
@@ -78,16 +80,22 @@ public class KeyguardPINView extends KeyguardAbsKeyInputView
|
||||
pinDelete.setVisibility(View.VISIBLE);
|
||||
pinDelete.setOnClickListener(new OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
CharSequence str = mPasswordEntry.getText();
|
||||
if (str.length() > 0) {
|
||||
mPasswordEntry.setText(str.subSequence(0, str.length()-1));
|
||||
// check for time-based lockouts
|
||||
if (mPasswordEntry.isEnabled()) {
|
||||
CharSequence str = mPasswordEntry.getText();
|
||||
if (str.length() > 0) {
|
||||
mPasswordEntry.setText(str.subSequence(0, str.length()-1));
|
||||
}
|
||||
}
|
||||
doHapticKeyClick();
|
||||
}
|
||||
});
|
||||
pinDelete.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
public boolean onLongClick(View v) {
|
||||
mPasswordEntry.setText("");
|
||||
// check for time-based lockouts
|
||||
if (mPasswordEntry.isEnabled()) {
|
||||
mPasswordEntry.setText("");
|
||||
}
|
||||
doHapticKeyClick();
|
||||
return true;
|
||||
}
|
||||
@@ -104,4 +112,9 @@ public class KeyguardPINView extends KeyguardAbsKeyInputView
|
||||
@Override
|
||||
public void showUsabilityHint() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWrongPasswordStringId() {
|
||||
return R.string.kg_wrong_pin;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,4 +195,9 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView
|
||||
@Override
|
||||
public void showUsabilityHint() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWrongPasswordStringId() {
|
||||
return R.string.kg_wrong_password;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package com.android.internal.policy.impl.keyguard;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.android.internal.R;
|
||||
@@ -51,18 +53,42 @@ public class KeyguardSecurityContainer extends FrameLayout {
|
||||
}
|
||||
|
||||
public void showBouncer(int duration) {
|
||||
SecurityMessageDisplay message = new KeyguardMessageArea.Helper(this);
|
||||
SecurityMessageDisplay message = new KeyguardMessageArea.Helper(getSecurityView());
|
||||
message.showBouncer(duration);
|
||||
Animator anim = ObjectAnimator.ofFloat(this, "BackgroundAlpha", 1f);
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
anim.playTogether(ObjectAnimator.ofFloat(this, "backgroundAlpha", 1f), getEcaAnim(0f));
|
||||
anim.setDuration(duration);
|
||||
anim.start();
|
||||
}
|
||||
|
||||
public void hideBouncer(int duration) {
|
||||
SecurityMessageDisplay message = new KeyguardMessageArea.Helper(this);
|
||||
SecurityMessageDisplay message = new KeyguardMessageArea.Helper(getSecurityView());
|
||||
message.hideBouncer(duration);
|
||||
Animator anim = ObjectAnimator.ofFloat(this, "BackgroundAlpha", 0f);
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
anim.playTogether(ObjectAnimator.ofFloat(this, "backgroundAlpha", 0f), getEcaAnim(1f));
|
||||
anim.setDuration(duration);
|
||||
anim.start();
|
||||
}
|
||||
|
||||
View getSecurityView() {
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
View child = getChildAt(i);
|
||||
if (child instanceof KeyguardSecurityViewFlipper) {
|
||||
return (View) (((KeyguardSecurityViewFlipper) child).getSecurityView());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Animator getEcaAnim(float alpha) {
|
||||
Animator anim = null;
|
||||
View securityView = getSecurityView();
|
||||
if (securityView != null) {
|
||||
View ecaView = securityView.findViewById(R.id.keyguard_selector_fade_container);
|
||||
if (ecaView != null) {
|
||||
anim = ObjectAnimator.ofFloat(ecaView, "alpha", alpha);
|
||||
}
|
||||
}
|
||||
return anim;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,47 +16,32 @@
|
||||
|
||||
package com.android.internal.policy.impl.keyguard;
|
||||
|
||||
import com.android.internal.telephony.ITelephony;
|
||||
|
||||
import android.content.Context;
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
|
||||
import com.android.internal.telephony.ITelephony;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.internal.widget.PasswordEntryKeyboardHelper;
|
||||
import com.android.internal.widget.PasswordEntryKeyboardView;
|
||||
import com.android.internal.R;
|
||||
|
||||
import android.text.Editable;
|
||||
import android.text.InputType;
|
||||
import android.text.TextWatcher;
|
||||
import android.text.method.DigitsKeyListener;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.TextView.OnEditorActionListener;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
/**
|
||||
* Displays a dialer like interface to unlock the SIM PIN.
|
||||
* Displays a PIN pad for unlocking.
|
||||
*/
|
||||
public class KeyguardSimPinView extends LinearLayout
|
||||
public class KeyguardSimPinView extends KeyguardAbsKeyInputView
|
||||
implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
|
||||
|
||||
private EditText mPinEntry;
|
||||
private ProgressDialog mSimUnlockProgressDialog = null;
|
||||
private KeyguardSecurityCallback mCallback;
|
||||
private PasswordEntryKeyboardView mKeyboardView;
|
||||
private PasswordEntryKeyboardHelper mKeyboardHelper;
|
||||
private LockPatternUtils mLockPatternUtils;
|
||||
private SecurityMessageDisplay mSecurityMessageDisplay;
|
||||
|
||||
private volatile boolean mSimCheckInProgress;
|
||||
|
||||
public KeyguardSimPinView(Context context) {
|
||||
@@ -65,68 +50,69 @@ public class KeyguardSimPinView extends LinearLayout
|
||||
|
||||
public KeyguardSimPinView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mLockPatternUtils = new LockPatternUtils(getContext());
|
||||
}
|
||||
|
||||
public void setKeyguardCallback(KeyguardSecurityCallback callback) {
|
||||
mCallback = callback;
|
||||
public void resetState() {
|
||||
mSecurityMessageDisplay.setMessage(R.string.kg_sim_pin_instructions, true);
|
||||
mPasswordEntry.setEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPasswordTextViewId() {
|
||||
return R.id.pinEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
|
||||
mPinEntry = (EditText) findViewById(R.id.sim_pin_entry);
|
||||
mPinEntry.setOnEditorActionListener(this);
|
||||
mPinEntry.addTextChangedListener(this);
|
||||
|
||||
mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard);
|
||||
mKeyboardHelper = new PasswordEntryKeyboardHelper(mContext, mKeyboardView, this, false,
|
||||
new int[] {
|
||||
R.xml.kg_password_kbd_numeric,
|
||||
com.android.internal.R.xml.password_kbd_qwerty,
|
||||
com.android.internal.R.xml.password_kbd_qwerty_shifted,
|
||||
com.android.internal.R.xml.password_kbd_symbols,
|
||||
com.android.internal.R.xml.password_kbd_symbols_shift
|
||||
});
|
||||
mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
|
||||
mKeyboardHelper.setEnableHaptics(mLockPatternUtils.isTactileFeedbackEnabled());
|
||||
|
||||
final View deleteButton = findViewById(R.id.delete_button);
|
||||
if (deleteButton != null) {
|
||||
deleteButton.setOnClickListener(new OnClickListener() {
|
||||
final View ok = findViewById(R.id.key_enter);
|
||||
if (ok != null) {
|
||||
ok.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mKeyboardHelper.handleBackspace();
|
||||
doHapticKeyClick();
|
||||
verifyPasswordAndUnlock();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this);
|
||||
mSecurityMessageDisplay.setTimeout(0);
|
||||
reset();
|
||||
}
|
||||
// The delete button is of the PIN keyboard itself in some (e.g. tablet) layouts,
|
||||
// not a separate view
|
||||
View pinDelete = findViewById(R.id.delete_button);
|
||||
if (pinDelete != null) {
|
||||
pinDelete.setVisibility(View.VISIBLE);
|
||||
pinDelete.setOnClickListener(new OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
CharSequence str = mPasswordEntry.getText();
|
||||
if (str.length() > 0) {
|
||||
mPasswordEntry.setText(str.subSequence(0, str.length()-1));
|
||||
}
|
||||
doHapticKeyClick();
|
||||
}
|
||||
});
|
||||
pinDelete.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
public boolean onLongClick(View v) {
|
||||
mPasswordEntry.setText("");
|
||||
doHapticKeyClick();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
|
||||
return mPinEntry.requestFocus(direction, previouslyFocusedRect);
|
||||
}
|
||||
mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance());
|
||||
mPasswordEntry.setInputType(InputType.TYPE_CLASS_NUMBER
|
||||
| InputType.TYPE_NUMBER_VARIATION_PASSWORD);
|
||||
|
||||
public void reset() {
|
||||
// start fresh
|
||||
mSecurityMessageDisplay.setMessage(R.string.kg_sim_pin_instructions, true);
|
||||
|
||||
// make sure that the number of entered digits is consistent when we
|
||||
// erase the SIM unlock code, including orientation changes.
|
||||
mPinEntry.setText("");
|
||||
mPinEntry.requestFocus();
|
||||
mPasswordEntry.requestFocus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showUsabilityHint() {
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void cleanUp() {
|
||||
@Override
|
||||
public void onPause() {
|
||||
// dismiss the dialog.
|
||||
if (mSimUnlockProgressDialog != null) {
|
||||
mSimUnlockProgressDialog.dismiss();
|
||||
@@ -167,19 +153,6 @@ public class KeyguardSimPinView extends LinearLayout
|
||||
}
|
||||
}
|
||||
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
// Check if this was the result of hitting the enter key
|
||||
mCallback.userActivity(KeyguardViewManager.DIGIT_PRESS_WAKE_MILLIS);
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN && (
|
||||
actionId == EditorInfo.IME_NULL
|
||||
|| actionId == EditorInfo.IME_ACTION_DONE
|
||||
|| actionId == EditorInfo.IME_ACTION_NEXT)) {
|
||||
checkPin();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private Dialog getSimUnlockProgressDialog() {
|
||||
if (mSimUnlockProgressDialog == null) {
|
||||
mSimUnlockProgressDialog = new ProgressDialog(mContext);
|
||||
@@ -195,11 +168,14 @@ public class KeyguardSimPinView extends LinearLayout
|
||||
return mSimUnlockProgressDialog;
|
||||
}
|
||||
|
||||
private void checkPin() {
|
||||
if (mPinEntry.getText().length() < 4) {
|
||||
@Override
|
||||
protected void verifyPasswordAndUnlock() {
|
||||
String entry = mPasswordEntry.getText().toString();
|
||||
|
||||
if (entry.length() < 4) {
|
||||
// otherwise, display a message to the user, and don't submit.
|
||||
mSecurityMessageDisplay.setMessage(R.string.kg_invalid_sim_pin_hint, true);
|
||||
mPinEntry.setText("");
|
||||
mPasswordEntry.setText("");
|
||||
mCallback.userActivity(0);
|
||||
return;
|
||||
}
|
||||
@@ -208,7 +184,7 @@ public class KeyguardSimPinView extends LinearLayout
|
||||
|
||||
if (!mSimCheckInProgress) {
|
||||
mSimCheckInProgress = true; // there should be only one
|
||||
new CheckSimPin(mPinEntry.getText().toString()) {
|
||||
new CheckSimPin(mPasswordEntry.getText().toString()) {
|
||||
void onSimCheckResponse(final boolean success) {
|
||||
post(new Runnable() {
|
||||
public void run() {
|
||||
@@ -223,7 +199,7 @@ public class KeyguardSimPinView extends LinearLayout
|
||||
} else {
|
||||
mSecurityMessageDisplay.setMessage
|
||||
(R.string.kg_password_wrong_pin_code, true);
|
||||
mPinEntry.setText("");
|
||||
mPasswordEntry.setText("");
|
||||
}
|
||||
mCallback.userActivity(0);
|
||||
mSimCheckInProgress = false;
|
||||
@@ -233,40 +209,5 @@ public class KeyguardSimPinView extends LinearLayout
|
||||
}.start();
|
||||
}
|
||||
}
|
||||
|
||||
public void setLockPatternUtils(LockPatternUtils utils) {
|
||||
mLockPatternUtils = utils;
|
||||
}
|
||||
|
||||
public boolean needsInput() {
|
||||
return false; // This view provides its own keypad
|
||||
}
|
||||
|
||||
public void onPause() {
|
||||
|
||||
}
|
||||
|
||||
public void onResume() {
|
||||
reset();
|
||||
}
|
||||
|
||||
public KeyguardSecurityCallback getCallback() {
|
||||
return mCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
if (mCallback != null) {
|
||||
mCallback.userActivity(KeyguardViewManager.DIGIT_PRESS_WAKE_MILLIS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -19,49 +19,30 @@ import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.text.Editable;
|
||||
import android.text.InputType;
|
||||
import android.text.TextWatcher;
|
||||
import android.text.method.DigitsKeyListener;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.TextView.OnEditorActionListener;
|
||||
|
||||
import com.android.internal.telephony.ITelephony;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.internal.widget.PasswordEntryKeyboardHelper;
|
||||
import com.android.internal.widget.PasswordEntryKeyboardView;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
public class KeyguardSimPukView extends LinearLayout implements View.OnClickListener,
|
||||
KeyguardSecurityView, OnEditorActionListener, TextWatcher {
|
||||
|
||||
private View mDeleteButton;
|
||||
/**
|
||||
* Displays a PIN pad for entering a PUK (Pin Unlock Kode) provided by a carrier.
|
||||
*/
|
||||
public class KeyguardSimPukView extends KeyguardAbsKeyInputView
|
||||
implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
|
||||
|
||||
private ProgressDialog mSimUnlockProgressDialog = null;
|
||||
private KeyguardSecurityCallback mCallback;
|
||||
|
||||
private SecurityMessageDisplay mSecurityMessageDisplay;
|
||||
|
||||
private PasswordEntryKeyboardView mKeyboardView;
|
||||
|
||||
private PasswordEntryKeyboardHelper mKeyboardHelper;
|
||||
|
||||
private LockPatternUtils mLockPatternUtils;
|
||||
|
||||
private volatile boolean mCheckInProgress;
|
||||
|
||||
private TextView mSimPinEntry;
|
||||
|
||||
private String mPukText;
|
||||
|
||||
private String mPinText;
|
||||
private StateMachine mStateMachine = new StateMachine();
|
||||
|
||||
@@ -95,10 +76,11 @@ public class KeyguardSimPukView extends LinearLayout implements View.OnClickList
|
||||
com.android.internal.R.string.lockscreen_sim_unlock_progress_dialog_message;
|
||||
updateSim();
|
||||
} else {
|
||||
state = ENTER_PIN; // try again?
|
||||
msg = R.string.kg_invalid_confirm_pin_hint;
|
||||
}
|
||||
}
|
||||
mSimPinEntry.setText(null);
|
||||
mPasswordEntry.setText(null);
|
||||
if (msg != 0) {
|
||||
mSecurityMessageDisplay.setMessage(msg, true);
|
||||
}
|
||||
@@ -109,7 +91,7 @@ public class KeyguardSimPukView extends LinearLayout implements View.OnClickList
|
||||
mPukText="";
|
||||
state = ENTER_PUK;
|
||||
mSecurityMessageDisplay.setMessage(R.string.kg_puk_enter_puk_hint, true);
|
||||
mSimPinEntry.requestFocus();
|
||||
mPasswordEntry.requestFocus();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,62 +101,71 @@ public class KeyguardSimPukView extends LinearLayout implements View.OnClickList
|
||||
|
||||
public KeyguardSimPukView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mLockPatternUtils = new LockPatternUtils(getContext());
|
||||
}
|
||||
|
||||
public void setKeyguardCallback(KeyguardSecurityCallback callback) {
|
||||
mCallback = callback;
|
||||
mLockPatternUtils = new LockPatternUtils(getContext());
|
||||
public void resetState() {
|
||||
mStateMachine.reset();
|
||||
mPasswordEntry.setEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPasswordTextViewId() {
|
||||
return R.id.pinEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
mSimPinEntry = (TextView) findViewById(R.id.sim_pin_entry);
|
||||
mSimPinEntry.setOnEditorActionListener(this);
|
||||
mSimPinEntry.addTextChangedListener(this);
|
||||
mDeleteButton = findViewById(R.id.delete_button);
|
||||
mDeleteButton.setOnClickListener(this);
|
||||
mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard);
|
||||
mKeyboardHelper = new PasswordEntryKeyboardHelper(mContext, mKeyboardView, this, false,
|
||||
new int[] {
|
||||
R.xml.kg_password_kbd_numeric,
|
||||
com.android.internal.R.xml.password_kbd_qwerty,
|
||||
com.android.internal.R.xml.password_kbd_qwerty_shifted,
|
||||
com.android.internal.R.xml.password_kbd_symbols,
|
||||
com.android.internal.R.xml.password_kbd_symbols_shift
|
||||
});
|
||||
mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
|
||||
mKeyboardHelper.setEnableHaptics(mLockPatternUtils.isTactileFeedbackEnabled());
|
||||
|
||||
mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this);
|
||||
final View ok = findViewById(R.id.key_enter);
|
||||
if (ok != null) {
|
||||
ok.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
doHapticKeyClick();
|
||||
verifyPasswordAndUnlock();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// The delete button is of the PIN keyboard itself in some (e.g. tablet) layouts,
|
||||
// not a separate view
|
||||
View pinDelete = findViewById(R.id.delete_button);
|
||||
if (pinDelete != null) {
|
||||
pinDelete.setVisibility(View.VISIBLE);
|
||||
pinDelete.setOnClickListener(new OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
CharSequence str = mPasswordEntry.getText();
|
||||
if (str.length() > 0) {
|
||||
mPasswordEntry.setText(str.subSequence(0, str.length()-1));
|
||||
}
|
||||
doHapticKeyClick();
|
||||
}
|
||||
});
|
||||
pinDelete.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
public boolean onLongClick(View v) {
|
||||
mPasswordEntry.setText("");
|
||||
doHapticKeyClick();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance());
|
||||
mPasswordEntry.setInputType(InputType.TYPE_CLASS_NUMBER
|
||||
| InputType.TYPE_NUMBER_VARIATION_PASSWORD);
|
||||
|
||||
mPasswordEntry.requestFocus();
|
||||
|
||||
mSecurityMessageDisplay.setTimeout(0); // don't show ownerinfo/charging status by default
|
||||
reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
|
||||
return mSimPinEntry.requestFocus(direction, previouslyFocusedRect);
|
||||
}
|
||||
|
||||
public boolean needsInput() {
|
||||
return false; // This view provides its own keypad
|
||||
}
|
||||
|
||||
public void onPause() {
|
||||
|
||||
}
|
||||
|
||||
public void onResume() {
|
||||
reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showUsabilityHint() {
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void cleanUp() {
|
||||
@Override
|
||||
public void onPause() {
|
||||
// dismiss the dialog.
|
||||
if (mSimUnlockProgressDialog != null) {
|
||||
mSimUnlockProgressDialog.dismiss();
|
||||
@@ -218,23 +209,11 @@ public class KeyguardSimPukView extends LinearLayout implements View.OnClickList
|
||||
}
|
||||
}
|
||||
|
||||
public void onClick(View v) {
|
||||
if (v == mDeleteButton) {
|
||||
mSimPinEntry.requestFocus();
|
||||
final Editable digits = mSimPinEntry.getEditableText();
|
||||
final int len = digits.length();
|
||||
if (len > 0) {
|
||||
digits.delete(len-1, len);
|
||||
}
|
||||
}
|
||||
mCallback.userActivity(KeyguardViewManager.DIGIT_PRESS_WAKE_MILLIS);
|
||||
}
|
||||
|
||||
private Dialog getSimUnlockProgressDialog() {
|
||||
if (mSimUnlockProgressDialog == null) {
|
||||
mSimUnlockProgressDialog = new ProgressDialog(mContext);
|
||||
mSimUnlockProgressDialog.setMessage(mContext.getString(
|
||||
R.string.kg_sim_unlock_progress_dialog_message));
|
||||
mSimUnlockProgressDialog.setMessage(
|
||||
mContext.getString(R.string.kg_sim_unlock_progress_dialog_message));
|
||||
mSimUnlockProgressDialog.setIndeterminate(true);
|
||||
mSimUnlockProgressDialog.setCancelable(false);
|
||||
if (!(mContext instanceof Activity)) {
|
||||
@@ -247,8 +226,8 @@ public class KeyguardSimPukView extends LinearLayout implements View.OnClickList
|
||||
|
||||
private boolean checkPuk() {
|
||||
// make sure the puk is at least 8 digits long.
|
||||
if (mSimPinEntry.getText().length() >= 8) {
|
||||
mPukText = mSimPinEntry.getText().toString();
|
||||
if (mPasswordEntry.getText().length() >= 8) {
|
||||
mPukText = mPasswordEntry.getText().toString();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -256,16 +235,16 @@ public class KeyguardSimPukView extends LinearLayout implements View.OnClickList
|
||||
|
||||
private boolean checkPin() {
|
||||
// make sure the PIN is between 4 and 8 digits
|
||||
int length = mSimPinEntry.getText().length();
|
||||
int length = mPasswordEntry.getText().length();
|
||||
if (length >= 4 && length <= 8) {
|
||||
mPinText = mSimPinEntry.getText().toString();
|
||||
mPinText = mPasswordEntry.getText().toString();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean confirmPin() {
|
||||
return mPinText.equals(mSimPinEntry.getText().toString());
|
||||
return mPinText.equals(mPasswordEntry.getText().toString());
|
||||
}
|
||||
|
||||
private void updateSim() {
|
||||
@@ -295,46 +274,9 @@ public class KeyguardSimPukView extends LinearLayout implements View.OnClickList
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
|
||||
// Check if this was the result of hitting the enter key
|
||||
mCallback.userActivity(KeyguardViewManager.DIGIT_PRESS_WAKE_MILLIS);
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
if (actionId == EditorInfo.IME_NULL || actionId == EditorInfo.IME_ACTION_DONE
|
||||
|| actionId == EditorInfo.IME_ACTION_NEXT) {
|
||||
mStateMachine.next();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLockPatternUtils(LockPatternUtils utils) {
|
||||
mLockPatternUtils = utils;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
mStateMachine.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyguardSecurityCallback getCallback() {
|
||||
return mCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
if (mCallback != null) {
|
||||
mCallback.userActivity(KeyguardViewManager.DIGIT_PRESS_WAKE_MILLIS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
protected void verifyPasswordAndUnlock() {
|
||||
mStateMachine.next();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -520,8 +520,22 @@ public class KeyguardViewMediator {
|
||||
mSystemReady = true;
|
||||
mUpdateMonitor.registerCallback(mUpdateCallback);
|
||||
|
||||
// Disable alternate unlock right after boot until things have settled.
|
||||
mUpdateMonitor.setAlternateUnlockEnabled(false);
|
||||
// Suppress biometric unlock right after boot until things have settled if it is the
|
||||
// selected security method, otherwise unsuppress it. It must be unsuppressed if it is
|
||||
// not the selected security method for the following reason: if the user starts
|
||||
// without a screen lock selected, the biometric unlock would be suppressed the first
|
||||
// time they try to use it.
|
||||
//
|
||||
// Note that the biometric unlock will still not show if it is not the selected method.
|
||||
// Calling setAlternateUnlockEnabled(true) simply says don't suppress it if it is the
|
||||
// selected method.
|
||||
if (mLockPatternUtils.usingBiometricWeak()
|
||||
&& mLockPatternUtils.isBiometricWeakInstalled()) {
|
||||
if (DEBUG) Log.d(TAG, "suppressing biometric unlock during boot");
|
||||
mUpdateMonitor.setAlternateUnlockEnabled(false);
|
||||
} else {
|
||||
mUpdateMonitor.setAlternateUnlockEnabled(true);
|
||||
}
|
||||
|
||||
doKeyguardLocked();
|
||||
}
|
||||
|
||||
@@ -101,10 +101,21 @@ public class KeyguardViewStateManager implements SlidingChallengeLayout.OnChalle
|
||||
((View) mKeyguardSecurityContainer).animate().alpha(1f).setDuration(duration);
|
||||
}
|
||||
|
||||
public void onPageSwitch(View newPage, int newPageIndex) {
|
||||
public void onPageSwitching(View newPage, int newPageIndex) {
|
||||
if (mPagedView != null && mChallengeLayout instanceof SlidingChallengeLayout) {
|
||||
boolean isCameraPage = newPage instanceof CameraWidgetFrame;
|
||||
((SlidingChallengeLayout) mChallengeLayout).setChallengeInteractive(!isCameraPage);
|
||||
}
|
||||
}
|
||||
|
||||
public void onPageSwitched(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.
|
||||
// This prevents conflicts.
|
||||
|
||||
// If the page hasn't switched, don't bother with any of this
|
||||
if (mCurrentPage != newPageIndex) return;
|
||||
|
||||
if (mPagedView != null && mChallengeLayout != null) {
|
||||
KeyguardWidgetFrame prevPage = mPagedView.getWidgetPageAt(mCurrentPage);
|
||||
if (prevPage != null && mCurrentPage != mPageListeningToSlider) {
|
||||
@@ -162,7 +173,6 @@ public class KeyguardViewStateManager implements SlidingChallengeLayout.OnChalle
|
||||
if (!challengeOverlapping) {
|
||||
frame.resetSize();
|
||||
}
|
||||
frame.onChallengeActive(mChallengeLayout.isChallengeShowing());
|
||||
frame.hideFrame(this);
|
||||
|
||||
if (challengeOverlapping) {
|
||||
@@ -196,8 +206,6 @@ public class KeyguardViewStateManager implements SlidingChallengeLayout.OnChalle
|
||||
}
|
||||
// View is on the move. Pause the security view until it completes.
|
||||
mKeyguardSecurityContainer.onPause();
|
||||
|
||||
frame.onChallengeActive(true);
|
||||
}
|
||||
mLastScrollState = scrollState;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.animation.Animator;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.PropertyValuesHolder;
|
||||
import android.appwidget.AppWidgetHostView;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
@@ -42,6 +43,10 @@ public class KeyguardWidgetFrame extends FrameLayout {
|
||||
new PorterDuffXfermode(PorterDuff.Mode.ADD);
|
||||
|
||||
static final float OUTLINE_ALPHA_MULTIPLIER = 0.6f;
|
||||
static final int HOVER_OVER_DELETE_DROP_TARGET_OVERLAY_COLOR = 0x99FF0000;
|
||||
|
||||
// Temporarily disable this for the time being until we know why the gfx is messing up
|
||||
static final boolean ENABLE_HOVER_OVER_DELETE_DROP_TARGET_OVERLAY = true;
|
||||
|
||||
private int mGradientColor;
|
||||
private LinearGradient mForegroundGradient;
|
||||
@@ -62,7 +67,20 @@ public class KeyguardWidgetFrame extends FrameLayout {
|
||||
private float mBackgroundAlphaMultiplier = 1.0f;
|
||||
private Drawable mBackgroundDrawable;
|
||||
private Rect mBackgroundRect = new Rect();
|
||||
private int mLastMeasuredWidth = -1;
|
||||
private int mLastMeasuredHeight = 1;
|
||||
|
||||
// These variables are all needed in order to size things properly before we're actually
|
||||
// measured.
|
||||
private int mSmallWidgetHeight;
|
||||
private int mSmallFrameHeight;
|
||||
private boolean mWidgetLockedSmall = false;
|
||||
private int mMaxChallengeTop = -1;
|
||||
|
||||
// This will hold the width value before we've actually been measured
|
||||
private int mFrameHeight;
|
||||
|
||||
private boolean mIsHoveringOverDeleteDropTarget;
|
||||
|
||||
// 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.
|
||||
@@ -98,8 +116,13 @@ public class KeyguardWidgetFrame extends FrameLayout {
|
||||
cancelLongPress();
|
||||
}
|
||||
|
||||
public void setMaxChallengeTop(int top) {
|
||||
mSmallWidgetHeight = top - getPaddingTop();
|
||||
void setIsHoveringOverDeleteDropTarget(boolean isHovering) {
|
||||
if (ENABLE_HOVER_OVER_DELETE_DROP_TARGET_OVERLAY) {
|
||||
if (mIsHoveringOverDeleteDropTarget != isHovering) {
|
||||
mIsHoveringOverDeleteDropTarget = isHovering;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -163,6 +186,12 @@ public class KeyguardWidgetFrame extends FrameLayout {
|
||||
c.drawRect(mForegroundRect, mGradientPaint);
|
||||
}
|
||||
|
||||
private void drawHoveringOverDeleteOverlay(Canvas c) {
|
||||
if (mIsHoveringOverDeleteDropTarget) {
|
||||
c.drawColor(HOVER_OVER_DELETE_DROP_TARGET_OVERLAY_COLOR);
|
||||
}
|
||||
}
|
||||
|
||||
protected void drawBg(Canvas canvas) {
|
||||
if (mBackgroundAlpha > 0.0f) {
|
||||
Drawable bg = mBackgroundDrawable;
|
||||
@@ -175,9 +204,16 @@ public class KeyguardWidgetFrame extends FrameLayout {
|
||||
|
||||
@Override
|
||||
protected void dispatchDraw(Canvas canvas) {
|
||||
if (ENABLE_HOVER_OVER_DELETE_DROP_TARGET_OVERLAY) {
|
||||
canvas.save();
|
||||
}
|
||||
drawBg(canvas);
|
||||
super.dispatchDraw(canvas);
|
||||
drawGradientOverlay(canvas);
|
||||
if (ENABLE_HOVER_OVER_DELETE_DROP_TARGET_OVERLAY) {
|
||||
drawHoveringOverDeleteOverlay(canvas);
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -220,8 +256,10 @@ public class KeyguardWidgetFrame extends FrameLayout {
|
||||
View content = getContent();
|
||||
if (content instanceof AppWidgetHostView) {
|
||||
return ((AppWidgetHostView) content).getAppWidgetId();
|
||||
} else {
|
||||
} else if (content instanceof KeyguardStatusView) {
|
||||
return ((KeyguardStatusView) content).getAppWidgetId();
|
||||
} else {
|
||||
return AppWidgetManager.INVALID_APPWIDGET_ID;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,22 +297,6 @@ public class KeyguardWidgetFrame extends FrameLayout {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the top location of the challenge.
|
||||
*
|
||||
* @param top The top of the challenge, in _local_ coordinates, or -1 to indicate the challenge
|
||||
* is down.
|
||||
*/
|
||||
private void setChallengeTop(int top, boolean updateWidgetSize) {
|
||||
// The widget starts below the padding, and extends to the top of the challengs.
|
||||
int widgetHeight = top - getPaddingTop();
|
||||
int frameHeight = top + getPaddingBottom();
|
||||
setFrameHeight(frameHeight);
|
||||
if (updateWidgetSize) {
|
||||
setWidgetHeight(widgetHeight);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Depending on whether the security is up, the widget size needs to change
|
||||
*
|
||||
@@ -295,28 +317,51 @@ public class KeyguardWidgetFrame extends FrameLayout {
|
||||
}
|
||||
}
|
||||
|
||||
public void setMaxChallengeTop(int top) {
|
||||
boolean dirty = mMaxChallengeTop != top;
|
||||
mSmallWidgetHeight = top - getPaddingTop();
|
||||
mSmallFrameHeight = top + getPaddingBottom();
|
||||
if (dirty && mIsSmall) {
|
||||
setWidgetHeight(mSmallWidgetHeight);
|
||||
setFrameHeight(mSmallFrameHeight);
|
||||
} else if (dirty && mWidgetLockedSmall) {
|
||||
setWidgetHeight(mSmallWidgetHeight);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSmall() {
|
||||
return mIsSmall;
|
||||
}
|
||||
|
||||
public void adjustFrame(int challengeTop) {
|
||||
setChallengeTop(challengeTop, false);
|
||||
int frameHeight = challengeTop + getPaddingBottom();
|
||||
setFrameHeight(frameHeight);
|
||||
}
|
||||
|
||||
public void shrinkWidget() {
|
||||
mIsSmall = true;
|
||||
setChallengeTop(mSmallWidgetHeight, true);
|
||||
setWidgetHeight(mSmallWidgetHeight);
|
||||
setFrameHeight(mSmallFrameHeight);
|
||||
}
|
||||
|
||||
public void setWidgetLockedSmall(boolean locked) {
|
||||
if (locked) {
|
||||
setWidgetHeight(mSmallWidgetHeight);
|
||||
}
|
||||
mWidgetLockedSmall = locked;
|
||||
}
|
||||
|
||||
public void resetSize() {
|
||||
mIsSmall = false;
|
||||
if (!mWidgetLockedSmall) {
|
||||
setWidgetHeight(LayoutParams.MATCH_PARENT);
|
||||
}
|
||||
setFrameHeight(getMeasuredHeight());
|
||||
setWidgetHeight(LayoutParams.MATCH_PARENT);
|
||||
}
|
||||
|
||||
public void setFrameHeight(int height) {
|
||||
height = Math.min(height, getMeasuredHeight());
|
||||
mBackgroundRect.set(0, 0, getMeasuredWidth(), height);
|
||||
mFrameHeight = height;
|
||||
mBackgroundRect.set(0, 0, getMeasuredWidth(), Math.min(mFrameHeight, getMeasuredHeight()));
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@@ -356,10 +401,38 @@ public class KeyguardWidgetFrame extends FrameLayout {
|
||||
mGradientColor, 0, Shader.TileMode.CLAMP);
|
||||
mRightToLeftGradient = new LinearGradient(x1, 0f, x0, 0f,
|
||||
mGradientColor, 0, Shader.TileMode.CLAMP);
|
||||
mBackgroundRect.set(0, 0, w, h);
|
||||
|
||||
if (!mIsSmall) {
|
||||
mFrameHeight = h;
|
||||
}
|
||||
|
||||
mBackgroundRect.set(0, 0, getMeasuredWidth(), Math.min(h, mFrameHeight));
|
||||
invalidate();
|
||||
}
|
||||
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
performAppWidgetSizeCallbacksIfNecessary();
|
||||
}
|
||||
|
||||
private void performAppWidgetSizeCallbacksIfNecessary() {
|
||||
View content = getContent();
|
||||
if (!(content instanceof AppWidgetHostView)) return;
|
||||
|
||||
boolean sizeDirty = content.getMeasuredWidth() != mLastMeasuredWidth ||
|
||||
content.getMeasuredHeight() != mLastMeasuredHeight;
|
||||
if (sizeDirty) {
|
||||
|
||||
}
|
||||
|
||||
AppWidgetHostView awhv = (AppWidgetHostView) content;
|
||||
float density = getResources().getDisplayMetrics().density;
|
||||
|
||||
int width = (int) (content.getMeasuredWidth() / density);
|
||||
int height = (int) (content.getMeasuredHeight() / density);
|
||||
awhv.updateAppWidgetSize(null, width, height, width, height, true);
|
||||
}
|
||||
|
||||
void setOverScrollAmount(float r, boolean left) {
|
||||
if (Float.compare(mOverScrollAmount, r) != 0) {
|
||||
mOverScrollAmount = r;
|
||||
@@ -373,12 +446,8 @@ public class KeyguardWidgetFrame extends FrameLayout {
|
||||
// hook for subclasses
|
||||
}
|
||||
|
||||
public boolean onUserInteraction(int action) {
|
||||
public boolean onUserInteraction(MotionEvent event) {
|
||||
// hook for subclasses
|
||||
return false;
|
||||
}
|
||||
|
||||
public void onChallengeActive(boolean challengeActive) {
|
||||
// hook for subclasses
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.PropertyValuesHolder;
|
||||
import android.animation.TimeInterpolator;
|
||||
import android.appwidget.AppWidgetHostView;
|
||||
import android.appwidget.AppWidgetProviderInfo;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Handler;
|
||||
@@ -31,9 +33,9 @@ import android.view.Gravity;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.View.OnLongClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.android.internal.R;
|
||||
@@ -117,7 +119,14 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSwitch(View newPage, int newPageIndex) {
|
||||
public void onPageSwitching(View newPage, int newPageIndex) {
|
||||
if (mViewStateManager != null) {
|
||||
mViewStateManager.onPageSwitching(newPage, newPageIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSwitched(View newPage, int newPageIndex) {
|
||||
boolean showingStatusWidget = false;
|
||||
if (newPage instanceof ViewGroup) {
|
||||
ViewGroup vg = (ViewGroup) newPage;
|
||||
@@ -156,7 +165,7 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
|
||||
}
|
||||
}
|
||||
if (mViewStateManager != null) {
|
||||
mViewStateManager.onPageSwitch(newPage, newPageIndex);
|
||||
mViewStateManager.onPageSwitched(newPage, newPageIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,7 +186,7 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
KeyguardWidgetFrame currentWidgetPage = getWidgetPageAt(getCurrentPage());
|
||||
if (currentWidgetPage != null && currentWidgetPage.onUserInteraction(ev.getAction())) {
|
||||
if (currentWidgetPage != null && currentWidgetPage.onUserInteraction(ev)) {
|
||||
return true;
|
||||
}
|
||||
return super.onTouchEvent(ev);
|
||||
@@ -250,10 +259,23 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
|
||||
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
|
||||
LayoutParams.MATCH_PARENT);
|
||||
lp.gravity = Gravity.TOP;
|
||||
|
||||
// The framework adds a default padding to AppWidgetHostView. We don't need this padding
|
||||
// for the Keyguard, so we override it to be 0.
|
||||
widget.setPadding(0, 0, 0, 0);
|
||||
frame.addView(widget, lp);
|
||||
|
||||
// We set whether or not this widget supports vertical resizing.
|
||||
if (widget instanceof AppWidgetHostView) {
|
||||
AppWidgetHostView awhv = (AppWidgetHostView) widget;
|
||||
AppWidgetProviderInfo info = awhv.getAppWidgetInfo();
|
||||
if ((info.resizeMode & AppWidgetProviderInfo.RESIZE_VERTICAL) != 0) {
|
||||
frame.setWidgetLockedSmall(false);
|
||||
} else {
|
||||
// Lock the widget to be small.
|
||||
frame.setWidgetLockedSmall(true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
frame = (KeyguardWidgetFrame) widget;
|
||||
}
|
||||
@@ -549,20 +571,20 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
|
||||
// coordinate relative to our children, hence we subtract the top padding.s
|
||||
maxChallengeTop = top - getPaddingTop();
|
||||
challengeShowing = scl.isChallengeShowing();
|
||||
}
|
||||
|
||||
int count = getChildCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
KeyguardWidgetFrame frame = getWidgetPageAt(i);
|
||||
frame.setMaxChallengeTop(maxChallengeTop);
|
||||
|
||||
// On the very first measure pass, if the challenge is showing, we need to make sure
|
||||
// that the widget on the current page is small.
|
||||
if (challengeShowing && i == mCurrentPage && !mHasMeasure) {
|
||||
frame.shrinkWidget();
|
||||
int count = getChildCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
KeyguardWidgetFrame frame = getWidgetPageAt(i);
|
||||
frame.setMaxChallengeTop(maxChallengeTop);
|
||||
// On the very first measure pass, if the challenge is showing, we need to make sure
|
||||
// that the widget on the current page is small.
|
||||
if (challengeShowing && i == mCurrentPage && !mHasMeasure) {
|
||||
frame.shrinkWidget();
|
||||
}
|
||||
}
|
||||
}
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
mHasMeasure = true;
|
||||
}
|
||||
|
||||
void animateOutlinesAndSidePages(final boolean show) {
|
||||
@@ -695,4 +717,10 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
|
||||
return indexOfChild((KeyguardWidgetFrame)view.getParent());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setPageHoveringOverDeleteDropTarget(int viewIndex, boolean isHovering) {
|
||||
KeyguardWidgetFrame child = getWidgetPageAt(viewIndex);
|
||||
child.setIsHoveringOverDeleteDropTarget(isHovering);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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.policy.impl.keyguard;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
|
||||
/**
|
||||
* Hover listener that implements lift-to-activate interaction for
|
||||
* accessibility. May be added to multiple views.
|
||||
*/
|
||||
class LiftToActivateListener implements View.OnHoverListener {
|
||||
/** Manager used to query accessibility enabled state. */
|
||||
private final AccessibilityManager mAccessibilityManager;
|
||||
|
||||
private boolean mCachedClickableState;
|
||||
|
||||
public LiftToActivateListener(Context context) {
|
||||
mAccessibilityManager = (AccessibilityManager) context.getSystemService(
|
||||
Context.ACCESSIBILITY_SERVICE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onHover(View v, MotionEvent event) {
|
||||
// When touch exploration is turned on, lifting a finger while
|
||||
// inside the view bounds should perform a click action.
|
||||
if (mAccessibilityManager.isEnabled()
|
||||
&& mAccessibilityManager.isTouchExplorationEnabled()) {
|
||||
switch (event.getActionMasked()) {
|
||||
case MotionEvent.ACTION_HOVER_ENTER:
|
||||
// Lift-to-type temporarily disables double-tap
|
||||
// activation by setting the view as not clickable.
|
||||
mCachedClickableState = v.isClickable();
|
||||
v.setClickable(false);
|
||||
break;
|
||||
case MotionEvent.ACTION_HOVER_EXIT:
|
||||
final int x = (int) event.getX();
|
||||
final int y = (int) event.getY();
|
||||
if ((x > v.getPaddingLeft()) && (y > v.getPaddingTop())
|
||||
&& (x < v.getWidth() - v.getPaddingRight())
|
||||
&& (y < v.getHeight() - v.getPaddingBottom())) {
|
||||
v.performClick();
|
||||
}
|
||||
v.setClickable(mCachedClickableState);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Pass the event to View.onHoverEvent() to handle accessibility.
|
||||
v.onHoverEvent(event);
|
||||
|
||||
// Consume the event so it doesn't fall through to other views.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -47,6 +47,7 @@ public class MultiPaneChallengeLayout extends ViewGroup implements ChallengeLayo
|
||||
private OnBouncerStateChangedListener mBouncerListener;
|
||||
|
||||
private final Rect mTempRect = new Rect();
|
||||
private final Context mContext;
|
||||
|
||||
private final OnClickListener mScrimClickListener = new OnClickListener() {
|
||||
@Override
|
||||
@@ -66,6 +67,8 @@ public class MultiPaneChallengeLayout extends ViewGroup implements ChallengeLayo
|
||||
public MultiPaneChallengeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
|
||||
mContext = context;
|
||||
|
||||
final TypedArray a = context.obtainStyledAttributes(attrs,
|
||||
R.styleable.MultiPaneChallengeLayout, defStyleAttr, 0);
|
||||
mOrientation = a.getInt(R.styleable.MultiPaneChallengeLayout_orientation,
|
||||
@@ -173,6 +176,8 @@ public class MultiPaneChallengeLayout extends ViewGroup implements ChallengeLayo
|
||||
throw new IllegalArgumentException(
|
||||
"MultiPaneChallengeLayout must be measured with an exact size");
|
||||
}
|
||||
float squashedLayoutThreshold =
|
||||
mContext.getResources().getDimension(R.dimen.kg_squashed_layout_threshold);
|
||||
|
||||
final int width = MeasureSpec.getSize(widthSpec);
|
||||
final int height = MeasureSpec.getSize(heightSpec);
|
||||
@@ -208,28 +213,32 @@ public class MultiPaneChallengeLayout extends ViewGroup implements ChallengeLayo
|
||||
mUserSwitcherView = child;
|
||||
|
||||
if (child.getVisibility() == GONE) continue;
|
||||
if (height < squashedLayoutThreshold) {
|
||||
int zero = MeasureSpec.makeMeasureSpec(0, MeasureSpec.EXACTLY);
|
||||
measureChild(child, zero, zero);
|
||||
} else {
|
||||
int adjustedWidthSpec = widthSpec;
|
||||
int adjustedHeightSpec = heightSpec;
|
||||
if (lp.maxWidth >= 0) {
|
||||
adjustedWidthSpec = MeasureSpec.makeMeasureSpec(
|
||||
Math.min(lp.maxWidth, MeasureSpec.getSize(widthSpec)),
|
||||
MeasureSpec.EXACTLY);
|
||||
}
|
||||
if (lp.maxHeight >= 0) {
|
||||
adjustedHeightSpec = MeasureSpec.makeMeasureSpec(
|
||||
Math.min(lp.maxHeight, MeasureSpec.getSize(heightSpec)),
|
||||
MeasureSpec.EXACTLY);
|
||||
}
|
||||
// measureChildWithMargins will resolve layout direction for the LayoutParams
|
||||
measureChildWithMargins(child, adjustedWidthSpec, 0, adjustedHeightSpec, 0);
|
||||
|
||||
int adjustedWidthSpec = widthSpec;
|
||||
int adjustedHeightSpec = heightSpec;
|
||||
if (lp.maxWidth >= 0) {
|
||||
adjustedWidthSpec = MeasureSpec.makeMeasureSpec(
|
||||
Math.min(lp.maxWidth, MeasureSpec.getSize(widthSpec)),
|
||||
MeasureSpec.EXACTLY);
|
||||
}
|
||||
if (lp.maxHeight >= 0) {
|
||||
adjustedHeightSpec = MeasureSpec.makeMeasureSpec(
|
||||
Math.min(lp.maxHeight, MeasureSpec.getSize(heightSpec)),
|
||||
MeasureSpec.EXACTLY);
|
||||
}
|
||||
// measureChildWithMargins will resolve layout direction for the LayoutParams
|
||||
measureChildWithMargins(child, adjustedWidthSpec, 0, adjustedHeightSpec, 0);
|
||||
|
||||
// Only subtract out space from one dimension. Favor vertical.
|
||||
// Offset by 1.5x to add some balance along the other edge.
|
||||
if (Gravity.isVertical(lp.gravity)) {
|
||||
heightUsed += child.getMeasuredHeight() * 1.5f;
|
||||
} else if (Gravity.isHorizontal(lp.gravity)) {
|
||||
widthUsed += child.getMeasuredWidth() * 1.5f;
|
||||
// Only subtract out space from one dimension. Favor vertical.
|
||||
// Offset by 1.5x to add some balance along the other edge.
|
||||
if (Gravity.isVertical(lp.gravity)) {
|
||||
heightUsed += child.getMeasuredHeight() * 1.5f;
|
||||
} else if (Gravity.isHorizontal(lp.gravity)) {
|
||||
widthUsed += child.getMeasuredWidth() * 1.5f;
|
||||
}
|
||||
}
|
||||
} else if (lp.childType == LayoutParams.CHILD_TYPE_SCRIM) {
|
||||
setScrimView(child);
|
||||
|
||||
@@ -22,9 +22,7 @@ import android.text.SpannableStringBuilder;
|
||||
import android.text.style.TextAppearanceSpan;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.HapticFeedbackConstants;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
@@ -51,7 +49,8 @@ public class NumPadKey extends Button {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mTextView != null) {
|
||||
// check for time-based lockouts
|
||||
if (mTextView != null && mTextView.isEnabled()) {
|
||||
mTextView.append(String.valueOf(mDigit));
|
||||
}
|
||||
doHapticKeyClick();
|
||||
@@ -75,6 +74,7 @@ public class NumPadKey extends Button {
|
||||
|
||||
setOnClickListener(mListener);
|
||||
setOnHoverListener(new LiftToActivateListener(context));
|
||||
setAccessibilityDelegate(new ObscureSpeechDelegate(context));
|
||||
|
||||
mEnableHaptics = new LockPatternUtils(context).isTactileFeedbackEnabled();
|
||||
|
||||
@@ -89,6 +89,7 @@ public class NumPadKey extends Button {
|
||||
final String extra = sKlondike[mDigit];
|
||||
final int extraLen = extra.length();
|
||||
if (extraLen > 0) {
|
||||
builder.append(" ");
|
||||
builder.append(extra);
|
||||
builder.setSpan(
|
||||
new TextAppearanceSpan(context, R.style.TextAppearance_NumPadKey_Klondike),
|
||||
@@ -99,6 +100,14 @@ public class NumPadKey extends Button {
|
||||
setText(builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
|
||||
// Reset the "announced headset" flag when detached.
|
||||
ObscureSpeechDelegate.sAnnouncedHeadset = false;
|
||||
}
|
||||
|
||||
public void setTextView(TextView tv) {
|
||||
mTextView = tv;
|
||||
}
|
||||
@@ -116,45 +125,4 @@ public class NumPadKey extends Button {
|
||||
| HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hover listener that implements lift-to-activate interaction for
|
||||
* accessibility. May be added to multiple views.
|
||||
*/
|
||||
static class LiftToActivateListener implements View.OnHoverListener {
|
||||
/** Manager used to query accessibility enabled state. */
|
||||
private final AccessibilityManager mAccessibilityManager;
|
||||
|
||||
public LiftToActivateListener(Context context) {
|
||||
mAccessibilityManager = (AccessibilityManager) context.getSystemService(
|
||||
Context.ACCESSIBILITY_SERVICE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onHover(View v, MotionEvent event) {
|
||||
// When touch exploration is turned on, lifting a finger while
|
||||
// inside the view bounds should perform a click action.
|
||||
if (mAccessibilityManager.isEnabled()
|
||||
&& mAccessibilityManager.isTouchExplorationEnabled()) {
|
||||
switch (event.getActionMasked()) {
|
||||
case MotionEvent.ACTION_HOVER_ENTER:
|
||||
// Lift-to-type temporarily disables double-tap
|
||||
// activation.
|
||||
v.setClickable(false);
|
||||
break;
|
||||
case MotionEvent.ACTION_HOVER_EXIT:
|
||||
final int x = (int) event.getX();
|
||||
final int y = (int) event.getY();
|
||||
if ((x > v.getPaddingLeft()) && (y > v.getPaddingTop())
|
||||
&& (x < v.getWidth() - v.getPaddingRight())
|
||||
&& (y < v.getHeight() - v.getPaddingBottom())) {
|
||||
v.performClick();
|
||||
}
|
||||
v.setClickable(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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.policy.impl.keyguard;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.media.AudioManager;
|
||||
import android.provider.Settings;
|
||||
import android.view.View;
|
||||
import android.view.View.AccessibilityDelegate;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
/**
|
||||
* Accessibility delegate that obscures speech for a view when the user has
|
||||
* not turned on the "speak passwords" preference and is not listening
|
||||
* through headphones.
|
||||
*/
|
||||
class ObscureSpeechDelegate extends AccessibilityDelegate {
|
||||
/** Whether any client has announced the "headset" notification. */
|
||||
static boolean sAnnouncedHeadset = false;
|
||||
|
||||
private final ContentResolver mContentResolver;
|
||||
private final AudioManager mAudioManager;
|
||||
|
||||
public ObscureSpeechDelegate(Context context) {
|
||||
mContentResolver = context.getContentResolver();
|
||||
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendAccessibilityEvent(View host, int eventType) {
|
||||
super.sendAccessibilityEvent(host, eventType);
|
||||
|
||||
// Play the "headset required" announcement the first time the user
|
||||
// places accessibility focus on a key.
|
||||
if ((eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED)
|
||||
&& !sAnnouncedHeadset && shouldObscureSpeech()) {
|
||||
sAnnouncedHeadset = true;
|
||||
host.announceForAccessibility(host.getContext().getString(
|
||||
R.string.keyboard_headset_required_to_hear_password));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
|
||||
super.onPopulateAccessibilityEvent(host, event);
|
||||
|
||||
if ((event.getEventType() != AccessibilityEvent.TYPE_ANNOUNCEMENT)
|
||||
&& shouldObscureSpeech()) {
|
||||
event.getText().clear();
|
||||
event.setContentDescription(host.getContext().getString(
|
||||
R.string.keyboard_password_character_no_headset));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
|
||||
super.onInitializeAccessibilityNodeInfo(host, info);
|
||||
|
||||
if (shouldObscureSpeech()) {
|
||||
final Context ctx = host.getContext();
|
||||
info.setText(null);
|
||||
info.setContentDescription(
|
||||
ctx.getString(R.string.keyboard_password_character_no_headset));
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private boolean shouldObscureSpeech() {
|
||||
// The user can optionally force speaking passwords.
|
||||
if (Settings.Secure.getInt(mContentResolver,
|
||||
Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD, 0) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Always speak if the user is listening through headphones.
|
||||
if (mAudioManager.isWiredHeadsetOn() || mAudioManager.isBluetoothA2dpOn()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't speak since this key is used to type a password.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -48,6 +48,7 @@ import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
import android.widget.Scroller;
|
||||
|
||||
import com.android.internal.R;
|
||||
@@ -205,6 +206,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
protected int REORDERING_ZOOM_IN_OUT_DURATION = 250;
|
||||
private int REORDERING_SIDE_PAGE_HOVER_TIMEOUT = 300;
|
||||
private float REORDERING_SIDE_PAGE_BUFFER_PERCENTAGE = 0.1f;
|
||||
private long REORDERING_DELETE_DROP_TARGET_FADE_DURATION = 150;
|
||||
private float mMinScale = 1f;
|
||||
protected View mDragView;
|
||||
private AnimatorSet mZoomInOutAnim;
|
||||
@@ -228,18 +230,25 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
// Convenience/caching
|
||||
private Matrix mTmpInvMatrix = new Matrix();
|
||||
private float[] mTmpPoint = new float[2];
|
||||
private Rect mTmpRect = new Rect();
|
||||
|
||||
// Fling to delete
|
||||
private int FLING_TO_DELETE_FADE_OUT_DURATION = 350;
|
||||
private float FLING_TO_DELETE_FRICTION = 0.035f;
|
||||
// The degrees specifies how much deviation from the up vector to still consider a fling "up"
|
||||
private float FLING_TO_DELETE_MAX_FLING_DEGREES = 35f;
|
||||
private int FLING_TO_DELETE_SLIDE_IN_SIDE_PAGE_DURATION = 250;
|
||||
private float FLING_TO_DELETE_MAX_FLING_DEGREES = 65f;
|
||||
protected int mFlingToDeleteThresholdVelocity = -1400;
|
||||
private boolean mIsFlingingToDelete = false;
|
||||
// Drag to delete
|
||||
private boolean mDeferringForDelete = false;
|
||||
private int DELETE_SLIDE_IN_SIDE_PAGE_DURATION = 250;
|
||||
private int DRAG_TO_DELETE_FADE_OUT_DURATION = 350;
|
||||
|
||||
// Drop to delete
|
||||
private View mDeleteDropTarget;
|
||||
|
||||
public interface PageSwitchListener {
|
||||
void onPageSwitch(View newPage, int newPageIndex);
|
||||
void onPageSwitching(View newPage, int newPageIndex);
|
||||
void onPageSwitched(View newPage, int newPageIndex);
|
||||
}
|
||||
|
||||
public PagedView(Context context) {
|
||||
@@ -293,19 +302,23 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
setOnHierarchyChangeListener(this);
|
||||
}
|
||||
|
||||
void setDeleteDropTarget(View v) {
|
||||
mDeleteDropTarget = v;
|
||||
}
|
||||
|
||||
// Convenience methods to map points from self to parent and vice versa
|
||||
float[] mapPointFromSelfToParent(float x, float y) {
|
||||
float[] mapPointFromViewToParent(View v, float x, float y) {
|
||||
mTmpPoint[0] = x;
|
||||
mTmpPoint[1] = y;
|
||||
getMatrix().mapPoints(mTmpPoint);
|
||||
mTmpPoint[0] += getLeft();
|
||||
mTmpPoint[1] += getTop();
|
||||
v.getMatrix().mapPoints(mTmpPoint);
|
||||
mTmpPoint[0] += v.getLeft();
|
||||
mTmpPoint[1] += v.getTop();
|
||||
return mTmpPoint;
|
||||
}
|
||||
float[] mapPointFromParentToSelf(float x, float y) {
|
||||
mTmpPoint[0] = x - getLeft();
|
||||
mTmpPoint[1] = y - getTop();
|
||||
getMatrix().invert(mTmpInvMatrix);
|
||||
float[] mapPointFromParentToView(View v, float x, float y) {
|
||||
mTmpPoint[0] = x - v.getLeft();
|
||||
mTmpPoint[1] = y - v.getTop();
|
||||
v.getMatrix().invert(mTmpInvMatrix);
|
||||
mTmpInvMatrix.mapPoints(mTmpPoint);
|
||||
return mTmpPoint;
|
||||
}
|
||||
@@ -328,7 +341,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
public void setScaleX(float scaleX) {
|
||||
super.setScaleX(scaleX);
|
||||
if (isReordering(true)) {
|
||||
float[] p = mapPointFromParentToSelf(mParentDownMotionX, mParentDownMotionY);
|
||||
float[] p = mapPointFromParentToView(this, mParentDownMotionX, mParentDownMotionY);
|
||||
mLastMotionX = p[0];
|
||||
mLastMotionY = p[1];
|
||||
updateDragViewTranslationDuringDrag();
|
||||
@@ -356,7 +369,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
public void setPageSwitchListener(PageSwitchListener pageSwitchListener) {
|
||||
mPageSwitchListener = pageSwitchListener;
|
||||
if (mPageSwitchListener != null) {
|
||||
mPageSwitchListener.onPageSwitch(getPageAt(mCurrentPage), mCurrentPage);
|
||||
mPageSwitchListener.onPageSwitched(getPageAt(mCurrentPage), mCurrentPage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -415,6 +428,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
* Sets the current page.
|
||||
*/
|
||||
void setCurrentPage(int currentPage) {
|
||||
notifyPageSwitching(currentPage);
|
||||
if (!mScroller.isFinished()) {
|
||||
mScroller.abortAnimation();
|
||||
}
|
||||
@@ -428,7 +442,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
mCurrentPage = Math.max(0, Math.min(currentPage, getPageCount() - 1));
|
||||
updateCurrentPageScroll();
|
||||
updateScrollingIndicator();
|
||||
notifyPageSwitchListener();
|
||||
notifyPageSwitched();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@@ -436,9 +450,15 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
mOnlyAllowEdgeSwipes = enable;
|
||||
}
|
||||
|
||||
protected void notifyPageSwitchListener() {
|
||||
protected void notifyPageSwitching(int whichPage) {
|
||||
if (mPageSwitchListener != null) {
|
||||
mPageSwitchListener.onPageSwitch(getPageAt(mCurrentPage), mCurrentPage);
|
||||
mPageSwitchListener.onPageSwitching(getPageAt(whichPage), whichPage);
|
||||
}
|
||||
}
|
||||
|
||||
protected void notifyPageSwitched() {
|
||||
if (mPageSwitchListener != null) {
|
||||
mPageSwitchListener.onPageSwitched(getPageAt(mCurrentPage), mCurrentPage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -511,7 +531,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
|
||||
// Update the last motion events when scrolling
|
||||
if (isReordering(true)) {
|
||||
float[] p = mapPointFromParentToSelf(mParentDownMotionX, mParentDownMotionY);
|
||||
float[] p = mapPointFromParentToView(this, mParentDownMotionX, mParentDownMotionY);
|
||||
mLastMotionX = p[0];
|
||||
mLastMotionY = p[1];
|
||||
updateDragViewTranslationDuringDrag();
|
||||
@@ -532,13 +552,14 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
} else if (mNextPage != INVALID_PAGE) {
|
||||
mCurrentPage = Math.max(0, Math.min(mNextPage, getPageCount() - 1));
|
||||
mNextPage = INVALID_PAGE;
|
||||
notifyPageSwitchListener();
|
||||
notifyPageSwitched();
|
||||
|
||||
// We don't want to trigger a page end moving unless the page has settled
|
||||
// and the user has stopped scrolling
|
||||
if (mTouchState == TOUCH_STATE_REST) {
|
||||
pageEndMoving();
|
||||
}
|
||||
|
||||
onPostReorderingAnimationCompleted();
|
||||
return true;
|
||||
}
|
||||
@@ -632,7 +653,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
// ensure that the cache is filled with good values.
|
||||
invalidateCachedOffsets();
|
||||
|
||||
if (mChildCountOnLastMeasure != getChildCount() && !mIsFlingingToDelete) {
|
||||
if (mChildCountOnLastMeasure != getChildCount() && !mDeferringForDelete) {
|
||||
setCurrentPage(mCurrentPage);
|
||||
}
|
||||
mChildCountOnLastMeasure = getChildCount();
|
||||
@@ -856,7 +877,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
final int pageCount = getChildCount();
|
||||
if (pageCount > 0) {
|
||||
getVisiblePages(mTempVisiblePagesRange);
|
||||
boundByReorderablePages(isReordering(false), mTempVisiblePagesRange);
|
||||
final int leftScreen = mTempVisiblePagesRange[0];
|
||||
final int rightScreen = mTempVisiblePagesRange[1];
|
||||
if (leftScreen != -1 && rightScreen != -1) {
|
||||
@@ -1038,7 +1058,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
mDownScrollX = getScrollX();
|
||||
mLastMotionX = x;
|
||||
mLastMotionY = y;
|
||||
float[] p = mapPointFromSelfToParent(x, y);
|
||||
float[] p = mapPointFromViewToParent(this, x, y);
|
||||
mParentDownMotionX = p[0];
|
||||
mParentDownMotionY = p[1];
|
||||
mLastMotionXRemainder = 0;
|
||||
@@ -1270,7 +1290,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
mDownMotionX = mLastMotionX = ev.getX();
|
||||
mDownMotionY = mLastMotionY = ev.getY();
|
||||
mDownScrollX = getScrollX();
|
||||
float[] p = mapPointFromSelfToParent(mLastMotionX, mLastMotionY);
|
||||
float[] p = mapPointFromViewToParent(this, mLastMotionX, mLastMotionY);
|
||||
mParentDownMotionX = p[0];
|
||||
mParentDownMotionY = p[1];
|
||||
mLastMotionXRemainder = 0;
|
||||
@@ -1322,7 +1342,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
|
||||
// Update the parent down so that our zoom animations take this new movement into
|
||||
// account
|
||||
float[] pt = mapPointFromSelfToParent(mLastMotionX, mLastMotionY);
|
||||
float[] pt = mapPointFromViewToParent(this, mLastMotionX, mLastMotionY);
|
||||
mParentDownMotionX = pt[0];
|
||||
mParentDownMotionY = pt[1];
|
||||
updateDragViewTranslationDuringDrag();
|
||||
@@ -1331,11 +1351,16 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
final int dragViewIndex = indexOfChild(mDragView);
|
||||
int bufferSize = (int) (REORDERING_SIDE_PAGE_BUFFER_PERCENTAGE *
|
||||
getViewportWidth());
|
||||
int leftBufferEdge = (int) (mapPointFromSelfToParent(mViewport.left, 0)[0]
|
||||
int leftBufferEdge = (int) (mapPointFromViewToParent(this, mViewport.left, 0)[0]
|
||||
+ bufferSize);
|
||||
int rightBufferEdge = (int) (mapPointFromSelfToParent(mViewport.right, 0)[0]
|
||||
int rightBufferEdge = (int) (mapPointFromViewToParent(this, mViewport.right, 0)[0]
|
||||
- bufferSize);
|
||||
|
||||
// Change the drag view if we are hovering over the drop target
|
||||
boolean isHoveringOverDelete = isHoveringOverDeleteDropTarget(
|
||||
(int) mParentDownMotionX, (int) mParentDownMotionY);
|
||||
setPageHoveringOverDeleteDropTarget(dragViewIndex, isHoveringOverDelete);
|
||||
|
||||
if (DEBUG) Log.d(TAG, "leftBufferEdge: " + leftBufferEdge);
|
||||
if (DEBUG) Log.d(TAG, "rightBufferEdge: " + rightBufferEdge);
|
||||
if (DEBUG) Log.d(TAG, "mLastMotionX: " + mLastMotionX);
|
||||
@@ -1352,7 +1377,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
}
|
||||
|
||||
final int pageUnderPointIndex = pageIndexToSnapTo;
|
||||
if (pageUnderPointIndex > -1) {
|
||||
if (pageUnderPointIndex > -1 && !isHoveringOverDelete) {
|
||||
mTempVisiblePagesRange[0] = 0;
|
||||
mTempVisiblePagesRange[1] = getPageCount() - 1;
|
||||
boundByReorderablePages(true, mTempVisiblePagesRange);
|
||||
@@ -1485,13 +1510,29 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
snapToDestination();
|
||||
}
|
||||
} else if (mTouchState == TOUCH_STATE_REORDERING) {
|
||||
// Update the last motion position
|
||||
mLastMotionX = ev.getX();
|
||||
mLastMotionY = ev.getY();
|
||||
|
||||
// Update the parent down so that our zoom animations take this new movement into
|
||||
// account
|
||||
float[] pt = mapPointFromViewToParent(this, mLastMotionX, mLastMotionY);
|
||||
mParentDownMotionX = pt[0];
|
||||
mParentDownMotionY = pt[1];
|
||||
updateDragViewTranslationDuringDrag();
|
||||
boolean handledFling = false;
|
||||
if (!DISABLE_FLING_TO_DELETE) {
|
||||
// Check the velocity and see if we are flinging-to-delete
|
||||
PointF flingToDeleteVector = isFlingingToDelete();
|
||||
if (flingToDeleteVector != null) {
|
||||
onFlingToDelete(flingToDeleteVector);
|
||||
handledFling = true;
|
||||
}
|
||||
}
|
||||
if (!handledFling && isHoveringOverDeleteDropTarget((int) mParentDownMotionX,
|
||||
(int) mParentDownMotionY)) {
|
||||
onDropToDelete();
|
||||
}
|
||||
} else {
|
||||
onUnhandledTap(ev);
|
||||
}
|
||||
@@ -1743,7 +1784,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
}
|
||||
protected void snapToPage(int whichPage, int delta, int duration, boolean immediate) {
|
||||
mNextPage = whichPage;
|
||||
|
||||
notifyPageSwitching(whichPage);
|
||||
View focusedChild = getFocusedChild();
|
||||
if (focusedChild != null && whichPage != mCurrentPage &&
|
||||
focusedChild == getPageAt(mCurrentPage)) {
|
||||
@@ -1761,13 +1802,14 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
if (!mScroller.isFinished()) mScroller.abortAnimation();
|
||||
mScroller.startScroll(mUnboundedScrollX, 0, delta, 0, duration);
|
||||
|
||||
notifyPageSwitchListener();
|
||||
notifyPageSwitched();
|
||||
|
||||
// Trigger a compute() to finish switching pages if necessary
|
||||
if (immediate) {
|
||||
computeScroll();
|
||||
}
|
||||
|
||||
mForceScreenScrolled = true;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@@ -1991,6 +2033,23 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
mZoomInOutAnim.playTogether(
|
||||
ObjectAnimator.ofFloat(this, "scaleX", mMinScale),
|
||||
ObjectAnimator.ofFloat(this, "scaleY", mMinScale));
|
||||
mZoomInOutAnim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
// Show the delete drop target
|
||||
if (mDeleteDropTarget != null) {
|
||||
mDeleteDropTarget.setVisibility(View.VISIBLE);
|
||||
mDeleteDropTarget.animate().alpha(1f)
|
||||
.setDuration(REORDERING_DELETE_DROP_TARGET_FADE_DURATION)
|
||||
.setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
mDeleteDropTarget.setAlpha(0f);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
mZoomInOutAnim.start();
|
||||
return true;
|
||||
}
|
||||
@@ -2007,6 +2066,15 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
mTouchState = TOUCH_STATE_REORDERING;
|
||||
mIsReordering = true;
|
||||
|
||||
// Mark all the non-widget pages as invisible
|
||||
getVisiblePages(mTempVisiblePagesRange);
|
||||
boundByReorderablePages(true, mTempVisiblePagesRange);
|
||||
for (int i = 0; i < getPageCount(); ++i) {
|
||||
if (i < mTempVisiblePagesRange[0] || i > mTempVisiblePagesRange[1]) {
|
||||
getPageAt(i).setAlpha(0f);
|
||||
}
|
||||
}
|
||||
|
||||
// We must invalidate to trigger a redraw to update the layers such that the drag view
|
||||
// is always drawn on top
|
||||
invalidate();
|
||||
@@ -2028,6 +2096,15 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
R.string.keyguard_accessibility_widget_reorder_end));
|
||||
}
|
||||
mIsReordering = false;
|
||||
|
||||
// Mark all the non-widget pages as visible again
|
||||
getVisiblePages(mTempVisiblePagesRange);
|
||||
boundByReorderablePages(true, mTempVisiblePagesRange);
|
||||
for (int i = 0; i < getPageCount(); ++i) {
|
||||
if (i < mTempVisiblePagesRange[0] || i > mTempVisiblePagesRange[1]) {
|
||||
getPageAt(i).setAlpha(1f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean startReordering() {
|
||||
@@ -2072,7 +2149,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
onEndReordering();
|
||||
}
|
||||
};
|
||||
if (!mIsFlingingToDelete) {
|
||||
if (!mDeferringForDelete) {
|
||||
mPostReorderingPreZoomInRunnable = new Runnable() {
|
||||
public void run() {
|
||||
zoomIn(onCompleteRunnable);
|
||||
@@ -2086,7 +2163,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
// Animate the drag view back to the front position
|
||||
animateDragViewToOriginalPosition();
|
||||
} else {
|
||||
zoomIn(onCompleteRunnable);
|
||||
// Handled in post-delete-animation-callbacks
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2102,6 +2179,20 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
ObjectAnimator.ofFloat(this, "scaleX", 1f),
|
||||
ObjectAnimator.ofFloat(this, "scaleY", 1f));
|
||||
mZoomInOutAnim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
// Hide the delete drop target
|
||||
if (mDeleteDropTarget != null) {
|
||||
mDeleteDropTarget.animate().alpha(0f)
|
||||
.setDuration(REORDERING_DELETE_DROP_TARGET_FADE_DURATION)
|
||||
.setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mDeleteDropTarget.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
mDragView = null;
|
||||
@@ -2186,6 +2277,97 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
}
|
||||
};
|
||||
|
||||
private Runnable createPostDeleteAnimationRunnable(final View dragView) {
|
||||
return new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int dragViewIndex = indexOfChild(dragView);
|
||||
|
||||
// For each of the pages around the drag view, animate them from the previous
|
||||
// position to the new position in the layout (as a result of the drag view moving
|
||||
// in the layout)
|
||||
// NOTE: We can make an assumption here because we have side-bound pages that we
|
||||
// will always have pages to animate in from the left
|
||||
getVisiblePages(mTempVisiblePagesRange);
|
||||
boundByReorderablePages(true, mTempVisiblePagesRange);
|
||||
boolean isLastWidgetPage = (mTempVisiblePagesRange[0] == mTempVisiblePagesRange[1]);
|
||||
boolean slideFromLeft = (isLastWidgetPage ||
|
||||
dragViewIndex > mTempVisiblePagesRange[0]);
|
||||
|
||||
// Setup the scroll to the correct page before we swap the views
|
||||
if (slideFromLeft) {
|
||||
snapToPageImmediately(dragViewIndex - 1);
|
||||
}
|
||||
|
||||
int firstIndex = (isLastWidgetPage ? 0 : mTempVisiblePagesRange[0]);
|
||||
int lastIndex = Math.min(mTempVisiblePagesRange[1], getPageCount() - 1);
|
||||
int lowerIndex = (slideFromLeft ? firstIndex : dragViewIndex + 1 );
|
||||
int upperIndex = (slideFromLeft ? dragViewIndex - 1 : lastIndex);
|
||||
ArrayList<Animator> animations = new ArrayList<Animator>();
|
||||
for (int i = lowerIndex; i <= upperIndex; ++i) {
|
||||
View v = getChildAt(i);
|
||||
// dragViewIndex < pageUnderPointIndex, so after we remove the
|
||||
// drag view all subsequent views to pageUnderPointIndex will
|
||||
// shift down.
|
||||
int oldX = 0;
|
||||
int newX = 0;
|
||||
if (slideFromLeft) {
|
||||
if (i == 0) {
|
||||
// Simulate the page being offscreen with the page spacing
|
||||
oldX = getViewportOffsetX() + getChildOffset(i) - getChildWidth(i)
|
||||
- mPageSpacing;
|
||||
} else {
|
||||
oldX = getViewportOffsetX() + getChildOffset(i - 1);
|
||||
}
|
||||
newX = getViewportOffsetX() + getChildOffset(i);
|
||||
} else {
|
||||
oldX = getChildOffset(i) - getChildOffset(i - 1);
|
||||
newX = 0;
|
||||
}
|
||||
|
||||
// Animate the view translation from its old position to its new
|
||||
// position
|
||||
AnimatorSet anim = (AnimatorSet) v.getTag();
|
||||
if (anim != null) {
|
||||
anim.cancel();
|
||||
}
|
||||
|
||||
// Note: Hacky, but we want to skip any optimizations to not draw completely
|
||||
// hidden views
|
||||
v.setAlpha(Math.max(v.getAlpha(), 0.01f));
|
||||
v.setTranslationX(oldX - newX);
|
||||
anim = new AnimatorSet();
|
||||
anim.playTogether(
|
||||
ObjectAnimator.ofFloat(v, "translationX", 0f),
|
||||
ObjectAnimator.ofFloat(v, "alpha", 1f));
|
||||
animations.add(anim);
|
||||
v.setTag(anim);
|
||||
}
|
||||
|
||||
AnimatorSet slideAnimations = new AnimatorSet();
|
||||
slideAnimations.playTogether(animations);
|
||||
slideAnimations.setDuration(DELETE_SLIDE_IN_SIDE_PAGE_DURATION);
|
||||
slideAnimations.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
final Runnable onCompleteRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mDeferringForDelete = false;
|
||||
onEndReordering();
|
||||
}
|
||||
};
|
||||
zoomIn(onCompleteRunnable);
|
||||
}
|
||||
});
|
||||
slideAnimations.start();
|
||||
|
||||
removeView(dragView);
|
||||
onRemoveView(dragView);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void onFlingToDelete(PointF vel) {
|
||||
final long startTime = AnimationUtils.currentAnimationTimeMillis();
|
||||
|
||||
@@ -2222,59 +2404,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
AnimatorUpdateListener updateCb = new FlingAlongVectorAnimatorUpdateListener(dragView, vel,
|
||||
from, startTime, FLING_TO_DELETE_FRICTION);
|
||||
|
||||
final Runnable onAnimationEndRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int dragViewIndex = indexOfChild(dragView);
|
||||
// Setup the scroll to the correct page before we swap the views
|
||||
snapToPageImmediately(dragViewIndex - 1);
|
||||
|
||||
// For each of the pages around the drag view, animate them from the previous
|
||||
// position to the new position in the layout (as a result of the drag view moving
|
||||
// in the layout)
|
||||
// NOTE: We can make an assumption here because we have side-bound pages that we
|
||||
// will always have pages to animate in from the left
|
||||
int lowerIndex = 0;
|
||||
int upperIndex = dragViewIndex - 1;
|
||||
for (int i = lowerIndex; i <= upperIndex; ++i) {
|
||||
View v = getChildAt(i);
|
||||
// dragViewIndex < pageUnderPointIndex, so after we remove the
|
||||
// drag view all subsequent views to pageUnderPointIndex will
|
||||
// shift down.
|
||||
int oldX = 0;
|
||||
if (i == 0) {
|
||||
oldX = -(getViewportOffsetX() + getChildOffset(i));
|
||||
} else {
|
||||
oldX = getViewportOffsetX() + getChildOffset(i - 1);
|
||||
}
|
||||
int newX = getViewportOffsetX() + getChildOffset(i);
|
||||
|
||||
// Animate the view translation from its old position to its new
|
||||
// position
|
||||
AnimatorSet anim = (AnimatorSet) v.getTag();
|
||||
if (anim != null) {
|
||||
anim.cancel();
|
||||
}
|
||||
|
||||
v.setTranslationX(oldX - newX);
|
||||
anim = new AnimatorSet();
|
||||
anim.setDuration(FLING_TO_DELETE_SLIDE_IN_SIDE_PAGE_DURATION);
|
||||
anim.playTogether(
|
||||
ObjectAnimator.ofFloat(v, "translationX", 0f));
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mIsFlingingToDelete = false;
|
||||
}
|
||||
});
|
||||
anim.start();
|
||||
v.setTag(anim);
|
||||
}
|
||||
|
||||
removeView(dragView);
|
||||
onRemoveView(dragView);
|
||||
}
|
||||
};
|
||||
final Runnable onAnimationEndRunnable = createPostDeleteAnimationRunnable(dragView);
|
||||
|
||||
// Create and start the animation
|
||||
ValueAnimator mDropAnim = new ValueAnimator();
|
||||
@@ -2288,11 +2418,57 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
}
|
||||
});
|
||||
mDropAnim.start();
|
||||
mIsFlingingToDelete = true;
|
||||
mDeferringForDelete = true;
|
||||
}
|
||||
|
||||
/* Drag to delete */
|
||||
private boolean isHoveringOverDeleteDropTarget(int x, int y) {
|
||||
if (mDeleteDropTarget != null) {
|
||||
mDeleteDropTarget.getGlobalVisibleRect(mTmpRect);
|
||||
return mTmpRect.contains(x, y);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void setPageHoveringOverDeleteDropTarget(int viewIndex, boolean isHovering) {}
|
||||
|
||||
private void onDropToDelete() {
|
||||
final View dragView = mDragView;
|
||||
|
||||
final float toScale = 0f;
|
||||
final float toAlpha = 0f;
|
||||
|
||||
// Create and start the complex animation
|
||||
ArrayList<Animator> animations = new ArrayList<Animator>();
|
||||
AnimatorSet motionAnim = new AnimatorSet();
|
||||
motionAnim.setInterpolator(new DecelerateInterpolator(2));
|
||||
motionAnim.playTogether(
|
||||
ObjectAnimator.ofFloat(dragView, "scaleX", toScale),
|
||||
ObjectAnimator.ofFloat(dragView, "scaleY", toScale));
|
||||
animations.add(motionAnim);
|
||||
|
||||
AnimatorSet alphaAnim = new AnimatorSet();
|
||||
alphaAnim.setInterpolator(new LinearInterpolator());
|
||||
alphaAnim.playTogether(
|
||||
ObjectAnimator.ofFloat(dragView, "alpha", toAlpha));
|
||||
animations.add(alphaAnim);
|
||||
|
||||
final Runnable onAnimationEndRunnable = createPostDeleteAnimationRunnable(dragView);
|
||||
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
anim.playTogether(animations);
|
||||
anim.setDuration(DRAG_TO_DELETE_FADE_OUT_DURATION);
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
onAnimationEndRunnable.run();
|
||||
}
|
||||
});
|
||||
anim.start();
|
||||
|
||||
mDeferringForDelete = true;
|
||||
}
|
||||
|
||||
/* Accessibility */
|
||||
|
||||
@Override
|
||||
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
|
||||
super.onInitializeAccessibilityNodeInfo(info);
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.internal.policy.impl.keyguard;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ObjectAnimator;
|
||||
@@ -29,7 +31,6 @@ import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.FloatProperty;
|
||||
import android.util.Log;
|
||||
import android.util.MathUtils;
|
||||
import android.util.Property;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.VelocityTracker;
|
||||
@@ -40,8 +41,6 @@ import android.view.accessibility.AccessibilityManager;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.widget.Scroller;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
/**
|
||||
* This layout handles interaction with the sliding security challenge views
|
||||
* that overlay/resize other keyguard contents.
|
||||
@@ -53,7 +52,7 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
|
||||
// The drag handle is measured in dp above & below the top edge of the
|
||||
// challenge view; these parameters change based on whether the challenge
|
||||
// is open or closed.
|
||||
private static final int DRAG_HANDLE_CLOSED_ABOVE = 64; // dp
|
||||
private static final int DRAG_HANDLE_CLOSED_ABOVE = 8; // dp
|
||||
private static final int DRAG_HANDLE_CLOSED_BELOW = 0; // dp
|
||||
private static final int DRAG_HANDLE_OPEN_ABOVE = 8; // dp
|
||||
private static final int DRAG_HANDLE_OPEN_BELOW = 0; // dp
|
||||
@@ -67,7 +66,7 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
|
||||
|
||||
// Initialized during measurement from child layoutparams
|
||||
private View mExpandChallengeView;
|
||||
private View mChallengeView;
|
||||
private KeyguardSecurityContainer mChallengeView;
|
||||
private View mScrimView;
|
||||
private View mWidgetsView;
|
||||
|
||||
@@ -123,6 +122,7 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
|
||||
private final Rect mTempRect = new Rect();
|
||||
|
||||
private boolean mHasGlowpad;
|
||||
private boolean mChallengeInteractive = true;
|
||||
|
||||
static final Property<SlidingChallengeLayout, Float> HANDLE_ALPHA =
|
||||
new FloatProperty<SlidingChallengeLayout>("handleAlpha") {
|
||||
@@ -276,6 +276,13 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
|
||||
}
|
||||
}
|
||||
|
||||
public void setChallengeInteractive(boolean interactive) {
|
||||
mChallengeInteractive = interactive;
|
||||
if (mExpandChallengeView != null) {
|
||||
mExpandChallengeView.setEnabled(interactive);
|
||||
}
|
||||
}
|
||||
|
||||
void animateHandle(boolean visible) {
|
||||
if (mHandleAnimation != null) {
|
||||
mHandleAnimation.cancel();
|
||||
@@ -504,7 +511,9 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
|
||||
if (mScrimView != null) {
|
||||
mScrimView.setVisibility(VISIBLE);
|
||||
}
|
||||
|
||||
if (mChallengeView != null) {
|
||||
mChallengeView.showBouncer(HANDLE_ANIMATE_DURATION);
|
||||
}
|
||||
// Mess with padding/margin to inset the bouncer frame.
|
||||
// We have more space available to us otherwise.
|
||||
if (mChallengeView != null) {
|
||||
@@ -533,6 +542,9 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
|
||||
if (mScrimView != null) {
|
||||
mScrimView.setVisibility(GONE);
|
||||
}
|
||||
if (mChallengeView != null) {
|
||||
mChallengeView.hideBouncer(HANDLE_ANIMATE_DURATION);
|
||||
}
|
||||
animateFrame(false, true);
|
||||
if (mBouncerListener != null) {
|
||||
mBouncerListener.onBouncerStateChanged(false);
|
||||
@@ -580,19 +592,17 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
|
||||
for (int i = 0; i < count; i++) {
|
||||
final float x = ev.getX(i);
|
||||
final float y = ev.getY(i);
|
||||
if (!mIsBouncing && mActivePointerId == INVALID_POINTER
|
||||
&& ((isInDragHandle(x, y) && MathUtils.sq(x - mGestureStartX)
|
||||
+ MathUtils.sq(y - mGestureStartY) > mTouchSlopSquare)
|
||||
|| crossedDragHandle(x, y, mGestureStartY)
|
||||
if (!mIsBouncing && mChallengeInteractive && mActivePointerId == INVALID_POINTER
|
||||
&& (crossedDragHandle(x, y, mGestureStartY)
|
||||
|| (isInChallengeView(x, y) &&
|
||||
mScrollState == SCROLL_STATE_SETTLING))) {
|
||||
mScrollState == SCROLL_STATE_SETTLING))) {
|
||||
mActivePointerId = ev.getPointerId(i);
|
||||
mGestureStartX = x;
|
||||
mGestureStartY = y;
|
||||
mGestureStartChallengeBottom = getChallengeBottom();
|
||||
mDragging = true;
|
||||
mChallengeView.setLayerType(LAYER_TYPE_HARDWARE, null);
|
||||
} else if (isInChallengeView(x, y)) {
|
||||
} else if (mChallengeShowing && isInChallengeView(x, y)) {
|
||||
mBlockDrag = true;
|
||||
}
|
||||
}
|
||||
@@ -630,7 +640,7 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
if (mDragging) {
|
||||
if (mDragging && mChallengeInteractive) {
|
||||
showChallenge(0);
|
||||
}
|
||||
resetTouch();
|
||||
@@ -641,7 +651,7 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
|
||||
break;
|
||||
}
|
||||
case MotionEvent.ACTION_UP:
|
||||
if (mDragging) {
|
||||
if (mDragging && mChallengeInteractive) {
|
||||
mVelocityTracker.computeCurrentVelocity(1000, mMaxVelocity);
|
||||
showChallenge((int) mVelocityTracker.getYVelocity(mActivePointerId));
|
||||
}
|
||||
@@ -657,7 +667,8 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
|
||||
|
||||
if ((isInDragHandle(x, y) || crossedDragHandle(x, y, mGestureStartY) ||
|
||||
(isInChallengeView(x, y) && mScrollState == SCROLL_STATE_SETTLING))
|
||||
&& mActivePointerId == INVALID_POINTER) {
|
||||
&& mActivePointerId == INVALID_POINTER
|
||||
&& mChallengeInteractive) {
|
||||
mGestureStartX = x;
|
||||
mGestureStartY = y;
|
||||
mActivePointerId = ev.getPointerId(i);
|
||||
@@ -767,11 +778,19 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
|
||||
}
|
||||
|
||||
private boolean crossedDragHandle(float x, float y, float initialY) {
|
||||
|
||||
final int challengeTop = mChallengeView.getTop();
|
||||
return x >= 0 &&
|
||||
x < getWidth() &&
|
||||
initialY < (challengeTop - getDragHandleSizeAbove()) &&
|
||||
y > challengeTop + getDragHandleSizeBelow();
|
||||
final boolean horizOk = x >= 0 && x < getWidth();
|
||||
|
||||
final boolean vertOk;
|
||||
if (mChallengeShowing) {
|
||||
vertOk = initialY < (challengeTop - getDragHandleSizeAbove()) &&
|
||||
y > challengeTop + getDragHandleSizeBelow();
|
||||
} else {
|
||||
vertOk = initialY > challengeTop + getDragHandleSizeBelow() &&
|
||||
y < challengeTop - getDragHandleSizeAbove();
|
||||
}
|
||||
return horizOk && vertOk;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -803,7 +822,11 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
|
||||
throw new IllegalStateException(
|
||||
"There may only be one child with layout_isChallenge=\"true\"");
|
||||
}
|
||||
mChallengeView = child;
|
||||
if (!(child instanceof KeyguardSecurityContainer)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Challenge must be a KeyguardSecurityContainer");
|
||||
}
|
||||
mChallengeView = (KeyguardSecurityContainer) child;
|
||||
if (mChallengeView != oldChallengeView) {
|
||||
mChallengeView.setVisibility(mChallengeShowing ? VISIBLE : INVISIBLE);
|
||||
}
|
||||
|
||||
@@ -599,7 +599,7 @@ class AppWidgetServiceImpl {
|
||||
}
|
||||
|
||||
public void bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options) {
|
||||
mContext.enforceCallingPermission(android.Manifest.permission.BIND_APPWIDGET,
|
||||
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BIND_APPWIDGET,
|
||||
"bindAppWidgetId appWidgetId=" + appWidgetId + " provider=" + provider);
|
||||
bindAppWidgetIdImpl(appWidgetId, provider, options);
|
||||
}
|
||||
@@ -607,7 +607,7 @@ class AppWidgetServiceImpl {
|
||||
public boolean bindAppWidgetIdIfAllowed(
|
||||
String packageName, int appWidgetId, ComponentName provider, Bundle options) {
|
||||
try {
|
||||
mContext.enforceCallingPermission(android.Manifest.permission.BIND_APPWIDGET, null);
|
||||
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BIND_APPWIDGET, null);
|
||||
} catch (SecurityException se) {
|
||||
if (!callerHasBindAppWidgetPermission(packageName)) {
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user