From edc74abf8ad5880b0e3caeb3fdf92249da202abe Mon Sep 17 00:00:00 2001 From: Jim Miller Date: Tue, 6 Nov 2012 21:46:11 -0800 Subject: [PATCH] Implement fallback clock in keyguard This clock is shown if widgets are ever disabled by DPM and the default clock package is not enabled. Fixes bug 7469367 Change-Id: I8cf140c0fc00dd56265e3a332aff2fe3b41e3ec0 --- .../res/layout-land/keyguard_status_area.xml | 39 -- .../res/layout-port/keyguard_status_area.xml | 39 -- .../keyguard_status_area.xml | 25 -- core/res/res/values/symbols.xml | 1 - .../impl/keyguard/KeyguardStatusView.java | 119 +++++- .../keyguard/KeyguardStatusViewManager.java | 341 ------------------ 6 files changed, 107 insertions(+), 457 deletions(-) delete mode 100644 policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java diff --git a/core/res/res/layout-land/keyguard_status_area.xml b/core/res/res/layout-land/keyguard_status_area.xml index f562d9f671fdd..51ee740befa19 100644 --- a/core/res/res/layout-land/keyguard_status_area.xml +++ b/core/res/res/layout-land/keyguard_status_area.xml @@ -53,43 +53,4 @@ android:drawablePadding="4dip" /> - - - - - \ No newline at end of file diff --git a/core/res/res/layout-port/keyguard_status_area.xml b/core/res/res/layout-port/keyguard_status_area.xml index c1f6aab1f0ac2..d274457ce2278 100644 --- a/core/res/res/layout-port/keyguard_status_area.xml +++ b/core/res/res/layout-port/keyguard_status_area.xml @@ -56,43 +56,4 @@ /> - - - - - - diff --git a/core/res/res/layout-sw600dp-port/keyguard_status_area.xml b/core/res/res/layout-sw600dp-port/keyguard_status_area.xml index 405ac141f2dbc..88dd760146a99 100644 --- a/core/res/res/layout-sw600dp-port/keyguard_status_area.xml +++ b/core/res/res/layout-sw600dp-port/keyguard_status_area.xml @@ -53,29 +53,4 @@ android:drawablePadding="4dip" /> - - - diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index f2e4d5123f528..aefbbf1c7d223 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1343,7 +1343,6 @@ - diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusView.java index f2cb5221d0a82..35b8509f92efc 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusView.java @@ -17,14 +17,52 @@ package com.android.internal.policy.impl.keyguard; import android.content.Context; +import android.content.res.Resources; +import android.graphics.Typeface; +import android.text.TextUtils; +import android.text.format.DateFormat; import android.util.AttributeSet; +import android.util.Slog; +import android.view.View; import android.widget.GridLayout; +import android.widget.TextView; +import com.android.internal.R; import com.android.internal.widget.LockPatternUtils; +import java.util.Date; + public class KeyguardStatusView extends GridLayout { - @SuppressWarnings("unused") - private KeyguardStatusViewManager mStatusViewManager; + private static final boolean DEBUG = KeyguardViewMediator.DEBUG; + private static final String TAG = "KeyguardStatusView"; + + public static final int LOCK_ICON = 0; // R.drawable.ic_lock_idle_lock; + public static final int ALARM_ICON = com.android.internal.R.drawable.ic_lock_idle_alarm; + public static final int CHARGING_ICON = 0; //R.drawable.ic_lock_idle_charging; + public static final int BATTERY_LOW_ICON = 0; //R.drawable.ic_lock_idle_low_battery; + + private CharSequence mDateFormatString; + private LockPatternUtils mLockPatternUtils; + + private TextView mDateView; + private TextView mAlarmStatusView; + private ClockView mClockView; + + private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() { + + @Override + public void onTimeChanged() { + refresh(); + } + + @Override + void onKeyguardVisibilityChanged(boolean showing) { + if (showing) { + if (DEBUG) Slog.v(TAG, "refresh statusview showing:" + showing); + refresh(); + } + }; + }; public KeyguardStatusView(Context context) { this(context, null, 0); @@ -38,19 +76,76 @@ public class KeyguardStatusView extends GridLayout { super(context, attrs, defStyle); } + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + Resources res = getContext().getResources(); + mDateFormatString = + res.getText(com.android.internal.R.string.abbrev_wday_month_day_no_year); + mDateView = (TextView) findViewById(R.id.date); + mAlarmStatusView = (TextView) findViewById(R.id.alarm_status); + mClockView = (ClockView) findViewById(R.id.clock_view); + mLockPatternUtils = new LockPatternUtils(getContext()); + + // Use custom font in mDateView + mDateView.setTypeface(Typeface.SANS_SERIF, Typeface.BOLD); + + // Required to get Marquee to work. + final View marqueeViews[] = { mDateView, mAlarmStatusView }; + for (int i = 0; i < marqueeViews.length; i++) { + View v = marqueeViews[i]; + if (v == null) { + throw new RuntimeException("Can't find widget at index " + i); + } + v.setSelected(true); + } + refresh(); + } + + protected void refresh() { + mClockView.updateTime(); + refreshDate(); + refreshAlarmStatus(); // might as well + } + + void refreshAlarmStatus() { + // Update Alarm status + String nextAlarm = mLockPatternUtils.getNextAlarm(); + if (!TextUtils.isEmpty(nextAlarm)) { + maybeSetUpperCaseText(mAlarmStatusView, nextAlarm); + mAlarmStatusView.setCompoundDrawablesWithIntrinsicBounds(ALARM_ICON, 0, 0, 0); + mAlarmStatusView.setVisibility(View.VISIBLE); + } else { + mAlarmStatusView.setVisibility(View.GONE); + } + } + + void refreshDate() { + maybeSetUpperCaseText(mDateView, DateFormat.format(mDateFormatString, new Date())); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mInfoCallback); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mInfoCallback); + } + public int getAppWidgetId() { return LockPatternUtils.ID_DEFAULT_STATUS_WIDGET; } - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - - // StatusView manages all of the widgets in this view. - mStatusViewManager = new KeyguardStatusViewManager(this); - } - - KeyguardStatusViewManager getManager() { - return mStatusViewManager; + private void maybeSetUpperCaseText(TextView textView, CharSequence text) { + if (KeyguardViewManager.USE_UPPER_CASE + && textView.getId() != R.id.owner_info) { // currently only required for date view + textView.setText(text != null ? text.toString().toUpperCase() : null); + } else { + textView.setText(text); + } } } diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java deleted file mode 100644 index 34356197f17ce..0000000000000 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright (C) 2011 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.content.res.Resources; -import android.graphics.Typeface; -import android.os.Handler; -import android.os.Looper; -import android.os.UserHandle; -import android.provider.Settings; -import android.text.TextUtils; -import android.text.format.DateFormat; -import android.util.Log; -import android.view.View; -import android.widget.TextView; - -import com.android.internal.R; -import com.android.internal.telephony.IccCardConstants; -import com.android.internal.widget.LockPatternUtils; - -import java.util.Date; - -import libcore.util.MutableInt; - -/*** - * Manages a number of views inside of the given layout. See below for a list of widgets. - */ -class KeyguardStatusViewManager implements SecurityMessageDisplay { - private static final boolean DEBUG = false; - private static final String TAG = "KeyguardStatusView"; - - public static final int LOCK_ICON = 0; // R.drawable.ic_lock_idle_lock; - public static final int ALARM_ICON = com.android.internal.R.drawable.ic_lock_idle_alarm; - public static final int CHARGING_ICON = 0; //R.drawable.ic_lock_idle_charging; - public static final int BATTERY_LOW_ICON = 0; //R.drawable.ic_lock_idle_low_battery; - - private CharSequence mDateFormatString; - - // Views that this class controls. - private TextView mDateView; - private TextView mStatus1View; - private TextView mOwnerInfoView; - private TextView mAlarmStatusView; - private TextView mSecurityMessage; - private static final int SECURITY_MESSAGE_DURATION = 5000; - private static final boolean SECURITY_MESSAGE_TIMES_OUT = false; - - // Top-level container view for above views - private View mContainer; - - // are we showing battery information? - private boolean mShowingBatteryInfo = false; - - // last known plugged in state - private boolean mPluggedIn = false; - - // Whether to use the last line as a combined line to either display owner info / charging. - // If false, each item will be given a dedicated space. - private boolean mShareStatusRegion = false; - - // last known battery level - private int mBatteryLevel = 100; - - // last known SIM state - protected IccCardConstants.State mSimState; - - private LockPatternUtils mLockPatternUtils; - private KeyguardUpdateMonitor mUpdateMonitor; - - // Shadowed text values - private ClockView mClockView; - protected boolean mBatteryCharged; - protected boolean mBatteryIsLow; - - private Handler mHandler; - private Runnable mClearSecurityMessageRunnable; - private CharSequence mSecurityMessageContents = ""; - - private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() { - @Override - public void onRefreshBatteryInfo(KeyguardUpdateMonitor.BatteryStatus status) { - mShowingBatteryInfo = status.isPluggedIn() || status.isBatteryLow(); - mPluggedIn = status.isPluggedIn(); - mBatteryLevel = status.level; - mBatteryCharged = status.isCharged(); - mBatteryIsLow = status.isBatteryLow(); - updateStatusLines(); - } - - @Override - public void onTimeChanged() { - refreshDate(); - } - }; - - /** - * @param view the containing view of all widgets - */ - public KeyguardStatusViewManager(View view) { - if (DEBUG) Log.v(TAG, "KeyguardStatusViewManager()"); - mContainer = view; - Resources res = getContext().getResources(); - mDateFormatString = - res.getText(com.android.internal.R.string.abbrev_wday_month_day_no_year); - mShareStatusRegion = res.getBoolean(com.android.internal.R.bool.kg_share_status_area); - mLockPatternUtils = new LockPatternUtils(view.getContext()); - mUpdateMonitor = KeyguardUpdateMonitor.getInstance(view.getContext()); - - mDateView = (TextView) view.findViewById(R.id.date); - mStatus1View = (TextView) view.findViewById(R.id.status1); - mAlarmStatusView = (TextView) view.findViewById(R.id.alarm_status); - mOwnerInfoView = (TextView) view.findViewById(R.id.owner_info); - mClockView = (ClockView) view.findViewById(R.id.clock_view); - mSecurityMessage = (TextView) view.findViewById(R.id.status_security_message); - - // This is required to ensure marquee works - if (mSecurityMessage != null) { - mSecurityMessage.setSelected(true); - } - - // Use custom font in mDateView - mDateView.setTypeface(Typeface.SANS_SERIF, Typeface.BOLD); - - // Required to get Marquee to work. - final View marqueeViews[] = { mDateView, mStatus1View, mOwnerInfoView, mAlarmStatusView }; - for (int i = 0; i < marqueeViews.length; i++) { - View v = marqueeViews[i]; - if (v == null) { - throw new RuntimeException("Can't find widget at index " + i); - } - v.setSelected(true); - } - - // Registering this callback immediately updates the battery state, among other things. - mUpdateMonitor.registerCallback(mInfoCallback); - - refreshDate(); - resetStatusInfo(); - - mHandler = new Handler(Looper.myLooper()); - mClearSecurityMessageRunnable = new Runnable() { - @Override - public void run() { - mSecurityMessageContents = ""; - updateStatusLines(); - } - }; - } - - public void onPause() { - if (DEBUG) Log.v(TAG, "onPause()"); - mUpdateMonitor.removeCallback(mInfoCallback); - } - - /** {@inheritDoc} */ - public void onResume(int reason) { - if (DEBUG) Log.v(TAG, "onResume()"); - - // Force-update the time when we show this view. - mClockView.updateTime(); - - mUpdateMonitor.registerCallback(mInfoCallback); - resetStatusInfo(); - } - - void resetStatusInfo() { - updateStatusLines(); - } - - public void setMessage(CharSequence msg, boolean important) { - if (!important) { - mSecurityMessageContents = ""; - } else { - mSecurityMessageContents = msg; - } - securityMessageChanged(); - } - - public void setMessage(int resId, boolean important) { - if (resId != 0 && important) { - mSecurityMessageContents = getContext().getResources().getText(resId); - } else { - mSecurityMessageContents = ""; - } - securityMessageChanged(); - } - - public void setMessage(int resId, boolean important, Object... formatArgs) { - if (resId != 0 && important) { - mSecurityMessageContents = getContext().getString(resId, formatArgs); - } else { - mSecurityMessageContents = ""; - } - securityMessageChanged(); - } - - public void securityMessageChanged() { - updateStatusLines(); - if (SECURITY_MESSAGE_TIMES_OUT) { - mHandler.removeCallbacks(mClearSecurityMessageRunnable); - mHandler.postDelayed(mClearSecurityMessageRunnable, SECURITY_MESSAGE_DURATION); - } - mSecurityMessage.announceForAccessibility(mSecurityMessage.getText()); - } - - /** - * Update the status lines based on these rules: - * AlarmStatus: Alarm state always gets it's own line. - * Status1 is shared between help, battery status and generic unlock instructions, - * prioritized in that order. - * @param showStatusLines status lines are shown if true - */ - void updateStatusLines() { - updateAlarmInfo(); - boolean statusAreaUsed = updateSecurityMessage(); - statusAreaUsed = updateStatus1(statusAreaUsed) || statusAreaUsed; - updateOwnerInfo(statusAreaUsed); - } - - private boolean updateSecurityMessage() { - if (mSecurityMessage == null) return false; - if (!TextUtils.isEmpty(mSecurityMessageContents)) { - mSecurityMessage.setText(mSecurityMessageContents); - mSecurityMessage.setVisibility(View.VISIBLE); - return true; - } else { - mSecurityMessage.setVisibility(View.GONE); - return false; - } - } - - private void updateAlarmInfo() { - String nextAlarm = mLockPatternUtils.getNextAlarm(); - if (!TextUtils.isEmpty(nextAlarm)) { - maybeSetUpperCaseText(mAlarmStatusView, nextAlarm); - mAlarmStatusView.setCompoundDrawablesWithIntrinsicBounds(ALARM_ICON, 0, 0, 0); - mAlarmStatusView.setVisibility(View.VISIBLE); - } else { - mAlarmStatusView.setVisibility(View.GONE); - } - } - - private boolean updateStatus1(boolean statusAreaUsed) { - MutableInt icon = new MutableInt(0); - CharSequence string = getPriorityTextMessage(icon); - - boolean dontShow = statusAreaUsed && mShareStatusRegion; - if (!dontShow && !TextUtils.isEmpty(string)) { - maybeSetUpperCaseText(mStatus1View, string); - mStatus1View.setCompoundDrawablesWithIntrinsicBounds(icon.value, 0, 0, 0); - mStatus1View.setVisibility(View.VISIBLE); - return true; - } else { - mStatus1View.setVisibility(View.GONE); - return false; - } - } - - private void updateOwnerInfo(boolean statusAreaUsed) { - final ContentResolver res = getContext().getContentResolver(); - final boolean ownerInfoEnabled = Settings.Secure.getIntForUser(res, - Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED, 1, UserHandle.USER_CURRENT) != 0; - String text = Settings.Secure.getStringForUser(res, Settings.Secure.LOCK_SCREEN_OWNER_INFO, - UserHandle.USER_CURRENT); - - boolean dontShow = statusAreaUsed && mShareStatusRegion; - if (!dontShow && ownerInfoEnabled && !TextUtils.isEmpty(text)) { - text = text.trim(); // Remove trailing newlines - maybeSetUpperCaseText(mOwnerInfoView, text); - mOwnerInfoView.setVisibility(View.VISIBLE); - } else { - mOwnerInfoView.setVisibility(View.GONE); - } - } - - private CharSequence getPriorityTextMessage(MutableInt icon) { - CharSequence string = null; - if (mShowingBatteryInfo) { - // Battery status - if (mPluggedIn) { - // Charging, charged or waiting to charge. - string = getContext().getString(mBatteryCharged ? - com.android.internal.R.string.lockscreen_charged - :com.android.internal.R.string.lockscreen_plugged_in, mBatteryLevel); - icon.value = CHARGING_ICON; - } else if (mBatteryIsLow) { - // Battery is low - string = getContext().getString( - com.android.internal.R.string.lockscreen_low_battery); - icon.value = BATTERY_LOW_ICON; - } - } - return string; - } - - void refreshDate() { - maybeSetUpperCaseText(mDateView, DateFormat.format(mDateFormatString, new Date())); - } - - private void maybeSetUpperCaseText(TextView textView, CharSequence text) { - if (KeyguardViewManager.USE_UPPER_CASE - && textView.getId() != R.id.owner_info) { // currently only required for date view - textView.setText(text != null ? text.toString().toUpperCase() : null); - } else { - textView.setText(text); - } - } - - private Context getContext() { - return mContainer.getContext(); - } - - @Override - public void showBouncer(int duration) { - } - - @Override - public void hideBouncer(int duration) { - } - - @Override - public void setTimeout(int timeout_ms) { - } - -}