EmergencyButton.java revision 8150d2a2a12b38598fd55d8ae3c3b5662ec3520f
1/* 2 * Copyright (C) 2008 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 17package com.android.keyguard; 18 19import android.content.Context; 20import android.content.Intent; 21import android.os.PowerManager; 22import android.os.SystemClock; 23import android.os.UserHandle; 24import android.telecom.TelecomManager; 25import android.util.AttributeSet; 26import android.view.View; 27import android.widget.Button; 28 29import com.android.internal.telephony.IccCardConstants.State; 30import com.android.internal.widget.LockPatternUtils; 31 32/** 33 * This class implements a smart emergency button that updates itself based 34 * on telephony state. When the phone is idle, it is an emergency call button. 35 * When there's a call in progress, it presents an appropriate message and 36 * allows the user to return to the call. 37 */ 38public class EmergencyButton extends Button { 39 private static final Intent INTENT_EMERGENCY_DIAL = new Intent() 40 .setAction("com.android.phone.EmergencyDialer.DIAL") 41 .setPackage("com.android.phone") 42 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 43 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 44 | Intent.FLAG_ACTIVITY_CLEAR_TASK); 45 46 KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() { 47 48 @Override 49 public void onSimStateChanged(int subId, int slotId, State simState) { 50 updateEmergencyCallButton(); 51 } 52 53 @Override 54 public void onPhoneStateChanged(int phoneState) { 55 updateEmergencyCallButton(); 56 } 57 }; 58 59 public interface EmergencyButtonCallback { 60 public void onEmergencyButtonClickedWhenInCall(); 61 } 62 63 private LockPatternUtils mLockPatternUtils; 64 private PowerManager mPowerManager; 65 private EmergencyButtonCallback mEmergencyButtonCallback; 66 67 private final boolean mIsVoiceCapable; 68 private final boolean mEnableEmergencyCallWhileSimLocked; 69 70 public EmergencyButton(Context context) { 71 this(context, null); 72 } 73 74 public EmergencyButton(Context context, AttributeSet attrs) { 75 super(context, attrs); 76 mIsVoiceCapable = context.getResources().getBoolean( 77 com.android.internal.R.bool.config_voice_capable); 78 mEnableEmergencyCallWhileSimLocked = mContext.getResources().getBoolean( 79 com.android.internal.R.bool.config_enable_emergency_call_while_sim_locked); 80 } 81 82 @Override 83 protected void onAttachedToWindow() { 84 super.onAttachedToWindow(); 85 KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mInfoCallback); 86 } 87 88 @Override 89 protected void onDetachedFromWindow() { 90 super.onDetachedFromWindow(); 91 KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mInfoCallback); 92 } 93 94 @Override 95 protected void onFinishInflate() { 96 super.onFinishInflate(); 97 mLockPatternUtils = new LockPatternUtils(mContext); 98 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 99 setOnClickListener(new OnClickListener() { 100 public void onClick(View v) { 101 takeEmergencyCallAction(); 102 } 103 }); 104 updateEmergencyCallButton(); 105 } 106 107 /** 108 * Shows the emergency dialer or returns the user to the existing call. 109 */ 110 public void takeEmergencyCallAction() { 111 // TODO: implement a shorter timeout once new PowerManager API is ready. 112 // should be the equivalent to the old userActivity(EMERGENCY_CALL_TIMEOUT) 113 mPowerManager.userActivity(SystemClock.uptimeMillis(), true); 114 if (isInCall()) { 115 resumeCall(); 116 if (mEmergencyButtonCallback != null) { 117 mEmergencyButtonCallback.onEmergencyButtonClickedWhenInCall(); 118 } 119 } else { 120 KeyguardUpdateMonitor.getInstance(mContext).reportEmergencyCallAction( 121 true /* bypassHandler */); 122 getContext().startActivityAsUser(INTENT_EMERGENCY_DIAL, 123 new UserHandle(mLockPatternUtils.getCurrentUser())); 124 } 125 } 126 127 private void updateEmergencyCallButton() { 128 boolean visible = false; 129 if (mIsVoiceCapable) { 130 // Emergency calling requires voice capability. 131 if (isInCall()) { 132 visible = true; // always show "return to call" if phone is off-hook 133 } else { 134 final boolean simLocked = KeyguardUpdateMonitor.getInstance(mContext) 135 .isSimPinVoiceSecure(); 136 if (simLocked) { 137 // Some countries can't handle emergency calls while SIM is locked. 138 visible = mEnableEmergencyCallWhileSimLocked; 139 } else { 140 // Only show if there is a secure screen (pin/pattern/SIM pin/SIM puk); 141 visible = mLockPatternUtils.isSecure(mLockPatternUtils.getCurrentUser()); 142 } 143 } 144 } 145 if (visible) { 146 setVisibility(View.VISIBLE); 147 148 int textId; 149 if (isInCall()) { 150 textId = com.android.internal.R.string.lockscreen_return_to_call; 151 } else { 152 textId = com.android.internal.R.string.lockscreen_emergency_call; 153 } 154 setText(textId); 155 } else { 156 setVisibility(View.GONE); 157 } 158 } 159 160 public void setCallback(EmergencyButtonCallback callback) { 161 mEmergencyButtonCallback = callback; 162 } 163 164 /** 165 * Resumes a call in progress. 166 */ 167 private void resumeCall() { 168 getTelecommManager().showInCallScreen(false); 169 } 170 171 /** 172 * @return {@code true} if there is a call currently in progress. 173 */ 174 private boolean isInCall() { 175 return getTelecommManager().isInCall(); 176 } 177 178 private TelecomManager getTelecommManager() { 179 return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE); 180 } 181} 182