• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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.incallui.answerproximitysensor;
18 
19 import android.content.Context;
20 import android.hardware.display.DisplayManager;
21 import android.os.PowerManager;
22 import android.view.Display;
23 import com.android.dialer.common.ConfigProviderBindings;
24 import com.android.dialer.common.LogUtil;
25 import com.android.incallui.call.DialerCall;
26 import com.android.incallui.call.DialerCall.State;
27 import com.android.incallui.call.DialerCallListener;
28 
29 /**
30  * This class prevents users from accidentally answering calls by keeping the screen off until the
31  * proximity sensor is unblocked. If the screen is already on or if this is a call waiting call then
32  * nothing is done.
33  */
34 public class AnswerProximitySensor
35     implements DialerCallListener, AnswerProximityWakeLock.ScreenOnListener {
36 
37   private static final String CONFIG_ANSWER_PROXIMITY_SENSOR_ENABLED =
38       "answer_proximity_sensor_enabled";
39   private static final String CONFIG_ANSWER_PSEUDO_PROXIMITY_WAKE_LOCK_ENABLED =
40       "answer_pseudo_proximity_wake_lock_enabled";
41 
42   private final DialerCall call;
43   private final AnswerProximityWakeLock answerProximityWakeLock;
44 
shouldUse(Context context, DialerCall call)45   public static boolean shouldUse(Context context, DialerCall call) {
46     // Don't use the AnswerProximitySensor for call waiting and other states. Those states are
47     // handled by the general ProximitySensor code.
48     if (call.getState() != State.INCOMING) {
49       LogUtil.i("AnswerProximitySensor.shouldUse", "call state is not incoming");
50       return false;
51     }
52 
53     if (!ConfigProviderBindings.get(context)
54         .getBoolean(CONFIG_ANSWER_PROXIMITY_SENSOR_ENABLED, true)) {
55       LogUtil.i("AnswerProximitySensor.shouldUse", "disabled by config");
56       return false;
57     }
58 
59     if (!context
60         .getSystemService(PowerManager.class)
61         .isWakeLockLevelSupported(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)) {
62       LogUtil.i("AnswerProximitySensor.shouldUse", "wake lock level not supported");
63       return false;
64     }
65 
66     if (isDefaultDisplayOn(context)) {
67       LogUtil.i("AnswerProximitySensor.shouldUse", "display is already on");
68       return false;
69     }
70 
71     return true;
72   }
73 
AnswerProximitySensor( Context context, DialerCall call, PseudoScreenState pseudoScreenState)74   public AnswerProximitySensor(
75       Context context, DialerCall call, PseudoScreenState pseudoScreenState) {
76     this.call = call;
77 
78     LogUtil.i("AnswerProximitySensor.constructor", "acquiring lock");
79     if (ConfigProviderBindings.get(context)
80         .getBoolean(CONFIG_ANSWER_PSEUDO_PROXIMITY_WAKE_LOCK_ENABLED, true)) {
81       answerProximityWakeLock = new PseudoProximityWakeLock(context, pseudoScreenState);
82     } else {
83       // TODO: choose a wake lock implementation base on framework/device.
84       // These bugs requires the PseudoProximityWakeLock workaround:
85       // b/30439151 Proximity sensor not working on M
86       // b/31499931 fautly touch input when screen is off on marlin/sailfish
87       answerProximityWakeLock = new SystemProximityWakeLock(context);
88     }
89     answerProximityWakeLock.setScreenOnListener(this);
90     answerProximityWakeLock.acquire();
91 
92     call.addListener(this);
93   }
94 
cleanup()95   private void cleanup() {
96     call.removeListener(this);
97     releaseProximityWakeLock();
98   }
99 
releaseProximityWakeLock()100   private void releaseProximityWakeLock() {
101     if (answerProximityWakeLock.isHeld()) {
102       LogUtil.i("AnswerProximitySensor.releaseProximityWakeLock", "releasing lock");
103       answerProximityWakeLock.release();
104     }
105   }
106 
isDefaultDisplayOn(Context context)107   private static boolean isDefaultDisplayOn(Context context) {
108     Display display =
109         context.getSystemService(DisplayManager.class).getDisplay(Display.DEFAULT_DISPLAY);
110     return display.getState() == Display.STATE_ON;
111   }
112 
113   @Override
onDialerCallDisconnect()114   public void onDialerCallDisconnect() {
115     LogUtil.i("AnswerProximitySensor.onDialerCallDisconnect", null);
116     cleanup();
117   }
118 
119   @Override
onDialerCallUpdate()120   public void onDialerCallUpdate() {
121     if (call.getState() != State.INCOMING) {
122       LogUtil.i("AnswerProximitySensor.onDialerCallUpdate", "no longer incoming, cleaning up");
123       cleanup();
124     }
125   }
126 
127   @Override
onDialerCallChildNumberChange()128   public void onDialerCallChildNumberChange() {}
129 
130   @Override
onDialerCallLastForwardedNumberChange()131   public void onDialerCallLastForwardedNumberChange() {}
132 
133   @Override
onDialerCallUpgradeToVideo()134   public void onDialerCallUpgradeToVideo() {}
135 
136   @Override
onWiFiToLteHandover()137   public void onWiFiToLteHandover() {}
138 
139   @Override
onHandoverToWifiFailure()140   public void onHandoverToWifiFailure() {}
141 
142   @Override
onInternationalCallOnWifi()143   public void onInternationalCallOnWifi() {}
144 
145   @Override
onDialerCallSessionModificationStateChange()146   public void onDialerCallSessionModificationStateChange() {}
147 
148   @Override
onScreenOn()149   public void onScreenOn() {
150     cleanup();
151   }
152 }
153