1dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller/* 2dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * Copyright (C) 2012 The Android Open Source Project 3dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * 4dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * Licensed under the Apache License, Version 2.0 (the "License"); 5dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * you may not use this file except in compliance with the License. 6dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * You may obtain a copy of the License at 7dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * 8dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * http://www.apache.org/licenses/LICENSE-2.0 9dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * 10dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * Unless required by applicable law or agreed to in writing, software 11dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * distributed under the License is distributed on an "AS IS" BASIS, 12dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * See the License for the specific language governing permissions and 14dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * limitations under the License. 15dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller */ 16dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 175ecd81154fa039961f65bb4e36d18ac555b0d1d6Jim Millerpackage com.android.keyguard; 18dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 19dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.content.Context; 200c48689b088b6379ae2ffa0e3c884b1349e8b8afJim Millerimport android.content.res.Resources; 21edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Millerimport android.text.TextUtils; 2238ab277ad478b1c858a852ba900ec0cd85fe2d2dJim Millerimport android.text.format.DateFormat; 23dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.util.AttributeSet; 2420daffd91e4a53054f8c4d7a66c2a68100abee03Jim Millerimport android.util.Log; 25edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Millerimport android.util.Slog; 26edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Millerimport android.view.View; 27dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.widget.GridLayout; 2838ab277ad478b1c858a852ba900ec0cd85fe2d2dJim Millerimport android.widget.TextClock; 29edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Millerimport android.widget.TextView; 30dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 311254f2f42f7173ef51d0034975ab5cb7d44f8209Michael Jurkaimport com.android.internal.widget.LockPatternUtils; 321254f2f42f7173ef51d0034975ab5cb7d44f8209Michael Jurka 3356018e577edada2721f4772bcec9274d043a06e7Chris Wrenimport java.util.Locale; 3456018e577edada2721f4772bcec9274d043a06e7Chris Wren 35dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerpublic class KeyguardStatusView extends GridLayout { 36edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller private static final boolean DEBUG = KeyguardViewMediator.DEBUG; 37edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller private static final String TAG = "KeyguardStatusView"; 38edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller 39edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller private LockPatternUtils mLockPatternUtils; 40edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller 41edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller private TextView mAlarmStatusView; 4238ab277ad478b1c858a852ba900ec0cd85fe2d2dJim Miller private TextClock mDateView; 430c48689b088b6379ae2ffa0e3c884b1349e8b8afJim Miller private TextClock mClockView; 44edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller 45edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() { 46edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller 47edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller @Override 48edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller public void onTimeChanged() { 49edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller refresh(); 50edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller } 51edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller 52edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller @Override 53edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller void onKeyguardVisibilityChanged(boolean showing) { 54edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller if (showing) { 55edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller if (DEBUG) Slog.v(TAG, "refresh statusview showing:" + showing); 56edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller refresh(); 57edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller } 58edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller }; 5920daffd91e4a53054f8c4d7a66c2a68100abee03Jim Miller 6038ab277ad478b1c858a852ba900ec0cd85fe2d2dJim Miller @Override 6120daffd91e4a53054f8c4d7a66c2a68100abee03Jim Miller public void onScreenTurnedOn() { 6220daffd91e4a53054f8c4d7a66c2a68100abee03Jim Miller setEnableMarquee(true); 6320daffd91e4a53054f8c4d7a66c2a68100abee03Jim Miller }; 6420daffd91e4a53054f8c4d7a66c2a68100abee03Jim Miller 6538ab277ad478b1c858a852ba900ec0cd85fe2d2dJim Miller @Override 6620daffd91e4a53054f8c4d7a66c2a68100abee03Jim Miller public void onScreenTurnedOff(int why) { 6720daffd91e4a53054f8c4d7a66c2a68100abee03Jim Miller setEnableMarquee(false); 6820daffd91e4a53054f8c4d7a66c2a68100abee03Jim Miller }; 69edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller }; 706212cc0d3f59139421ceeaf630f6494239d81cd1Jim Miller 71dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller public KeyguardStatusView(Context context) { 72dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller this(context, null, 0); 73dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 74dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 75dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller public KeyguardStatusView(Context context, AttributeSet attrs) { 76dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller this(context, attrs, 0); 77dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 78dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 79dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller public KeyguardStatusView(Context context, AttributeSet attrs, int defStyle) { 80dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller super(context, attrs, defStyle); 81dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 82dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 8320daffd91e4a53054f8c4d7a66c2a68100abee03Jim Miller private void setEnableMarquee(boolean enabled) { 8420daffd91e4a53054f8c4d7a66c2a68100abee03Jim Miller if (DEBUG) Log.v(TAG, (enabled ? "Enable" : "Disable") + " transport text marquee"); 8531049d76c55b18a6d9993f0d9687598740b16014Adam Powell if (mAlarmStatusView != null) mAlarmStatusView.setSelected(enabled); 8620daffd91e4a53054f8c4d7a66c2a68100abee03Jim Miller } 8720daffd91e4a53054f8c4d7a66c2a68100abee03Jim Miller 88dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller @Override 89dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller protected void onFinishInflate() { 90dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller super.onFinishInflate(); 91edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller mAlarmStatusView = (TextView) findViewById(R.id.alarm_status); 9238ab277ad478b1c858a852ba900ec0cd85fe2d2dJim Miller mDateView = (TextClock) findViewById(R.id.date_view); 930c48689b088b6379ae2ffa0e3c884b1349e8b8afJim Miller mClockView = (TextClock) findViewById(R.id.clock_view); 94edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller mLockPatternUtils = new LockPatternUtils(getContext()); 9520daffd91e4a53054f8c4d7a66c2a68100abee03Jim Miller final boolean screenOn = KeyguardUpdateMonitor.getInstance(mContext).isScreenOn(); 9620daffd91e4a53054f8c4d7a66c2a68100abee03Jim Miller setEnableMarquee(screenOn); 97edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller refresh(); 98edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller } 99dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 100edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller protected void refresh() { 101385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock Patterns.update(mContext); 102385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock 103385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock mDateView.setFormat24Hour(Patterns.dateView); 104385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock mDateView.setFormat12Hour(Patterns.dateView); 105385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock 106385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock mClockView.setFormat12Hour(Patterns.clockView12); 107385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock mClockView.setFormat24Hour(Patterns.clockView24); 1080c48689b088b6379ae2ffa0e3c884b1349e8b8afJim Miller 10938ab277ad478b1c858a852ba900ec0cd85fe2d2dJim Miller refreshAlarmStatus(); 110edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller } 111edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller 112edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller void refreshAlarmStatus() { 113edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller // Update Alarm status 114edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller String nextAlarm = mLockPatternUtils.getNextAlarm(); 115edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller if (!TextUtils.isEmpty(nextAlarm)) { 116e38c8e28ba50d5fe7f4f2bc5fe68a9f10bafe0f0Jim Miller mAlarmStatusView.setText(nextAlarm); 117edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller mAlarmStatusView.setVisibility(View.VISIBLE); 118edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller } else { 119edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller mAlarmStatusView.setVisibility(View.GONE); 120edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller } 121edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller } 122edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller 123edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller @Override 124edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller protected void onAttachedToWindow() { 125edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller super.onAttachedToWindow(); 126edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mInfoCallback); 127edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller } 128edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller 129edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller @Override 130edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller protected void onDetachedFromWindow() { 131edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller super.onDetachedFromWindow(); 132edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mInfoCallback); 133edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller } 134edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller 135edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller public int getAppWidgetId() { 136edc74abf8ad5880b0e3caeb3fdf92249da202abeJim Miller return LockPatternUtils.ID_DEFAULT_STATUS_WIDGET; 137dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 138dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 139385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock // DateFormat.getBestDateTimePattern is extremely expensive, and refresh is called often. 140385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock // This is an optimization to ensure we only recompute the patterns when the inputs change. 141385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock private static final class Patterns { 142385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock static String dateView; 143385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock static String clockView12; 144385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock static String clockView24; 145385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock static String cacheKey; 146385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock 147385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock static void update(Context context) { 148385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock final Locale locale = Locale.getDefault(); 149385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock final Resources res = context.getResources(); 150385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock final String dateViewSkel = res.getString(R.string.abbrev_wday_month_day_no_year); 151385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock final String clockView12Skel = res.getString(R.string.clock_12hr_format); 152385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock final String clockView24Skel = res.getString(R.string.clock_24hr_format); 153385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock final String key = locale.toString() + dateViewSkel + clockView12Skel + clockView24Skel; 154385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock if (key.equals(cacheKey)) return; 155385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock 156385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock dateView = DateFormat.getBestDateTimePattern(locale, dateViewSkel); 157385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock 158385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock clockView12 = DateFormat.getBestDateTimePattern(locale, clockView12Skel); 159385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock // CLDR insists on adding an AM/PM indicator even though it wasn't in the skeleton 160385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock // format. The following code removes the AM/PM indicator if we didn't want it. 161385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock if (!clockView12Skel.contains("a")) { 162385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock clockView12 = clockView12.replaceAll("a", "").trim(); 163385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock } 164385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock 165385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock clockView24 = DateFormat.getBestDateTimePattern(locale, clockView24Skel); 166385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock 167385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock cacheKey = key; 168385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock } 169385a63d56a1f5afdf064539d033da999b748289aJohn Spurlock } 170dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller} 171