Home | History | Annotate | Download | only in answerproximitysensor
      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.LogUtil;
     24 import com.android.dialer.configprovider.ConfigProviderBindings;
     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 
     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 
     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 
     95   private void cleanup() {
     96     call.removeListener(this);
     97     releaseProximityWakeLock();
     98   }
     99 
    100   private void releaseProximityWakeLock() {
    101     if (answerProximityWakeLock.isHeld()) {
    102       LogUtil.i("AnswerProximitySensor.releaseProximityWakeLock", "releasing lock");
    103       answerProximityWakeLock.release();
    104     }
    105   }
    106 
    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
    114   public void onDialerCallDisconnect() {
    115     LogUtil.i("AnswerProximitySensor.onDialerCallDisconnect", null);
    116     cleanup();
    117   }
    118 
    119   @Override
    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
    128   public void onDialerCallChildNumberChange() {}
    129 
    130   @Override
    131   public void onDialerCallLastForwardedNumberChange() {}
    132 
    133   @Override
    134   public void onDialerCallUpgradeToVideo() {}
    135 
    136   @Override
    137   public void onWiFiToLteHandover() {}
    138 
    139   @Override
    140   public void onHandoverToWifiFailure() {}
    141 
    142   @Override
    143   public void onInternationalCallOnWifi() {}
    144 
    145   @Override
    146   public void onEnrichedCallSessionUpdate() {}
    147 
    148   @Override
    149   public void onDialerCallSessionModificationStateChange() {}
    150 
    151   @Override
    152   public void onScreenOn() {
    153     cleanup();
    154   }
    155 }
    156