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