1ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian/* 2ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Copyright (C) 2013 The Android Open Source Project 3ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 4ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Licensed under the Apache License, Version 2.0 (the "License"); 5ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * you may not use this file except in compliance with the License. 6ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * You may obtain a copy of the License at 7ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 8ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * http://www.apache.org/licenses/LICENSE-2.0 9ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 10ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Unless required by applicable law or agreed to in writing, software 11ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * distributed under the License is distributed on an "AS IS" BASIS, 12ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * See the License for the specific language governing permissions and 14ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * limitations under the License 15ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 16ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 17ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianpackage com.android.incallui; 18ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 19ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.content.Context; 20ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.hardware.display.DisplayManager; 21ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.hardware.display.DisplayManager.DisplayListener; 22ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.os.PowerManager; 23ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.support.annotation.NonNull; 24ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.telecom.CallAudioState; 25ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.view.Display; 26ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.dialer.common.LogUtil; 27ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.InCallPresenter.InCallState; 28ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.InCallPresenter.InCallStateListener; 298369df095a73a77b3715f8ae7ba06089cebca4ceEric Erfanianimport com.android.incallui.audiomode.AudioModeProvider; 308369df095a73a77b3715f8ae7ba06089cebca4ceEric Erfanianimport com.android.incallui.audiomode.AudioModeProvider.AudioModeListener; 31ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.call.CallList; 32d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport com.android.incallui.call.DialerCall; 33ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 34ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian/** 35ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Class manages the proximity sensor for the in-call UI. We enable the proximity sensor while the 36ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * user in a phone call. The Proximity sensor turns off the touchscreen and display when the user is 37ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * close to the screen to prevent user's cheek from causing touch events. The class requires special 38ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * knowledge of the activity and device state to know when the proximity sensor should be enabled 39ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * and disabled. Most of that state is fed into this class through public methods. 40ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 41ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianpublic class ProximitySensor 42ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian implements AccelerometerListener.OrientationListener, InCallStateListener, AudioModeListener { 43ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 44ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private static final String TAG = ProximitySensor.class.getSimpleName(); 45ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 46ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private final PowerManager mPowerManager; 47ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private final PowerManager.WakeLock mProximityWakeLock; 48ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private final AudioModeProvider mAudioModeProvider; 49ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private final AccelerometerListener mAccelerometerListener; 50ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private final ProximityDisplayListener mDisplayListener; 51ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private int mOrientation = AccelerometerListener.ORIENTATION_UNKNOWN; 52ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private boolean mUiShowing = false; 53ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private boolean mIsPhoneOffhook = false; 54ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private boolean mDialpadVisible; 55ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private boolean mIsAttemptingVideoCall; 56ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private boolean mIsVideoCall; 57ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 58ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public ProximitySensor( 59ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @NonNull Context context, 60ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @NonNull AudioModeProvider audioModeProvider, 61ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @NonNull AccelerometerListener accelerometerListener) { 62ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); 63ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mPowerManager.isWakeLockLevelSupported(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)) { 64ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mProximityWakeLock = 65ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mPowerManager.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, TAG); 66ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } else { 67ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.i("ProximitySensor.constructor", "Device does not support proximity wake lock."); 68ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mProximityWakeLock = null; 69ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 70ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mAccelerometerListener = accelerometerListener; 71ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mAccelerometerListener.setListener(this); 72ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 73ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mDisplayListener = 74ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian new ProximityDisplayListener( 75ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE)); 76ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mDisplayListener.register(); 77ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 78ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mAudioModeProvider = audioModeProvider; 79ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mAudioModeProvider.addListener(this); 80ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 81ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 82ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void tearDown() { 83ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mAudioModeProvider.removeListener(this); 84ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 85ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mAccelerometerListener.enable(false); 86ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mDisplayListener.unregister(); 87ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 88ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian turnOffProximitySensor(true); 89ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 90ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 91ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** Called to identify when the device is laid down flat. */ 92ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 93ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void orientationChanged(int orientation) { 94ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mOrientation = orientation; 95ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian updateProximitySensorMode(); 96ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 97ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 98ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** Called to keep track of the overall UI state. */ 99ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 100ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onStateChange(InCallState oldState, InCallState newState, CallList callList) { 101ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // We ignore incoming state because we do not want to enable proximity 102ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // sensor during incoming call screen. We check hasLiveCall() because a disconnected call 103ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // can also put the in-call screen in the INCALL state. 104ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian boolean hasOngoingCall = InCallState.INCALL == newState && callList.hasLiveCall(); 10510ae593a59aa50963e1d3159747da2d65ca79bedEric Erfanian boolean isOffhook = (InCallState.OUTGOING == newState) || hasOngoingCall; 106ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 107d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian DialerCall activeCall = callList.getActiveCall(); 108d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian boolean isVideoCall = activeCall != null && activeCall.isVideoCall(); 109ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 110ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (isOffhook != mIsPhoneOffhook || mIsVideoCall != isVideoCall) { 111ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mIsPhoneOffhook = isOffhook; 112ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mIsVideoCall = isVideoCall; 113ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 114ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mOrientation = AccelerometerListener.ORIENTATION_UNKNOWN; 115ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mAccelerometerListener.enable(mIsPhoneOffhook); 116ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 117ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian updateProximitySensorMode(); 118ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 119ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 120ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 121ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 122ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onAudioStateChanged(CallAudioState audioState) { 123ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian updateProximitySensorMode(); 124ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 125ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 126ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onDialpadVisible(boolean visible) { 127ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mDialpadVisible = visible; 128ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian updateProximitySensorMode(); 129ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 130ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 131ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void setIsAttemptingVideoCall(boolean isAttemptingVideoCall) { 132ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.i( 133ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian "ProximitySensor.setIsAttemptingVideoCall", 134ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian "isAttemptingVideoCall: %b", 135ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian isAttemptingVideoCall); 136ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mIsAttemptingVideoCall = isAttemptingVideoCall; 137ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian updateProximitySensorMode(); 138ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 139ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** Used to save when the UI goes in and out of the foreground. */ 140ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onInCallShowing(boolean showing) { 141ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (showing) { 142ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mUiShowing = true; 143ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 144ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // We only consider the UI not showing for instances where another app took the foreground. 145ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // If we stopped showing because the screen is off, we still consider that showing. 146ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } else if (mPowerManager.isScreenOn()) { 147ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mUiShowing = false; 148ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 149ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian updateProximitySensorMode(); 150ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 151ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 152ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian void onDisplayStateChanged(boolean isDisplayOn) { 153ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.i("ProximitySensor.onDisplayStateChanged", "isDisplayOn: %b", isDisplayOn); 154ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mAccelerometerListener.enable(isDisplayOn); 155ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 156ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 157ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 158ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * TODO: There is no way to determine if a screen is off due to proximity or if it is legitimately 159ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * off, but if ever we can do that in the future, it would be useful here. Until then, this 160ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * function will simply return true of the screen is off. TODO: Investigate whether this can be 161ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * replaced with the ProximityDisplayListener. 162ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 163ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public boolean isScreenReallyOff() { 164ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return !mPowerManager.isScreenOn(); 165ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 166ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 167ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private void turnOnProximitySensor() { 168ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mProximityWakeLock != null) { 169ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (!mProximityWakeLock.isHeld()) { 170ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.i("ProximitySensor.turnOnProximitySensor", "acquiring wake lock"); 171ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mProximityWakeLock.acquire(); 172ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } else { 173ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.i("ProximitySensor.turnOnProximitySensor", "wake lock already acquired"); 174ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 175ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 176ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 177ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 178ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private void turnOffProximitySensor(boolean screenOnImmediately) { 179ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mProximityWakeLock != null) { 180ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mProximityWakeLock.isHeld()) { 181ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.i("ProximitySensor.turnOffProximitySensor", "releasing wake lock"); 182ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian int flags = (screenOnImmediately ? 0 : PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY); 183ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mProximityWakeLock.release(flags); 184ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } else { 185ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.i("ProximitySensor.turnOffProximitySensor", "wake lock already released"); 186ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 187ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 188ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 189ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 190ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 191ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Updates the wake lock used to control proximity sensor behavior, based on the current state of 192ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * the phone. 193ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 194ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * <p>On devices that have a proximity sensor, to avoid false touches during a call, we hold a 195ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * PROXIMITY_SCREEN_OFF_WAKE_LOCK wake lock whenever the phone is off hook. (When held, that wake 196ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * lock causes the screen to turn off automatically when the sensor detects an object close to the 197ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * screen.) 198ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 199ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * <p>This method is a no-op for devices that don't have a proximity sensor. 200ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 201ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * <p>Proximity wake lock will be released if any of the following conditions are true: the audio 202ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * is routed through bluetooth, a wired headset, or the speaker; the user requested, received a 203ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * request for, or is in a video call; or the phone is horizontal while in a call. 204ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 205ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private synchronized void updateProximitySensorMode() { 206ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final int audioRoute = mAudioModeProvider.getAudioState().getRoute(); 207ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 208ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian boolean screenOnImmediately = 209ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian (CallAudioState.ROUTE_WIRED_HEADSET == audioRoute 210ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian || CallAudioState.ROUTE_SPEAKER == audioRoute 211ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian || CallAudioState.ROUTE_BLUETOOTH == audioRoute 212ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian || mIsAttemptingVideoCall 213ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian || mIsVideoCall); 214ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 215ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // We do not keep the screen off when the user is outside in-call screen and we are 216ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // horizontal, but we do not force it on when we become horizontal until the 217ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // proximity sensor goes negative. 218ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final boolean horizontal = (mOrientation == AccelerometerListener.ORIENTATION_HORIZONTAL); 219ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian screenOnImmediately |= !mUiShowing && horizontal; 220ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 221ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // We do not keep the screen off when dialpad is visible, we are horizontal, and 222ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // the in-call screen is being shown. 223ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // At that moment we're pretty sure users want to use it, instead of letting the 224ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // proximity sensor turn off the screen by their hands. 225ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian screenOnImmediately |= mDialpadVisible && horizontal; 226ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 227ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.i( 228ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian "ProximitySensor.updateProximitySensorMode", 229ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian "screenOnImmediately: %b, dialPadVisible: %b, " 230ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian + "offHook: %b, horizontal: %b, uiShowing: %b, audioRoute: %s", 231ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian screenOnImmediately, 232ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mDialpadVisible, 233ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mIsPhoneOffhook, 234ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mOrientation == AccelerometerListener.ORIENTATION_HORIZONTAL, 235ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mUiShowing, 236ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian CallAudioState.audioRouteToString(audioRoute)); 237ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 238ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mIsPhoneOffhook && !screenOnImmediately) { 239ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.v("ProximitySensor.updateProximitySensorMode", "turning on proximity sensor"); 240ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // Phone is in use! Arrange for the screen to turn off 241ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // automatically when the sensor detects a close object. 242ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian turnOnProximitySensor(); 243ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } else { 244ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.v("ProximitySensor.updateProximitySensorMode", "turning off proximity sensor"); 245ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // Phone is either idle, or ringing. We don't want any special proximity sensor 246ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // behavior in either case. 247ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian turnOffProximitySensor(screenOnImmediately); 248ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 249ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 250ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 251ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 252ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Implementation of a {@link DisplayListener} that maintains a binary state: Screen on vs screen 253ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * off. Used by the proximity sensor manager to decide whether or not it needs to listen to 254ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * accelerometer events. 255ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 256ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public class ProximityDisplayListener implements DisplayListener { 257ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 258ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private DisplayManager mDisplayManager; 259ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private boolean mIsDisplayOn = true; 260ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 261ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian ProximityDisplayListener(DisplayManager displayManager) { 262ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mDisplayManager = displayManager; 263ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 264ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 265ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian void register() { 266ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mDisplayManager.registerDisplayListener(this, null); 267ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 268ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 269ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian void unregister() { 270ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mDisplayManager.unregisterDisplayListener(this); 271ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 272ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 273ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 274ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onDisplayRemoved(int displayId) {} 275ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 276ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 277ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onDisplayChanged(int displayId) { 278ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (displayId == Display.DEFAULT_DISPLAY) { 279ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final Display display = mDisplayManager.getDisplay(displayId); 280ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 281ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final boolean isDisplayOn = display.getState() != Display.STATE_OFF; 282ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // For call purposes, we assume that as long as the screen is not truly off, it is 283ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // considered on, even if it is in an unknown or low power idle state. 284ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (isDisplayOn != mIsDisplayOn) { 285ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mIsDisplayOn = isDisplayOn; 286ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian onDisplayStateChanged(mIsDisplayOn); 287ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 288ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 289ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 290ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 291ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 292ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onDisplayAdded(int displayId) {} 293ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 294ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian} 295