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 1769bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandlerpackage com.android.internal.policy.impl.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 2969bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandlerimport com.android.internal.R; 30acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandlerimport com.android.internal.widget.LockPatternUtils; 3169bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler 3269bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandlerpublic class NumPadKey extends Button { 33d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler // list of "ABC", etc per digit, starting with '0' 34d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler static String sKlondike[]; 3569bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler 3669bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler int mDigit = -1; 3769bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler int mTextViewResId; 3869bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler TextView mTextView = null; 39acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandler boolean mEnableHaptics; 4069bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler 4169bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler private View.OnClickListener mListener = new View.OnClickListener() { 4269bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler @Override 4369bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler public void onClick(View thisView) { 4469bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler if (mTextView == null) { 4569bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler if (mTextViewResId > 0) { 4669bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler final View v = NumPadKey.this.getRootView().findViewById(mTextViewResId); 4769bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler if (v != null && v instanceof TextView) { 4869bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler mTextView = (TextView) v; 4969bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler } 5069bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler } 5169bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler } 526a64ac56b7a8b81e6f24b5ad9856185488f4178dDaniel Sandler // check for time-based lockouts 536a64ac56b7a8b81e6f24b5ad9856185488f4178dDaniel Sandler if (mTextView != null && mTextView.isEnabled()) { 5469bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler mTextView.append(String.valueOf(mDigit)); 5569bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler } 56acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandler doHapticKeyClick(); 5769bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler } 5869bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler }; 5969bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler 6069bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler public NumPadKey(Context context) { 6169bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler this(context, null); 6269bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler } 6369bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler 6469bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler public NumPadKey(Context context, AttributeSet attrs) { 6569bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler this(context, attrs, 0); 6669bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler } 6769bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler 6869bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler public NumPadKey(Context context, AttributeSet attrs, int defStyle) { 6969bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler super(context, attrs, defStyle); 7069bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler 7169bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NumPadKey); 7269bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler mDigit = a.getInt(R.styleable.NumPadKey_digit, mDigit); 7369bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler setTextViewResId(a.getResourceId(R.styleable.NumPadKey_textView, 0)); 7469bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler 7569bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler setOnClickListener(mListener); 76c7375afef77b29b7fdb25f48dbe649b7b7fd487calanv setOnHoverListener(new LiftToActivateListener(context)); 770cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv setAccessibilityDelegate(new ObscureSpeechDelegate(context)); 7869bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler 79acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandler mEnableHaptics = new LockPatternUtils(context).isTactileFeedbackEnabled(); 80acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandler 8169bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler SpannableStringBuilder builder = new SpannableStringBuilder(); 8269bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler builder.append(String.valueOf(mDigit)); 8369bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler if (mDigit >= 0) { 84d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler if (sKlondike == null) { 85d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler sKlondike = context.getResources().getStringArray( 86d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler R.array.lockscreen_num_pad_klondike); 87d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler } 88d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler if (sKlondike != null && sKlondike.length > mDigit) { 89d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler final String extra = sKlondike[mDigit]; 90d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler final int extraLen = extra.length(); 91d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler if (extraLen > 0) { 9280bc85a7916713aae0b49e06b4b63bb3760a7a39Daniel Sandler builder.append(" "); 93d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler builder.append(extra); 94d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler builder.setSpan( 95d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler new TextAppearanceSpan(context, R.style.TextAppearance_NumPadKey_Klondike), 9669bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler builder.length()-extraLen, builder.length(), 0); 97d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler } 9869bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler } 9969bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler } 10069bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler setText(builder); 10169bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler } 10269bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler 1030cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv @Override 1040cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv public void onDetachedFromWindow() { 1050cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv super.onDetachedFromWindow(); 1060cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv 1070cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv // Reset the "announced headset" flag when detached. 1080cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv ObscureSpeechDelegate.sAnnouncedHeadset = false; 1090cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv } 1100cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv 11169bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler public void setTextView(TextView tv) { 11269bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler mTextView = tv; 11369bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler } 11469bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler 11569bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler public void setTextViewResId(int resId) { 11669bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler mTextView = null; 11769bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler mTextViewResId = resId; 11869bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler } 119acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandler 120acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandler // Cause a VIRTUAL_KEY vibration 121acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandler public void doHapticKeyClick() { 122acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandler if (mEnableHaptics) { 123acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandler performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, 124acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandler HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING 125acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandler | HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); 126acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandler } 127acb60fb57783b517e52fa60b1fa5f977141180c1Daniel Sandler } 128d5692742c1ff056e9fe55a495632229c86ed5384Daniel Sandler} 129