1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.keyguard; 18 19 import android.content.Context; 20 import android.content.res.Resources; 21 import android.text.TextUtils; 22 import android.text.format.DateFormat; 23 import android.util.AttributeSet; 24 import android.util.Log; 25 import android.util.Slog; 26 import android.view.View; 27 import android.widget.GridLayout; 28 import android.widget.TextClock; 29 import android.widget.TextView; 30 31 import com.android.internal.widget.LockPatternUtils; 32 33 import java.util.Locale; 34 35 public class KeyguardStatusView extends GridLayout { 36 private static final boolean DEBUG = KeyguardViewMediator.DEBUG; 37 private static final String TAG = "KeyguardStatusView"; 38 39 private LockPatternUtils mLockPatternUtils; 40 41 private TextView mAlarmStatusView; 42 private TextClock mDateView; 43 private TextClock mClockView; 44 45 private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() { 46 47 @Override 48 public void onTimeChanged() { 49 refresh(); 50 } 51 52 @Override 53 void onKeyguardVisibilityChanged(boolean showing) { 54 if (showing) { 55 if (DEBUG) Slog.v(TAG, "refresh statusview showing:" + showing); 56 refresh(); 57 } 58 }; 59 60 @Override 61 public void onScreenTurnedOn() { 62 setEnableMarquee(true); 63 }; 64 65 @Override 66 public void onScreenTurnedOff(int why) { 67 setEnableMarquee(false); 68 }; 69 }; 70 KeyguardStatusView(Context context)71 public KeyguardStatusView(Context context) { 72 this(context, null, 0); 73 } 74 KeyguardStatusView(Context context, AttributeSet attrs)75 public KeyguardStatusView(Context context, AttributeSet attrs) { 76 this(context, attrs, 0); 77 } 78 KeyguardStatusView(Context context, AttributeSet attrs, int defStyle)79 public KeyguardStatusView(Context context, AttributeSet attrs, int defStyle) { 80 super(context, attrs, defStyle); 81 } 82 setEnableMarquee(boolean enabled)83 private void setEnableMarquee(boolean enabled) { 84 if (DEBUG) Log.v(TAG, (enabled ? "Enable" : "Disable") + " transport text marquee"); 85 if (mAlarmStatusView != null) mAlarmStatusView.setSelected(enabled); 86 } 87 88 @Override onFinishInflate()89 protected void onFinishInflate() { 90 super.onFinishInflate(); 91 mAlarmStatusView = (TextView) findViewById(R.id.alarm_status); 92 mDateView = (TextClock) findViewById(R.id.date_view); 93 mClockView = (TextClock) findViewById(R.id.clock_view); 94 mLockPatternUtils = new LockPatternUtils(getContext()); 95 final boolean screenOn = KeyguardUpdateMonitor.getInstance(mContext).isScreenOn(); 96 setEnableMarquee(screenOn); 97 refresh(); 98 } 99 refresh()100 protected void refresh() { 101 Patterns.update(mContext); 102 103 mDateView.setFormat24Hour(Patterns.dateView); 104 mDateView.setFormat12Hour(Patterns.dateView); 105 106 mClockView.setFormat12Hour(Patterns.clockView12); 107 mClockView.setFormat24Hour(Patterns.clockView24); 108 109 refreshAlarmStatus(); 110 } 111 refreshAlarmStatus()112 void refreshAlarmStatus() { 113 // Update Alarm status 114 String nextAlarm = mLockPatternUtils.getNextAlarm(); 115 if (!TextUtils.isEmpty(nextAlarm)) { 116 mAlarmStatusView.setText(nextAlarm); 117 mAlarmStatusView.setVisibility(View.VISIBLE); 118 } else { 119 mAlarmStatusView.setVisibility(View.GONE); 120 } 121 } 122 123 @Override onAttachedToWindow()124 protected void onAttachedToWindow() { 125 super.onAttachedToWindow(); 126 KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mInfoCallback); 127 } 128 129 @Override onDetachedFromWindow()130 protected void onDetachedFromWindow() { 131 super.onDetachedFromWindow(); 132 KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mInfoCallback); 133 } 134 getAppWidgetId()135 public int getAppWidgetId() { 136 return LockPatternUtils.ID_DEFAULT_STATUS_WIDGET; 137 } 138 139 // DateFormat.getBestDateTimePattern is extremely expensive, and refresh is called often. 140 // This is an optimization to ensure we only recompute the patterns when the inputs change. 141 private static final class Patterns { 142 static String dateView; 143 static String clockView12; 144 static String clockView24; 145 static String cacheKey; 146 update(Context context)147 static void update(Context context) { 148 final Locale locale = Locale.getDefault(); 149 final Resources res = context.getResources(); 150 final String dateViewSkel = res.getString(R.string.abbrev_wday_month_day_no_year); 151 final String clockView12Skel = res.getString(R.string.clock_12hr_format); 152 final String clockView24Skel = res.getString(R.string.clock_24hr_format); 153 final String key = locale.toString() + dateViewSkel + clockView12Skel + clockView24Skel; 154 if (key.equals(cacheKey)) return; 155 156 dateView = DateFormat.getBestDateTimePattern(locale, dateViewSkel); 157 158 clockView12 = DateFormat.getBestDateTimePattern(locale, clockView12Skel); 159 // CLDR insists on adding an AM/PM indicator even though it wasn't in the skeleton 160 // format. The following code removes the AM/PM indicator if we didn't want it. 161 if (!clockView12Skel.contains("a")) { 162 clockView12 = clockView12.replaceAll("a", "").trim(); 163 } 164 165 clockView24 = DateFormat.getBestDateTimePattern(locale, clockView24Skel); 166 167 cacheKey = key; 168 } 169 } 170 } 171