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