Home | History | Annotate | Download | only in hardware
      1 /*
      2  * Copyright (C) 2017 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.systemui.utils.hardware;
     18 
     19 import android.content.Context;
     20 import android.hardware.HardwareBuffer;
     21 import android.hardware.Sensor;
     22 import android.hardware.SensorAdditionalInfo;
     23 import android.hardware.SensorDirectChannel;
     24 import android.hardware.SensorEvent;
     25 import android.hardware.SensorEventListener;
     26 import android.hardware.SensorManager;
     27 import android.hardware.TriggerEventListener;
     28 import android.os.Handler;
     29 import android.os.MemoryFile;
     30 import android.os.SystemClock;
     31 import android.util.ArraySet;
     32 
     33 import com.android.internal.util.Preconditions;
     34 
     35 import java.lang.reflect.Constructor;
     36 import java.lang.reflect.Field;
     37 import java.lang.reflect.Method;
     38 import java.util.ArrayList;
     39 import java.util.Arrays;
     40 import java.util.List;
     41 import java.util.stream.Collectors;
     42 
     43 /**
     44  * Rudimentary fake for SensorManager
     45  *
     46  * Currently only supports the proximity sensor.
     47  *
     48  * Note that this class ignores the "Handler" argument, so the test is responsible for calling the
     49  * listener on the right thread.
     50  */
     51 public class FakeSensorManager extends SensorManager {
     52 
     53     private final MockProximitySensor mMockProximitySensor;
     54     private final FakeGenericSensor mFakeLightSensor;
     55     private final FakeGenericSensor[] mSensors;
     56 
     57     public FakeSensorManager(Context context) throws Exception {
     58         Sensor proxSensor = context.getSystemService(SensorManager.class)
     59                 .getDefaultSensor(Sensor.TYPE_PROXIMITY);
     60         if (proxSensor == null) {
     61             // No prox? Let's create a fake one!
     62             proxSensor = createSensor(Sensor.TYPE_PROXIMITY);
     63         }
     64 
     65         mSensors = new FakeGenericSensor[]{
     66                 mMockProximitySensor = new MockProximitySensor(proxSensor),
     67                 mFakeLightSensor = new FakeGenericSensor(createSensor(Sensor.TYPE_LIGHT)),
     68         };
     69     }
     70 
     71     public MockProximitySensor getMockProximitySensor() {
     72         return mMockProximitySensor;
     73     }
     74 
     75     public FakeGenericSensor getFakeLightSensor() {
     76         return mFakeLightSensor;
     77     }
     78 
     79     @Override
     80     public Sensor getDefaultSensor(int type) {
     81         Sensor s = super.getDefaultSensor(type);
     82         if (s != null) {
     83             return s;
     84         }
     85         // Our mock sensors aren't wakeup, and it's a pain to create them that way. Instead, just
     86         // return non-wakeup sensors if we can't find a wakeup sensor.
     87         return getDefaultSensor(type, false /* wakeup */);
     88     }
     89 
     90     @Override
     91     protected List<Sensor> getFullSensorList() {
     92         return Arrays
     93                 .stream(mSensors)
     94                 .map(i -> i.mSensor)
     95                 .collect(Collectors.toList());
     96     }
     97 
     98     @Override
     99     protected List<Sensor> getFullDynamicSensorList() {
    100         return new ArrayList<>();
    101     }
    102 
    103     @Override
    104     protected void unregisterListenerImpl(SensorEventListener listener, Sensor sensor) {
    105         Preconditions.checkNotNull(listener);
    106         for (FakeGenericSensor s : mSensors) {
    107             if (sensor == null || s.mSensor == sensor) {
    108                 s.mListeners.remove(listener);
    109             }
    110         }
    111     }
    112 
    113     @Override
    114     protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
    115             int delayUs,
    116             Handler handler, int maxReportLatencyUs, int reservedFlags) {
    117         Preconditions.checkNotNull(sensor);
    118         Preconditions.checkNotNull(listener);
    119         for (FakeGenericSensor s : mSensors) {
    120             if (s.mSensor == sensor) {
    121                 s.mListeners.add(listener);
    122                 return true;
    123             }
    124         }
    125         return false;
    126     }
    127 
    128     @Override
    129     protected boolean flushImpl(SensorEventListener listener) {
    130         return false;
    131     }
    132 
    133     @Override
    134     protected SensorDirectChannel createDirectChannelImpl(MemoryFile memoryFile,
    135             HardwareBuffer hardwareBuffer) {
    136         return null;
    137     }
    138 
    139     @Override
    140     protected void destroyDirectChannelImpl(SensorDirectChannel channel) {
    141 
    142     }
    143 
    144     @Override
    145     protected int configureDirectChannelImpl(SensorDirectChannel channel, Sensor s, int rate) {
    146         return 0;
    147     }
    148 
    149     @Override
    150     protected void registerDynamicSensorCallbackImpl(DynamicSensorCallback callback,
    151             Handler handler) {
    152 
    153     }
    154 
    155     @Override
    156     protected void unregisterDynamicSensorCallbackImpl(
    157             DynamicSensorCallback callback) {
    158 
    159     }
    160 
    161     @Override
    162     protected boolean requestTriggerSensorImpl(TriggerEventListener listener, Sensor sensor) {
    163         return false;
    164     }
    165 
    166     @Override
    167     protected boolean cancelTriggerSensorImpl(TriggerEventListener listener, Sensor sensor,
    168             boolean disable) {
    169         return false;
    170     }
    171 
    172     @Override
    173     protected boolean initDataInjectionImpl(boolean enable) {
    174         return false;
    175     }
    176 
    177     @Override
    178     protected boolean injectSensorDataImpl(Sensor sensor, float[] values, int accuracy,
    179             long timestamp) {
    180         return false;
    181     }
    182 
    183     @Override
    184     protected boolean setOperationParameterImpl(SensorAdditionalInfo parameter) {
    185         return false;
    186     }
    187 
    188     private Sensor createSensor(int type) throws Exception {
    189         Constructor<Sensor> constr = Sensor.class.getDeclaredConstructor();
    190         constr.setAccessible(true);
    191         Sensor sensor = constr.newInstance();
    192 
    193         setSensorType(sensor, type);
    194         setSensorField(sensor, "mName", "Mock " + sensor.getStringType() + "/" + type);
    195         setSensorField(sensor, "mVendor", "Mock Vendor");
    196         setSensorField(sensor, "mVersion", 1);
    197         setSensorField(sensor, "mHandle", -1);
    198         setSensorField(sensor, "mMaxRange", 10);
    199         setSensorField(sensor, "mResolution", 1);
    200         setSensorField(sensor, "mPower", 1);
    201         setSensorField(sensor, "mMinDelay", 1000);
    202         setSensorField(sensor, "mMaxDelay", 1000000000);
    203         setSensorField(sensor, "mFlags", 0);
    204         setSensorField(sensor, "mId", -1);
    205 
    206         return sensor;
    207     }
    208 
    209     private void setSensorField(Sensor sensor, String fieldName, Object value) throws Exception {
    210         Field field = Sensor.class.getDeclaredField(fieldName);
    211         field.setAccessible(true);
    212         field.set(sensor, value);
    213     }
    214 
    215     private void setSensorType(Sensor sensor, int type) throws Exception {
    216         Method setter = Sensor.class.getDeclaredMethod("setType", Integer.TYPE);
    217         setter.setAccessible(true);
    218         setter.invoke(sensor, type);
    219     }
    220 
    221     public class MockProximitySensor extends FakeGenericSensor {
    222 
    223         private MockProximitySensor(Sensor sensor) {
    224             super(sensor);
    225         }
    226 
    227         public void sendProximityResult(boolean far) {
    228             sendSensorEvent(far ? getSensor().getMaximumRange() : 0);
    229         }
    230     }
    231 
    232     public class FakeGenericSensor {
    233 
    234         private final Sensor mSensor;
    235         private final ArraySet<SensorEventListener> mListeners = new ArraySet<>();
    236 
    237         public FakeGenericSensor(
    238                 Sensor sensor) {
    239             this.mSensor = sensor;
    240         }
    241 
    242         public Sensor getSensor() {
    243             return mSensor;
    244         }
    245 
    246         public void sendSensorEvent(float... values) {
    247             SensorEvent event = createSensorEvent(values.length);
    248             System.arraycopy(values, 0, event.values, 0, values.length);
    249             for (SensorEventListener listener : mListeners) {
    250                 listener.onSensorChanged(event);
    251             }
    252         }
    253 
    254         private SensorEvent createSensorEvent(int valuesSize) {
    255             SensorEvent event;
    256             try {
    257                 Constructor<SensorEvent> constr =
    258                         SensorEvent.class.getDeclaredConstructor(Integer.TYPE);
    259                 constr.setAccessible(true);
    260                 event = constr.newInstance(valuesSize);
    261             } catch (Exception e) {
    262                 throw new RuntimeException(e);
    263             }
    264             event.sensor = mSensor;
    265             event.timestamp = SystemClock.elapsedRealtimeNanos();
    266 
    267             return event;
    268         }
    269     }
    270 }
    271