1e41f4b71Sopenharmony_ci# Motion
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci## Overview
4e41f4b71Sopenharmony_ci
5e41f4b71Sopenharmony_ci### Function
6e41f4b71Sopenharmony_ci
7e41f4b71Sopenharmony_ciThe motion module provides motion recognition and control capabilities. OpenHarmony supports recognition of pick-up, flip, shake, and rotation.
8e41f4b71Sopenharmony_ci
9e41f4b71Sopenharmony_ciThe 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.
10e41f4b71Sopenharmony_ci
11e41f4b71Sopenharmony_ciThe 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.
12e41f4b71Sopenharmony_ci
13e41f4b71Sopenharmony_ci**Figure 1** Motion driver architecture
14e41f4b71Sopenharmony_ci
15e41f4b71Sopenharmony_ci![](figures/motion_driver_architecture.png)
16e41f4b71Sopenharmony_ci
17e41f4b71Sopenharmony_ci### Working Principles
18e41f4b71Sopenharmony_ci
19e41f4b71Sopenharmony_ciThe figure below illustrates how a motion driver works.
20e41f4b71Sopenharmony_ci
21e41f4b71Sopenharmony_ci**Figure 2** How a motion driver works
22e41f4b71Sopenharmony_ci
23e41f4b71Sopenharmony_ci![](figures/motion_driver_work.png)
24e41f4b71Sopenharmony_ci
25e41f4b71Sopenharmony_ci1. MSDP: The MSDP service obtains a Motion HDI service instance from the Motion Proxy and calls the Motion HDI API.
26e41f4b71Sopenharmony_ci2. IDL: The MSDP service obtains a Motion HDI service instance from the Motion Proxy and calls the Motion HDI API. The interface instance is allocated by IService Manager.  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.
27e41f4b71Sopenharmony_ci3. 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.
28e41f4b71Sopenharmony_ci
29e41f4b71Sopenharmony_ci## Development Guidelines
30e41f4b71Sopenharmony_ci
31e41f4b71Sopenharmony_ci### When to Use
32e41f4b71Sopenharmony_ci
33e41f4b71Sopenharmony_ciThe 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.
34e41f4b71Sopenharmony_ci
35e41f4b71Sopenharmony_ci### Available APIs
36e41f4b71Sopenharmony_ci
37e41f4b71Sopenharmony_ci**Table 1** Available APIs
38e41f4b71Sopenharmony_ci
39e41f4b71Sopenharmony_ci**NOTE**<br>The following table lists the C++ function interfaces generated by the IDL interface description. For details about the interface declaration, see the IDL file [/drivers/interface/motion/v1_0/](https://gitee.com/openharmony/drivers_interface/tree/master/motion).
40e41f4b71Sopenharmony_ci
41e41f4b71Sopenharmony_ci| API                                                      | Description                    |
42e41f4b71Sopenharmony_ci| ------------------------------------------------------------ | ---------------------------- |
43e41f4b71Sopenharmony_ci| 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.|
44e41f4b71Sopenharmony_ci| int32_t DisableMotion(int32_t motionType)                    | Disables motion recognition of the specified type.            |
45e41f4b71Sopenharmony_ci| int32_t Register(const sptr\<IMotionCallback\> &callbackObj)   | Registers a callback for motion recognition so that the subscriber can receive the motion recognition data.|
46e41f4b71Sopenharmony_ci| int32_t Unregister(const sptr\<IMotionCallback\> &callbackObj) | Unregisters the motion recognition callback.|
47e41f4b71Sopenharmony_ci
48e41f4b71Sopenharmony_ci### How to Develop
49e41f4b71Sopenharmony_ci
50e41f4b71Sopenharmony_ciThe development procedure is as follows:
51e41f4b71Sopenharmony_ci
52e41f4b71Sopenharmony_ci1. Develop the user-mode driver for motion recognition based on the HDF.
53e41f4b71Sopenharmony_ci
54e41f4b71Sopenharmony_ci2. Implement the **EnableMotion**, **DisableMotion**, **Register**, and **Unregister** APIs.
55e41f4b71Sopenharmony_ci
56e41f4b71Sopenharmony_ciThe motion recognition directory structure is as follows:
57e41f4b71Sopenharmony_ci
58e41f4b71Sopenharmony_ci```
59e41f4b71Sopenharmony_ci/drivers/peripheral/motion            // Developed by the vendor.
60e41f4b71Sopenharmony_ci├── hdi_service              		 // Driver capability provided by the motion module for upper-layer services.
61e41f4b71Sopenharmony_ci├── test                              // Test codes for the motion module.
62e41f4b71Sopenharmony_ci   │   └── unittest\hdi               // HDI unit test code of the motion driver module.
63e41f4b71Sopenharmony_ci```
64e41f4b71Sopenharmony_ci
65e41f4b71Sopenharmony_ciThe following describes how to develop a user-mode motion driver based on the HDF. For details, see [motion_if_driver.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/motion/hdi_service/motion_if_driver.cpp).
66e41f4b71Sopenharmony_ci
67e41f4b71Sopenharmony_ciYou 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()**.
68e41f4b71Sopenharmony_ci
69e41f4b71Sopenharmony_ci```c
70e41f4b71Sopenharmony_ci/* Custom HdfMotionInterfaceHost object. */
71e41f4b71Sopenharmony_cistruct HdfMotionInterfaceHost {
72e41f4b71Sopenharmony_ci    struct IDeviceIoService ioService;
73e41f4b71Sopenharmony_ci    OHOS::sptr<OHOS::IRemoteObject> stub;
74e41f4b71Sopenharmony_ci};
75e41f4b71Sopenharmony_ci
76e41f4b71Sopenharmony_ci/* Enable the IPC service to call the response API. */
77e41f4b71Sopenharmony_cistatic int32_t MotionInterfaceDriverDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data,
78e41f4b71Sopenharmony_ci    struct HdfSBuf *reply)
79e41f4b71Sopenharmony_ci{
80e41f4b71Sopenharmony_ci    auto *hdfMotionInterfaceHost = CONTAINER_OF(client->device->service, struct HdfMotionInterfaceHost, ioService);
81e41f4b71Sopenharmony_ci
82e41f4b71Sopenharmony_ci    OHOS::MessageParcel *dataParcel = nullptr;
83e41f4b71Sopenharmony_ci    OHOS::MessageParcel *replyParcel = nullptr;
84e41f4b71Sopenharmony_ci    OHOS::MessageOption option;
85e41f4b71Sopenharmony_ci
86e41f4b71Sopenharmony_ci    if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) {
87e41f4b71Sopenharmony_ci        HDF_LOGE("%{public}s: invalid data sbuf object to dispatch", __func__);
88e41f4b71Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
89e41f4b71Sopenharmony_ci    }
90e41f4b71Sopenharmony_ci    if (SbufToParcel(reply, &replyParcel) != HDF_SUCCESS) {
91e41f4b71Sopenharmony_ci        HDF_LOGE("%{public}s: invalid reply sbuf object to dispatch", __func__);
92e41f4b71Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
93e41f4b71Sopenharmony_ci    }
94e41f4b71Sopenharmony_ci
95e41f4b71Sopenharmony_ci    return hdfMotionInterfaceHost->stub->SendRequest(cmdId, *dataParcel, *replyParcel, option);
96e41f4b71Sopenharmony_ci}
97e41f4b71Sopenharmony_ci
98e41f4b71Sopenharmony_ci/* Initialize the HdfMotionInterface driver. */
99e41f4b71Sopenharmony_ciint HdfMotionInterfaceDriverInit(struct HdfDeviceObject *deviceObject)
100e41f4b71Sopenharmony_ci{
101e41f4b71Sopenharmony_ci    HDF_LOGI("HdfMotionInterfaceDriverInit enter");
102e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
103e41f4b71Sopenharmony_ci}
104e41f4b71Sopenharmony_ci
105e41f4b71Sopenharmony_ci/* Bind the services provided by the motion driver to the HDF. */
106e41f4b71Sopenharmony_ciint HdfMotionInterfaceDriverBind(struct HdfDeviceObject *deviceObject)
107e41f4b71Sopenharmony_ci{
108e41f4b71Sopenharmony_ci    HDF_LOGI("HdfMotionInterfaceDriverBind enter");
109e41f4b71Sopenharmony_ci
110e41f4b71Sopenharmony_ci    auto *hdfMotionInterfaceHost = new (std::nothrow) HdfMotionInterfaceHost;
111e41f4b71Sopenharmony_ci    if (hdfMotionInterfaceHost == nullptr) {
112e41f4b71Sopenharmony_ci        HDF_LOGE("%{public}s: failed to create HdfMotionInterfaceHost object", __func__);
113e41f4b71Sopenharmony_ci        return HDF_FAILURE;
114e41f4b71Sopenharmony_ci    }
115e41f4b71Sopenharmony_ci
116e41f4b71Sopenharmony_ci    hdfMotionInterfaceHost->ioService.Dispatch = MotionInterfaceDriverDispatch;
117e41f4b71Sopenharmony_ci    hdfMotionInterfaceHost->ioService.Open = NULL;
118e41f4b71Sopenharmony_ci    hdfMotionInterfaceHost->ioService.Release = NULL;
119e41f4b71Sopenharmony_ci
120e41f4b71Sopenharmony_ci    auto serviceImpl = IMotionInterface::Get(true);
121e41f4b71Sopenharmony_ci    if (serviceImpl == nullptr) {
122e41f4b71Sopenharmony_ci        HDF_LOGE("%{public}s: failed to get of implement service", __func__);
123e41f4b71Sopenharmony_ci        return HDF_FAILURE;
124e41f4b71Sopenharmony_ci    }
125e41f4b71Sopenharmony_ci
126e41f4b71Sopenharmony_ci    hdfMotionInterfaceHost->stub = OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl,
127e41f4b71Sopenharmony_ci        IMotionInterface::GetDescriptor());
128e41f4b71Sopenharmony_ci    if (hdfMotionInterfaceHost->stub == nullptr) {
129e41f4b71Sopenharmony_ci        HDF_LOGE("%{public}s: failed to get stub object", __func__);
130e41f4b71Sopenharmony_ci        return HDF_FAILURE;
131e41f4b71Sopenharmony_ci    }
132e41f4b71Sopenharmony_ci
133e41f4b71Sopenharmony_ci    deviceObject->service = &hdfMotionInterfaceHost->ioService;
134e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
135e41f4b71Sopenharmony_ci}
136e41f4b71Sopenharmony_ci
137e41f4b71Sopenharmony_ci/* Release the resources used by the motion driver. */
138e41f4b71Sopenharmony_civoid HdfMotionInterfaceDriverRelease(struct HdfDeviceObject *deviceObject)
139e41f4b71Sopenharmony_ci{
140e41f4b71Sopenharmony_ci    HDF_LOGI("HdfMotionInterfaceDriverRelease enter");
141e41f4b71Sopenharmony_ci    auto *hdfMotionInterfaceHost = CONTAINER_OF(deviceObject->service, struct HdfMotionInterfaceHost, ioService);
142e41f4b71Sopenharmony_ci    delete hdfMotionInterfaceHost;
143e41f4b71Sopenharmony_ci    hdfMotionInterfaceHost = nullptr;
144e41f4b71Sopenharmony_ci}
145e41f4b71Sopenharmony_ci
146e41f4b71Sopenharmony_ci/* Register the HDF driver entry g_motioninterfaceDriverEntry. */
147e41f4b71Sopenharmony_cistruct HdfDriverEntry g_motioninterfaceDriverEntry = {
148e41f4b71Sopenharmony_ci    .moduleVersion = 1,
149e41f4b71Sopenharmony_ci    .moduleName = "motion_service",
150e41f4b71Sopenharmony_ci    .Bind = HdfMotionInterfaceDriverBind,
151e41f4b71Sopenharmony_ci    .Init = HdfMotionInterfaceDriverInit,
152e41f4b71Sopenharmony_ci    .Release = HdfMotionInterfaceDriverRelease,
153e41f4b71Sopenharmony_ci};
154e41f4b71Sopenharmony_ci
155e41f4b71Sopenharmony_ci/* 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. */
156e41f4b71Sopenharmony_ciHDF_INIT(g_userAuthInterfaceDriverEntry);
157e41f4b71Sopenharmony_ci```
158e41f4b71Sopenharmony_ci
159e41f4b71Sopenharmony_ci### Verification
160e41f4b71Sopenharmony_ci
161e41f4b71Sopenharmony_ciThe procedure is as follows:
162e41f4b71Sopenharmony_ci
163e41f4b71Sopenharmony_ci1. Call **IMotionInterface::Get()** to obtain a motion recognition instance and assign it with the **g_motionInterface** object of the **IMotionInterface** type.
164e41f4b71Sopenharmony_ci
165e41f4b71Sopenharmony_ci2. Call **Register()** using the **g_motionInterface** instance to register a callback. The callback needs to be designed based on service requirements.
166e41f4b71Sopenharmony_ci
167e41f4b71Sopenharmony_ci3. 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.
168e41f4b71Sopenharmony_ci
169e41f4b71Sopenharmony_ci4. Call **DisableMotion** using the **g_motionInterface** instance to disable motion recognition.
170e41f4b71Sopenharmony_ci
171e41f4b71Sopenharmony_ci5. Call **Unregister** to unregister the callback for returning the motion data. The callback must have been registered. Otherwise, the **Unregister** will fail.
172e41f4b71Sopenharmony_ci
173e41f4b71Sopenharmony_ci   The sample code is as follows:
174e41f4b71Sopenharmony_ci
175e41f4b71Sopenharmony_ci   ```c++
176e41f4b71Sopenharmony_ci   using namespace OHOS::HDI::Motion::V1_0;
177e41f4b71Sopenharmony_ci   using namespace testing::ext;
178e41f4b71Sopenharmony_ci   
179e41f4b71Sopenharmony_ci   namespace {
180e41f4b71Sopenharmony_ci       sptr<IMotionInterface> g_motionInterface = nullptr;
181e41f4b71Sopenharmony_ci       sptr<IMotionCallback> g_motionCallback = new MotionCallbackService();
182e41f4b71Sopenharmony_ci       sptr<IMotionCallback> g_motionCallbackUnregistered = new MotionCallbackService();
183e41f4b71Sopenharmony_ci   }
184e41f4b71Sopenharmony_ci   
185e41f4b71Sopenharmony_ci   class HdfMotionTest : public testing::Test {
186e41f4b71Sopenharmony_ci   public:
187e41f4b71Sopenharmony_ci       static void SetUpTestCase();
188e41f4b71Sopenharmony_ci       static void TearDownTestCase();
189e41f4b71Sopenharmony_ci       void SetUp();
190e41f4b71Sopenharmony_ci       void TearDown();
191e41f4b71Sopenharmony_ci   };
192e41f4b71Sopenharmony_ci   
193e41f4b71Sopenharmony_ci   void HdfMotionTest::SetUpTestCase()
194e41f4b71Sopenharmony_ci   {
195e41f4b71Sopenharmony_ci       // 1. Obtain a motion recognition instance.
196e41f4b71Sopenharmony_ci       g_motionInterface = IMotionInterface::Get();
197e41f4b71Sopenharmony_ci   }
198e41f4b71Sopenharmony_ci   
199e41f4b71Sopenharmony_ci   void HdfMotionTest::TearDownTestCase()
200e41f4b71Sopenharmony_ci   {
201e41f4b71Sopenharmony_ci   }
202e41f4b71Sopenharmony_ci   
203e41f4b71Sopenharmony_ci   void HdfMotionTest::SetUp()
204e41f4b71Sopenharmony_ci   {
205e41f4b71Sopenharmony_ci   }
206e41f4b71Sopenharmony_ci   
207e41f4b71Sopenharmony_ci   void HdfMotionTest::TearDown()
208e41f4b71Sopenharmony_ci   {
209e41f4b71Sopenharmony_ci   }
210e41f4b71Sopenharmony_ci   
211e41f4b71Sopenharmony_ci   HWTEST_F(HdfMotionTest, EnableMotion_001, TestSize.Level1)
212e41f4b71Sopenharmony_ci   {
213e41f4b71Sopenharmony_ci       if (g_motionInterface == nullptr) {
214e41f4b71Sopenharmony_ci           ASSERT_NE(nullptr, g_motionInterface);
215e41f4b71Sopenharmony_ci           return;
216e41f4b71Sopenharmony_ci       }
217e41f4b71Sopenharmony_ci   
218e41f4b71Sopenharmony_ci       vector<int> vec;
219e41f4b71Sopenharmony_ci       vec.push_back(HDF_MOTION_TYPE_PICKUP);
220e41f4b71Sopenharmony_ci       vec.push_back(HDF_MOTION_TYPE_FLIP);
221e41f4b71Sopenharmony_ci       vec.push_back(HDF_MOTION_TYPE_SHAKE);
222e41f4b71Sopenharmony_ci       vec.push_back(HDF_MOTION_TYPE_ROTATION);
223e41f4b71Sopenharmony_ci   
224e41f4b71Sopenharmony_ci       // 2. Register a callback for subscribing to motion recognition data.
225e41f4b71Sopenharmony_ci       int32_t ret = g_motionInterface->Register(g_motionCallback);
226e41f4b71Sopenharmony_ci       EXPECT_EQ(HDF_SUCCESS, ret);
227e41f4b71Sopenharmony_ci   
228e41f4b71Sopenharmony_ci       for (int i = 0; i < vec.size(); i++) {
229e41f4b71Sopenharmony_ci           // 3. Enable motion recognition.
230e41f4b71Sopenharmony_ci           ret = g_motionInterface->EnableMotion(vec[i]);
231e41f4b71Sopenharmony_ci           if (ret == HDF_SUCCESS) {
232e41f4b71Sopenharmony_ci               printf("Motion %d enabled successfully\n", vec[i]);
233e41f4b71Sopenharmony_ci           } else {
234e41f4b71Sopenharmony_ci               printf("Motion %d enable failed\n", vec[i]);
235e41f4b71Sopenharmony_ci           }
236e41f4b71Sopenharmony_ci           EXPECT_EQ(HDF_SUCCESS, ret);
237e41f4b71Sopenharmony_ci           OsalSleep(15);
238e41f4b71Sopenharmony_ci           // 4. Disable motion recognition.
239e41f4b71Sopenharmony_ci           ret = g_motionInterface->DisableMotion(vec[i]);
240e41f4b71Sopenharmony_ci           if (ret == HDF_SUCCESS) {
241e41f4b71Sopenharmony_ci               printf("Motion %d disabled successfully\n", vec[i]);
242e41f4b71Sopenharmony_ci           } else {
243e41f4b71Sopenharmony_ci               printf("Motion %d disable failed\n", vec[i]);
244e41f4b71Sopenharmony_ci           }
245e41f4b71Sopenharmony_ci           EXPECT_EQ(HDF_SUCCESS, ret);
246e41f4b71Sopenharmony_ci           OsalSleep(2);
247e41f4b71Sopenharmony_ci       }
248e41f4b71Sopenharmony_ci       // 5. Unregister the callback for returning the motion recognition data.
249e41f4b71Sopenharmony_ci       ret = g_motionInterface->Unregister(g_motionCallback);
250e41f4b71Sopenharmony_ci       EXPECT_EQ(HDF_SUCCESS, ret);
251e41f4b71Sopenharmony_ci   }
252e41f4b71Sopenharmony_ci   ```
253e41f4b71Sopenharmony_ci   
254