2 * Copyright (C) 2008 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.keyguard;
19 import android.app.ActivityManagerNative;
20 import android.app.ActivityOptions;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.res.Configuration;
24 import android.os.PowerManager;
25 import android.os.RemoteException;
26 import android.os.SystemClock;
27 import android.os.UserHandle;
28 import android.telecom.TelecomManager;
29 import android.util.AttributeSet;
30 import android.util.Slog;
31 import android.view.View;
32 import android.widget.Button;
34 import com.android.internal.logging.MetricsLogger;
35 import com.android.internal.logging.MetricsProto.MetricsEvent;
36 import com.android.internal.telephony.IccCardConstants.State;
37 import com.android.internal.widget.LockPatternUtils;
40 * This class implements a smart emergency button that updates itself based
41 * on telephony state. When the phone is idle, it is an emergency call button.
42 * When there's a call in progress, it presents an appropriate message and
43 * allows the user to return to the call.
45 public class EmergencyButton extends Button {
46 private static final Intent INTENT_EMERGENCY_DIAL = new Intent()
47 .setAction("com.android.phone.EmergencyDialer.DIAL")
48 .setPackage("com.android.phone")
49 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
50 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
51 | Intent.FLAG_ACTIVITY_CLEAR_TOP);
53 private static final String LOG_TAG = "EmergencyButton";
55 KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
58 public void onSimStateChanged(int subId, int slotId, State simState) {
59 updateEmergencyCallButton();
63 public void onPhoneStateChanged(int phoneState) {
64 updateEmergencyCallButton();
68 public interface EmergencyButtonCallback {
69 public void onEmergencyButtonClickedWhenInCall();
72 private LockPatternUtils mLockPatternUtils;
73 private PowerManager mPowerManager;
74 private EmergencyButtonCallback mEmergencyButtonCallback;
76 private final boolean mIsVoiceCapable;
77 private final boolean mEnableEmergencyCallWhileSimLocked;
79 public EmergencyButton(Context context) {
83 public EmergencyButton(Context context, AttributeSet attrs) {
84 super(context, attrs);
85 mIsVoiceCapable = context.getResources().getBoolean(
86 com.android.internal.R.bool.config_voice_capable);
87 mEnableEmergencyCallWhileSimLocked = mContext.getResources().getBoolean(
88 com.android.internal.R.bool.config_enable_emergency_call_while_sim_locked);
92 protected void onAttachedToWindow() {
93 super.onAttachedToWindow();
94 KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mInfoCallback);
98 protected void onDetachedFromWindow() {
99 super.onDetachedFromWindow();
100 KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mInfoCallback);
104 protected void onFinishInflate() {
105 super.onFinishInflate();
106 mLockPatternUtils = new LockPatternUtils(mContext);
107 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
108 setOnClickListener(new OnClickListener() {
109 public void onClick(View v) {
110 takeEmergencyCallAction();
113 updateEmergencyCallButton();
117 protected void onConfigurationChanged(Configuration newConfig) {
118 super.onConfigurationChanged(newConfig);
119 updateEmergencyCallButton();
123 * Shows the emergency dialer or returns the user to the existing call.
125 public void takeEmergencyCallAction() {
126 MetricsLogger.action(mContext, MetricsEvent.ACTION_EMERGENCY_CALL);
127 // TODO: implement a shorter timeout once new PowerManager API is ready.
128 // should be the equivalent to the old userActivity(EMERGENCY_CALL_TIMEOUT)
129 mPowerManager.userActivity(SystemClock.uptimeMillis(), true);
131 ActivityManagerNative.getDefault().stopSystemLockTaskMode();
132 } catch (RemoteException e) {
133 Slog.w(LOG_TAG, "Failed to stop app pinning");
137 if (mEmergencyButtonCallback != null) {
138 mEmergencyButtonCallback.onEmergencyButtonClickedWhenInCall();
141 KeyguardUpdateMonitor.getInstance(mContext).reportEmergencyCallAction(
142 true /* bypassHandler */);
143 getContext().startActivityAsUser(INTENT_EMERGENCY_DIAL,
144 ActivityOptions.makeCustomAnimation(getContext(), 0, 0).toBundle(),
145 new UserHandle(KeyguardUpdateMonitor.getCurrentUser()));
149 private void updateEmergencyCallButton() {
150 boolean visible = false;
151 if (mIsVoiceCapable) {
152 // Emergency calling requires voice capability.
154 visible = true; // always show "return to call" if phone is off-hook
156 final boolean simLocked = KeyguardUpdateMonitor.getInstance(mContext)
157 .isSimPinVoiceSecure();
159 // Some countries can't handle emergency calls while SIM is locked.
160 visible = mEnableEmergencyCallWhileSimLocked;
162 // Only show if there is a secure screen (pin/pattern/SIM pin/SIM puk);
163 visible = mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser());
168 setVisibility(View.VISIBLE);
172 textId = com.android.internal.R.string.lockscreen_return_to_call;
174 textId = com.android.internal.R.string.lockscreen_emergency_call;
178 setVisibility(View.GONE);
182 public void setCallback(EmergencyButtonCallback callback) {
183 mEmergencyButtonCallback = callback;
187 * Resumes a call in progress.
189 private void resumeCall() {
190 getTelecommManager().showInCallScreen(false);
194 * @return {@code true} if there is a call currently in progress.
196 private boolean isInCall() {
197 return getTelecommManager().isInCall();
200 private TelecomManager getTelecommManager() {
201 return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);