Jim Miller | 109f1fd | 2012-09-19 20:44:16 -0700 | [diff] [blame] | 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 | |
Jim Miller | 5ecd811 | 2013-01-09 18:50:26 -0800 | [diff] [blame] | 17 | package com.android.keyguard; |
Jim Miller | 109f1fd | 2012-09-19 20:44:16 -0700 | [diff] [blame] | 18 | |
Lucas Dupin | 8968f6a | 2019-08-09 17:41:15 -0700 | [diff] [blame] | 19 | import static com.android.systemui.DejankUtils.whitelistIpcs; |
| 20 | |
Adrian Roos | b5947e0 | 2015-05-14 16:14:29 -0700 | [diff] [blame] | 21 | import android.app.ActivityOptions; |
Wale Ogunwale | 04d9cb5 | 2018-04-30 13:55:07 -0700 | [diff] [blame] | 22 | import android.app.ActivityTaskManager; |
Jim Miller | 109f1fd | 2012-09-19 20:44:16 -0700 | [diff] [blame] | 23 | import android.content.Context; |
| 24 | import android.content.Intent; |
Jorim Jaggi | 76511c7 | 2015-05-04 15:34:22 -0700 | [diff] [blame] | 25 | import android.content.res.Configuration; |
Jim Miller | 109f1fd | 2012-09-19 20:44:16 -0700 | [diff] [blame] | 26 | import android.os.PowerManager; |
Hall Liu | 7dac366 | 2016-05-27 13:30:09 -0700 | [diff] [blame] | 27 | import android.os.RemoteException; |
Jim Miller | 109f1fd | 2012-09-19 20:44:16 -0700 | [diff] [blame] | 28 | import android.os.SystemClock; |
Jim Miller | 450a3a1 | 2013-03-12 18:54:44 -0700 | [diff] [blame] | 29 | import android.os.UserHandle; |
Adrian Roos | c2e0168 | 2015-01-15 23:20:20 +0100 | [diff] [blame] | 30 | import android.telecom.TelecomManager; |
Jim Miller | 109f1fd | 2012-09-19 20:44:16 -0700 | [diff] [blame] | 31 | import android.util.AttributeSet; |
Hall Liu | 7dac366 | 2016-05-27 13:30:09 -0700 | [diff] [blame] | 32 | import android.util.Slog; |
Selim Cinek | 705442f | 2016-09-13 16:02:33 -0700 | [diff] [blame] | 33 | import android.view.MotionEvent; |
Jim Miller | 109f1fd | 2012-09-19 20:44:16 -0700 | [diff] [blame] | 34 | import android.view.View; |
Selim Cinek | 705442f | 2016-09-13 16:02:33 -0700 | [diff] [blame] | 35 | import android.view.ViewConfiguration; |
Jim Miller | 109f1fd | 2012-09-19 20:44:16 -0700 | [diff] [blame] | 36 | import android.widget.Button; |
| 37 | |
Chris Wren | de0a21f | 2015-06-05 17:17:55 -0400 | [diff] [blame] | 38 | import com.android.internal.logging.MetricsLogger; |
Tamas Berghammer | 383db5eb | 2016-06-22 15:21:38 +0100 | [diff] [blame] | 39 | import com.android.internal.logging.nano.MetricsProto.MetricsEvent; |
Jim Miller | 109f1fd | 2012-09-19 20:44:16 -0700 | [diff] [blame] | 40 | import com.android.internal.telephony.IccCardConstants.State; |
Jason Monk | 361915c | 2017-03-21 20:33:59 -0400 | [diff] [blame] | 41 | import com.android.internal.util.EmergencyAffordanceManager; |
Gus Prevas | ab33679 | 2018-11-14 13:52:20 -0500 | [diff] [blame] | 42 | import com.android.internal.widget.LockPatternUtils; |
Dave Mankoff | e229469 | 2019-08-14 11:53:13 -0400 | [diff] [blame] | 43 | import com.android.systemui.Dependency; |
Shaotang Li | 5c42263 | 2018-07-04 14:18:40 +0800 | [diff] [blame] | 44 | import com.android.systemui.util.EmergencyDialerConstants; |
Jim Miller | 109f1fd | 2012-09-19 20:44:16 -0700 | [diff] [blame] | 45 | |
| 46 | /** |
| 47 | * This class implements a smart emergency button that updates itself based |
| 48 | * on telephony state. When the phone is idle, it is an emergency call button. |
| 49 | * When there's a call in progress, it presents an appropriate message and |
| 50 | * allows the user to return to the call. |
| 51 | */ |
| 52 | public class EmergencyButton extends Button { |
Jim Miller | 109f1fd | 2012-09-19 20:44:16 -0700 | [diff] [blame] | 53 | |
Hall Liu | 7dac366 | 2016-05-27 13:30:09 -0700 | [diff] [blame] | 54 | private static final String LOG_TAG = "EmergencyButton"; |
Selim Cinek | 705442f | 2016-09-13 16:02:33 -0700 | [diff] [blame] | 55 | private final EmergencyAffordanceManager mEmergencyAffordanceManager; |
Hall Liu | 7dac366 | 2016-05-27 13:30:09 -0700 | [diff] [blame] | 56 | |
Selim Cinek | 705442f | 2016-09-13 16:02:33 -0700 | [diff] [blame] | 57 | private int mDownX; |
| 58 | private int mDownY; |
Jim Miller | 109f1fd | 2012-09-19 20:44:16 -0700 | [diff] [blame] | 59 | KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() { |
| 60 | |
| 61 | @Override |
Jim Miller | 52a6133 | 2014-11-12 19:29:51 -0800 | [diff] [blame] | 62 | public void onSimStateChanged(int subId, int slotId, State simState) { |
| 63 | updateEmergencyCallButton(); |
Jim Miller | 109f1fd | 2012-09-19 20:44:16 -0700 | [diff] [blame] | 64 | } |
| 65 | |
Jorim Jaggi | 5cf1787 | 2014-03-26 18:31:48 +0100 | [diff] [blame] | 66 | @Override |
| 67 | public void onPhoneStateChanged(int phoneState) { |
Jim Miller | 52a6133 | 2014-11-12 19:29:51 -0800 | [diff] [blame] | 68 | updateEmergencyCallButton(); |
Jorim Jaggi | 5cf1787 | 2014-03-26 18:31:48 +0100 | [diff] [blame] | 69 | } |
Jim Miller | 109f1fd | 2012-09-19 20:44:16 -0700 | [diff] [blame] | 70 | }; |
Selim Cinek | 705442f | 2016-09-13 16:02:33 -0700 | [diff] [blame] | 71 | private boolean mLongPressWasDragged; |
Andrew Lee | 72b46d4 | 2015-01-30 13:23:21 -0800 | [diff] [blame] | 72 | |
| 73 | public interface EmergencyButtonCallback { |
| 74 | public void onEmergencyButtonClickedWhenInCall(); |
| 75 | } |
| 76 | |
Jim Miller | 109f1fd | 2012-09-19 20:44:16 -0700 | [diff] [blame] | 77 | private LockPatternUtils mLockPatternUtils; |
| 78 | private PowerManager mPowerManager; |
Andrew Lee | 72b46d4 | 2015-01-30 13:23:21 -0800 | [diff] [blame] | 79 | private EmergencyButtonCallback mEmergencyButtonCallback; |
Jim Miller | 109f1fd | 2012-09-19 20:44:16 -0700 | [diff] [blame] | 80 | |
Adrian Roos | c2e0168 | 2015-01-15 23:20:20 +0100 | [diff] [blame] | 81 | private final boolean mIsVoiceCapable; |
| 82 | private final boolean mEnableEmergencyCallWhileSimLocked; |
| 83 | |
Jim Miller | 109f1fd | 2012-09-19 20:44:16 -0700 | [diff] [blame] | 84 | public EmergencyButton(Context context) { |
| 85 | this(context, null); |
| 86 | } |
| 87 | |
| 88 | public EmergencyButton(Context context, AttributeSet attrs) { |
| 89 | super(context, attrs); |
Adrian Roos | c2e0168 | 2015-01-15 23:20:20 +0100 | [diff] [blame] | 90 | mIsVoiceCapable = context.getResources().getBoolean( |
| 91 | com.android.internal.R.bool.config_voice_capable); |
| 92 | mEnableEmergencyCallWhileSimLocked = mContext.getResources().getBoolean( |
| 93 | com.android.internal.R.bool.config_enable_emergency_call_while_sim_locked); |
Selim Cinek | 705442f | 2016-09-13 16:02:33 -0700 | [diff] [blame] | 94 | mEmergencyAffordanceManager = new EmergencyAffordanceManager(context); |
Jim Miller | 109f1fd | 2012-09-19 20:44:16 -0700 | [diff] [blame] | 95 | } |
| 96 | |
| 97 | @Override |
Jim Miller | 0928e01 | 2012-11-06 18:43:22 -0800 | [diff] [blame] | 98 | protected void onAttachedToWindow() { |
| 99 | super.onAttachedToWindow(); |
Dave Mankoff | e229469 | 2019-08-14 11:53:13 -0400 | [diff] [blame] | 100 | Dependency.get(KeyguardUpdateMonitor.class).registerCallback(mInfoCallback); |
Jim Miller | 0928e01 | 2012-11-06 18:43:22 -0800 | [diff] [blame] | 101 | } |
| 102 | |
| 103 | @Override |
| 104 | protected void onDetachedFromWindow() { |
| 105 | super.onDetachedFromWindow(); |
Dave Mankoff | e229469 | 2019-08-14 11:53:13 -0400 | [diff] [blame] | 106 | Dependency.get(KeyguardUpdateMonitor.class).removeCallback(mInfoCallback); |
Jim Miller | 0928e01 | 2012-11-06 18:43:22 -0800 | [diff] [blame] | 107 | } |
| 108 | |
| 109 | @Override |
Jim Miller | 109f1fd | 2012-09-19 20:44:16 -0700 | [diff] [blame] | 110 | protected void onFinishInflate() { |
| 111 | super.onFinishInflate(); |
| 112 | mLockPatternUtils = new LockPatternUtils(mContext); |
| 113 | mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); |
| 114 | setOnClickListener(new OnClickListener() { |
| 115 | public void onClick(View v) { |
| 116 | takeEmergencyCallAction(); |
| 117 | } |
| 118 | }); |
Selim Cinek | 705442f | 2016-09-13 16:02:33 -0700 | [diff] [blame] | 119 | setOnLongClickListener(new OnLongClickListener() { |
| 120 | @Override |
| 121 | public boolean onLongClick(View v) { |
| 122 | if (!mLongPressWasDragged |
| 123 | && mEmergencyAffordanceManager.needsEmergencyAffordance()) { |
| 124 | mEmergencyAffordanceManager.performEmergencyCall(); |
| 125 | return true; |
| 126 | } |
| 127 | return false; |
| 128 | } |
| 129 | }); |
Lucas Dupin | 8968f6a | 2019-08-09 17:41:15 -0700 | [diff] [blame] | 130 | whitelistIpcs(this::updateEmergencyCallButton); |
Jim Miller | 109f1fd | 2012-09-19 20:44:16 -0700 | [diff] [blame] | 131 | } |
| 132 | |
Jorim Jaggi | 76511c7 | 2015-05-04 15:34:22 -0700 | [diff] [blame] | 133 | @Override |
Selim Cinek | 705442f | 2016-09-13 16:02:33 -0700 | [diff] [blame] | 134 | public boolean onTouchEvent(MotionEvent event) { |
| 135 | final int x = (int) event.getX(); |
| 136 | final int y = (int) event.getY(); |
| 137 | if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { |
| 138 | mDownX = x; |
| 139 | mDownY = y; |
| 140 | mLongPressWasDragged = false; |
| 141 | } else { |
| 142 | final int xDiff = Math.abs(x - mDownX); |
| 143 | final int yDiff = Math.abs(y - mDownY); |
| 144 | int touchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop(); |
| 145 | if (Math.abs(yDiff) > touchSlop || Math.abs(xDiff) > touchSlop) { |
| 146 | mLongPressWasDragged = true; |
| 147 | } |
| 148 | } |
| 149 | return super.onTouchEvent(event); |
| 150 | } |
| 151 | |
| 152 | @Override |
| 153 | public boolean performLongClick() { |
| 154 | return super.performLongClick(); |
| 155 | } |
| 156 | |
| 157 | @Override |
Jorim Jaggi | 76511c7 | 2015-05-04 15:34:22 -0700 | [diff] [blame] | 158 | protected void onConfigurationChanged(Configuration newConfig) { |
| 159 | super.onConfigurationChanged(newConfig); |
| 160 | updateEmergencyCallButton(); |
| 161 | } |
| 162 | |
Jim Miller | 109f1fd | 2012-09-19 20:44:16 -0700 | [diff] [blame] | 163 | /** |
| 164 | * Shows the emergency dialer or returns the user to the existing call. |
| 165 | */ |
| 166 | public void takeEmergencyCallAction() { |
Chris Wren | f6e9228b | 2016-01-26 18:04:35 -0500 | [diff] [blame] | 167 | MetricsLogger.action(mContext, MetricsEvent.ACTION_EMERGENCY_CALL); |
Jim Miller | 109f1fd | 2012-09-19 20:44:16 -0700 | [diff] [blame] | 168 | // TODO: implement a shorter timeout once new PowerManager API is ready. |
| 169 | // should be the equivalent to the old userActivity(EMERGENCY_CALL_TIMEOUT) |
| 170 | mPowerManager.userActivity(SystemClock.uptimeMillis(), true); |
Hall Liu | 7dac366 | 2016-05-27 13:30:09 -0700 | [diff] [blame] | 171 | try { |
Wale Ogunwale | 04d9cb5 | 2018-04-30 13:55:07 -0700 | [diff] [blame] | 172 | ActivityTaskManager.getService().stopSystemLockTaskMode(); |
Hall Liu | 7dac366 | 2016-05-27 13:30:09 -0700 | [diff] [blame] | 173 | } catch (RemoteException e) { |
| 174 | Slog.w(LOG_TAG, "Failed to stop app pinning"); |
| 175 | } |
Adrian Roos | c2e0168 | 2015-01-15 23:20:20 +0100 | [diff] [blame] | 176 | if (isInCall()) { |
| 177 | resumeCall(); |
Andrew Lee | 72b46d4 | 2015-01-30 13:23:21 -0800 | [diff] [blame] | 178 | if (mEmergencyButtonCallback != null) { |
| 179 | mEmergencyButtonCallback.onEmergencyButtonClickedWhenInCall(); |
| 180 | } |
Jim Miller | 109f1fd | 2012-09-19 20:44:16 -0700 | [diff] [blame] | 181 | } else { |
Dave Mankoff | e229469 | 2019-08-14 11:53:13 -0400 | [diff] [blame] | 182 | Dependency.get(KeyguardUpdateMonitor.class).reportEmergencyCallAction( |
Adrian Roos | 8d75c14 | 2015-03-24 12:57:20 -0700 | [diff] [blame] | 183 | true /* bypassHandler */); |
Fan Zhang | f991476 | 2019-11-01 15:58:38 -0700 | [diff] [blame] | 184 | Intent emergencyDialIntent = |
| 185 | getTelecommManager().createLaunchEmergencyDialerIntent(null /* number*/) |
| 186 | .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
| 187 | | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
| 188 | | Intent.FLAG_ACTIVITY_CLEAR_TOP) |
| 189 | .putExtra(EmergencyDialerConstants.EXTRA_ENTRY_TYPE, |
| 190 | EmergencyDialerConstants.ENTRY_TYPE_LOCKSCREEN_BUTTON); |
| 191 | |
| 192 | getContext().startActivityAsUser(emergencyDialIntent, |
Adrian Roos | b5947e0 | 2015-05-14 16:14:29 -0700 | [diff] [blame] | 193 | ActivityOptions.makeCustomAnimation(getContext(), 0, 0).toBundle(), |
Adrian Roos | d6aa6cb | 2015-04-16 19:31:29 -0700 | [diff] [blame] | 194 | new UserHandle(KeyguardUpdateMonitor.getCurrentUser())); |
Jim Miller | 109f1fd | 2012-09-19 20:44:16 -0700 | [diff] [blame] | 195 | } |
| 196 | } |
| 197 | |
Jim Miller | 52a6133 | 2014-11-12 19:29:51 -0800 | [diff] [blame] | 198 | private void updateEmergencyCallButton() { |
Adrian Roos | c2e0168 | 2015-01-15 23:20:20 +0100 | [diff] [blame] | 199 | boolean visible = false; |
| 200 | if (mIsVoiceCapable) { |
| 201 | // Emergency calling requires voice capability. |
| 202 | if (isInCall()) { |
| 203 | visible = true; // always show "return to call" if phone is off-hook |
Jim Miller | 3efe106 | 2012-09-28 16:59:31 -0700 | [diff] [blame] | 204 | } else { |
Dave Mankoff | e229469 | 2019-08-14 11:53:13 -0400 | [diff] [blame] | 205 | final boolean simLocked = Dependency.get(KeyguardUpdateMonitor.class) |
Adrian Roos | c2e0168 | 2015-01-15 23:20:20 +0100 | [diff] [blame] | 206 | .isSimPinVoiceSecure(); |
| 207 | if (simLocked) { |
| 208 | // Some countries can't handle emergency calls while SIM is locked. |
| 209 | visible = mEnableEmergencyCallWhileSimLocked; |
| 210 | } else { |
| 211 | // Only show if there is a secure screen (pin/pattern/SIM pin/SIM puk); |
Adrian Roos | d6aa6cb | 2015-04-16 19:31:29 -0700 | [diff] [blame] | 212 | visible = mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser()); |
Adrian Roos | c2e0168 | 2015-01-15 23:20:20 +0100 | [diff] [blame] | 213 | } |
Jim Miller | 3efe106 | 2012-09-28 16:59:31 -0700 | [diff] [blame] | 214 | } |
Jim Miller | 109f1fd | 2012-09-19 20:44:16 -0700 | [diff] [blame] | 215 | } |
Adrian Roos | c2e0168 | 2015-01-15 23:20:20 +0100 | [diff] [blame] | 216 | if (visible) { |
| 217 | setVisibility(View.VISIBLE); |
| 218 | |
| 219 | int textId; |
| 220 | if (isInCall()) { |
| 221 | textId = com.android.internal.R.string.lockscreen_return_to_call; |
| 222 | } else { |
| 223 | textId = com.android.internal.R.string.lockscreen_emergency_call; |
| 224 | } |
| 225 | setText(textId); |
| 226 | } else { |
| 227 | setVisibility(View.GONE); |
| 228 | } |
Jim Miller | 109f1fd | 2012-09-19 20:44:16 -0700 | [diff] [blame] | 229 | } |
| 230 | |
Andrew Lee | 72b46d4 | 2015-01-30 13:23:21 -0800 | [diff] [blame] | 231 | public void setCallback(EmergencyButtonCallback callback) { |
| 232 | mEmergencyButtonCallback = callback; |
| 233 | } |
Adrian Roos | c2e0168 | 2015-01-15 23:20:20 +0100 | [diff] [blame] | 234 | |
| 235 | /** |
| 236 | * Resumes a call in progress. |
| 237 | */ |
| 238 | private void resumeCall() { |
| 239 | getTelecommManager().showInCallScreen(false); |
| 240 | } |
| 241 | |
| 242 | /** |
| 243 | * @return {@code true} if there is a call currently in progress. |
| 244 | */ |
| 245 | private boolean isInCall() { |
| 246 | return getTelecommManager().isInCall(); |
| 247 | } |
| 248 | |
| 249 | private TelecomManager getTelecommManager() { |
| 250 | return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE); |
| 251 | } |
Jim Miller | 109f1fd | 2012-09-19 20:44:16 -0700 | [diff] [blame] | 252 | } |