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 package android.hardware; 17 18 import android.annotation.IntDef; 19 import android.os.MemoryFile; 20 21 import dalvik.system.CloseGuard; 22 23 import java.io.IOException; 24 import java.lang.annotation.Retention; 25 import java.lang.annotation.RetentionPolicy; 26 import java.nio.channels.Channel; 27 import java.util.concurrent.atomic.AtomicBoolean; 28 29 /** 30 * Class representing a sensor direct channel. Use 31 * {@link SensorManager#createDirectChannel(android.os.MemoryFile)} or 32 * {@link SensorManager#createDirectChannel(android.hardware.HardwareBuffer)} 33 * to obtain an object. The channel object can be then configured 34 * (see {@link #configure(Sensor, int)}) 35 * to start delivery of sensor events into shared memory buffer. 36 */ 37 public final class SensorDirectChannel implements Channel { 38 39 // shared memory types 40 41 /** @hide */ 42 @Retention(RetentionPolicy.SOURCE) 43 @IntDef(flag = true, prefix = { "TYPE_" }, value = { 44 TYPE_MEMORY_FILE, 45 TYPE_HARDWARE_BUFFER 46 }) 47 public @interface MemoryType {} 48 49 /** 50 * Shared memory type ashmem, wrapped in MemoryFile object. 51 * 52 * @see SensorManager#createDirectChannel(MemoryFile) 53 */ 54 public static final int TYPE_MEMORY_FILE = 1; 55 56 /** 57 * Shared memory type wrapped by HardwareBuffer object. 58 * 59 * @see SensorManager#createDirectChannel(HardwareBuffer) 60 */ 61 public static final int TYPE_HARDWARE_BUFFER = 2; 62 63 // sensor rate levels 64 65 /** @hide */ 66 @Retention(RetentionPolicy.SOURCE) 67 @IntDef(flag = true, prefix = { "RATE_" }, value = { 68 RATE_STOP, 69 RATE_NORMAL, 70 RATE_FAST, 71 RATE_VERY_FAST 72 }) 73 public @interface RateLevel {} 74 75 /** 76 * Sensor stopped (no event output). 77 * 78 * @see #configure(Sensor, int) 79 */ 80 public static final int RATE_STOP = 0; 81 /** 82 * Sensor operates at nominal rate of 50Hz. 83 * 84 * The actual rate is expected to be between 55% to 220% of nominal rate, thus between 27.5Hz to 85 * 110Hz. 86 * 87 * @see #configure(Sensor, int) 88 */ 89 public static final int RATE_NORMAL = 1; //50Hz 90 /** 91 * Sensor operates at nominal rate of 200Hz. 92 * 93 * The actual rate is expected to be between 55% to 220% of nominal rate, thus between 110Hz to 94 * 440Hz. 95 * 96 * @see #configure(Sensor, int) 97 */ 98 public static final int RATE_FAST = 2; // ~200Hz 99 /** 100 * Sensor operates at nominal rate of 800Hz. 101 * 102 * The actual rate is expected to be between 55% to 220% of nominal rate, thus between 440Hz to 103 * 1760Hz. 104 * 105 * @see #configure(Sensor, int) 106 */ 107 public static final int RATE_VERY_FAST = 3; // ~800Hz 108 109 /** 110 * Determine if a channel is still valid. A channel is invalidated after {@link #close()} is 111 * called. 112 * 113 * @return <code>true</code> if channel is valid. 114 */ 115 @Override isOpen()116 public boolean isOpen() { 117 return !mClosed.get(); 118 } 119 120 /** @removed */ 121 @Deprecated isValid()122 public boolean isValid() { 123 return isOpen(); 124 } 125 126 /** 127 * Close sensor direct channel. 128 * 129 * Stop all active sensor in the channel and free sensor system resource related to channel. 130 * Shared memory used for creating the direct channel need to be closed or freed separately. 131 * 132 * @see SensorManager#createDirectChannel(MemoryFile) 133 * @see SensorManager#createDirectChannel(HardwareBuffer) 134 */ 135 @Override close()136 public void close() { 137 if (mClosed.compareAndSet(false, true)) { 138 mCloseGuard.close(); 139 // actual close action 140 mManager.destroyDirectChannel(this); 141 } 142 } 143 144 /** 145 * Configure sensor rate or stop sensor report. 146 * 147 * To start event report of a sensor, or change rate of existing report, call this function with 148 * rateLevel other than {@link android.hardware.SensorDirectChannel#RATE_STOP}. Sensor events 149 * will be added into a queue formed by the shared memory used in creation of direction channel. 150 * Each element of the queue has size of 104 bytes and represents a sensor event. Data 151 * structure of an element (all fields in little-endian): 152 * 153 * <pre> 154 * offset type name 155 * ------------------------------------------------------------------------ 156 * 0x0000 int32_t size (always 104) 157 * 0x0004 int32_t sensor report token 158 * 0x0008 int32_t type (see SensorType) 159 * 0x000C uint32_t atomic counter 160 * 0x0010 int64_t timestamp (see Event) 161 * 0x0018 float[16]/int64_t[8] data (data type depends on sensor type) 162 * 0x0058 int32_t[4] reserved (set to zero) 163 * </pre> 164 * 165 * There are no head or tail pointers. The sequence and frontier of new sensor events is 166 * determined by the atomic counter, which counts from 1 after creation of direct channel and 167 * increments 1 for each new event. Atomic counter will wrap back to 1 after it reaches 168 * UINT32_MAX, skipping value 0 to avoid confusion with uninitialized memory. The writer in 169 * sensor system will wrap around from the start of shared memory region when it reaches the 170 * end. If size of memory region is not a multiple of size of element (104 bytes), the residual 171 * is not used at the end. Function returns a positive sensor report token on success. This 172 * token can be used to differentiate sensor events from multiple sensor of the same type. For 173 * example, if there are two accelerometers in the system A and B, it is guaranteed different 174 * report tokens will be returned when starting sensor A and B. 175 * 176 * To stop a sensor, call this function with rateLevel equal {@link 177 * android.hardware.SensorDirectChannel#RATE_STOP}. If the sensor parameter is left to be null, 178 * this will stop all active sensor report associated with the direct channel specified. 179 * Function return 1 on success or 0 on failure. 180 * 181 * @param sensor A {@link android.hardware.Sensor} object to denote sensor to be operated. 182 * @param rateLevel rate level defined in {@link android.hardware.SensorDirectChannel}. 183 * @return * starting report or changing rate: positive sensor report token on success, 184 * 0 on failure; 185 * * stopping report: 1 on success, 0 on failure. 186 * @throws NullPointerException when channel is null. 187 */ configure(Sensor sensor, @RateLevel int rateLevel)188 public int configure(Sensor sensor, @RateLevel int rateLevel) { 189 return mManager.configureDirectChannelImpl(this, sensor, rateLevel); 190 } 191 192 /** @hide */ SensorDirectChannel(SensorManager manager, int id, int type, long size)193 SensorDirectChannel(SensorManager manager, int id, int type, long size) { 194 mManager = manager; 195 mNativeHandle = id; 196 mType = type; 197 mSize = size; 198 mCloseGuard.open("SensorDirectChannel"); 199 } 200 201 /** @hide */ getNativeHandle()202 int getNativeHandle() { 203 return mNativeHandle; 204 } 205 206 /** 207 * This function encode handle information in {@link android.os.MemoryFile} into a long array to 208 * be passed down to native methods. 209 * 210 * @hide */ encodeData(MemoryFile ashmem)211 static long[] encodeData(MemoryFile ashmem) { 212 int fd; 213 try { 214 fd = ashmem.getFileDescriptor().getInt$(); 215 } catch (IOException e) { 216 fd = -1; 217 } 218 return new long[] { 1 /*numFds*/, 0 /*numInts*/, fd }; 219 } 220 221 @Override finalize()222 protected void finalize() throws Throwable { 223 try { 224 if (mCloseGuard != null) { 225 mCloseGuard.warnIfOpen(); 226 } 227 228 close(); 229 } finally { 230 super.finalize(); 231 } 232 } 233 234 private final AtomicBoolean mClosed = new AtomicBoolean(); 235 private final CloseGuard mCloseGuard = CloseGuard.get(); 236 private final SensorManager mManager; 237 private final int mNativeHandle; 238 private final long mSize; 239 private final int mType; 240 } 241