am bb01e9b8: am b1938777: am 40962880: Merge "Implement fallback clock in keyguard" into jb-mr1-lockscreen-dev

* commit 'bb01e9b82f296102f9f5fdcf0545d61664e6ca06':
  Implement fallback clock in keyguard
This commit is contained in:
Jim Miller
2012-11-08 15:45:43 -08:00
committed by Android Git Automerger
6 changed files with 107 additions and 457 deletions

View File

@@ -53,43 +53,4 @@
android:drawablePadding="4dip"
/>
<TextView
android:id="@+id/owner_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginTop="4dp"
android:layout_marginEnd="@dimen/kg_status_line_font_right_margin"
android:singleLine="true"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearance"
android:textSize="@dimen/kg_status_line_font_size"
/>
<TextView
android:id="@+id/status1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginTop="4dp"
android:layout_marginEnd="@dimen/kg_status_line_font_right_margin"
android:singleLine="true"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearance"
android:textSize="@dimen/kg_status_line_font_size"
/>
<TextView
android:id="@+id/status_security_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="right"
android:layout_marginTop="12dp"
android:singleLine="false"
android:maxLines="3"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearance"
android:textSize="16dp"
/>
</LinearLayout>

View File

@@ -56,43 +56,4 @@
/>
</LinearLayout>
<TextView
android:id="@+id/owner_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginTop="4dp"
android:layout_marginEnd="@dimen/kg_status_line_font_right_margin"
android:singleLine="true"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearance"
android:textSize="@dimen/kg_status_line_font_size"
/>
<TextView
android:id="@+id/status1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginTop="4dp"
android:layout_marginEnd="@dimen/kg_status_line_font_right_margin"
android:singleLine="true"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearance"
android:textSize="@dimen/kg_status_line_font_size"
/>
<TextView
android:id="@+id/status_security_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginTop="4dp"
android:layout_marginEnd="@dimen/kg_status_line_font_right_margin"
android:singleLine="true"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearance"
android:textSize="@dimen/kg_status_line_font_size"
/>
</LinearLayout>

View File

@@ -53,29 +53,4 @@
android:drawablePadding="4dip"
/>
<TextView
android:id="@+id/owner_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginTop="4dp"
android:layout_marginEnd="@dimen/kg_status_line_font_right_margin"
android:singleLine="true"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearance"
android:textSize="@dimen/kg_status_line_font_size"
/>
<TextView
android:id="@+id/status1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginTop="4dp"
android:layout_marginEnd="@dimen/kg_status_line_font_right_margin"
android:singleLine="true"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearance"
android:textSize="@dimen/kg_status_line_font_size"
/>
</LinearLayout>

View File

@@ -1343,7 +1343,6 @@
<java-symbol type="id" name="clock_text" />
<java-symbol type="id" name="clock_view" />
<java-symbol type="id" name="keyguard_multi_user_selector" />
<java-symbol type="id" name="status_security_message" />
<java-symbol type="id" name="sliding_layout" />
<java-symbol type="id" name="keyguard_add_widget" />
<java-symbol type="id" name="keyguard_add_widget_view" />

View File

@@ -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);
}
}
}

View File

@@ -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) {
}
}