• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright 2014 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 package org.appspot.apprtc;
12 
13 import android.content.Context;
14 import android.hardware.Sensor;
15 import android.hardware.SensorEvent;
16 import android.hardware.SensorEventListener;
17 import android.hardware.SensorManager;
18 import android.os.Build;
19 import android.support.annotation.Nullable;
20 import android.util.Log;
21 import org.appspot.apprtc.util.AppRTCUtils;
22 import org.webrtc.ThreadUtils;
23 
24 /**
25  * AppRTCProximitySensor manages functions related to the proximity sensor in
26  * the AppRTC demo.
27  * On most device, the proximity sensor is implemented as a boolean-sensor.
28  * It returns just two values "NEAR" or "FAR". Thresholding is done on the LUX
29  * value i.e. the LUX value of the light sensor is compared with a threshold.
30  * A LUX-value more than the threshold means the proximity sensor returns "FAR".
31  * Anything less than the threshold value and the sensor  returns "NEAR".
32  */
33 public class AppRTCProximitySensor implements SensorEventListener {
34   private static final String TAG = "AppRTCProximitySensor";
35 
36   // This class should be created, started and stopped on one thread
37   // (e.g. the main thread). We use |nonThreadSafe| to ensure that this is
38   // the case. Only active when |DEBUG| is set to true.
39   private final ThreadUtils.ThreadChecker threadChecker = new ThreadUtils.ThreadChecker();
40 
41   private final Runnable onSensorStateListener;
42   private final SensorManager sensorManager;
43   @Nullable private Sensor proximitySensor;
44   private boolean lastStateReportIsNear;
45 
46   /** Construction */
create(Context context, Runnable sensorStateListener)47   static AppRTCProximitySensor create(Context context, Runnable sensorStateListener) {
48     return new AppRTCProximitySensor(context, sensorStateListener);
49   }
50 
AppRTCProximitySensor(Context context, Runnable sensorStateListener)51   private AppRTCProximitySensor(Context context, Runnable sensorStateListener) {
52     Log.d(TAG, "AppRTCProximitySensor" + AppRTCUtils.getThreadInfo());
53     onSensorStateListener = sensorStateListener;
54     sensorManager = ((SensorManager) context.getSystemService(Context.SENSOR_SERVICE));
55   }
56 
57   /**
58    * Activate the proximity sensor. Also do initialization if called for the
59    * first time.
60    */
start()61   public boolean start() {
62     threadChecker.checkIsOnValidThread();
63     Log.d(TAG, "start" + AppRTCUtils.getThreadInfo());
64     if (!initDefaultSensor()) {
65       // Proximity sensor is not supported on this device.
66       return false;
67     }
68     sensorManager.registerListener(this, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL);
69     return true;
70   }
71 
72   /** Deactivate the proximity sensor. */
stop()73   public void stop() {
74     threadChecker.checkIsOnValidThread();
75     Log.d(TAG, "stop" + AppRTCUtils.getThreadInfo());
76     if (proximitySensor == null) {
77       return;
78     }
79     sensorManager.unregisterListener(this, proximitySensor);
80   }
81 
82   /** Getter for last reported state. Set to true if "near" is reported. */
sensorReportsNearState()83   public boolean sensorReportsNearState() {
84     threadChecker.checkIsOnValidThread();
85     return lastStateReportIsNear;
86   }
87 
88   @Override
onAccuracyChanged(Sensor sensor, int accuracy)89   public final void onAccuracyChanged(Sensor sensor, int accuracy) {
90     threadChecker.checkIsOnValidThread();
91     AppRTCUtils.assertIsTrue(sensor.getType() == Sensor.TYPE_PROXIMITY);
92     if (accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE) {
93       Log.e(TAG, "The values returned by this sensor cannot be trusted");
94     }
95   }
96 
97   @Override
onSensorChanged(SensorEvent event)98   public final void onSensorChanged(SensorEvent event) {
99     threadChecker.checkIsOnValidThread();
100     AppRTCUtils.assertIsTrue(event.sensor.getType() == Sensor.TYPE_PROXIMITY);
101     // As a best practice; do as little as possible within this method and
102     // avoid blocking.
103     float distanceInCentimeters = event.values[0];
104     if (distanceInCentimeters < proximitySensor.getMaximumRange()) {
105       Log.d(TAG, "Proximity sensor => NEAR state");
106       lastStateReportIsNear = true;
107     } else {
108       Log.d(TAG, "Proximity sensor => FAR state");
109       lastStateReportIsNear = false;
110     }
111 
112     // Report about new state to listening client. Client can then call
113     // sensorReportsNearState() to query the current state (NEAR or FAR).
114     if (onSensorStateListener != null) {
115       onSensorStateListener.run();
116     }
117 
118     Log.d(TAG, "onSensorChanged" + AppRTCUtils.getThreadInfo() + ": "
119             + "accuracy=" + event.accuracy + ", timestamp=" + event.timestamp + ", distance="
120             + event.values[0]);
121   }
122 
123   /**
124    * Get default proximity sensor if it exists. Tablet devices (e.g. Nexus 7)
125    * does not support this type of sensor and false will be returned in such
126    * cases.
127    */
initDefaultSensor()128   private boolean initDefaultSensor() {
129     if (proximitySensor != null) {
130       return true;
131     }
132     proximitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
133     if (proximitySensor == null) {
134       return false;
135     }
136     logProximitySensorInfo();
137     return true;
138   }
139 
140   /** Helper method for logging information about the proximity sensor. */
logProximitySensorInfo()141   private void logProximitySensorInfo() {
142     if (proximitySensor == null) {
143       return;
144     }
145     StringBuilder info = new StringBuilder("Proximity sensor: ");
146     info.append("name=").append(proximitySensor.getName());
147     info.append(", vendor: ").append(proximitySensor.getVendor());
148     info.append(", power: ").append(proximitySensor.getPower());
149     info.append(", resolution: ").append(proximitySensor.getResolution());
150     info.append(", max range: ").append(proximitySensor.getMaximumRange());
151     info.append(", min delay: ").append(proximitySensor.getMinDelay());
152     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
153       // Added in API level 20.
154       info.append(", type: ").append(proximitySensor.getStringType());
155     }
156     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
157       // Added in API level 21.
158       info.append(", max delay: ").append(proximitySensor.getMaxDelay());
159       info.append(", reporting mode: ").append(proximitySensor.getReportingMode());
160       info.append(", isWakeUpSensor: ").append(proximitySensor.isWakeUpSensor());
161     }
162     Log.d(TAG, info.toString());
163   }
164 }
165