• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Motion
2
3## Overview
4
5### Function
6
7The motion module provides motion recognition and control capabilities. OpenHarmony supports recognition of pick-up, flip, shake, and rotation.
8
9The motion driver is developed based on the hardware driver foundation (HDF). It shields hardware differences and provides APIs for the Multimodal Sensor Data Platform (MSDP) to implement capabilities such as enabling or disabling motion recognition, and subscribing to or unsubscribing from motion recognition data.
10
11The following figure shows the motion driver architecture. The framework layer provides MSDP services, and interacts with the Motion Stub through the Motion Proxy in the User Hardware Driver Foundation (UHDF). The Motion Stub calls the Motion HDI Impl APIs to provide motion recognition capabilities for upper-layer services.
12
13**Figure 1** Motion driver architecture
14
15![](figures/motion_driver_architecture.png)
16
17### Working Principles
18
19The figure below illustrates how a motion driver works.
20
21**Figure 2** How a motion driver works
22
23![](figures/motion_driver_work.png)
24
251. MSDP: The MSDP service obtains a Motion HDI service instance from the Motion Proxy and calls the Motion HDI API.
262. IDL: The IService Manager allocates a Motion HDI instance requested by the MSDP service, and the Motion Proxy forwards the instance to the MSDP service.  After the MSDP service calls the HDI API provided by the Motion Proxy, Motion Stub is called through Inter-Process Communication (IPC) to invoke the Motion Service API. The code is automatically generated by a tool and does not need to be developed by the component vendor.
273. HDI Service: The HDI service consists of Motion Interface Driver, Motion Service, and Motion Impl. Motion Interface Driver provides the motion driver code. A **HdfDriverEntry** structure is defined to implement the **Init**, **Bind**, and **Release** functions. The **HDF_INIT** macro is used to load the driver in the functions. Motion Service provides the motion recognition service interface class. The specific implementation is described in Motion Impl. The code of HDI Service must be developed by the component vendor.
28
29## Development Guidelines
30
31### When to Use
32
33The motion driver provides capabilities for the MSDP service to enable or disable motion recognition and subscribe to or unsubscribe from motion recognition data. It can be used for motion recognition when a user picks up, flips, shakes, and rotates a device.
34
35### Available APIs
36
37**Table 1** Available APIs
38
39| API                                                      | Description                    |
40| ------------------------------------------------------------ | ---------------------------- |
41| int32_t EnableMotion(int32_t motionType)                     | Enables motion recognition of the specified type. The motion recognition data can be obtained only after the motion recognition is enabled.|
42| int32_t DisableMotion(int32_t motionType)                    | Disables motion recognition of the specified type.            |
43| int32_t Register(const sptr\<IMotionCallback\> &callbackObj)   | Registers a callback for motion recognition so that the subscriber can receive the motion recognition data.|
44| int32_t Unregister(const sptr\<IMotionCallback\> &callbackObj) | Unregisters the motion recognition callback.|
45
46### How to Develop
47
48The development procedure is as follows:
49
501. Develop the user-mode driver for motion recognition based on the HDF.
512. Implement the **EnableMotion**, **DisableMotion**, **Register**, and **Unregister** APIs.
52
53The motion recognition directory structure is as follows:
54
55```undefined
56/drivers/peripheral/motion          # Developed by the vendor.
57├── hdi_service                     # Driver capabilities provided by the motion recognition module for the MSDP service layer.
58├── test                            # Test code for the motion recognition module.
59│   └── unittest\hdi                # HDI unit test code for the motion recognition module.
60```
61
62The following describes how to develop a user-mode motion driver based on the HDF. For details, see [motion_interface_driver.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/motion/hdi_service/motion_interface_driver.cpp).
63
64You need to implement the **Bind()**, **Init()**, **Release()**, and **Dispatch()** functions. The **Bind()** function binds the service capability with the driver; **Init()** implements the initialization required before the driver is loaded; **Release()** reclaims resources when **Init()** fails; **Dispatch()** implements the service, which is bound in **Bind()**.
65
66```c++
67// Custom HdfMotionInterfaceHost object
68struct HdfMotionInterfaceHost {
69    struct IDeviceIoService ioService;
70    OHOS::sptr<OHOS::IRemoteObject> stub;
71};
72
73// Enable the IPC service to call the response API.
74static int32_t MotionInterfaceDriverDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data,
75    struct HdfSBuf *reply)
76{
77    auto *hdfMotionInterfaceHost = CONTAINER_OF(client->device->service, struct HdfMotionInterfaceHost, ioService);
78
79    OHOS::MessageParcel *dataParcel = nullptr;
80    OHOS::MessageParcel *replyParcel = nullptr;
81    OHOS::MessageOption option;
82
83    if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) {
84        HDF_LOGE("%{public}s: invalid data sbuf object to dispatch", __func__);
85        return HDF_ERR_INVALID_PARAM;
86    }
87    if (SbufToParcel(reply, &replyParcel) != HDF_SUCCESS) {
88        HDF_LOGE("%{public}s: invalid reply sbuf object to dispatch", __func__);
89        return HDF_ERR_INVALID_PARAM;
90    }
91
92    return hdfMotionInterfaceHost->stub->SendRequest(cmdId, *dataParcel, *replyParcel, option);
93}
94
95// Initialize the HdfMotionInterface driver.
96int HdfMotionInterfaceDriverInit(struct HdfDeviceObject *deviceObject)
97{
98    HDF_LOGI("HdfMotionInterfaceDriverInit enter");
99    return HDF_SUCCESS;
100}
101
102// Bind the services provided by the motion driver to the HDF.
103int HdfMotionInterfaceDriverBind(struct HdfDeviceObject *deviceObject)
104{
105    HDF_LOGI("HdfMotionInterfaceDriverBind enter");
106
107    auto *hdfMotionInterfaceHost = new (std::nothrow) HdfMotionInterfaceHost;
108    if (hdfMotionInterfaceHost == nullptr) {
109        HDF_LOGE("%{public}s: failed to create HdfMotionInterfaceHost object", __func__);
110        return HDF_FAILURE;
111    }
112
113    hdfMotionInterfaceHost->ioService.Dispatch = MotionInterfaceDriverDispatch;
114    hdfMotionInterfaceHost->ioService.Open = NULL;
115    hdfMotionInterfaceHost->ioService.Release = NULL;
116
117    auto serviceImpl = IMotionInterface::Get(true);
118    if (serviceImpl == nullptr) {
119        HDF_LOGE("%{public}s: failed to get of implement service", __func__);
120        return HDF_FAILURE;
121    }
122
123    hdfMotionInterfaceHost->stub = OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl,
124        IMotionInterface::GetDescriptor());
125    if (hdfMotionInterfaceHost->stub == nullptr) {
126        HDF_LOGE("%{public}s: failed to get stub object", __func__);
127        return HDF_FAILURE;
128    }
129
130    deviceObject->service = &hdfMotionInterfaceHost->ioService;
131    return HDF_SUCCESS;
132}
133
134// Release the resources used by the motion driver.
135void HdfMotionInterfaceDriverRelease(struct HdfDeviceObject *deviceObject)
136{
137    HDF_LOGI("HdfMotionInterfaceDriverRelease enter");
138    auto *hdfMotionInterfaceHost = CONTAINER_OF(deviceObject->service, struct HdfMotionInterfaceHost, ioService);
139    delete hdfMotionInterfaceHost;
140    hdfMotionInterfaceHost = nullptr;
141}
142
143// Register the HDF driver entry g_motioninterfaceDriverEntry.
144struct HdfDriverEntry g_motioninterfaceDriverEntry = {
145    .moduleVersion = 1,
146    .moduleName = "motion_service",
147    .Bind = HdfMotionInterfaceDriverBind,
148    .Init = HdfMotionInterfaceDriverInit,
149    .Release = HdfMotionInterfaceDriverRelease,
150};
151
152// Call HDF_INIT to register the driver entry with the HDF. When loading the driver, the HDF calls the Bind function and then the Init function. If the Init function fails to be called, the HDF will call Release to release driver resources and exit the driver model.
153HDF_INIT(g_userAuthInterfaceDriverEntry);
154```
155
156### Verification
157
158The procedure is as follows:
159
1601. Call **IMotionInterface::Get()** to obtain a motion recognition instance and assign it with the **g_motionInterface** object of the **IMotionInterface** type.
161
1622. Call **Register()** using the **g_motionInterface** instance to register a callback. The callback needs to be designed based on service requirements.
163
1643. Call **EnableMotion** using the **g_motionInterface** instance to enable motion recognition of the specified type. Currently, **HDF_MOTION_TYPE_PICKUP**, **HDF_MOTION_TYPE_FLIP**, **HDF_MOTION_TYPE_SHAKE**, and **HDF_MOTION_TYPE_ROTATION** are supported.
165
1664. Call **DisableMotion** using the **g_motionInterface** instance to disable motion recognition.
167
1685. Call **Unregister** to unregister the callback for returning the motion data. The callback must have been registered. Otherwise, the **Unregister** will fail.
169
170   The sample code is as follows:
171
172   ```c++
173   using namespace OHOS::HDI::Motion::V1_0;
174   using namespace testing::ext;
175
176   namespace {
177       sptr<IMotionInterface> g_motionInterface = nullptr;
178       sptr<IMotionCallback> g_motionCallback = new MotionCallbackService();
179       sptr<IMotionCallback> g_motionCallbackUnregistered = new MotionCallbackService();
180   }
181
182   class HdfMotionTest : public testing::Test {
183   public:
184       static void SetUpTestCase();
185       static void TearDownTestCase();
186       void SetUp();
187       void TearDown();
188   };
189
190   void HdfMotionTest::SetUpTestCase()
191   {
192       // 1. Obtain a motion recognition instance.
193       g_motionInterface = IMotionInterface::Get();
194   }
195
196   void HdfMotionTest::TearDownTestCase()
197   {
198   }
199
200   void HdfMotionTest::SetUp()
201   {
202   }
203
204   void HdfMotionTest::TearDown()
205   {
206   }
207
208   HWTEST_F(HdfMotionTest, EnableMotion_001, TestSize.Level1)
209   {
210       if (g_motionInterface == nullptr) {
211           ASSERT_NE(nullptr, g_motionInterface);
212           return;
213       }
214
215       vector<int> vec;
216       vec.push_back(HDF_MOTION_TYPE_PICKUP);
217       vec.push_back(HDF_MOTION_TYPE_FLIP);
218       vec.push_back(HDF_MOTION_TYPE_SHAKE);
219       vec.push_back(HDF_MOTION_TYPE_ROTATION);
220
221       // 2. Register a callback for subscribing to motion recognition data.
222       int32_t ret = g_motionInterface->Register(g_motionCallback);
223       EXPECT_EQ(HDF_SUCCESS, ret);
224
225       for (int i = 0; i < vec.size(); i++) {
226           // 3. Enable motion recognition.
227           ret = g_motionInterface->EnableMotion(vec[i]);
228           if (ret == HDF_SUCCESS) {
229               printf("Motion %d enabled successfully\n", vec[i]);
230           } else {
231               printf("Motion %d enable failed\n", vec[i]);
232           }
233           EXPECT_EQ(HDF_SUCCESS, ret);
234           OsalSleep(15);
235           // 4. Disable motion recognition.
236           ret = g_motionInterface->DisableMotion(vec[i]);
237           if (ret == HDF_SUCCESS) {
238               printf("Motion %d disabled successfully\n", vec[i]);
239           } else {
240               printf("Motion %d disable failed\n", vec[i]);
241           }
242           EXPECT_EQ(HDF_SUCCESS, ret);
243           OsalSleep(2);
244       }
245       // 5. Unregister the callback for returning the motion recognition data.
246       ret = g_motionInterface->Unregister(g_motionCallback);
247       EXPECT_EQ(HDF_SUCCESS, ret);
248   }
249   ```
250
251