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