blob: 7d5bf6b6454a45cd0160ed90a4bb1e19489e142b [file] [log] [blame]
Jim Miller109f1fd2012-09-19 20:44:16 -07001/*
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
Jim Miller5ecd8112013-01-09 18:50:26 -080017package com.android.keyguard;
Jim Miller109f1fd2012-09-19 20:44:16 -070018
19import android.content.Context;
20import android.content.Intent;
21import android.os.PowerManager;
22import android.os.SystemClock;
Jim Miller450a3a12013-03-12 18:54:44 -070023import android.os.UserHandle;
Adrian Roosc2e01682015-01-15 23:20:20 +010024import android.telecom.TelecomManager;
Jim Miller109f1fd2012-09-19 20:44:16 -070025import android.util.AttributeSet;
26import android.view.View;
Jim Miller109f1fd2012-09-19 20:44:16 -070027import 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 {
Adrian Roos8d75c142015-03-24 12:57:20 -070039 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 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
Jim Miller109f1fd2012-09-19 20:44:16 -070043
44 KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
45
46 @Override
Jim Miller52a61332014-11-12 19:29:51 -080047 public void onSimStateChanged(int subId, int slotId, State simState) {
48 updateEmergencyCallButton();
Jim Miller109f1fd2012-09-19 20:44:16 -070049 }
50
Jorim Jaggi5cf17872014-03-26 18:31:48 +010051 @Override
52 public void onPhoneStateChanged(int phoneState) {
Jim Miller52a61332014-11-12 19:29:51 -080053 updateEmergencyCallButton();
Jorim Jaggi5cf17872014-03-26 18:31:48 +010054 }
Jim Miller109f1fd2012-09-19 20:44:16 -070055 };
Andrew Lee72b46d42015-01-30 13:23:21 -080056
57 public interface EmergencyButtonCallback {
58 public void onEmergencyButtonClickedWhenInCall();
59 }
60
Jim Miller109f1fd2012-09-19 20:44:16 -070061 private LockPatternUtils mLockPatternUtils;
62 private PowerManager mPowerManager;
Andrew Lee72b46d42015-01-30 13:23:21 -080063 private EmergencyButtonCallback mEmergencyButtonCallback;
Jim Miller109f1fd2012-09-19 20:44:16 -070064
Adrian Roosc2e01682015-01-15 23:20:20 +010065 private final boolean mIsVoiceCapable;
66 private final boolean mEnableEmergencyCallWhileSimLocked;
67
Jim Miller109f1fd2012-09-19 20:44:16 -070068 public EmergencyButton(Context context) {
69 this(context, null);
70 }
71
72 public EmergencyButton(Context context, AttributeSet attrs) {
73 super(context, attrs);
Adrian Roosc2e01682015-01-15 23:20:20 +010074 mIsVoiceCapable = context.getResources().getBoolean(
75 com.android.internal.R.bool.config_voice_capable);
76 mEnableEmergencyCallWhileSimLocked = mContext.getResources().getBoolean(
77 com.android.internal.R.bool.config_enable_emergency_call_while_sim_locked);
Jim Miller109f1fd2012-09-19 20:44:16 -070078 }
79
80 @Override
Jim Miller0928e012012-11-06 18:43:22 -080081 protected void onAttachedToWindow() {
82 super.onAttachedToWindow();
83 KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mInfoCallback);
84 }
85
86 @Override
87 protected void onDetachedFromWindow() {
88 super.onDetachedFromWindow();
89 KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mInfoCallback);
90 }
91
92 @Override
Jim Miller109f1fd2012-09-19 20:44:16 -070093 protected void onFinishInflate() {
94 super.onFinishInflate();
95 mLockPatternUtils = new LockPatternUtils(mContext);
96 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
97 setOnClickListener(new OnClickListener() {
98 public void onClick(View v) {
99 takeEmergencyCallAction();
100 }
101 });
Jim Miller52a61332014-11-12 19:29:51 -0800102 updateEmergencyCallButton();
Jim Miller109f1fd2012-09-19 20:44:16 -0700103 }
104
105 /**
106 * Shows the emergency dialer or returns the user to the existing call.
107 */
108 public void takeEmergencyCallAction() {
109 // TODO: implement a shorter timeout once new PowerManager API is ready.
110 // should be the equivalent to the old userActivity(EMERGENCY_CALL_TIMEOUT)
111 mPowerManager.userActivity(SystemClock.uptimeMillis(), true);
Adrian Roosc2e01682015-01-15 23:20:20 +0100112 if (isInCall()) {
113 resumeCall();
Andrew Lee72b46d42015-01-30 13:23:21 -0800114 if (mEmergencyButtonCallback != null) {
115 mEmergencyButtonCallback.onEmergencyButtonClickedWhenInCall();
116 }
Jim Miller109f1fd2012-09-19 20:44:16 -0700117 } else {
Adrian Roos8d75c142015-03-24 12:57:20 -0700118 KeyguardUpdateMonitor.getInstance(mContext).reportEmergencyCallAction(
119 true /* bypassHandler */);
120 getContext().startActivityAsUser(INTENT_EMERGENCY_DIAL,
Jim Miller450a3a12013-03-12 18:54:44 -0700121 new UserHandle(mLockPatternUtils.getCurrentUser()));
Jim Miller109f1fd2012-09-19 20:44:16 -0700122 }
123 }
124
Jim Miller52a61332014-11-12 19:29:51 -0800125 private void updateEmergencyCallButton() {
Adrian Roosc2e01682015-01-15 23:20:20 +0100126 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
Jim Miller3efe1062012-09-28 16:59:31 -0700131 } else {
Adrian Roosc2e01682015-01-15 23:20:20 +0100132 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 }
Jim Miller3efe1062012-09-28 16:59:31 -0700141 }
Jim Miller109f1fd2012-09-19 20:44:16 -0700142 }
Adrian Roosc2e01682015-01-15 23:20:20 +0100143 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 }
Jim Miller109f1fd2012-09-19 20:44:16 -0700156 }
157
Andrew Lee72b46d42015-01-30 13:23:21 -0800158 public void setCallback(EmergencyButtonCallback callback) {
159 mEmergencyButtonCallback = callback;
160 }
Adrian Roosc2e01682015-01-15 23:20:20 +0100161
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 }
Jim Miller109f1fd2012-09-19 20:44:16 -0700179}