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