Merge "Update keyguard selector view to match UX design spec - Use new Roboto-Thin font - Add new keyguard-specific date format - Layout tweaks to keyguard selector screen. - Add smart EmergencyButton class - Add selective upper-casing of components on the display to enable later UX decision - Work around SIM state bug" into jb-mr1-dev

This commit is contained in:
Jim Miller
2012-09-19 21:26:50 -07:00
committed by Android (Google) Code Review
18 changed files with 565 additions and 315 deletions

View File

@@ -1112,8 +1112,13 @@ public class LockPatternUtils {
* {@link TelephonyManager#CALL_STATE_RINGING}
* {@link TelephonyManager#CALL_STATE_OFFHOOK}
* @param shown indicates whether the given screen wants the emergency button to show at all
* @param button
* @param phoneState
* @param shown shown if true; hidden if false
* @param upperCase if true, converts button label string to upper case
*/
public void updateEmergencyCallButtonState(Button button, int phoneState, boolean shown) {
public void updateEmergencyCallButtonState(Button button, int phoneState, boolean shown,
boolean upperCase, boolean showIcon) {
if (isEmergencyCallCapable() && shown) {
button.setVisibility(View.VISIBLE);
} else {
@@ -1125,14 +1130,30 @@ public class LockPatternUtils {
if (phoneState == TelephonyManager.CALL_STATE_OFFHOOK) {
// show "return to call" text and show phone icon
textId = R.string.lockscreen_return_to_call;
int phoneCallIcon = R.drawable.stat_sys_phone_call;
int phoneCallIcon = showIcon ? R.drawable.stat_sys_phone_call : 0;
button.setCompoundDrawablesWithIntrinsicBounds(phoneCallIcon, 0, 0, 0);
} else {
textId = R.string.lockscreen_emergency_call;
int emergencyIcon = R.drawable.ic_emergency;
int emergencyIcon = showIcon ? R.drawable.ic_emergency : 0;
button.setCompoundDrawablesWithIntrinsicBounds(emergencyIcon, 0, 0, 0);
}
button.setText(textId);
if (upperCase) {
CharSequence original = mContext.getResources().getText(textId);
String upper = original != null ? original.toString().toUpperCase() : null;
button.setText(upper);
} else {
button.setText(textId);
}
}
/**
* @deprecated
* @param button
* @param phoneState
* @param shown
*/
public void updateEmergencyCallButtonState(Button button, int phoneState, boolean shown) {
updateEmergencyCallButtonState(button, phoneState, shown, false, true);
}
/**

View File

@@ -13,7 +13,8 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<alpha xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@interpolator/accelerate_quad"
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@interpolator/accelerate_quad"
android:fromAlpha="1.0"
android:toAlpha="0.0"
android:duration="@integer/kg_security_fade_duration"

View File

@@ -30,7 +30,7 @@
android:id="@+id/app_widget_container"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:layout_weight="0.45"
android:visibility="gone">
<!-- TODO: Remove this when supported as a widget -->
<include layout="@layout/keyguard_status_view"/>
@@ -40,7 +40,7 @@
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="0dip"
android:layout_weight="1"
android:layout_weight="0.55"
android:layout_gravity="center"
android:gravity="center">
@@ -64,27 +64,34 @@
prvandroid:glowRadius="@*android:dimen/glowpadview_glow_radius"
prvandroid:pointDrawable="@*android:drawable/ic_lockscreen_glowdot"/>
<Button
android:id="@+id/emergency_call_button"
android:layout_width="wrap_content"
<LinearLayout
android:id="@+id/keyguard_selector_fade_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/lockscreen_emergency_button"
android:text="@string/kg_emergency_call_label"
style="?android:attr/buttonBarButtonStyle"
android:drawablePadding="8dip"
android:layout_alignParentBottom="true"
/>
android:orientation="vertical"
android:gravity="center_horizontal"
android:layout_alignParentBottom="true">
<com.android.internal.policy.impl.keyguard.CarrierText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/emergency_call_button"
android:singleLine="true"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
android:textColor="?android:attr/textColorSecondary"
/>
<com.android.internal.policy.impl.keyguard.CarrierText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="@*android:dimen/keyguard_lockscreen_status_line_font_size"
android:textColor="?android:attr/textColorSecondary"
/>
<com.android.internal.policy.impl.keyguard.EmergencyButton
android:id="@+id/emergency_call_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@*android:drawable/lockscreen_emergency_button"
android:text="@string/kg_emergency_call_label"
style="?android:attr/buttonBarButtonStyle"
android:drawablePadding="8dip" />
</LinearLayout>
</RelativeLayout>

View File

@@ -31,101 +31,69 @@
android:layout_height="match_parent"
android:gravity="center_horizontal">
<com.android.internal.widget.DigitalClock android:id="@+id/time"
android:layout_marginTop="@*android:dimen/keyguard_lockscreen_status_line_clockfont_top_margin"
android:layout_marginBottom="12dip"
android:layout_marginEnd="@*android:dimen/keyguard_lockscreen_status_line_font_right_margin"
<com.android.internal.policy.impl.keyguard.ClockView
android:id="@+id/clock_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/kg_status_line_font_right_margin"
android:layout_gravity="end">
<!-- Because we can't have multi-tone fonts, we render two TextViews, one on
top of the other. Hence the redundant layout... -->
<TextView android:id="@*android:id/timeDisplayBackground"
<TextView android:id="@+id/clock_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="none"
android:textSize="@*android:dimen/keyguard_lockscreen_clock_font_size"
android:textSize="@dimen/kg_status_clock_font_size"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_marginBottom="6dip"
android:textColor="@*android:color/lockscreen_clock_background"
android:textColor="#ffffffff"
/>
<TextView android:id="@*android:id/timeDisplayForeground"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="none"
android:textSize="@*android:dimen/keyguard_lockscreen_clock_font_size"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_marginBottom="6dip"
android:textColor="@*android:color/lockscreen_clock_foreground"
android:layout_alignStart="@*android:id/timeDisplayBackground"
android:layout_alignTop="@*android:id/timeDisplayBackground"
/>
</com.android.internal.widget.DigitalClock>
<LinearLayout
android:orientation="horizontal"
android:layout_gravity="end"
android:layout_marginEnd="@*android:dimen/keyguard_lockscreen_status_line_font_right_margin">
<TextView
android:id="@*android:id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="@*android:dimen/keyguard_lockscreen_status_line_font_size"
/>
<TextView
android:id="@*android:id/alarm_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dip"
android:singleLine="true"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="@*android:dimen/keyguard_lockscreen_status_line_font_size"
android:drawablePadding="4dip"
/>
</LinearLayout>
</com.android.internal.policy.impl.keyguard.ClockView>
<TextView
android:id="@+id/status1"
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginEnd="@*android:dimen/keyguard_lockscreen_status_line_font_right_margin"
android:layout_marginTop="-16dp"
android:layout_marginEnd="@dimen/kg_status_line_font_right_margin"
android:singleLine="true"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="@*android:dimen/keyguard_lockscreen_status_line_font_size"
android:drawablePadding="4dip"
android:textSize="@dimen/kg_status_date_font_size"
/>
<TextView
android:id="@+id/owner_info"
android:layout_gravity="end"
android:layout_marginEnd="@*android:dimen/keyguard_lockscreen_status_line_font_right_margin"
android:layout_marginTop="16dp"
android:layout_marginEnd="@dimen/kg_status_line_font_right_margin"
android:singleLine="true"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="@*android:dimen/keyguard_lockscreen_status_line_font_size"
android:drawablePadding="4dip"
android:textSize="@dimen/kg_status_line_font_size"
/>
<TextView
android:id="@+id/carrier"
android:id="@+id/alarm_status"
android:layout_gravity="end"
android:layout_marginEnd="@*android:dimen/keyguard_lockscreen_status_line_font_right_margin"
android:layout_marginEnd="@dimen/kg_status_line_font_right_margin"
android:singleLine="true"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="@*android:dimen/keyguard_lockscreen_status_line_font_size"
android:textColor="?android:attr/textColorSecondary"
android:textSize="@dimen/kg_status_line_font_size"
/>
<TextView
android:id="@+id/status1"
android:layout_gravity="end"
android:layout_marginEnd="@dimen/kg_status_line_font_right_margin"
android:singleLine="true"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="@dimen/kg_status_line_font_size"
/>
</com.android.internal.policy.impl.keyguard.KeyguardStatusView>
</com.android.internal.policy.impl.keyguard.KeyguardWidgetFrame>

View File

@@ -256,4 +256,17 @@
<!-- Padding surrounding each widget page -->
<dimen name="kg_widget_page_padding">10dp</dimen>
<!-- Size of the clock font in keyguard's status view -->
<dimen name="kg_status_clock_font_size">94dp</dimen>
<!-- Size of the date font in keyguard's status view -->
<dimen name="kg_status_date_font_size">24dp</dimen>
<!-- Size of the generic status lines keyguard's status view -->
<dimen name="kg_status_line_font_size">12sp</dimen>
<!-- Size of margin on the right of keyguard's status view -->
<dimen name="kg_status_line_font_right_margin">32dp</dimen>
</resources>

View File

@@ -57,4 +57,5 @@
<string name="full_wday_month_day_no_year">EEEE, MMMM d</string>
<string name="abbrev_wday_month_day_no_year">EEE, MMMM d</string>
<string name="abbrev_wday_month_day_year">EEE, MMM d, yyyy</string>
<string name="keyguard_wday_day_month">EEE <b>d</b> MMM</string>
</resources>

View File

@@ -1250,6 +1250,7 @@
<java-symbol type="id" name="keyguard_sim_pin_view" />
<java-symbol type="id" name="keyguard_sim_puk_view" />
<java-symbol type="id" name="keyguard_account_view" />
<java-symbol type="id" name="keyguard_selector_fade_container" />
<java-symbol type="id" name="app_widget_container" />
<java-symbol type="id" name="view_flipper" />
<java-symbol type="id" name="emergency_call_button" />
@@ -1269,6 +1270,8 @@
<java-symbol type="id" name="keyguard_transport_control" />
<java-symbol type="id" name="keyguard_status_view" />
<java-symbol type="id" name="keyguard_users_grid" />
<java-symbol type="id" name="clock_text" />
<java-symbol type="id" name="clock_view" />
<java-symbol type="integer" name="config_carDockRotation" />
<java-symbol type="integer" name="config_defaultUiModeType" />
<java-symbol type="integer" name="config_deskDockRotation" />
@@ -1357,6 +1360,7 @@
<java-symbol type="string" name="lockscreen_too_many_failed_pin_attempts_dialog_message" />
<java-symbol type="string" name="lockscreen_unlock_label" />
<java-symbol type="string" name="status_bar_device_locked" />
<java-symbol type="string" name="keyguard_wday_day_month" />
<java-symbol type="style" name="Animation.LockScreen" />
<java-symbol type="style" name="Theme.Dialog.RecentApplications" />
<java-symbol type="style" name="Theme.ExpandedMenu" />

View File

@@ -1,3 +1,19 @@
/*
* Copyright (C) 2012 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.Context;
@@ -34,14 +50,15 @@ public class CarrierText extends TextView {
/**
* The status of this lock screen. Primarily used for widgets on LockScreen.
*/
enum StatusMode {
private static enum StatusMode {
Normal, // Normal case (sim card present, it's not locked)
NetworkLocked, // SIM card is 'network locked'.
SimMissing, // SIM card is missing.
SimMissingLocked, // SIM card is missing, and device isn't provisioned; don't allow access
SimPukLocked, // SIM card is PUK locked because SIM entered wrong too many times
SimLocked, // SIM card is currently locked
SimPermDisabled; // SIM card is permanently disabled due to PUK unlock failure
SimPermDisabled, // SIM card is permanently disabled due to PUK unlock failure
SimNotReady; // SIM is not ready yet. May never be on devices w/o a SIM.
}
public CarrierText(Context context) {
@@ -54,7 +71,12 @@ public class CarrierText extends TextView {
}
protected void updateCarrierText(State simState, CharSequence plmn, CharSequence spn) {
setText(getCarrierTextForSimState(simState, plmn, spn));
CharSequence text = getCarrierTextForSimState(simState, plmn, spn);
if (KeyguardViewManager.USE_UPPER_CASE) {
setText(text != null ? text.toString().toUpperCase() : null);
} else {
setText(text);
}
}
@Override
@@ -82,6 +104,10 @@ public class CarrierText extends TextView {
carrierText = concatenate(plmn, spn);
break;
case SimNotReady:
carrierText = null; // nothing to display yet.
break;
case NetworkLocked:
carrierText = makeCarrierStringOnEmergencyCapable(
mContext.getText(R.string.lockscreen_network_locked_message), plmn);
@@ -157,7 +183,7 @@ public class CarrierText extends TextView {
case NETWORK_LOCKED:
return StatusMode.SimMissingLocked;
case NOT_READY:
return StatusMode.SimMissing;
return StatusMode.SimNotReady;
case PIN_REQUIRED:
return StatusMode.SimLocked;
case PUK_REQUIRED:

View File

@@ -0,0 +1,223 @@
/*
* Copyright (C) 2012 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.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.graphics.Typeface;
import android.os.Handler;
import android.provider.Settings;
import android.text.format.DateFormat;
import android.util.AttributeSet;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;
import java.lang.ref.WeakReference;
import java.text.DateFormatSymbols;
import java.util.Calendar;
import com.android.internal.R;
/**
* Displays the time
*/
public class ClockView extends RelativeLayout {
private final static String M12 = "h:mm";
private final static String M24 = "kk:mm";
private Calendar mCalendar;
private String mFormat;
private TextView mTimeView;
private AmPm mAmPm;
private ContentObserver mFormatChangeObserver;
private int mAttached = 0; // for debugging - tells us whether attach/detach is unbalanced
/* called by system on minute ticks */
private final Handler mHandler = new Handler();
private BroadcastReceiver mIntentReceiver;
private static class TimeChangedReceiver extends BroadcastReceiver {
private WeakReference<ClockView> mClock;
private Context mContext;
public TimeChangedReceiver(ClockView clock) {
mClock = new WeakReference<ClockView>(clock);
mContext = clock.getContext();
}
@Override
public void onReceive(Context context, Intent intent) {
// Post a runnable to avoid blocking the broadcast.
final boolean timezoneChanged =
intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED);
final ClockView clock = mClock.get();
if (clock != null) {
clock.mHandler.post(new Runnable() {
public void run() {
if (timezoneChanged) {
clock.mCalendar = Calendar.getInstance();
}
clock.updateTime();
}
});
} else {
try {
mContext.unregisterReceiver(this);
} catch (RuntimeException e) {
// Shouldn't happen
}
}
}
};
static class AmPm {
private TextView mAmPmTextView;
private String mAmString, mPmString;
AmPm(View parent, Typeface tf) {
// No longer used, uncomment if we decide to use AM/PM indicator again
// mAmPmTextView = (TextView) parent.findViewById(R.id.am_pm);
if (mAmPmTextView != null && tf != null) {
mAmPmTextView.setTypeface(tf);
}
String[] ampm = new DateFormatSymbols().getAmPmStrings();
mAmString = ampm[0];
mPmString = ampm[1];
}
void setShowAmPm(boolean show) {
if (mAmPmTextView != null) {
mAmPmTextView.setVisibility(show ? View.VISIBLE : View.GONE);
}
}
void setIsMorning(boolean isMorning) {
if (mAmPmTextView != null) {
mAmPmTextView.setText(isMorning ? mAmString : mPmString);
}
}
}
private static class FormatChangeObserver extends ContentObserver {
private WeakReference<ClockView> mClock;
private Context mContext;
public FormatChangeObserver(ClockView clock) {
super(new Handler());
mClock = new WeakReference<ClockView>(clock);
mContext = clock.getContext();
}
@Override
public void onChange(boolean selfChange) {
ClockView digitalClock = mClock.get();
if (digitalClock != null) {
digitalClock.setDateFormat();
digitalClock.updateTime();
} else {
try {
mContext.getContentResolver().unregisterContentObserver(this);
} catch (RuntimeException e) {
// Shouldn't happen
}
}
}
}
public ClockView(Context context) {
this(context, null);
}
public ClockView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mTimeView = (TextView) findViewById(R.id.clock_text);
mTimeView.setTypeface(Typeface.create("sans-serif-thin", Typeface.NORMAL));
mAmPm = new AmPm(this, null);
mCalendar = Calendar.getInstance();
setDateFormat();
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mAttached++;
/* monitor time ticks, time changed, timezone */
if (mIntentReceiver == null) {
mIntentReceiver = new TimeChangedReceiver(this);
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_TICK);
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
mContext.registerReceiver(mIntentReceiver, filter);
}
/* monitor 12/24-hour display preference */
if (mFormatChangeObserver == null) {
mFormatChangeObserver = new FormatChangeObserver(this);
mContext.getContentResolver().registerContentObserver(
Settings.System.CONTENT_URI, true, mFormatChangeObserver);
}
updateTime();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mAttached--;
if (mIntentReceiver != null) {
mContext.unregisterReceiver(mIntentReceiver);
}
if (mFormatChangeObserver != null) {
mContext.getContentResolver().unregisterContentObserver(
mFormatChangeObserver);
}
mFormatChangeObserver = null;
mIntentReceiver = null;
}
void updateTime(Calendar c) {
mCalendar = c;
updateTime();
}
public void updateTime() {
mCalendar.setTimeInMillis(System.currentTimeMillis());
CharSequence newTime = DateFormat.format(mFormat, mCalendar);
mTimeView.setText(newTime);
mAmPm.setIsMorning(mCalendar.get(Calendar.AM_PM) == 0);
}
private void setDateFormat() {
mFormat = android.text.format.DateFormat.is24HourFormat(getContext()) ? M24 : M12;
mAmPm.setShowAmPm(mFormat.equals(M12));
}
}

View File

@@ -0,0 +1,111 @@
/*
* Copyright (C) 2008 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.Context;
import android.content.Intent;
import android.os.PowerManager;
import android.os.SystemClock;
import android.telephony.TelephonyManager;
import android.util.AttributeSet;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.android.internal.telephony.IccCardConstants.State;
import com.android.internal.widget.LockPatternUtils;
/**
* This class implements a smart emergency button that updates itself based
* on telephony state. When the phone is idle, it is an emergency call button.
* When there's a call in progress, it presents an appropriate message and
* allows the user to return to the call.
*/
public class EmergencyButton extends Button {
private static final int EMERGENCY_CALL_TIMEOUT = 10000; // screen timeout after starting e.d.
private static final String ACTION_EMERGENCY_DIAL = "com.android.phone.EmergencyDialer.DIAL";
KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
@Override
public void onSimStateChanged(State simState) {
int phoneState = KeyguardUpdateMonitor.getInstance(mContext).getPhoneState();
updateEmergencyCallButton(simState, phoneState);
}
void onPhoneStateChanged(int phoneState) {
State simState = KeyguardUpdateMonitor.getInstance(mContext).getSimState();
updateEmergencyCallButton(simState, phoneState);
};
};
private LockPatternUtils mLockPatternUtils;
private PowerManager mPowerManager;
public EmergencyButton(Context context) {
this(context, null);
}
public EmergencyButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mLockPatternUtils = new LockPatternUtils(mContext);
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
setOnClickListener(new OnClickListener() {
public void onClick(View v) {
takeEmergencyCallAction();
}
});
int phoneState = KeyguardUpdateMonitor.getInstance(mContext).getPhoneState();
State simState = KeyguardUpdateMonitor.getInstance(mContext).getSimState();
updateEmergencyCallButton(simState, phoneState);
}
/**
* Shows the emergency dialer or returns the user to the existing call.
*/
public void takeEmergencyCallAction() {
// TODO: implement a shorter timeout once new PowerManager API is ready.
// should be the equivalent to the old userActivity(EMERGENCY_CALL_TIMEOUT)
mPowerManager.userActivity(SystemClock.uptimeMillis(), true);
if (TelephonyManager.getDefault().getCallState()
== TelephonyManager.CALL_STATE_OFFHOOK) {
mLockPatternUtils.resumeCall();
} else {
Intent intent = new Intent(ACTION_EMERGENCY_DIAL);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
getContext().startActivity(intent);
}
}
private void updateEmergencyCallButton(State simState, int phoneState) {
boolean enabled = mLockPatternUtils.isEmergencyCallCapable()
|| (phoneState == TelephonyManager.CALL_STATE_OFFHOOK); // voice call in progress
if (enabled && KeyguardUpdateMonitor.isSimLocked(simState)) {
// Some countries can't handle emergency calls while SIM is locked.
enabled = mLockPatternUtils.isEmergencyCallEnabledWhileSimLocked();
}
mLockPatternUtils.updateEmergencyCallButtonState(this, phoneState, enabled,
KeyguardViewManager.USE_UPPER_CASE, false);
}
}

View File

@@ -23,8 +23,7 @@ import android.view.View;
import android.widget.LinearLayout;
import com.android.internal.R;
import com.android.internal.policy.impl.keyguard.BiometricSensorUnlock;
import com.android.internal.policy.impl.keyguard.FaceUnlock;
import com.android.internal.widget.LockPatternUtils;
public class KeyguardFaceUnlockView extends LinearLayout implements KeyguardSecurityView {

View File

@@ -28,7 +28,6 @@ import android.view.WindowManagerGlobal;
import android.widget.FrameLayout;
import com.android.internal.R;
import com.android.internal.policy.impl.keyguard.KeyguardHostView.UserSwitcherCallback;
import java.util.ArrayList;
import java.util.Collections;
@@ -39,7 +38,7 @@ public class KeyguardMultiUserSelectorView extends FrameLayout implements View.O
private KeyguardSubdivisionLayout mUsersGrid;
private KeyguardMultiUserAvatar mActiveUserAvatar;
private UserSwitcherCallback mCallback;
private KeyguardHostView.UserSwitcherCallback mCallback;
private static final int SWITCH_ANIMATION_DURATION = 150;
private static final int FADE_OUT_ANIMATION_DURATION = 100;
@@ -59,7 +58,7 @@ public class KeyguardMultiUserSelectorView extends FrameLayout implements View.O
init();
}
public void setCallback(UserSwitcherCallback callback) {
public void setCallback(KeyguardHostView.UserSwitcherCallback callback) {
mCallback = callback;
}

View File

@@ -64,8 +64,8 @@ public class KeyguardSecurityModel {
}
SecurityMode getSecurityMode() {
KeyguardUpdateMonitor mUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
final IccCardConstants.State simState = mUpdateMonitor.getSimState();
KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
final IccCardConstants.State simState = updateMonitor.getSimState();
SecurityMode mode = SecurityMode.None;
if (simState == IccCardConstants.State.PIN_REQUIRED) {
mode = SecurityMode.SimPin;

View File

@@ -45,13 +45,11 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri
private static final String TAG = "SecuritySelectorView";
private static final String ASSIST_ICON_METADATA_NAME =
"com.android.systemui.action_assist_icon";
private static final int EMERGENCY_CALL_TIMEOUT = 10000; // screen timeout after starting e.d.
static final String ACTION_EMERGENCY_DIAL = "com.android.phone.EmergencyDialer.DIAL";
private KeyguardSecurityCallback mCallback;
private GlowPadView mGlowPadView;
private Button mEmergencyCallButton;
private ObjectAnimator mAnim;
private View mFadeView;
private boolean mCameraDisabled;
private boolean mSearchDisabled;
private LockPatternUtils mLockPatternUtils;
@@ -86,11 +84,11 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri
}
public void onReleased(View v, int handle) {
doTransition(mEmergencyCallButton, 1.0f);
doTransition(mFadeView, 1.0f);
}
public void onGrabbed(View v, int handle) {
doTransition(mEmergencyCallButton, 0.0f);
doTransition(mFadeView, 0.0f);
}
public void onGrabbedStateChange(View v, int handle) {
@@ -103,18 +101,6 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri
};
private void updateEmergencyCallButton(State simState, int phoneState) {
if (mEmergencyCallButton != null) {
boolean en = mLockPatternUtils.isEmergencyCallCapable()
|| (phoneState == TelephonyManager.CALL_STATE_OFFHOOK); // voice call in progress
if (en && KeyguardUpdateMonitor.isSimLocked(simState)) {
// Some countries can't handle emergency calls while SIM is locked.
en = mLockPatternUtils.isEmergencyCallEnabledWhileSimLocked();
}
mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton, phoneState, en);
}
}
KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
@Override
@@ -124,15 +110,8 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri
@Override
public void onSimStateChanged(State simState) {
int phoneState = KeyguardUpdateMonitor.getInstance(mContext).getPhoneState();
updateEmergencyCallButton(simState, phoneState);
updateTargets();
}
void onPhoneStateChanged(int phoneState) {
State simState = KeyguardUpdateMonitor.getInstance(mContext).getSimState();
updateEmergencyCallButton(simState, phoneState);
};
};
public KeyguardSelectorView(Context context) {
@@ -161,31 +140,10 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri
super.onFinishInflate();
mGlowPadView = (GlowPadView) findViewById(R.id.glow_pad_view);
mGlowPadView.setOnTriggerListener(mOnTriggerListener);
mEmergencyCallButton = (Button) findViewById(R.id.emergency_call_button);
mEmergencyCallButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
takeEmergencyCallAction();
}
});
mFadeView = (View) findViewById(R.id.keyguard_selector_fade_container);
updateTargets();
}
/**
* Shows the emergency dialer or returns the user to the existing call.
*/
public void takeEmergencyCallAction() {
mCallback.userActivity(EMERGENCY_CALL_TIMEOUT);
if (TelephonyManager.getDefault().getCallState()
== TelephonyManager.CALL_STATE_OFFHOOK) {
mLockPatternUtils.resumeCall();
} else {
Intent intent = new Intent(ACTION_EMERGENCY_DIAL);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
getContext().startActivity(intent);
}
}
public boolean isTargetPresent(int resId) {
return mGlowPadView.getTargetPosition(resId) != -1;
}
@@ -242,11 +200,11 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri
.ic_action_assist_generic, !mSearchDisabled);
}
void doTransition(Object v, float to) {
void doTransition(View view, float to) {
if (mAnim != null) {
mAnim.cancel();
}
mAnim = ObjectAnimator.ofFloat(mEmergencyCallButton, "alpha", to);
mAnim = ObjectAnimator.ofFloat(view, "alpha", to);
mAnim.start();
}

View File

@@ -27,6 +27,7 @@ import libcore.util.MutableInt;
import android.content.ContentResolver;
import android.content.Context;
import android.graphics.Typeface;
import android.provider.Settings;
import android.text.TextUtils;
import android.text.format.DateFormat;
@@ -42,21 +43,13 @@ class KeyguardStatusViewManager {
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 = R.drawable.ic_lock_idle_alarm;
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 static final int INSTRUCTION_TEXT = 10;
private static final int CARRIER_TEXT = 11;
private static final int CARRIER_HELP_TEXT = 12;
private static final int HELP_MESSAGE_TEXT = 13;
private static final int OWNER_INFO = 14;
private static final int BATTERY_INFO = 15;
private CharSequence mDateFormatString;
// Views that this class controls.
// NOTE: These may be null in some LockScreen screens and should protect from NPE
private TextView mDateView;
private TextView mStatus1View;
private TextView mOwnerInfoView;
@@ -81,32 +74,55 @@ class KeyguardStatusViewManager {
private KeyguardUpdateMonitor mUpdateMonitor;
// Shadowed text values
private CharSequence mCarrierText;
private CharSequence mCarrierHelpText;
private String mHelpMessageText;
private String mInstructionText;
private CharSequence mOwnerInfoText;
private boolean mShowingStatus;
private DigitalClock mDigitalClock;
private ClockView mClockView;
protected boolean mBatteryCharged;
protected boolean mBatteryIsLow;
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;
mDateFormatString = getContext().getResources()
.getText(R.string.abbrev_wday_month_day_no_year);
mDateFormatString = getContext().getResources().getText(R.string.keyguard_wday_day_month);
mLockPatternUtils = new LockPatternUtils(view.getContext());
mUpdateMonitor = KeyguardUpdateMonitor.getInstance(view.getContext());
mDateView = (TextView) findViewById(R.id.date);
mStatus1View = (TextView) findViewById(R.id.status1);
mAlarmStatusView = (TextView) findViewById(R.id.alarm_status);
mOwnerInfoView = (TextView) findViewById(R.id.owner_info);
mDigitalClock = (DigitalClock) findViewById(R.id.time);
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);
// Use custom font in mDateView
mDateView.setTypeface(Typeface.create("sans-serif-thin", Typeface.NORMAL));
// 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);
@@ -114,62 +130,6 @@ class KeyguardStatusViewManager {
resetStatusInfo();
refreshDate();
updateOwnerInfo();
// Required to get Marquee to work.
final View scrollableViews[] = { mDateView, mStatus1View, mOwnerInfoView,
mAlarmStatusView };
for (View v : scrollableViews) {
if (v != null) {
v.setSelected(true);
}
}
}
void setInstructionText(String string) {
mInstructionText = string;
update(INSTRUCTION_TEXT, string);
}
void setCarrierText(CharSequence string) {
mCarrierText = string;
update(CARRIER_TEXT, string);
}
void setOwnerInfo(CharSequence string) {
mOwnerInfoText = string;
update(OWNER_INFO, string);
}
/**
* Sets the carrier help text message, if view is present. Carrier help text messages are
* typically for help dealing with SIMS and connectivity.
*
* @param resId resource id of the message
*/
public void setCarrierHelpText(int resId) {
mCarrierHelpText = getText(resId);
update(CARRIER_HELP_TEXT, mCarrierHelpText);
}
private CharSequence getText(int resId) {
return resId == 0 ? null : getContext().getText(resId);
}
/**
* Unlock help message. This is typically for help with unlock widgets, e.g. "wrong password"
* or "try again."
*
* @param textResId
* @param lockIcon
*/
public void setHelpMessage(int textResId, int lockIcon) {
final CharSequence tmp = getText(textResId);
mHelpMessageText = tmp == null ? null : tmp.toString();
update(HELP_MESSAGE_TEXT, mHelpMessageText);
}
private void update(int what, CharSequence string) {
updateStatusLines(mShowingStatus);
}
public void onPause() {
@@ -181,18 +141,15 @@ class KeyguardStatusViewManager {
public void onResume() {
if (DEBUG) Log.v(TAG, "onResume()");
// First update the clock, if present.
if (mDigitalClock != null) {
mDigitalClock.updateTime();
}
// Force-update the time when we show this view.
mClockView.updateTime();
mUpdateMonitor.registerCallback(mInfoCallback);
resetStatusInfo();
}
void resetStatusInfo() {
mInstructionText = null;
updateStatusLines(true);
updateStatusLines();
}
/**
@@ -202,21 +159,20 @@ class KeyguardStatusViewManager {
* prioritized in that order.
* @param showStatusLines status lines are shown if true
*/
void updateStatusLines(boolean showStatusLines) {
if (DEBUG) Log.v(TAG, "updateStatusLines(" + showStatusLines + ")");
mShowingStatus = showStatusLines;
void updateStatusLines() {
updateAlarmInfo();
updateOwnerInfo();
updateStatus1();
}
private void updateAlarmInfo() {
if (mAlarmStatusView != null) {
String nextAlarm = mLockPatternUtils.getNextAlarm();
boolean showAlarm = mShowingStatus && !TextUtils.isEmpty(nextAlarm);
mAlarmStatusView.setText(nextAlarm);
String nextAlarm = mLockPatternUtils.getNextAlarm();
if (!TextUtils.isEmpty(nextAlarm)) {
maybeSetUpperCaseText(mAlarmStatusView, nextAlarm);
mAlarmStatusView.setCompoundDrawablesWithIntrinsicBounds(ALARM_ICON, 0, 0, 0);
mAlarmStatusView.setVisibility(showAlarm ? View.VISIBLE : View.GONE);
mAlarmStatusView.setVisibility(View.VISIBLE);
} else {
mAlarmStatusView.setVisibility(View.GONE);
}
}
@@ -224,102 +180,62 @@ class KeyguardStatusViewManager {
final ContentResolver res = getContext().getContentResolver();
final boolean ownerInfoEnabled = Settings.Secure.getInt(res,
Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED, 1) != 0;
mOwnerInfoText = ownerInfoEnabled ?
Settings.Secure.getString(res, Settings.Secure.LOCK_SCREEN_OWNER_INFO) : null;
if (mOwnerInfoView != null) {
mOwnerInfoView.setText(mOwnerInfoText);
mOwnerInfoView.setVisibility(TextUtils.isEmpty(mOwnerInfoText) ? View.GONE:View.VISIBLE);
String text = Settings.Secure.getString(res, Settings.Secure.LOCK_SCREEN_OWNER_INFO);
if (ownerInfoEnabled && !TextUtils.isEmpty(text)) {
maybeSetUpperCaseText(mOwnerInfoView, text);
mOwnerInfoView.setVisibility(View.VISIBLE);
} else {
mOwnerInfoView.setVisibility(View.GONE);
}
}
private void updateStatus1() {
if (mStatus1View != null) {
MutableInt icon = new MutableInt(0);
CharSequence string = getPriorityTextMessage(icon);
mStatus1View.setText(string);
MutableInt icon = new MutableInt(0);
CharSequence string = getPriorityTextMessage(icon);
if (!TextUtils.isEmpty(string)) {
maybeSetUpperCaseText(mStatus1View, string);
mStatus1View.setCompoundDrawablesWithIntrinsicBounds(icon.value, 0, 0, 0);
mStatus1View.setVisibility(mShowingStatus ? View.VISIBLE : View.INVISIBLE);
mStatus1View.setVisibility(View.VISIBLE);
} else {
mStatus1View.setVisibility(View.GONE);
}
}
private CharSequence getAltTextMessage(MutableInt icon) {
// If we have replaced the status area with a single widget, then this code
// prioritizes what to show in that space when all transient messages are 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 ? R.string.lockscreen_charged
:R.string.lockscreen_plugged_in, mBatteryLevel);
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(R.string.lockscreen_low_battery);
string = getContext().getString(
com.android.internal.R.string.lockscreen_low_battery);
icon.value = BATTERY_LOW_ICON;
}
} else {
string = mCarrierText;
}
return string;
}
private CharSequence getPriorityTextMessage(MutableInt icon) {
CharSequence string = null;
if (!TextUtils.isEmpty(mInstructionText)) {
// Instructions only
string = mInstructionText;
icon.value = LOCK_ICON;
} else if (mShowingBatteryInfo) {
// Battery status
if (mPluggedIn) {
// Charging, charged or waiting to charge.
string = getContext().getString(mBatteryCharged ? R.string.lockscreen_charged
:R.string.lockscreen_plugged_in, mBatteryLevel);
icon.value = CHARGING_ICON;
} else if (mBatteryIsLow) {
// Battery is low
string = getContext().getString(R.string.lockscreen_low_battery);
icon.value = BATTERY_LOW_ICON;
}
} else if (mOwnerInfoView == null && mOwnerInfoText != null) {
string = mOwnerInfoText;
}
return string;
}
void refreshDate() {
if (mDateView != null) {
mDateView.setText(DateFormat.format(mDateFormatString, new Date()));
}
maybeSetUpperCaseText(mDateView, DateFormat.format(mDateFormatString, new Date()));
}
private void maybeSetUpperCaseText(TextView textView, CharSequence text) {
if (KeyguardViewManager.USE_UPPER_CASE
&& (textView == mDateView)) { // currently only required for date view
textView.setText(text != null ? text.toString().toUpperCase() : null);
} else {
textView.setText(text);
}
}
private Context getContext() {
return mContainer.getContext();
}
private View findViewById(int id) {
return mContainer.findViewById(id);
}
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();
final MutableInt tmpIcon = new MutableInt(0);
update(BATTERY_INFO, getAltTextMessage(tmpIcon));
}
@Override
public void onTimeChanged() {
refreshDate();
}
};
}

View File

@@ -46,10 +46,7 @@ import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.internal.R;
import com.android.internal.policy.impl.keyguard.KeyguardHostView.TransportCallback;
/**
* This is the widget responsible for showing music controls in keyguard.
*/
@@ -125,7 +122,7 @@ public class KeyguardTransportControlView extends KeyguardWidgetFrame implements
}
}
};
private TransportCallback mTransportCallback;
private KeyguardHostView.TransportCallback mTransportCallback;
/**
* This class is required to have weak linkage to the current TransportControlView
@@ -528,7 +525,7 @@ public class KeyguardTransportControlView extends KeyguardWidgetFrame implements
}
}
public void setKeyguardCallback(TransportCallback transportCallback) {
public void setKeyguardCallback(KeyguardHostView.TransportCallback transportCallback) {
mTransportCallback = transportCallback;
}
}

View File

@@ -238,6 +238,11 @@ public class KeyguardUpdateMonitor {
}
} else if (IccCardConstants.INTENT_VALUE_LOCKED_NETWORK.equals(stateExtra)) {
state = IccCardConstants.State.NETWORK_LOCKED;
} else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(stateExtra)
|| IccCardConstants.INTENT_VALUE_ICC_IMSI.equals(stateExtra)) {
// This is required because telephony doesn't return to "READY" after
// these state transitions. See bug 7197471.
state = IccCardConstants.State.READY;
} else {
state = IccCardConstants.State.UNKNOWN;
}

View File

@@ -46,6 +46,7 @@ import com.android.internal.R;
public class KeyguardViewManager {
private final static boolean DEBUG = false;
private static String TAG = "KeyguardViewManager";
public static boolean USE_UPPER_CASE = false;
private final Context mContext;
private final ViewManager mViewManager;