SensorDirectChannel.java revision 3c8c6a4cc91ad2aed52e0d331ecb8abc287a4a11
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 */
16package android.hardware;
17
18import android.annotation.IntDef;
19import android.os.MemoryFile;
20
21import dalvik.system.CloseGuard;
22
23import java.io.IOException;
24import java.lang.annotation.Retention;
25import java.lang.annotation.RetentionPolicy;
26import java.nio.channels.Channel;
27import 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 */
37public 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            mCloseGuard.warnIfOpen();
216            close();
217        } finally {
218            super.finalize();
219        }
220    }
221
222    private final AtomicBoolean mClosed = new AtomicBoolean();
223    private final CloseGuard mCloseGuard = CloseGuard.get();
224    private final SensorManager mManager;
225    private final int mNativeHandle;
226    private final long mSize;
227    private final int mType;
228}
229