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