169bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler/* 269bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler * Copyright (C) 2012 The Android Open Source Project 369bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler * 469bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler * Licensed under the Apache License, Version 2.0 (the "License"); 569bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler * you may not use this file except in compliance with the License. 669bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler * You may obtain a copy of the License at 769bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler * 869bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler * http://www.apache.org/licenses/LICENSE-2.0 969bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler * 1069bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler * Unless required by applicable law or agreed to in writing, software 1169bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler * distributed under the License is distributed on an "AS IS" BASIS, 1269bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1369bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler * See the License for the specific language governing permissions and 1469bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler * limitations under the License. 1569bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler */ 1669bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler 175ecd81154fa039961f65bb4e36d18ac555b0d1d6Jim Millerpackage com.android.keyguard; 1869bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler 1969bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandlerimport android.content.Context; 2069bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandlerimport android.content.res.TypedArray; 2169bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandlerimport android.text.SpannableStringBuilder; 2269bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandlerimport android.text.style.TextAppearanceSpan; 2369bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandlerimport android.util.AttributeSet; 24acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandlerimport android.view.HapticFeedbackConstants; 2569bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandlerimport android.view.View; 2669bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandlerimport android.widget.Button; 2769bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandlerimport android.widget.TextView; 2869bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler 29acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandlerimport com.android.internal.widget.LockPatternUtils; 3069bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler 3169bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandlerpublic class NumPadKey extends Button { 32d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler // list of "ABC", etc per digit, starting with '0' 33d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler static String sKlondike[]; 3469bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler 3569bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler int mDigit = -1; 3669bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler int mTextViewResId; 3769bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler TextView mTextView = null; 38acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandler boolean mEnableHaptics; 3969bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler 4069bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler private View.OnClickListener mListener = new View.OnClickListener() { 4169bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler @Override 4269bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler public void onClick(View thisView) { 4369bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler if (mTextView == null) { 4469bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler if (mTextViewResId > 0) { 4569bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler final View v = NumPadKey.this.getRootView().findViewById(mTextViewResId); 4669bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler if (v != null && v instanceof TextView) { 4769bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler mTextView = (TextView) v; 4869bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler } 4969bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler } 5069bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler } 516a64ac56b7a8b81e6f24b5ad9856185488f4178dDaniel Sandler // check for time-based lockouts 526a64ac56b7a8b81e6f24b5ad9856185488f4178dDaniel Sandler if (mTextView != null && mTextView.isEnabled()) { 5369bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler mTextView.append(String.valueOf(mDigit)); 5469bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler } 55acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandler doHapticKeyClick(); 5669bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler } 5769bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler }; 5869bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler 5969bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler public NumPadKey(Context context) { 6069bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler this(context, null); 6169bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler } 6269bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler 6369bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler public NumPadKey(Context context, AttributeSet attrs) { 6469bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler this(context, attrs, 0); 6569bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler } 6669bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler 6769bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler public NumPadKey(Context context, AttributeSet attrs, int defStyle) { 6869bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler super(context, attrs, defStyle); 6969bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler 7069bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NumPadKey); 7169bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler mDigit = a.getInt(R.styleable.NumPadKey_digit, mDigit); 7269bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler setTextViewResId(a.getResourceId(R.styleable.NumPadKey_textView, 0)); 7369bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler 7469bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler setOnClickListener(mListener); 75c7375afef77b29b7fdb25f48dbe649b7b7fd487calanv setOnHoverListener(new LiftToActivateListener(context)); 760cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv setAccessibilityDelegate(new ObscureSpeechDelegate(context)); 7769bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler 78acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandler mEnableHaptics = new LockPatternUtils(context).isTactileFeedbackEnabled(); 79acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandler 8069bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler SpannableStringBuilder builder = new SpannableStringBuilder(); 8169bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler builder.append(String.valueOf(mDigit)); 8269bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler if (mDigit >= 0) { 83d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler if (sKlondike == null) { 84d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler sKlondike = context.getResources().getStringArray( 85d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler R.array.lockscreen_num_pad_klondike); 86d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler } 87d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler if (sKlondike != null && sKlondike.length > mDigit) { 88d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler final String extra = sKlondike[mDigit]; 89d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler final int extraLen = extra.length(); 90d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler if (extraLen > 0) { 9180bc85a7916713aae0b49e06b4b63bb3760a7a39Daniel Sandler builder.append(" "); 92d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler builder.append(extra); 93d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler builder.setSpan( 94d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler new TextAppearanceSpan(context, R.style.TextAppearance_NumPadKey_Klondike), 9569bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler builder.length()-extraLen, builder.length(), 0); 96d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler } 9769bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler } 9869bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler } 9969bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler setText(builder); 10069bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler } 10169bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler 1020cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv @Override 1030cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv public void onDetachedFromWindow() { 1040cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv super.onDetachedFromWindow(); 1050cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv 1060cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv // Reset the "announced headset" flag when detached. 1070cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv ObscureSpeechDelegate.sAnnouncedHeadset = false; 1080cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv } 1090cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv 11069bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler public void setTextView(TextView tv) { 11169bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler mTextView = tv; 11269bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler } 11369bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler 11469bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler public void setTextViewResId(int resId) { 11569bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler mTextView = null; 11669bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler mTextViewResId = resId; 11769bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler } 118acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandler 119acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandler // Cause a VIRTUAL_KEY vibration 120acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandler public void doHapticKeyClick() { 121acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandler if (mEnableHaptics) { 122acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandler performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, 123acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandler HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING 124acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandler | HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); 125acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandler } 126acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandler } 127d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler} 128