• 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.ConfigProviderBindings;
26 import com.android.incallui.call.DialerCall;
27 import com.android.incallui.call.DialerCall.State;
28 import com.android.incallui.call.DialerCallListener;
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() != State.INCOMING) {
51       LogUtil.i("AnswerProximitySensor.shouldUse", "call state is not incoming");
52       Trace.endSection();
53       return false;
54     }
55 
56     if (!ConfigProviderBindings.get(context)
57         .getBoolean(CONFIG_ANSWER_PROXIMITY_SENSOR_ENABLED, true)) {
58       LogUtil.i("AnswerProximitySensor.shouldUse", "disabled by config");
59       Trace.endSection();
60       return false;
61     }
62 
63     if (!context
64         .getSystemService(PowerManager.class)
65         .isWakeLockLevelSupported(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)) {
66       LogUtil.i("AnswerProximitySensor.shouldUse", "wake lock level not supported");
67       Trace.endSection();
68       return false;
69     }
70 
71     if (isDefaultDisplayOn(context)) {
72       LogUtil.i("AnswerProximitySensor.shouldUse", "display is already on");
73       Trace.endSection();
74       return false;
75     }
76 
77     Trace.endSection();
78     return true;
79   }
80 
AnswerProximitySensor( Context context, DialerCall call, PseudoScreenState pseudoScreenState)81   public AnswerProximitySensor(
82       Context context, DialerCall call, PseudoScreenState pseudoScreenState) {
83     Trace.beginSection("AnswerProximitySensor Constructor");
84     this.call = call;
85 
86     LogUtil.i("AnswerProximitySensor.constructor", "acquiring lock");
87     if (ConfigProviderBindings.get(context)
88         .getBoolean(CONFIG_ANSWER_PSEUDO_PROXIMITY_WAKE_LOCK_ENABLED, true)) {
89       answerProximityWakeLock = new PseudoProximityWakeLock(context, pseudoScreenState);
90     } else {
91       // TODO(twyen): choose a wake lock implementation base on framework/device.
92       // These bugs requires the PseudoProximityWakeLock workaround:
93       // a bug Proximity sensor not working on M
94       // a bug fautly touch input when screen is off on marlin/sailfish
95       answerProximityWakeLock = new SystemProximityWakeLock(context);
96     }
97     answerProximityWakeLock.setScreenOnListener(this);
98     answerProximityWakeLock.acquire();
99 
100     call.addListener(this);
101     Trace.endSection();
102   }
103 
cleanup()104   private void cleanup() {
105     Trace.beginSection("AnswerProximitySensor.Cleanup");
106     call.removeListener(this);
107     releaseProximityWakeLock();
108     Trace.endSection();
109   }
110 
releaseProximityWakeLock()111   private void releaseProximityWakeLock() {
112     if (answerProximityWakeLock.isHeld()) {
113       LogUtil.i("AnswerProximitySensor.releaseProximityWakeLock", "releasing lock");
114       answerProximityWakeLock.release();
115     }
116   }
117 
isDefaultDisplayOn(Context context)118   private static boolean isDefaultDisplayOn(Context context) {
119     Display display =
120         context.getSystemService(DisplayManager.class).getDisplay(Display.DEFAULT_DISPLAY);
121     return display.getState() == Display.STATE_ON;
122   }
123 
124   @Override
onDialerCallDisconnect()125   public void onDialerCallDisconnect() {
126     LogUtil.i("AnswerProximitySensor.onDialerCallDisconnect", null);
127     cleanup();
128   }
129 
130   @Override
onDialerCallUpdate()131   public void onDialerCallUpdate() {
132     if (call.getState() != State.INCOMING) {
133       LogUtil.i("AnswerProximitySensor.onDialerCallUpdate", "no longer incoming, cleaning up");
134       cleanup();
135     }
136   }
137 
138   @Override
onDialerCallChildNumberChange()139   public void onDialerCallChildNumberChange() {}
140 
141   @Override
onDialerCallLastForwardedNumberChange()142   public void onDialerCallLastForwardedNumberChange() {}
143 
144   @Override
onDialerCallUpgradeToVideo()145   public void onDialerCallUpgradeToVideo() {}
146 
147   @Override
onWiFiToLteHandover()148   public void onWiFiToLteHandover() {}
149 
150   @Override
onHandoverToWifiFailure()151   public void onHandoverToWifiFailure() {}
152 
153   @Override
onInternationalCallOnWifi()154   public void onInternationalCallOnWifi() {}
155 
156   @Override
onEnrichedCallSessionUpdate()157   public void onEnrichedCallSessionUpdate() {}
158 
159   @Override
onDialerCallSessionModificationStateChange()160   public void onDialerCallSessionModificationStateChange() {}
161 
162   @Override
onScreenOn()163   public void onScreenOn() {
164     cleanup();
165   }
166 }
167