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