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 
17 package com.android.keyguard;
18 
19 import android.content.Context;
20 import android.util.AttributeSet;
21 import android.view.MotionEvent;
22 import android.view.View;
23 import android.view.ViewConfiguration;
24 import android.widget.Button;
25 
26 import com.android.internal.util.EmergencyAffordanceManager;
27 
28 /**
29  * This class implements a smart emergency button that updates itself based
30  * on telephony state.  When the phone is idle, it is an emergency call button.
31  * When there's a call in progress, it presents an appropriate message and
32  * allows the user to return to the call.
33  */
34 public class EmergencyButton extends Button {
35 
36     private final EmergencyAffordanceManager mEmergencyAffordanceManager;
37 
38     private int mDownX;
39     private int mDownY;
40     private boolean mLongPressWasDragged;
41 
42     private final boolean mEnableEmergencyCallWhileSimLocked;
43 
EmergencyButton(Context context)44     public EmergencyButton(Context context) {
45         this(context, null);
46     }
47 
EmergencyButton(Context context, AttributeSet attrs)48     public EmergencyButton(Context context, AttributeSet attrs) {
49         super(context, attrs);
50         mEnableEmergencyCallWhileSimLocked = mContext.getResources().getBoolean(
51                 com.android.internal.R.bool.config_enable_emergency_call_while_sim_locked);
52         mEmergencyAffordanceManager = new EmergencyAffordanceManager(context);
53     }
54 
55     @Override
onFinishInflate()56     protected void onFinishInflate() {
57         super.onFinishInflate();
58         if (mEmergencyAffordanceManager.needsEmergencyAffordance()) {
59             setOnLongClickListener(v -> {
60                 if (!mLongPressWasDragged
61                         && mEmergencyAffordanceManager.needsEmergencyAffordance()) {
62                     mEmergencyAffordanceManager.performEmergencyCall();
63                     return true;
64                 }
65                 return false;
66             });
67         }
68     }
69 
70     @Override
onTouchEvent(MotionEvent event)71     public boolean onTouchEvent(MotionEvent event) {
72         final int x = (int) event.getX();
73         final int y = (int) event.getY();
74         if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
75             mDownX = x;
76             mDownY = y;
77             mLongPressWasDragged = false;
78         } else {
79             final int xDiff = Math.abs(x - mDownX);
80             final int yDiff = Math.abs(y - mDownY);
81             int touchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
82             if (Math.abs(yDiff) > touchSlop || Math.abs(xDiff) > touchSlop) {
83                 mLongPressWasDragged = true;
84             }
85         }
86         return super.onTouchEvent(event);
87     }
88 
89     @Override
performLongClick()90     public boolean performLongClick() {
91         return super.performLongClick();
92     }
93 
updateEmergencyCallButton(boolean isInCall, boolean hasTelephonyRadio, boolean simLocked, boolean isSecure)94     void updateEmergencyCallButton(boolean isInCall, boolean hasTelephonyRadio, boolean simLocked,
95             boolean isSecure) {
96         boolean visible = false;
97         if (hasTelephonyRadio) {
98             // Emergency calling requires a telephony radio.
99             if (isInCall) {
100                 visible = true; // always show "return to call" if phone is off-hook
101             } else {
102                 if (simLocked) {
103                     // Some countries can't handle emergency calls while SIM is locked.
104                     visible = mEnableEmergencyCallWhileSimLocked;
105                 } else {
106                     // Only show if there is a secure screen (pin/pattern/SIM pin/SIM puk);
107                     visible = isSecure;
108                 }
109             }
110         }
111         if (visible) {
112             setVisibility(View.VISIBLE);
113 
114             int textId;
115             if (isInCall) {
116                 textId = com.android.internal.R.string.lockscreen_return_to_call;
117             } else {
118                 textId = com.android.internal.R.string.lockscreen_emergency_call;
119             }
120             setText(textId);
121         } else {
122             setVisibility(View.GONE);
123         }
124     }
125 }
126