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