update OpenHarmony 2.0 Canary

This commit is contained in:
mamingshuai 2021-06-02 00:05:38 +08:00
parent b201636188
commit 483c66de10
130 changed files with 23812 additions and 61 deletions

15
.gitattributes vendored Normal file
View File

@ -0,0 +1,15 @@
*.tgz filter=lfs diff=lfs merge=lfs -text
*.trp filter=lfs diff=lfs merge=lfs -text
*.apk filter=lfs diff=lfs merge=lfs -text
*.jar filter=lfs diff=lfs merge=lfs -text
*.mp4 filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.asm filter=lfs diff=lfs merge=lfs -text
*.8svn filter=lfs diff=lfs merge=lfs -text
*.9svn filter=lfs diff=lfs merge=lfs -text
*.dylib filter=lfs diff=lfs merge=lfs -text
*.exe filter=lfs diff=lfs merge=lfs -text
*.a filter=lfs diff=lfs merge=lfs -text
*.so filter=lfs diff=lfs merge=lfs -text
*.bin filter=lfs diff=lfs merge=lfs -text
*.dll filter=lfs diff=lfs merge=lfs -text

43
BUILD.gn Executable file
View File

@ -0,0 +1,43 @@
# Copyright (C) 2021 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//build/ohos.gni")
import("//build/ohos_var.gni")
SUBSYSTEM_DIR = "//foundation/communication/ipc"
IPC_CORE_ROOT = "$SUBSYSTEM_DIR/ipc/native"
config("ipc_util_config") {
# header file path
include_dirs = [
"$SUBSYSTEM_DIR/interfaces/innerkits/ipc_core/include",
"$IPC_CORE_ROOT/src/core/include",
"$IPC_CORE_ROOT/src/mock/include",
"//utils/native/base/include",
]
cflags = []
if (is_double_framework) {
cflags = [ "-DCONFIG_DUAL_FRAMEWORK" ]
}
if (target_cpu == "arm") {
cflags += [ "-DBINDER_IPC_32BIT" ]
}
if (is_standard_system) {
cflags += [ "-DCONFIG_STANDARD_SYSTEM" ]
}
if (defined(build_public_version) && build_public_version) {
cflags += [ "-DBUILD_PUBLIC_VERSION" ]
}
}

178
LICENSE Executable file
View File

@ -0,0 +1,178 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

View File

@ -1,36 +0,0 @@
# communication_ipc
#### Description
Inter-process communication (IPC) and Remote Procedure Call (RPC) | 跨进程通信与跨设备的远程过程调用
#### Software Architecture
Software architecture description
#### Installation
1. xxxx
2. xxxx
3. xxxx
#### Instructions
1. xxxx
2. xxxx
3. xxxx
#### Contribution
1. Fork the repository
2. Create Feat_xxx branch
3. Commit your code
4. Create Pull Request
#### Gitee Feature
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
4. The most valuable open source project [GVP](https://gitee.com/gvp)
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

275
README.md Normal file → Executable file
View File

@ -1,37 +1,262 @@
# communication_ipc # communication\_ipc<a name="EN-US_TOPIC_0000001103602398"></a>
#### 介绍 - [Introduction](#section11660541593)
Inter-process communication (IPC) and Remote Procedure Call (RPC) | 跨进程通信与跨设备的远程过程调用 - [Architecture](#section1950291414611)
- [Directory Structure](#section161941989596)
- [Constraints](#section119744591305)
- [Compilation and Building](#section137768191623)
- [Usage](#section1312121216216)
- [Available APIs](#section1551164914237)
- [Usage Guidelines](#section129654513264)
#### 软件架构 - [Repositories Involved](#section1371113476307)
软件架构说明
## Introduction<a name="section11660541593"></a>
#### 安装教程 The inter-process communication \(IPC\) and remote procedure call \(RPC\) mechanisms are used to implement cross-process communication. The difference between them lies in that IPC uses the Binder driver to implement cross-process communication within a device, whereas RPC uses the DSoftBus driver to implement cross-process communication across devices. IPC and RPC generally use a client-server model. The service requester \(client\) can obtain the proxy of the service provider \(server\) and use the proxy to read and write data, thus implementing data communication between processes. Generally, the server registers system abilities \(SAs\) with the system ability manager \(SAMgr\), which manages the SAs and provides APIs for the client. To communicate with a specific SA, the client must obtain the proxy of the SA from SAMgr. In this document, Proxy represents the service requester, and Stub represents the service provider.
1. xxxx ## Architecture<a name="section1950291414611"></a>
2. xxxx
3. xxxx
#### 使用说明 **Figure 1** IPC architecture<a name="fig312319321710"></a>
![](figures/ipc-architecture.png "ipc-architecture")
1. xxxx ## Directory Structure<a name="section161941989596"></a>
2. xxxx
3. xxxx
#### 参与贡献 ```
/foundation/communication/ipc
├── interfaces # APIs exposed externally
│ └── innerkits # Header files for internal subsystems
│ ├── ipc_core # IPC APIs
│ └── libdbinder # dbinder APIs
├── ipc # IPC framework
│ ├── native # IPC native implementation
│ ├── src # IPC native source code
│ └── test # IPC native unit test cases
│ └── test # IPC native module test cases
├── service # dbinder implementation
│ └── dbinder # dbinder source code
```
1. Fork 本仓库 ## Constraints<a name="section119744591305"></a>
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
Currently, cross-device RPC communication is not supported.
#### 特技 ## Compilation and Building<a name="section137768191623"></a>
**Native Dependency**
SDK dependency:
```
external_deps = [
"ipc:ipc_core",
]
```
In addition, the refbase implementation on which IPC/RPC depends is stored in **//utils**. Add the dependency on the Utils source code.
```
deps = [
"//utils/native/base:utils",
]
```
## Usage<a name="section1312121216216"></a>
The procedure for implementing cross-process communication using native APIs is similar to that using Java APIs.
1. Define an interface.
The interface inherits **IRemoteBroker** and defines descriptors, functions, and message code.
2. Implement the server provider \(stub\).
The stub inherits **IRemoteStub\(Native\)** or **RemoteObject\(Java\)** as well as **AsObject** and **OnRemoteRequest**.
3. Implement the service requester \(proxy\).
The proxy inherits **IRemoteProxy\(Native\)** or **RemoteProxy\(Java\)**, encapsulates functions, and calls **SendRequest** to send requests to the stub.
4. Register an SA.
After the process where the service provider resides starts, apply for the unique SA ID and register the stub with SAMgr.
5. Obtain the SA.
6. Obtain the proxy from the SAMgr based on the SA ID and device ID, and implement cross-process communication with the stub through the proxy.
### Available APIs<a name="section1551164914237"></a>
**Table 1** Native IPC APIs
<a name="table178849240013"></a>
<table><thead align="left"><tr id="row6884924608"><th class="cellrowborder" valign="top" width="14.12141214121412%" id="mcps1.2.4.1.1"><p id="p98846241706"><a name="p98846241706"></a><a name="p98846241706"></a>Class/Interface</p>
</th>
<th class="cellrowborder" valign="top" width="52.54525452545254%" id="mcps1.2.4.1.2"><p id="p1488482414020"><a name="p1488482414020"></a><a name="p1488482414020"></a>Method</p>
</th>
<th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.2.4.1.3"><p id="p388516244016"><a name="p388516244016"></a><a name="p388516244016"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row15885824402"><td class="cellrowborder" valign="top" width="14.12141214121412%" headers="mcps1.2.4.1.1 "><p id="p08859241008"><a name="p08859241008"></a><a name="p08859241008"></a>IRemoteBroker</p>
</td>
<td class="cellrowborder" valign="top" width="52.54525452545254%" headers="mcps1.2.4.1.2 "><p id="p388572412010"><a name="p388572412010"></a><a name="p388572412010"></a>sptr&lt;IRemoteObject&gt; AsObject()</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p13885724405"><a name="p13885724405"></a><a name="p13885724405"></a>Obtains the holder of a remote proxy object. This method must be implemented by the derived classes of <strong id="b9012379013"><a name="b9012379013"></a><a name="b9012379013"></a>IRemoteBroker</strong>. If you call this method on the stub, the <strong id="b11613719015"><a name="b11613719015"></a><a name="b11613719015"></a>RemoteObject</strong> is returned; if you call this method on the proxy, the proxy object is returned.</p>
</td>
</tr>
<tr id="row138859241808"><td class="cellrowborder" valign="top" width="14.12141214121412%" headers="mcps1.2.4.1.1 "><p id="p1888515245012"><a name="p1888515245012"></a><a name="p1888515245012"></a>IRemoteStub</p>
</td>
<td class="cellrowborder" valign="top" width="52.54525452545254%" headers="mcps1.2.4.1.2 "><p id="p1388516240011"><a name="p1388516240011"></a><a name="p1388516240011"></a>virtual int OnRemoteRequest(uint32_t code, MessageParcel &amp;data, MessageParcel &amp;reply, MessageOption &amp;option)</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p1188582414016"><a name="p1188582414016"></a><a name="p1188582414016"></a>Called to process a request from the proxy and return the result. Derived classes need to override this method.</p>
</td>
</tr>
<tr id="row108856241904"><td class="cellrowborder" valign="top" width="14.12141214121412%" headers="mcps1.2.4.1.1 "><p id="p6885924609"><a name="p6885924609"></a><a name="p6885924609"></a>IRemoteProxy</p>
</td>
<td class="cellrowborder" valign="top" width="52.54525452545254%" headers="mcps1.2.4.1.2 ">&nbsp;&nbsp;</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p688592413018"><a name="p688592413018"></a><a name="p688592413018"></a>Service proxy classes are derived from the <strong id="b8934204311212"><a name="b8934204311212"></a><a name="b8934204311212"></a>IRemoteProxy</strong> class.</p>
</td>
</tr>
</tbody>
</table>
### Usage Guidelines<a name="section129654513264"></a>
**Native**
Define the IPC interface **ITestAbility**.
**ITestAbility** inherits the IPC base class **IRemoteBroker** and defines descriptors, functions, and message code. The functions need to be implemented on both the proxy and stub.
```
class ITestAbility : public IRemoteBroker {
public:
// DECLARE_INTERFACE_DESCRIPTOR is mandatory, and the input parameter is std::u16string.
DECLARE_INTERFACE_DESCRIPTOR(u"test.ITestAbility");
int TRANS_ID_PING_ABILITY = 1; // Define the message code.
virtual int TestPingAbility(const std::u16string &dummy) = 0; // Define functions.
};
```
Define and implement service provider **TestAbilityStub**.
This class is related to the IPC framework and needs to inherit **IRemoteStub<ITestAbility\>**. You need to override **OnRemoteRequest** on the stub to receive requests from the proxy.
```
class TestAbilityStub : public IRemoteStub<ITestAbility> {
public:
virtual int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override;
int TestPingAbility(const std::u16string &dummy) override;
};
int TestServiceStub::OnRemoteRequest(uint32_t code,
MessageParcel &data, MessageParcel &reply, MessageOption &option)
{
switch (code) {
case TRANS_ID_PING_ABILITY: {
std::u16string dummy = data.ReadString16();
int result = TestPingAbility(dummy);
reply.WriteInt32(result);
return 0;
}
default:
return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
}
}
```
Define the **TestAbility** class that implements functions for the stub.
```
class TestAbility : public TestAbilityStub {
public:
int TestPingAbility(const std::u16string &dummy);
}
int TestAbility::TestPingAbility(const std::u16string &dummy) {
return 0;
}
```
Define and implement **TestAbilityProxy**.
This class is implemented on the proxy and inherits **IRemoteProxy<ITestAbility\>**. You can call **SendRequest** to send a request to the stub and expose the capabilities provided by the stub.
```
class TestAbilityProxy : public IRemoteProxy<ITestAbility> {
public:
explicit TestAbilityProxy(const sptr<IRemoteObject> &impl);
int TestPingService(const std::u16string &dummy) override;
private:
static inline BrokerDelegator<TestAbilityProxy> delegator_; // Use the iface_cast macro.
}
TestAbilityProxy::TestAbilityProxy(const sptr<IRemoteObject> &impl)
: IRemoteProxy<ITestAbility>(impl)
{
}
int TestAbilityProxy::TestPingService(const std::u16string &dummy) {
MessageOption option;
MessageParcel dataParcel, replyParcel;
dataParcel.WriteString16(dummy);
int error = Remote()->SendRequest(TRANS_ID_PING_ABILITY, dataParcel, replyParcel, option);
int result = (error == ERR_NONE) ? replyParcel.ReadInt32() : -1;
return result;
}
```
Send a request synchronously or asynchronously.
The **MessageOption** parameter for the **sendRequest\(\)** method can be set to **TF\_SYNC**, **TF\_ASYNC**, or **TF\_ACCEPT\_FDS** using the **MessageOption** constructor or **void SetFlags\(int flags\)**. The default value is **TF\_SYNC**.
```
int SendRequest(uint32_t code, MessageParcel &data,
MessageParcel &reply, MessageOption &option) override;
MessageOption option = { MessageOption::TF_ASYNC };
```
Register and start an SA.
Call **AddSystemAbility** to register the **TestAbilityStub** instance of the SA with **SystemAbilityManager**. The registration parameters vary depending on whether the **SystemAbilityManager** resides on the same device as the SA.
```
// Register the TestAbilityStub instance with the SystemAbilityManager on the same device as the SA.
auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
samgr->AddSystemAbility(said, new TestAbility());
// Register the TestAbilityStub instance with the SystemAbilityManager on a different device.
auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
ISystemAbilityManager::SAExtraProp saExtra;
saExtra.isDistributed = true; // Set a distributed SA.
int result = samgr->AddSystemAbility(said, new TestAbility(), saExtra);
```
Obtain the SA.
Call the **GetSystemAbility** function of the **SystemAbilityManager** class to obtain the **IRemoteObject** for the SA, and create a **TestAbilityProxy** instance.
```
// Obtain the proxy of the SA registered on the local device.
sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
sptr<IRemoteObject> remoteObject = samgr->GetSystemAbility(said);
sptr<ITestAbility> testAbility = iface_cast<ITestAbility>(remoteObject); // Use the iface_cast macro to convert the proxy to a specific type.
// Obtain the proxies of the SAs registered with other devices.
sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
sptr<IRemoteObject> remoteObject = samgr->GetSystemAbility(sdid, deviceId); // deviceId identifies a device.
sptr<TestAbilityProxy> proxy(new TestAbilityProxy(remoteObject)); // Construct a proxy.
```
## Repositories Involved<a name="section1371113476307"></a>
DSoftBus subsystem
**communication\_ipc**
utils
utils\_native
distributedschedule\_samgr
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

264
README_zh.md Executable file
View File

@ -0,0 +1,264 @@
# IPC/RPC组件<a name="ZH-CN_TOPIC_0000001103602398"></a>
- [简介](#section11660541593)
- [系统架构](#section1950291414611)
- [目录](#section161941989596)
- [约束](#section119744591305)
- [编译构建](#section137768191623)
- [说明](#section1312121216216)
- [接口说明](#section1551164914237)
- [使用说明](#section129654513264)
- [相关仓](#section1371113476307)
## 简介<a name="section11660541593"></a>
IPCInter-Process Communication与RPCRemote Procedure Call机制用于实现跨进程通信不同的是前者使用Binder驱动用于设备内的跨进程通信而后者使用软总线驱动用于跨设备跨进程通信。IPC和RPC通常采用客户端-服务器Client-Server模型服务请求方Client可获取提供服务提供方Server的代理 Proxy并通过此代理读写数据来实现进程间的数据通信。通常Server会先注册系统能力System Ability到系统能力管理者System Ability Manager缩写SAMgrSAMgr负责管理这些SA并向Client提供相关的接口。Client要和某个具体的SA通信必须先从SAMgr中获取该SA的代理然后使用代理和SA通信。下文使用Proxy表示服务请求方Stub表示服务提供方。
## 系统架构<a name="section1950291414611"></a>
**图 1** IPC通信机制架构图<a name="fig312319321710"></a>
![](figures/ipc-architecture.png "IPC通信机制架构图")
## 目录<a name="section161941989596"></a>
```
/foundation/communication/ipc
├── interfaces # 对外接口存放目录
│ └── innerkits # 对内部子系统暴露的头文件存放目录
│ ├── ipc_core # ipc 接口存放目录
│ └── libdbinder # dbinder 接口存放目录
├── ipc # ipc 框架代码
│ ├── native # ipc native 实现存放目录
│ ├── src # ipc native 源代码存放目录
│ └── test # ipc native 单元测试用例存放目录
│ └── test # ipc native 模块测试用例存放目录
├── service # dbinder 实现存放目录
│ └── dbinder # dbinder 源代码存放目录
```
## 约束<a name="section119744591305"></a>
目前暂不支持的场景:
跨设备RPC调用
## 编译构建<a name="section137768191623"></a>
**Native侧编译依赖**
sdk依赖
```
external_deps = [
"ipc:ipc_core",
]
```
此外, IPC/RPC依赖的refbase实现在公共基础库实现//utils下请增加对utils的源码依赖
```
deps = [
"//utils/native/base:utils",
]
```
## 说明<a name="section1312121216216"></a>
Native侧和Java侧实现跨进程通信的步骤基本相同。
1. 定义接口类
接口类继承IRemoteBroker定义描述符、业务函数和消息码。
2. 实现服务提供端\(Stub\)
Stub继承IRemoteStub\(Native\)或者RemoteObject\(Java\)除了接口类中未实现方法外还需要实现AsObject方法及OnRemoteRequest方法。
3. 实现服务请求端\(Proxy\)
Proxy继承IRemoteProxy\(Native\)或者RemoteProxy\(Java\)封装业务函数调用SendRequest将请求发送到Stub。
4. 注册SA
服务提供方所在进程启动后申请SA的唯一标识将Stub注册到SAMgr。
5. 获取SA
6. 通过SA的标识和设备标识从SAMgr获取Proxy通过Proxy实现与Stub的跨进程通信。
### 接口说明<a name="section1551164914237"></a>
**表 1** Native侧IPC接口
<a name="table178849240013"></a>
<table><thead align="left"><tr id="row6884924608"><th class="cellrowborder" valign="top" width="14.12141214121412%" id="mcps1.2.4.1.1"><p id="p98846241706"><a name="p98846241706"></a><a name="p98846241706"></a>类/接口</p>
</th>
<th class="cellrowborder" valign="top" width="52.54525452545254%" id="mcps1.2.4.1.2"><p id="p1488482414020"><a name="p1488482414020"></a><a name="p1488482414020"></a>方法</p>
</th>
<th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.2.4.1.3"><p id="p388516244016"><a name="p388516244016"></a><a name="p388516244016"></a>功能说明</p>
</th>
</tr>
</thead>
<tbody><tr id="row15885824402"><td class="cellrowborder" valign="top" width="14.12141214121412%" headers="mcps1.2.4.1.1 "><p id="p08859241008"><a name="p08859241008"></a><a name="p08859241008"></a>IRemoteBroker</p>
</td>
<td class="cellrowborder" valign="top" width="52.54525452545254%" headers="mcps1.2.4.1.2 "><p id="p388572412010"><a name="p388572412010"></a><a name="p388572412010"></a>sptr&lt;IRemoteObject&gt; AsObject()</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p13885724405"><a name="p13885724405"></a><a name="p13885724405"></a>返回通信对象。派生类需要实现Stub端返回RemoteObject对象本身Proxy端返回代理对象。</p>
</td>
</tr>
<tr id="row138859241808"><td class="cellrowborder" valign="top" width="14.12141214121412%" headers="mcps1.2.4.1.1 "><p id="p1888515245012"><a name="p1888515245012"></a><a name="p1888515245012"></a>IRemoteStub</p>
</td>
<td class="cellrowborder" valign="top" width="52.54525452545254%" headers="mcps1.2.4.1.2 "><p id="p1388516240011"><a name="p1388516240011"></a><a name="p1388516240011"></a>virtual int OnRemoteRequest(uint32_t code, MessageParcel &amp;data, MessageParcel &amp;reply, MessageOption &amp;option)</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p1188582414016"><a name="p1188582414016"></a><a name="p1188582414016"></a>请求处理方法派生类需要重写处理Proxy的请求并返回结果。</p>
</td>
</tr>
<tr id="row108856241904"><td class="cellrowborder" valign="top" width="14.12141214121412%" headers="mcps1.2.4.1.1 "><p id="p6885924609"><a name="p6885924609"></a><a name="p6885924609"></a>IRemoteProxy</p>
</td>
<td class="cellrowborder" valign="top" width="52.54525452545254%" headers="mcps1.2.4.1.2 ">&nbsp;&nbsp;</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p688592413018"><a name="p688592413018"></a><a name="p688592413018"></a>业务Proxy类派生自IRemoteProxy类。</p>
</td>
</tr>
</tbody>
</table>
### 使用说明<a name="section129654513264"></a>
**Native侧使用说明**
定义IPC接口ITestAbility
IPC接口继承IPC基类接口IRemoteBroker接口里定义描述符、业务函数和消息码其中业务函数在Proxy端和Stub端都需要实现。
```
class ITestAbility : public IRemoteBroker {
public:
// DECLARE_INTERFACE_DESCRIPTOR是必须的 入参需使用std::u16string
DECLARE_INTERFACE_DESCRIPTOR(u"test.ITestAbility");
int TRANS_ID_PING_ABILITY = 1; // 定义消息码
virtual int TestPingAbility(const std::u16string &dummy) = 0; // 定义业务函数
};
```
定义和实现服务端TestAbilityStub
该类是和IPC框架相关的实现需要继承 IRemoteStub<ITestAbility\>Stub端作为接收请求的一端需重写OnRemoteRequest方法用于接收客户端调用
```
class TestAbilityStub : public IRemoteStub<ITestAbility> {
public:
virtual int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override;
int TestPingAbility(const std::u16string &dummy) override;
};
int TestServiceStub::OnRemoteRequest(uint32_t code,
MessageParcel &data, MessageParcel &reply, MessageOption &option)
{
switch (code) {
case TRANS_ID_PING_ABILITY: {
std::u16string dummy = data.ReadString16();
int result = TestPingAbility(dummy);
reply.WriteInt32(result);
return 0;
}
default:
return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
}
}
```
定义服务端业务函数具体实现类TestAbility
```
class TestAbility : public TestAbilityStub {
public:
int TestPingAbility(const std::u16string &dummy);
}
int TestAbility::TestPingAbility(const std::u16string &dummy) {
return 0;
}
```
定义和实现客户端TestAbilityProxy
该类是Proxy端实现继承IRemoteProxy<ITestAbility\>调用SendRequest接口向Stub端发送请求对外暴露服务端提供的能力
```
class TestAbilityProxy : public IRemoteProxy<ITestAbility> {
public:
explicit TestAbilityProxy(const sptr<IRemoteObject> &impl);
int TestPingService(const std::u16string &dummy) override;
private:
static inline BrokerDelegator<TestAbilityProxy> delegator_; // 方便使用iface_cast宏
}
TestAbilityProxy::TestAbilityProxy(const sptr<IRemoteObject> &impl)
: IRemoteProxy<ITestAbility>(impl)
{
}
int TestAbilityProxy::TestPingService(const std::u16string &dummy) {
MessageOption option;
MessageParcel dataParcel, replyParcel;
dataParcel.WriteString16(dummy);
int error = Remote()->SendRequest(TRANS_ID_PING_ABILITY, dataParcel, replyParcel, option);
int result = (error == ERR_NONE) ? replyParcel.ReadInt32() : -1;
return result;
}
```
同步调用与异步调用
MessageOption作为发送接口原型如下的入参可设定同步TF\_SYNC、异步TF\_ASYNC、接收FDTF\_ACCEPT\_FDS默认情况下设定为同步其余可通过MessageOption构造方法或void SetFlags\(int flags\)设定。
```
int SendRequest(uint32_t code, MessageParcel &data,
MessageParcel &reply, MessageOption &option) override;
MessageOption option = { MessageOption::TF_ASYNC };
```
SA注册与启动
SA需要将自己的TestAbilityStub实例通过AddSystemAbility接口注册到SystemAbilityManager设备内与分布式的注册参数不同。
```
// 注册到本设备内
auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
samgr->AddSystemAbility(said, new TestAbility());
// 在组网场景下,会被同步到其他设备上
auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
ISystemAbilityManager::SAExtraProp saExtra;
saExtra.isDistributed = true; // 设置为分布式SA
int result = samgr->AddSystemAbility(said, new TestAbility(), saExtra);
```
SA获取与调用
通过SystemAbilityManager的GetSystemAbility方法可获取到对应SA的代理IRemoteObject然后构造TestAbilityProxy即可。
```
// 获取本设备内注册的SA的proxy
sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
sptr<IRemoteObject> remoteObject = samgr->GetSystemAbility(said);
sptr<ITestAbility> testAbility = iface_cast<ITestAbility>(remoteObject); // 使用iface_cast宏转换成具体类型
// 获取其他设备注册的SA的Proxy
sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
sptr<IRemoteObject> remoteObject = samgr->GetSystemAbility(sdid, deviceId); // deviceId是指定设备的标识符
sptr<TestAbilityProxy> proxy(new TestAbilityProxy(remoteObject)); // 直接构造具体Proxy
```
## 相关仓<a name="section1371113476307"></a>
分布式软总线子系统
**communication\_ipc**
utils
utils\_native
distributedschedule\_samgr

BIN
figures/ipc-architecture.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

@ -0,0 +1,67 @@
# Copyright (C) 2021 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//build/ohos.gni")
SUBSYSTEM_DIR = "//foundation/communication/ipc"
IPC_CORE_ROOT = "$SUBSYSTEM_DIR/ipc/native"
config("libipc_core_private_config") {
cflags_cc = [ "-O2" ]
}
ohos_shared_library("ipc_core") {
include_dirs = [
"$SUBSYSTEM_DIR/utils/include",
]
sources = [
"$IPC_CORE_ROOT/src/core/source/buffer_object.cpp",
"$IPC_CORE_ROOT/src/core/source/comm_auth_info.cpp",
"$IPC_CORE_ROOT/src/core/source/databus_session_callback.cpp",
"$IPC_CORE_ROOT/src/core/source/dbinder_session_object.cpp",
"$IPC_CORE_ROOT/src/core/source/ipc_file_descriptor.cpp",
"$IPC_CORE_ROOT/src/core/source/ipc_object_proxy.cpp",
"$IPC_CORE_ROOT/src/core/source/ipc_object_stub.cpp",
"$IPC_CORE_ROOT/src/core/source/ipc_process_skeleton.cpp",
"$IPC_CORE_ROOT/src/core/source/ipc_skeleton.cpp",
"$IPC_CORE_ROOT/src/core/source/ipc_thread_pool.cpp",
"$IPC_CORE_ROOT/src/core/source/ipc_thread_skeleton.cpp",
"$IPC_CORE_ROOT/src/core/source/ipc_workthread.cpp",
"$IPC_CORE_ROOT/src/core/source/iremote_broker.cpp",
"$IPC_CORE_ROOT/src/core/source/iremote_object.cpp",
"$IPC_CORE_ROOT/src/core/source/message_option.cpp",
"$IPC_CORE_ROOT/src/core/source/message_parcel.cpp",
"$IPC_CORE_ROOT/src/core/source/peer_holder.cpp",
"$IPC_CORE_ROOT/src/core/source/stub_refcount_object.cpp",
"$IPC_CORE_ROOT/src/mock/source/binder_connector.cpp",
"$IPC_CORE_ROOT/src/mock/source/binder_debug.cpp",
"$IPC_CORE_ROOT/src/mock/source/binder_invoker.cpp",
"$IPC_CORE_ROOT/src/mock/source/dbinder_databus_invoker.cpp",
"$IPC_CORE_ROOT/src/mock/source/invoker_factory.cpp",
"$IPC_CORE_ROOT/src/mock/source/invoker_rawdata.cpp",
]
configs = [
"$SUBSYSTEM_DIR:ipc_util_config",
":libipc_core_private_config",
]
public_configs = [ "$SUBSYSTEM_DIR:ipc_util_config" ]
deps = [ "//utils/native/base:utils" ]
external_deps = [
"dsoftbus_standard:softbus_client",
"hiviewdfx_hilog_native:libhilog",
]
subsystem_name = "communication"
part_name = "ipc"
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_IPC_FILE_DESCRIPTOR_H
#define OHOS_IPC_IPC_FILE_DESCRIPTOR_H
#include "parcel.h"
namespace OHOS {
class IPCFileDescriptor : public virtual Parcelable {
public:
IPCFileDescriptor();
explicit IPCFileDescriptor(int fd);
~IPCFileDescriptor();
bool Marshalling(Parcel &parcel) const override;
static bool Marshalling(Parcel &parcel, const sptr<IPCFileDescriptor> &object);
static IPCFileDescriptor *Unmarshalling(Parcel &parcel);
int GetFd() const;
void SetFd(int fd);
private:
int fd_ = -1;
};
} // namespace OHOS
#endif // OHOS_IPC_IPC_FILE_DESCRIPTOR_H

View File

@ -0,0 +1,117 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_IPC_OBJECT_PROXY_H
#define OHOS_IPC_IPC_OBJECT_PROXY_H
#include <mutex>
#include <vector>
#include "iremote_object.h"
namespace OHOS {
class IPCObjectProxy : public IRemoteObject {
public:
explicit IPCObjectProxy(int handle, std::u16string descriptor = std::u16string(),
int proto = IRemoteObject::IF_PROT_DEFAULT);
~IPCObjectProxy();
int SendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &optionoption) override;
bool IsProxyObject() const override
{
return true;
};
bool IsObjectDead() const;
int32_t GetObjectRefCount() override;
int Dump(int fd, const std::vector<std::u16string> &args) override;
void OnFirstStrongRef(const void *objectId) override;
void OnLastStrongRef(const void *objectId) override;
bool AddDeathRecipient(const sptr<DeathRecipient> &recipient) override;
bool RemoveDeathRecipient(const sptr<DeathRecipient> &recipient) override;
void SendObituary();
bool IsSubscribeDeathNotice() const
{
if (recipients_.empty()) {
return false;
}
return true;
};
uint32_t GetHandle() const
{
return handle_;
};
int InvokeListenThread(MessageParcel &data, MessageParcel &reply);
int32_t NoticeServiceDie();
std::string GetPidAndUidInfo();
std::string GetDataBusName();
int GetProto() const;
void WaitForInit();
std::u16string GetInterfaceDescriptor();
private:
void MarkObjectDied();
int SendLocalRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &optionoption);
int SendRequestInner(bool isLocal, uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option);
#ifndef CONFIG_IPC_SINGLE
void SetProto(int proto);
int UpdateProto();
void ReleaseProto();
void IncRefToRemote();
int GetSessionFromDBinderService();
bool AddDbinderDeathRecipient();
bool RemoveDbinderDeathRecipient();
void ReleaseDatabusProto();
void ReleaseBinderProto();
bool UpdateDatabusClientSession(int handle, MessageParcel &reply);
bool CheckHaveSession(uint32_t &type);
#endif
private:
std::mutex initMutex_;
std::recursive_mutex mutex_;
std::vector<sptr<DeathRecipient>> recipients_;
const uint32_t handle_;
int proto_;
bool isFinishInit_;
bool isRemoteDead_;
std::u16string remoteDescriptor_;
};
} // namespace OHOS
#endif // OHOS_IPC_IPC_OBJECT_PROXY_H

View File

@ -0,0 +1,84 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_IPC_OBJECT_STUB_H
#define OHOS_IPC_IPC_OBJECT_STUB_H
#include "iremote_object.h"
#include <list>
#include "ipc_object_proxy.h"
namespace OHOS {
struct RefCountNode {
int remotePid;
std::string deviceId;
};
class IPCObjectStub : public IRemoteObject {
public:
explicit IPCObjectStub(std::u16string descriptor = nullptr);
~IPCObjectStub();
bool IsProxyObject() const override
{
return false;
};
int32_t GetObjectRefCount() override;
int Dump(int fd, const std::vector<std::u16string> &args) override;
virtual int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option);
int SendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override;
void OnFirstStrongRef(const void *objectId) override;
void OnLastStrongRef(const void *objectId) override;
bool AddDeathRecipient(const sptr<DeathRecipient> &recipient) override;
bool RemoveDeathRecipient(const sptr<DeathRecipient> &recipient) override;
int GetCallingPid();
int GetCallingUid();
virtual int OnRemoteDump(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option);
virtual int32_t ProcessProto(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option);
#ifndef CONFIG_IPC_SINGLE
int32_t InvokerThread(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option);
int32_t NoticeServiceDie(MessageParcel &data, MessageParcel &reply, MessageOption &option);
int32_t InvokerDataBusThread(MessageParcel &data, MessageParcel &reply);
int32_t IncStubRefs(MessageParcel &data, MessageParcel &reply);
int32_t DecStubRefs(MessageParcel &data, MessageParcel &reply);
int32_t AddAuthInfo(MessageParcel &data, MessageParcel &reply);
private:
int32_t GrantDataBusName(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option);
std::string CreateDatabusName(int uid, int pid);
std::string GetDataBusName();
#endif
private:
bool IsDeviceIdIllegal(const std::string &deviceID);
};
} // namespace OHOS
#endif // OHOS_IPC_IPC_OBJECT_STUB_H

View File

@ -0,0 +1,59 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_IPC_SKELETON_H
#define OHOS_IPC_IPC_SKELETON_H
#include "iremote_object.h"
namespace OHOS {
class IPCSkeleton {
public:
IPCSkeleton() = default;
~IPCSkeleton() = default;
// default max is 4, only if you need a customize value
static bool SetMaxWorkThreadNum(int maxThreadNum);
// join current thread into work loop.
static void JoinWorkThread();
// remove current thread from work loop.
static void StopWorkThread();
static pid_t GetCallingPid();
static pid_t GetCallingUid();
static std::string GetLocalDeviceID();
static std::string GetCallingDeviceID();
static bool IsLocalCalling();
static IPCSkeleton &GetInstance();
static sptr<IRemoteObject> GetContextObject();
static bool SetContextObject(sptr<IRemoteObject> &object);
static int FlushCommands(IRemoteObject *object);
static std::string ResetCallingIdentity();
static bool SetCallingIdentity(std::string &identity);
};
} // namespace OHOS
#endif // OHOS_IPC_IPC_SKELETON_H

View File

@ -0,0 +1,122 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_IPC_TYPES_H
#define OHOS_IPC_IPC_TYPES_H
#include <sys/types.h>
#include <errno.h>
#include "errors.h"
namespace OHOS {
#define ZIPC_PACK_CHARS(c1, c2, c3, c4) ((((c1) << 24)) | (((c2) << 16)) | (((c3) << 8)) | (c4))
constexpr int REGISTRY_HANDLE = 0;
enum {
FIRST_CALL_TRANSACTION = 0x00000001,
LAST_CALL_TRANSACTION = 0x00ffffff,
PING_TRANSACTION = ZIPC_PACK_CHARS('_', 'P', 'N', 'G'),
DUMP_TRANSACTION = ZIPC_PACK_CHARS('_', 'D', 'M', 'P'),
SHELL_COMMAND_TRANSACTION = ZIPC_PACK_CHARS('_', 'C', 'M', 'D'),
INTERFACE_TRANSACTION = ZIPC_PACK_CHARS('_', 'N', 'T', 'F'),
SYSPROPS_TRANSACTION = ZIPC_PACK_CHARS('_', 'S', 'P', 'R'),
SYNCHRONIZE_REFERENCE = ZIPC_PACK_CHARS('_', 'S', 'Y', 'C'),
INVOKE_LISTEN_THREAD = ZIPC_PACK_CHARS('_', 'I', 'L', 'T'),
GET_PROTO_INFO = ZIPC_PACK_CHARS('_', 'G', 'R', 'I'),
GET_UIDPID_INFO = ZIPC_PACK_CHARS('_', 'G', 'U', 'I'),
GRANT_DATABUS_NAME = ZIPC_PACK_CHARS('_', 'G', 'D', 'N'),
DBINDER_OBITUARY_TRANSACTION = ZIPC_PACK_CHARS('_', 'D', 'O', 'T'),
DBINDER_INCREFS_TRANSACTION = ZIPC_PACK_CHARS('_', 'D', 'I', 'T'),
DBINDER_DECREFS_TRANSACTION = ZIPC_PACK_CHARS('_', 'D', 'D', 'T'),
DBINDER_ADD_COMMAUTH = ZIPC_PACK_CHARS('_', 'D', 'A', 'C'),
TRANS_SYNC = 0,
TRANS_ASYNC = 1,
};
enum {
NO_ERROR = 0,
TRANSACTION_ERR,
FLATTEN_ERR = 3,
UNKNOWN_TRANSACTION = 4,
INVALID_DATA = 5,
OBJECT_NULL = 7,
INVALID_OPERATION = 8,
DEAD_OBJECT = -EPIPE,
UNKNOWN_ERROR,
};
constexpr int MIN_TRANSACTION_ID = 0x1;
constexpr int MAX_TRANSACTION_ID = 0x00ffffff;
constexpr int INVALID_FD = -1;
enum {
ERR_NONE = 0,
ERR_TRANSACTION_FAILED = 1,
ERR_UNKNOWN_OBJECT = 2,
ERR_FLATTEN_OBJECT = 3,
ERR_UNKNOWN_TRANSACTION = 4,
ERR_INVALID_DATA = 5,
ERR_NULL_OBJECT = 7,
ERR_UNKNOWN_REASON,
ERR_INVALID_REPLY,
ERR_INVALID_STATE,
IPC_SKELETON_ERR = 100,
IPC_SKELETON_NULL_OBJECT_ERR,
IPC_PROXY_ERR = 200,
IPC_PROXY_DEAD_OBJECT_ERR,
IPC_PROXY_NULL_INVOKER_ERR,
IPC_PROXY_TRANSACTION_ERR,
IPC_PROXY_INVALID_CODE_ERR,
IPC_STUB_ERR = 300,
IPC_STUB_WRITE_PARCEL_ERR,
IPC_STUB_INVOKE_THREAD_ERR,
IPC_STUB_INVALID_DATA_ERR,
IPC_STUB_CURRENT_NULL_ERR,
IPC_STUB_UNKNOW_TRANS_ERR,
IPC_STUB_CREATE_BUS_SERVER_ERR,
IPC_INVOKER_ERR = 400,
IPC_INVOKER_WRITE_TRANS_ERR,
IPC_INVOKER_TRANSLATE_ERR,
IPC_INVOKER_CONNECT_ERR,
IPC_INVOKER_ON_TRANSACT_ERR,
IPC_INVOKER_INVALID_DATA_ERR,
IPC_INVOKER_INVALID_REPLY_ERR,
RPC_BASE_INVOKER_ERR = 500,
RPC_BASE_INVOKER_INVALID_REPLY_ERR,
RPC_BASE_INVOKER_WAIT_REPLY_ERR,
RPC_BASE_INVOKER_CURRENT_NULL_ERR,
RPC_BASE_INVOKER_INVALID_DATA_ERR,
RPC_BASE_INVOKER_WRITE_TRANS_ERR,
RPC_BASE_INVOKER_SEND_REPLY_ERR,
RPC_DATABUS_INVOKER_ERR = 600,
RPC_DATABUS_INVOKER_INVALID_DATA_ERR,
RPC_DATABUS_INVOKER_CLOSED_PEER_ERR,
RPC_DATABUS_INVOKER_INVALID_STUB_INDEX,
DBINDER_SERVICE_ERR = 700,
DBINDER_SERVICE_INVALID_DATA_ERR,
DBINDER_SERVICE_NOTICE_DIE_ERR,
DBINDER_SERVICE_PROCESS_PROTO_ERR,
DBINDER_SERVICE_UNKNOW_TRANS_ERR,
DBINDER_SERVICE_ADD_DEATH_ERR,
DBINDER_SERVICE_REMOVE_DEATH_ERR,
DBINDER_SERVICE_WRONG_SESSION,
SESSION_WRONG_FD_ERR = 800,
SESSION_INVOKER_NULL_ERR,
SESSION_UNAUTHENTICATED_ERR,
SESSION_UNOPEN_ERR = -1,
};
} // namespace OHOS
#endif // OHOS_IPC_IPC_TYPES_H

View File

@ -0,0 +1,109 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_IREMOTE_BROKER_H
#define OHOS_IPC_IREMOTE_BROKER_H
#include <unordered_map>
#include <functional>
#include "iremote_object.h"
#include "refbase.h"
namespace OHOS {
template <typename T> class BrokerCreator {
public:
BrokerCreator() = default;
~BrokerCreator() = default;
sptr<IRemoteBroker> operator () (const sptr<IRemoteObject> &object)
{
return static_cast<IRemoteBroker *>(new T(object));
};
};
class IRemoteBroker : public virtual RefBase {
public:
IRemoteBroker() = default;
virtual ~IRemoteBroker() override = default;
virtual sptr<IRemoteObject> AsObject() = 0;
static inline sptr<IRemoteBroker> AsImplement(const sptr<IRemoteObject> &object)
{
return nullptr;
}
};
#define DECLARE_INTERFACE_DESCRIPTOR(DESCRIPTOR) \
static inline const std::u16string metaDescriptor_ = { DESCRIPTOR }; \
static inline const std::u16string &GetDescriptor() \
{ \
return metaDescriptor_; \
}
class BrokerRegistration {
using Constructor = std::function<sptr<IRemoteBroker>(const sptr<IRemoteObject> &object)>;
public:
static BrokerRegistration &Get();
bool Register(const std::u16string &descriptor, const Constructor &creator);
void Unregister(const std::u16string &descriptor);
sptr<IRemoteBroker> NewInstance(const std::u16string &descriptor, const sptr<IRemoteObject> &object);
protected:
BrokerRegistration() = default;
~BrokerRegistration();
private:
BrokerRegistration(const BrokerRegistration &) = delete;
BrokerRegistration(BrokerRegistration &&) = delete;
BrokerRegistration &operator = (const BrokerRegistration &) = delete;
BrokerRegistration &operator = (BrokerRegistration &&) = delete;
std::mutex creatorMutex_;
std::unordered_map<std::u16string, Constructor> creators_;
};
template <typename T> class BrokerDelegator {
public:
BrokerDelegator();
~BrokerDelegator();
private:
BrokerDelegator(const BrokerDelegator &) = delete;
BrokerDelegator(BrokerDelegator &&) = delete;
BrokerDelegator &operator = (const BrokerDelegator &) = delete;
BrokerDelegator &operator = (BrokerDelegator &&) = delete;
};
template <typename T> BrokerDelegator<T>::BrokerDelegator()
{
const std::u16string descriptor = T::GetDescriptor();
BrokerRegistration &registration = BrokerRegistration::Get();
registration.Register(descriptor, BrokerCreator<T>());
}
template <typename T> BrokerDelegator<T>::~BrokerDelegator()
{
const std::u16string descriptor = T::GetDescriptor();
BrokerRegistration &registration = BrokerRegistration::Get();
registration.Unregister(descriptor);
}
template <typename INTERFACE> inline sptr<INTERFACE> iface_cast(const sptr<IRemoteObject> &object)
{
const std::u16string descriptor = INTERFACE::GetDescriptor();
BrokerRegistration &registration = BrokerRegistration::Get();
sptr<IRemoteBroker> broker = registration.NewInstance(descriptor, object);
return static_cast<INTERFACE *>(broker.GetRefPtr());
}
} // namespace OHOS
#endif // OHOS_IPC_IREMOTE_BROKER_H

View File

@ -0,0 +1,86 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_IREMOTE_OBJECT_H
#define OHOS_IPC_IREMOTE_OBJECT_H
#include <codecvt>
#include <locale>
#include <vector>
#include <string>
#include "ipc_types.h"
#include "message_parcel.h"
#include "message_option.h"
namespace OHOS {
class IRemoteBroker;
inline std::u16string to_utf16(const std::string &str)
{
return std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> {}.from_bytes(str);
}
class IRemoteObject : public virtual Parcelable, public virtual RefBase {
public:
enum {
IF_PROT_DEFAULT, /* Invoker family. */
IF_PROT_BINDER = IF_PROT_DEFAULT,
IF_PROT_DATABUS,
};
enum {
DATABUS_TYPE,
};
class DeathRecipient : public RefBase {
public:
enum {
ADD_DEATH_RECIPIENT,
REMOVE_DEATH_RECIPIENT,
NOTICE_DEATH_RECIPIENT,
TEST_SERVICE_DEATH_RECIPIENT,
TEST_DEVICE_DEATH_RECIPIENT,
};
virtual void OnRemoteDied(const wptr<IRemoteObject> &object) = 0;
};
virtual int32_t GetObjectRefCount() = 0;
virtual int SendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) = 0;
virtual bool IsProxyObject() const;
virtual bool CheckObjectLegality() const;
virtual bool AddDeathRecipient(const sptr<DeathRecipient> &recipient) = 0;
virtual bool RemoveDeathRecipient(const sptr<DeathRecipient> &recipient) = 0;
virtual bool Marshalling(Parcel &parcel) const override;
static IRemoteObject *Unmarshalling(Parcel &parcel);
static bool Marshalling(Parcel &parcel, const sptr<IRemoteObject> &object);
virtual sptr<IRemoteBroker> AsInterface();
virtual int Dump(int fd, const std::vector<std::u16string> &args) = 0;
const std::u16string descriptor_;
std::u16string GetObjectDescriptor() const;
protected:
explicit IRemoteObject(std::u16string descriptor = nullptr);
};
} // namespace OHOS
#endif // OHOS_IPC_IREMOTE_OBJECT_H

View File

@ -0,0 +1,43 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_IREMOTE_PROXY_H
#define OHOS_IPC_IREMOTE_PROXY_H
#include "iremote_broker.h"
#include "peer_holder.h"
#include "iremote_object.h"
namespace OHOS {
template <typename INTERFACE> class IRemoteProxy : public PeerHolder, public INTERFACE {
public:
explicit IRemoteProxy(const sptr<IRemoteObject> &object);
~IRemoteProxy() override = default;
protected:
sptr<IRemoteObject> AsObject() override;
};
template <typename INTERFACE>
IRemoteProxy<INTERFACE>::IRemoteProxy(const sptr<IRemoteObject> &object) : PeerHolder(object)
{
}
template <typename INTERFACE> sptr<IRemoteObject> IRemoteProxy<INTERFACE>::AsObject()
{
return Remote();
}
} // namespace OHOS
#endif // OHOS_IPC_IREMOTE_PROXY_H

View File

@ -0,0 +1,44 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_IREMOTE_STUB_H
#define OHOS_IPC_IREMOTE_STUB_H
#include <string>
#include "iremote_broker.h"
#include "ipc_object_stub.h"
namespace OHOS {
template <typename INTERFACE> class IRemoteStub : public IPCObjectStub, public INTERFACE {
public:
IRemoteStub();
virtual ~IRemoteStub() = default;
sptr<IRemoteObject> AsObject() override;
sptr<IRemoteBroker> AsInterface() override;
};
template <typename INTERFACE> IRemoteStub<INTERFACE>::IRemoteStub() : IPCObjectStub(INTERFACE::GetDescriptor()) {}
template <typename INTERFACE> sptr<IRemoteBroker> IRemoteStub<INTERFACE>::AsInterface()
{
return this;
}
template <typename INTERFACE> sptr<IRemoteObject> IRemoteStub<INTERFACE>::AsObject()
{
return this;
}
} // namespace OHOS
#endif // OHOS_IPC_IREMOTE_STUB_H

View File

@ -0,0 +1,26 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_JNI_HELP_H
#define OHOS_IPC_JNI_HELP_H
#include <jni.h>
#include <refbase.h>
#include <iremote_object.h>
namespace OHOS {
jobject JNIHelperGetJavaRemoteObject(JNIEnv *env, const sptr<IRemoteObject> &target);
} // namespace OHOS
#endif // OHOS_IPC_JNI_HELP_H

View File

@ -0,0 +1,43 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_MESSAGE_OPTION_H
#define OHOS_IPC_MESSAGE_OPTION_H
#include <memory>
namespace OHOS {
class MessageOption {
public:
enum {
TF_SYNC = 0x00,
TF_ASYNC = 0x01,
TF_STATUS_CODE = 0x08,
TF_ACCEPT_FDS = 0x10,
TF_WAIT_TIME = 0x4,
};
MessageOption(int flags = TF_SYNC, int waitTime = TF_WAIT_TIME);
~MessageOption() = default;
void SetFlags(int flags);
int GetFlags() const;
void SetWaitTime(int waitTime);
int GetWaitTime() const;
private:
uint32_t flags_;
int waitTime_;
};
using MessageOptionPtr = std::shared_ptr<MessageOption>;
} // namespace OHOS
#endif // OHOS_IPC_MESSAGE_OPTION_H

View File

@ -0,0 +1,67 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_MESSAGE_PARCEL_H
#define OHOS_IPC_MESSAGE_PARCEL_H
#include <string>
#include "parcel.h"
#include "refbase.h"
#include <ashmem.h>
namespace OHOS {
class IRemoteObject;
class MessageParcel : public Parcel {
public:
MessageParcel();
~MessageParcel();
explicit MessageParcel(Allocator *allocator);
bool WriteRemoteObject(const sptr<IRemoteObject> &object);
sptr<IRemoteObject> ReadRemoteObject();
bool WriteFileDescriptor(int fd);
int ReadFileDescriptor();
bool ContainFileDescriptors() const;
bool WriteInterfaceToken(std::u16string name);
std::u16string ReadInterfaceToken();
bool WriteRawData(const void *data, size_t size);
const void *ReadRawData(size_t size);
bool RestoreRawData(std::shared_ptr<char> rawData, size_t size);
const void *GetRawData() const;
size_t GetRawDataSize() const;
size_t GetRawDataCapacity() const;
void WriteNoException();
int32_t ReadException();
bool WriteAshmem(sptr<Ashmem> ashmem);
sptr<Ashmem> ReadAshmem();
void ClearFileDescriptor();
void SetClearFdFlag()
{
needCloseFd_ = true;
};
private:
static constexpr size_t MAX_RAWDATA_SIZE = 128 * 1024 * 1024; // 128M
static constexpr size_t MIN_RAWDATA_SIZE = 32 * 1024; // 32k
bool needCloseFd_ = false;
std::vector<sptr<Parcelable>> holders_;
int writeRawDataFd_;
int readRawDataFd_;
void *kernelMappedWrite_;
void *kernelMappedRead_;
std::shared_ptr<char> rawData_;
size_t rawDataSize_;
};
} // namespace OHOS
#endif // OHOS_IPC_MESSAGE_PARCEL_H

View File

@ -0,0 +1,34 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_PEER_HOLDER_H
#define OHOS_IPC_PEER_HOLDER_H
#include "iremote_object.h"
namespace OHOS {
class PeerHolder {
protected:
PeerHolder(const sptr<IRemoteObject> &object);
~PeerHolder() = default;
sptr<IRemoteObject> Remote();
private:
const sptr<IRemoteObject> remoteObject_;
};
} // namespace OHOS
#endif // OHOS_IPC_PEER_HOLDER_H

View File

@ -0,0 +1,58 @@
# Copyright (C) 2021 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//build/ohos.gni")
SUBSYSTEM_DIR = "//foundation/communication/ipc"
IPC_CORE_ROOT = "$SUBSYSTEM_DIR/ipc/native"
config("libipc_single_private_config") {
cflags_cc = [
"-DCONFIG_IPC_SINGLE",
"-O2",
]
}
ohos_shared_library("ipc_single") {
include_dirs = [ "$SUBSYSTEM_DIR/utils/include" ]
sources = [
"$IPC_CORE_ROOT/src/core/source/ipc_file_descriptor.cpp",
"$IPC_CORE_ROOT/src/core/source/ipc_object_proxy.cpp",
"$IPC_CORE_ROOT/src/core/source/ipc_object_stub.cpp",
"$IPC_CORE_ROOT/src/core/source/ipc_process_skeleton.cpp",
"$IPC_CORE_ROOT/src/core/source/ipc_skeleton.cpp",
"$IPC_CORE_ROOT/src/core/source/ipc_thread_pool.cpp",
"$IPC_CORE_ROOT/src/core/source/ipc_thread_skeleton.cpp",
"$IPC_CORE_ROOT/src/core/source/ipc_workthread.cpp",
"$IPC_CORE_ROOT/src/core/source/iremote_broker.cpp",
"$IPC_CORE_ROOT/src/core/source/iremote_object.cpp",
"$IPC_CORE_ROOT/src/core/source/message_option.cpp",
"$IPC_CORE_ROOT/src/core/source/message_parcel.cpp",
"$IPC_CORE_ROOT/src/core/source/peer_holder.cpp",
"$IPC_CORE_ROOT/src/mock/source/binder_connector.cpp",
"$IPC_CORE_ROOT/src/mock/source/binder_debug.cpp",
"$IPC_CORE_ROOT/src/mock/source/binder_invoker.cpp",
"$IPC_CORE_ROOT/src/mock/source/invoker_factory.cpp",
"$IPC_CORE_ROOT/src/mock/source/invoker_rawdata.cpp",
]
configs = [
"$SUBSYSTEM_DIR:ipc_util_config",
":libipc_single_private_config",
]
public_configs = [ "$SUBSYSTEM_DIR:ipc_util_config" ]
deps = [ "//utils/native/base:utils" ]
external_deps = [ "hiviewdfx_hilog_native:libhilog" ]
subsystem_name = "communication"
part_name = "ipc"
}

View File

@ -0,0 +1,66 @@
# Copyright (C) 2021 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//build/ohos.gni")
SUBSYSTEM_DIR = "//foundation/communication/ipc"
DBINDER_ROOT = "$SUBSYSTEM_DIR/services/dbinder"
config("libdbinder_config") {
visibility = [ ":*" ]
cflags = []
if (target_cpu == "arm") {
cflags = [ "-DBINDER_IPC_32BIT" ]
}
if (is_standard_system) {
cflags += [ "-DCONFIG_STANDARD_SYSTEM" ]
}
include_dirs = [
"//utils/native/base/include",
"$SUBSYSTEM_DIR/interfaces/innerkits/ipc_core/include",
"$SUBSYSTEM_DIR/interfaces/innerkits/libdbinder/include",
"$DBINDER_ROOT/dbinder_service/include",
]
}
config("libdbinder_private_config") {
visibility = [ ":*" ]
cflags_cc = [
"-DLOG_TAG=\"libdbinder\"",
"-O2",
]
}
ohos_shared_library("libdbinder") {
include_dirs = [ "$SUBSYSTEM_DIR/utils/include" ]
sources = [
"$DBINDER_ROOT/dbinder_service/src/dbinder_death_recipient.cpp",
"$DBINDER_ROOT/dbinder_service/src/dbinder_sa_death_recipient.cpp",
"$DBINDER_ROOT/dbinder_service/src/dbinder_service.cpp",
"$DBINDER_ROOT/dbinder_service/src/dbinder_service_stub.cpp",
"$DBINDER_ROOT/dbinder_service/src/socket/dbinder_remote_listener.cpp",
]
public_configs = [ ":libdbinder_config" ]
configs = [ ":libdbinder_private_config" ]
deps = [
"$SUBSYSTEM_DIR/interfaces/innerkits/ipc_core:ipc_core",
"//utils/native/base:utils",
]
external_deps = [
"dsoftbus_standard:softbus_client",
"hiviewdfx_hilog_native:libhilog",
"samgr_L2:samgr_proxy",
]
subsystem_name = "communication"
part_name = "ipc"
}

View File

@ -0,0 +1,194 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_SERVICES_DBINDER_DBINDER_SERVICE_H
#define OHOS_IPC_SERVICES_DBINDER_DBINDER_SERVICE_H
#include <string>
#include <map>
#include <mutex>
#include <shared_mutex>
#include <memory>
#include <list>
#include <thread>
#include "ipc_object_proxy.h"
#include "ipc_object_stub.h"
#include "dbinder_service_stub.h"
namespace OHOS {
class DBinderRemoteListener;
constexpr int DEVICEID_LENGTH = 64;
constexpr int SERVICENAME_LENGTH = 200;
constexpr int VERSION_NUM = 1;
constexpr int ENCRYPT_HEAD_LEN = 28;
constexpr int ENCRYPT_LENGTH = 4;
struct DeviceIdInfo {
uint16_t afType;
uint16_t reserved;
char fromDeviceId[DEVICEID_LENGTH + 1];
char toDeviceId[DEVICEID_LENGTH + 1];
};
struct DHandleEntryHead {
uint32_t len;
uint32_t version;
};
struct DHandleEntryTxRx {
struct DHandleEntryHead head;
uint32_t transType;
uint32_t dBinderCode;
uint16_t fromPort;
uint16_t toPort;
uint64_t stubIndex;
uint32_t seqNumber;
binder_uintptr_t binderObject;
struct DeviceIdInfo deviceIdInfo;
binder_uintptr_t stub;
uint16_t serviceNameLength;
char serviceName[SERVICENAME_LENGTH + 1];
uint32_t pid;
uint32_t uid;
};
struct SessionInfo {
uint32_t type;
uint16_t toPort;
uint16_t fromPort;
uint64_t stubIndex;
uint32_t socketFd;
std::string serviceName;
struct DeviceIdInfo deviceIdInfo;
};
enum DBinderCode {
MESSAGE_AS_INVOKER = 1,
MESSAGE_AS_REPLY = 2,
MESSAGE_AS_OBITUARY = 3,
};
enum AfType {
IPV4_TYPE = 1,
IPV6_TYPE = 2,
DATABBUS_TYPE = 3,
};
struct ThreadLockInfo {
std::mutex mutex;
std::condition_variable condition;
bool ready = false;
};
class DBinderService : public virtual RefBase {
public:
DBinderService();
virtual ~DBinderService();
public:
static sptr<DBinderService> GetInstance();
bool StartDBinderService();
sptr<DBinderServiceStub> MakeRemoteBinder(const std::u16string &serviceName,
const std::string &deviceID, binder_uintptr_t binderObject, uint64_t pid = 0);
bool RegisterRemoteProxy(std::u16string serviceName, sptr<IRemoteObject> binderObject);
bool OnRemoteMessageTask(const struct DHandleEntryTxRx *message);
std::shared_ptr<struct SessionInfo> QuerySessionObject(binder_uintptr_t stub);
bool DetachDeathRecipient(sptr<IRemoteObject> object);
bool AttachDeathRecipient(sptr<IRemoteObject> object, sptr<IRemoteObject::DeathRecipient> deathRecipient);
sptr<IRemoteObject::DeathRecipient> QueryDeathRecipient(sptr<IRemoteObject> object);
bool DetachCallbackProxy(sptr<IRemoteObject> object);
bool AttachCallbackProxy(sptr<IRemoteObject> object, DBinderServiceStub *dbStub);
int32_t NoticeServiceDie(const std::u16string &serviceName, const std::string &deviceID);
int32_t NoticeDeviceDie(const std::string &deviceID);
bool DetachBusNameObject(IPCObjectProxy *proxy);
std::string CreateDatabusName(int uid, int pid);
bool DetachProxyObject(binder_uintptr_t binderObject);
private:
static std::shared_ptr<DBinderRemoteListener> GetRemoteListener();
static bool StartRemoteListener();
static void StopRemoteListener();
static std::string ConvertToSecureDeviceID(const std::string &deviceID);
std::u16string GetRegisterService(binder_uintptr_t binderObject);
bool InvokerRemoteDBinder(const sptr<DBinderServiceStub> stub, uint32_t seqNumber);
bool OnRemoteReplyMessage(const struct DHandleEntryTxRx *replyMessage);
void MakeSessionByReplyMessage(const struct DHandleEntryTxRx *replyMessage);
bool OnRemoteInvokerMessage(const struct DHandleEntryTxRx *message);
void WakeupThreadByStub(uint32_t seqNumber);
void DetachThreadLockInfo(uint32_t seqNumber);
bool AttachThreadLockInfo(uint32_t seqNumber, std::shared_ptr<struct ThreadLockInfo> object);
std::shared_ptr<struct ThreadLockInfo> QueryThreadLockInfo(uint32_t seqNumber);
bool AttachProxyObject(sptr<IRemoteObject> object, binder_uintptr_t binderObject);
sptr<IRemoteObject> QueryProxyObject(binder_uintptr_t binderObject);
bool DetachSessionObject(binder_uintptr_t stub);
bool AttachSessionObject(std::shared_ptr<struct SessionInfo> object, binder_uintptr_t stub);
sptr<IRemoteObject> FindOrNewProxy(binder_uintptr_t binderObject);
bool SendEntryToRemote(const sptr<DBinderServiceStub> stub, uint32_t seqNumber);
uint16_t AllocFreeSocketPort();
std::string GetLocalDeviceID();
bool CheckBinderObject(const sptr<DBinderServiceStub> &stub, binder_uintptr_t binderObject);
bool HasDBinderStub(binder_uintptr_t binderObject);
bool IsSameStubObject(const sptr<DBinderServiceStub> &stub, const std::u16string &service,
const std::string &device);
sptr<DBinderServiceStub> FindDBinderStub(const std::u16string &service, const std::string &device);
bool DeleteDBinderStub(const std::u16string &service, const std::string &device);
sptr<DBinderServiceStub> FindOrNewDBinderStub(const std::u16string &service,
const std::string &device, binder_uintptr_t binderObject);
void ProcessCallbackProxy(sptr<DBinderServiceStub> dbStub);
bool NoticeCallbackProxy(sptr<DBinderServiceStub> dbStub);
std::list<std::u16string> FindServicesByDeviceID(const std::string &deviceID);
int32_t NoticeServiceDieInner(const std::u16string &serviceName, const std::string &deviceID);
uint32_t GetRemoteTransType();
bool OnRemoteInvokerDataBusMessage(IPCObjectProxy *proxy, struct DHandleEntryTxRx *replyMessage,
std::string &remoteDeviceId, int pid, int uid);
bool IsDeviceIdIllegal(const std::string &deviceID);
bool AttachBusNameObject(IPCObjectProxy *proxy, const std::string &name);
std::string QueryBusNameObject(IPCObjectProxy *proxy);
std::string GetDatabusNameByProxy(IPCObjectProxy *proxy);
uint32_t GetSeqNumber();
private:
DISALLOW_COPY_AND_MOVE(DBinderService);
static std::mutex instanceMutex_;
static constexpr int WAIT_FOR_REPLY_MAX_SEC = 4;
static constexpr int RETRY_TIMES = 2;
static std::shared_ptr<DBinderRemoteListener> remoteListener_;
static bool mainThreadCreated_;
static sptr<DBinderService> instance_;
std::shared_mutex remoteBinderMutex_;
std::shared_mutex busNameMutex_;
std::shared_mutex proxyMutex_;
std::shared_mutex deathRecipientMutex_;
std::shared_mutex sessionMutex_;
std::mutex handleEntryMutex_;
std::mutex threadLockMutex_;
std::mutex callbackProxyMutex_;
std::mutex deathNotificationMutex_;
uint32_t seqNumber_ = 0; /* indicate make remote binder message sequence number, and can be overflow */
std::list<sptr<DBinderServiceStub>> DBinderStubRegisted_;
std::map<std::u16string, binder_uintptr_t> mapRemoteBinderObjects_;
std::map<uint32_t, std::shared_ptr<struct ThreadLockInfo>> threadLockInfo_;
std::map<int, sptr<IRemoteObject>> proxyObject_;
std::map<binder_uintptr_t, std::shared_ptr<struct SessionInfo>> sessionObject_;
std::map<sptr<IRemoteObject>, DBinderServiceStub *> noticeProxy_;
std::map<sptr<IRemoteObject>, sptr<IRemoteObject::DeathRecipient>> deathRecipients_;
std::map<IPCObjectProxy *, std::string> busNameObject_;
};
} // namespace OHOS
#endif // OHOS_IPC_SERVICES_DBINDER_DBINDER_SERVICE_H

View File

@ -0,0 +1,51 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_SERVICES_DBINDER_DBINDER_STUB_H
#define OHOS_IPC_SERVICES_DBINDER_DBINDER_STUB_H
#include <string>
#include <parcel.h>
#include "ipc_object_stub.h"
namespace OHOS {
#ifdef BINDER_IPC_32BIT
typedef unsigned int binder_uintptr_t;
#else
typedef unsigned long long binder_uintptr_t;
#endif
class DBinderServiceStub : public IPCObjectStub {
public:
explicit DBinderServiceStub(const std::string& serviceName, const std::string& deviceID,
binder_uintptr_t binderObject);
~DBinderServiceStub();
int32_t ProcessProto(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override;
int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override;
const std::string& GetServiceName();
const std::string& GetDeviceID();
binder_uintptr_t GetBinderObject() const;
private:
const std::string serviceName_;
const std::string deviceID_;
binder_uintptr_t binderObject_;
int32_t ProcessDeathRecipient(MessageParcel &data, MessageParcel &reply);
int32_t AddDbinderDeathRecipient(MessageParcel &data, MessageParcel &reply);
int32_t RemoveDbinderDeathRecipient(MessageParcel &data, MessageParcel &reply);
};
} // namespace OHOS
#endif // OHOS_IPC_SERVICES_DBINDER_DBINDER_STUB_H

View File

@ -0,0 +1,76 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_BUFFER_OBJECT_H
#define OHOS_IPC_BUFFER_OBJECT_H
#include <pthread.h>
#include <mutex>
#include <string>
#include <cstdint>
#include <sys/types.h>
#include "nocopyable.h"
namespace OHOS {
constexpr int SOCKET_DEFAULT_BUFF_SIZE = 4 * 1024;
constexpr int SOCKET_MAX_BUFF_SIZE = 1024 * 1024;
constexpr int SOCKET_BUFF_RESERVED_SIZE = 256;
constexpr size_t MAX_RAWDATA_SIZE = 128 * 1024 * 1024; // 128M
constexpr uint32_t SOCKET_BUFF_SIZE_USER_S = 4 * 1024;
constexpr uint32_t SOCKET_BUFF_SIZE_USER_M = 16 * 1024;
constexpr uint32_t SOCKET_BUFF_SIZE_USER_L = 64 * 1024;
constexpr uint32_t SOCKET_BUFF_SIZE_USER_HUGE = 1024 * 1024;
class BufferObject {
public:
explicit BufferObject();
~BufferObject();
void UpdateReceiveBuffer();
void UpdateSendBuffer();
char *GetSendBufferAndLock(uint32_t size);
char *GetReceiveBufferAndLock(uint32_t size);
void ReleaseSendBufferLock();
void ReleaseReceiveBufferLock();
ssize_t GetReceiveBufferWriteCursor() const;
void SetReceiveBufferWriteCursor(ssize_t newWriteCursor);
ssize_t GetReceiveBufferReadCursor() const;
void SetReceiveBufferReadCursor(ssize_t newReadCursor);
ssize_t GetSendBufferWriteCursor() const;
void SetSendBufferWriteCursor(ssize_t newWriteCursor);
ssize_t GetSendBufferReadCursor() const;
void SetSendBufferReadCursor(ssize_t newReadCursor);
uint32_t GetNeedBufferSize(uint32_t size) const;
uint32_t GetSendBufferSize() const;
uint32_t GetRecvBufferSize() const;
private:
DISALLOW_COPY_AND_MOVE(BufferObject);
ssize_t recvBufferCursorW_ = 0;
ssize_t recvBufferCursorR_ = 0;
ssize_t sendBufferCursorW_ = 0;
ssize_t sendBufferCursorR_ = 0;
char *receiveBuffer_ = nullptr;
char *sendBuffer_ = nullptr;
std::mutex sendMutex_;
std::mutex recvMutex_;
uint32_t sendBuffSize_ = 0;
uint32_t recvBuffSize_ = 0;
};
} // namespace OHOS
#endif // OHOS_IPC_BUFFER_OBJECT_H

View File

@ -0,0 +1,39 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_COMMAUTHINFO_H
#define OHOS_IPC_COMMAUTHINFO_H
#include "iremote_object.h"
#include "ipc_object_stub.h"
namespace OHOS {
class CommAuthInfo {
public:
CommAuthInfo(IRemoteObject *stub, int pid, int uid, const std::string &deviceId);
virtual ~CommAuthInfo();
const IRemoteObject *GetStubObject() const;
int GetRemotePid() const;
int GetRemoteUid() const;
std::string GetRemoteDeviceId() const;
private:
IRemoteObject *stub_;
int remotePid_;
int remoteUid_;
std::string deviceId_;
};
} // namespace OHOS
#endif // OHOS_IPC_COMMAUTHINFO_H

View File

@ -0,0 +1,42 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_DBINDER_DATABUS_SESSION_CALLBACK_H
#define OHOS_IPC_DBINDER_DATABUS_SESSION_CALLBACK_H
#include "ISessionListener.h"
using Communication::SoftBus::ISessionListener;
using Communication::SoftBus::Session;
namespace OHOS {
static const std::string DBINDER_SERVER_PKG_NAME = "DBinderBus";
class DatabusSessionCallback : public ISessionListener {
public:
explicit DatabusSessionCallback() = default;
~DatabusSessionCallback() = default;
int OnSessionOpened(std::shared_ptr<Session> session) override;
void OnSessionClosed(std::shared_ptr<Session> session) override;
void OnMessageReceived(std::shared_ptr<Session> session, const char* data, ssize_t len) override {}
void OnBytesReceived(std::shared_ptr<Session> session, const char *data, ssize_t len) override;
bool OnDataAvailable(std::shared_ptr<Session> session, uint32_t status) override
{
return true;
};
};
} // namespace OHOS
#endif // OHOS_IPC_DBINDER_DATABUS_SESSION_CALLBACK_H

View File

@ -0,0 +1,144 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_DBINDER_ERROR_CODE_H
#define OHOS_IPC_DBINDER_ERROR_CODE_H
#include<string>
#ifndef BUILD_PUBLIC_VERSION
#include "hiview.h"
#include "hievent.h"
#endif
namespace OHOS {
class DbinderErrorCode {
public:
static const int SYSTEM_ENVIRONMENT_ERROR = 950000601;
static const int NETWORK_ERROR = 950000602;
static const int SKELETON_ERROR = 950000603;
static const int DBINDER_SERVICE_ERROR = 950000604;
static const int TRANSMISSION_ERROR = 950000605;
static const int COMMON_DRIVER_ERROR = 950000606;
static const int KERNEL_DRIVER_ERROR = 950000607;
static const int SOCKET_DRIVER_ERROR = 950000608;
inline static const std::string ERROR_TYPE = "ErrType";
inline static const std::string ERROR_CODE = "ErrCode";
// 601
enum SystemEnvironmentError {
CREATE_EPOLL = 1,
BIND_EPOLL,
REMOVE_EPOLL,
};
// 602
enum NetworkError {
WRONG_DEVICE_ID = 1,
WRONG_SUBSCRIPTION,
};
// 603
enum SkeletonError {
WRONG_KERNEL_DRIVER = 1,
WRONG_SOCKET_DRIVER,
WRONG_TYPE_PROXY,
UPDATE_SESSION_FAILURE,
RELEASE_FD_FAILURE,
RELEASE_SESSION_FAILURE,
UNKNOWN_CMD,
};
// 604
enum DbinderServiceError {
START_DBS_FAILURE = 1,
CLOSE_DBS_FAILURE,
WRONG_INPUT_PARAMETER,
LOCAL_OBJECT_SEND_MESSAGE_FAILURE,
RECEIVE_MESSAGE_FAILURE,
INVOKE_LISTENER_FAILURE,
ALLOCATE_INDEX_FAILURE,
REMOTE_OBJECT_SEND_MESSAGE_FAILURE,
INITIATE_DATABUS_FAILURE,
DATABUS_SEND_FAILURE,
DATABUS_RECEIVE_FAILURE,
CLOSE_DATABUS_FAILURE,
OPERATE_MESSAGE_FAILURE,
};
// 605
enum TransmissionError {
RECEIVE_PKT_LOSS = 1,
SEND_PKT_LOSS,
HANDLE_OVERMUCH_THREADS,
OVERSIZE_PKT,
};
// 606
enum CommonDriverType {
IPC_DRIVER = 1,
RPC_DRIVER,
};
enum CommonDriverError {
TRANSACT_DATA_FAILURE = 1,
HANDLE_RECV_DATA_FAILURE,
SET_DEATH_RECIPIENT_FAILURE,
REMOVE_DEATH_RECIPIENT_FAILURE,
HANDLE_DEATH_RECIPIENT_FAILURE,
FLATTEN_OBJECT_FAILURE,
UNFLATTEN_OBJECT_FAILURE,
};
// 607
enum KernelDriverError {
INITIATE_IPC_DRIVER_FAILURE = 1,
OPEN_IPC_DRIVER_FAILURE,
WRITE_IPC_DRIVER_FAILURE,
};
// 608
enum SocketDriverError {
OPEN_RPC_DRIVER_FAILURE = 1,
CONNECT_RPC_REMOTE_FAILURE,
SEND_RPC_DATA_FAILURE,
RECEIVE_RPC_DATA_FAILURE,
INVOKE_RPC_THREAD_FAILURE,
};
};
#ifndef BUILD_PUBLIC_VERSION
inline void ReportEvent(int code, const std::string &type, int num)
{
if (code == 0 || type.empty() || num == 0) {
return;
}
HiEvent hiEvent(code);
hiEvent.PutInt(type, num);
HiView::Report(hiEvent);
}
inline void ReportDriverEvent(int code, const std::string &type, int num, const std::string &errorType, int errorNum)
{
if (code == 0 || type.empty() || num == 0 || errorType.empty() || errorNum == 0) {
return;
}
HiEvent hiEvent(code);
hiEvent.PutInt(type, num);
hiEvent.PutInt(errorType, errorNum);
HiView::Report(hiEvent);
}
#endif
} // namespace OHOS
#endif // OHOS_IPC_DBINDER_ERROR_CODE_H

View File

@ -0,0 +1,70 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_DBINDER_SESSION_OBJECT_H
#define OHOS_IPC_DBINDER_SESSION_OBJECT_H
#include <string>
#include <mutex>
#include "nocopyable.h"
#include "buffer_object.h"
#include "Session.h"
#include "ISessionService.h"
using Communication::SoftBus::ISessionService;
using Communication::SoftBus::Session;
namespace OHOS {
constexpr int DEVICEID_LENGTH = 64;
constexpr int SERVICENAME_LENGTH = 200;
/* struct FlatDBinderSession is for flat DatabusSessionObject to transfer to another device */
struct FlatDBinderSession {
uint64_t stubIndex;
uint16_t deviceIdLength;
uint16_t serviceNameLength;
char deviceId[DEVICEID_LENGTH + 1];
char serviceName[SERVICENAME_LENGTH + 1];
};
class DBinderSessionObject {
public:
static uint32_t GetFlatSessionLen();
explicit DBinderSessionObject(std::shared_ptr<Session> session, const std::string &serviceName,
const std::string &serverDeviceId);
~DBinderSessionObject();
void SetBusSession(std::shared_ptr<Session> session);
void SetServiceName(const std::string &serviceName);
void SetDeviceId(const std::string &serverDeviceId);
std::shared_ptr<BufferObject> GetSessionBuff();
std::shared_ptr<Session> GetBusSession() const;
std::string GetServiceName() const;
std::string GetDeviceId() const;
uint32_t GetSessionHandle() const;
private:
DISALLOW_COPY_AND_MOVE(DBinderSessionObject);
/* Session is defined from softBus session, when import socket driver, we need use interface abstraction */
std::shared_ptr<Session> session_;
std::mutex buffMutex_;
std::shared_ptr<BufferObject> buff_;
std::string serviceName_;
std::string serverDeviceId_;
};
} // namespace OHOS
#endif // OHOS_IPC_DBINDER_SESSION_OBJECT_H

View File

@ -0,0 +1,62 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_IPC_DEBUG_H
#define OHOS_IPC_IPC_DEBUG_H
#include <map>
#include <string>
#include "hilog/log.h"
#include "string_ex.h"
namespace OHOS {
// if need enable ipc debug log, use '#define CONFIG_IPC_DEBUG'
#define ZLOGW(TAG, ...) (void)HiviewDFX::HiLog::Warn(TAG, __VA_ARGS__)
#define ZLOGE(TAG, ...) (void)HiviewDFX::HiLog::Error(TAG, __VA_ARGS__)
#if (defined CONFIG_IPC_DEBUG)
#define ZLOGI(TAG, ...) (void)HiviewDFX::HiLog::Info(TAG, __VA_ARGS__)
#else
#define ZLOGI(TAG, ...)
#endif /* CONFIG_IPC_DEBUG */
using ErrorMap = std::map<uint32_t, std::string>;
class ErrorBase {
public:
virtual ~ErrorBase() = default;
inline const std::string &GetErrorDesc(uint32_t error);
virtual ErrorMap &GetErrorMap() = 0;
};
inline const std::string &ErrorBase::GetErrorDesc(uint32_t error)
{
static const std::string unknowCommand = "UNKNOWN COMMAND";
ErrorMap::iterator found = GetErrorMap().find(error);
if (found == GetErrorMap().end()) {
return unknowCommand;
} else {
return found->second;
}
}
class IPCError : public ErrorBase {
public:
IPCError() = default;
~IPCError() = default;
static const std::string &ToString(int value);
virtual ErrorMap &GetErrorMap() override;
};
} // namespace OHOS
#endif // OHOS_IPC_IPC_DEBUG_H

View File

@ -0,0 +1,258 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_IPC_PROCESS_SKELETON_H
#define OHOS_IPC_IPC_PROCESS_SKELETON_H
#include <map>
#include <list>
#include <shared_mutex>
#include "refbase.h"
#include "iremote_object.h"
#include "ipc_thread_pool.h"
#include "nocopyable.h"
#include "ipc_object_proxy.h"
#include "ipc_object_stub.h"
#include "invoker_rawdata.h"
#include "sys_binder.h"
#ifndef CONFIG_IPC_SINGLE
#include "dbinder_session_object.h"
#include "Session.h"
#include "ISessionService.h"
#include "stub_refcount_object.h"
#include "comm_auth_info.h"
using Communication::SoftBus::ISessionService;
using Communication::SoftBus::Session;
#endif
namespace OHOS {
#ifdef CONFIG_IPC_SINGLE
namespace IPC_SINGLE {
#endif
#ifndef CONFIG_IPC_SINGLE
struct SocketThreadLockInfo {
std::mutex mutex;
std::condition_variable condition;
bool ready = false;
};
struct ThreadMessageInfo {
std::thread::id threadId;
uint32_t flags;
binder_size_t bufferSize;
binder_size_t offsetsSize;
binder_uintptr_t offsets;
uint32_t socketId;
void *buffer;
};
struct ThreadProcessInfo {
uint32_t listenFd;
uint32_t packageSize;
std::shared_ptr<char> buffer;
};
#endif
class IPCProcessSkeleton : public virtual RefBase {
public:
enum {
LISTEN_THREAD_CREATE_OK, // Invoker family.
LISTEN_THREAD_CREATE_FAILED,
LISTEN_THREAD_CREATED_ALREADY,
LISTEN_THREAD_CREATED_TIMEOUT
};
~IPCProcessSkeleton() override;
static IPCProcessSkeleton *GetCurrent();
#ifndef CONFIG_IPC_SINGLE
static uint32_t ConvertChannelID2Int(int64_t databusChannelId);
#endif
bool SetMaxWorkThread(int maxThreadNum);
sptr<IRemoteObject> GetRegistryObject();
bool SpawnThread(int policy = IPCWorkThread::SPAWN_PASSIVE, int proto = IRemoteObject::IF_PROT_DEFAULT);
std::u16string MakeHandleDescriptor(int handle);
IRemoteObject *FindOrNewObject(int handle);
bool IsContainsObject(IRemoteObject *object);
IRemoteObject *QueryObject(const std::u16string &descriptor);
IRemoteObject *QueryObjectInner(const std::u16string &descriptor);
bool AttachObject(IRemoteObject *object);
bool AttachObjectInner(IRemoteObject *object);
bool DetachObject(IRemoteObject *object);
bool OnThreadTerminated(const std::string &threadName);
bool SetRegistryObject(sptr<IRemoteObject> &object);
bool AttachRawData(uint32_t fd, std::shared_ptr<InvokerRawData> rawData);
bool DetachRawData(uint32_t fd);
std::shared_ptr<InvokerRawData> QueryRawData(uint32_t fd);
#ifndef CONFIG_IPC_SINGLE
sptr<IRemoteObject> GetSAMgrObject();
bool ProxyDetachDBinderSession(uint32_t handle);
bool ProxyAttachDBinderSession(uint32_t handle, std::shared_ptr<DBinderSessionObject> object);
std::shared_ptr<DBinderSessionObject> ProxyQueryDBinderSession(uint32_t handle);
bool QueryProxyBySessionHandle(uint32_t handle, std::vector<uint32_t> &proxyHandle);
std::shared_ptr<DBinderSessionObject> QuerySessionByInfo(const std::string &name, const std::string &deviceId);
bool DetachThreadLockInfo(const std::thread::id &threadId);
bool AttachThreadLockInfo(std::shared_ptr<SocketThreadLockInfo> object, const std::thread::id &threadId);
std::shared_ptr<SocketThreadLockInfo> QueryThreadLockInfo(const std::thread::id &threadId);
void EraseThreadBySeqNumber(uint64_t seqNumber);
bool AddThreadBySeqNumber(uint64_t seqNumber, std::shared_ptr<ThreadMessageInfo> messageInfo);
std::shared_ptr<ThreadMessageInfo> QueryThreadBySeqNumber(uint64_t seqNumber);
bool AddSendThreadInWait(uint64_t seqNumber, std::shared_ptr<ThreadMessageInfo> messageInfo, int userWaitTime);
std::thread::id GetIdleSocketThread();
int GetSocketIdleThreadNum() const;
int GetSocketTotalThreadNum() const;
int PopSocketIdFromThread(const std::thread::id &threadId);
void WakeUpSocketIOThread(const std::thread::id &threadID);
void WakeUpThreadBySeqNumber(uint64_t seqNumber, uint32_t handle);
IRemoteObject *QueryStubByIndex(uint64_t stubIndex);
uint64_t AddStubByIndex(IRemoteObject *stubObject);
uint64_t GetSeqNumber();
uint32_t GetDBinderIdleHandle(uint64_t stubIndex);
std::shared_ptr<SocketThreadLockInfo> GetListenThreadLockInfo();
std::string GetLocalDeviceID();
bool AttachCallbackStub(IPCObjectProxy *ipcProxy, sptr<IPCObjectStub> callbackStub);
bool DetachCallbackStub(IPCObjectStub *callbackStub);
sptr<IPCObjectStub> QueryCallbackStub(IPCObjectProxy *ipcProxy);
IPCObjectProxy *QueryCallbackProxy(IPCObjectStub *callbackStub);
bool DetachCallbackStubByProxy(IPCObjectProxy *ipcProxy);
uint32_t QueryHandleByDatabusSession(const std::string &name, const std::string &deviceId, uint64_t stubIndex);
bool StubDetachDBinderSession(uint32_t handle);
std::shared_ptr<DBinderSessionObject> StubQueryDBinderSession(uint32_t handle);
bool StubAttachDBinderSession(uint32_t handle, std::shared_ptr<DBinderSessionObject> object);
std::string GetDatabusName();
bool CreateSoftbusServer(const std::string &name);
bool DetachHandleToIndex(uint32_t handle);
bool AttachHandleToIndex(uint32_t handle, uint64_t stubIndex);
uint64_t QueryHandleToIndex(uint32_t handle);
uint64_t QueryHandleToIndex(std::list<uint32_t> &handleList, uint32_t &handle);
bool AttachStubRecvRefInfo(IRemoteObject *stub, int pid, const std::string &deviceId);
void DetachStubRecvRefInfo(int pid, const std::string &deviceId);
bool DetachStubRecvRefInfo(const IRemoteObject *stub, int pid, const std::string &deviceId);
void DetachStubRecvRefInfo(const IRemoteObject *stub);
std::list<IRemoteObject *> QueryStubRecvRefInfo(int pid, const std::string &deviceId);
void DetachStubRefInfo(const int pid, const std::string &deviceId);
void DetachStubRefInfo(IRemoteObject *stub, int pid, const std::string &deviceId);
bool AttachStubSendRefInfo(IRemoteObject *stub, int pid, const std::string &deviceId);
void DetachStubSendRefInfo(int pid, const std::string &deviceId);
void DetachStubSendRefInfo(IRemoteObject *stub, int pid, const std::string &deviceId);
void DetachStubSendRefInfo(IRemoteObject *stub);
bool IncStubRefTimes(IRemoteObject *stub);
bool DecStubRefTimes(IRemoteObject *stub);
bool DetachStubRefTimes(IRemoteObject *stub);
bool AttachCommAuthInfo(IRemoteObject *stub, int pid, int uid, const std::string &deviceId);
void DetachCommAuthInfo(IRemoteObject *stub, int pid, int uid, const std::string &deviceId);
void DetachCommAuthInfoByStub(IRemoteObject *stub);
bool QueryIsAuth(int pid, int uid, const std::string &deviceId);
bool AddDataThreadToIdle(const std::thread::id &threadId);
bool DeleteDataThreadFromIdle(const std::thread::id &threadId);
std::thread::id GetIdleDataThread();
void AddDataInfoToThread(const std::thread::id &threadId, std::shared_ptr<ThreadProcessInfo> processInfo);
std::shared_ptr<ThreadProcessInfo> PopDataInfoFromThread(const std::thread::id &threadId);
void WakeUpDataThread(const std::thread::id &threadID);
void AddDataThreadInWait(const std::thread::id &threadId);
bool IsSameRemoteObject(IRemoteObject *stub, int pid, int uid, const std::string &deviceId,
const std::shared_ptr<CommAuthInfo> &auth);
bool IsSameRemoteObject(int pid, int uid, const std::string &deviceId, const std::shared_ptr<CommAuthInfo> &auth);
uint64_t EraseStubIndex(IRemoteObject *stubObject);
bool DetachAppInfoToStubIndex(uint32_t pid, uint32_t uid, const std::string &deviceId, uint64_t stubIndex);
void DetachAppInfoToStubIndex(uint64_t stubIndex);
bool AttachAppInfoToStubIndex(uint32_t pid, uint32_t uid, const std::string &deviceId, uint64_t stubIndex);
bool QueryAppInfoToStubIndex(uint32_t pid, uint32_t uid, const std::string &deviceId, uint64_t stubIndex);
#endif
public:
static constexpr int DEFAULT_WORK_THREAD_NUM = 16;
static constexpr uint32_t DBINDER_HANDLE_BASE = 100000;
static constexpr uint32_t DBINDER_HANDLE_RANG = 100;
#ifndef CONFIG_IPC_SINGLE
std::shared_ptr<SocketThreadLockInfo> listenThreadReady_ = nullptr;
static constexpr int TRANS_TIME_INIT_VALUE = 1;
static constexpr int SEC_TO_MS = 1000;
#endif
private:
DISALLOW_COPY_AND_MOVE(IPCProcessSkeleton);
IPCProcessSkeleton();
static IPCProcessSkeleton *instance_;
static std::mutex procMutex_;
std::shared_mutex mutex_;
std::shared_mutex rawDataMutex_;
std::map<std::u16string, wptr<IRemoteObject>> objects_;
std::map<IRemoteObject *, bool> isContainStub_;
std::map<uint32_t, std::shared_ptr<InvokerRawData>> rawData_;
IPCWorkThreadPool *threadPool_ = nullptr;
sptr<IRemoteObject> registryObject_ = nullptr;
#ifndef CONFIG_IPC_SINGLE
std::mutex databusProcMutex_;
std::mutex sessionNameMutex_;
std::mutex seqNumberMutex_;
std::mutex transTimesMutex_;
std::mutex stubSendRefMutex_;
std::mutex idleDataMutex_;
std::mutex dataQueueMutex_;
std::mutex findThreadMutex_;
std::recursive_mutex proxyToSessionMutex_;
std::shared_mutex databusSessionMutex_;
std::shared_mutex handleToIndexMutex_;
std::shared_mutex threadLockMutex_;
std::shared_mutex callbackStubMutex_;
std::shared_mutex stubObjectsMutex_;
std::shared_mutex stubRecvRefMutex_;
std::shared_mutex appInfoToIndexMutex_;
std::shared_mutex commAuthMutex_;
std::map<uint64_t, std::shared_ptr<ThreadMessageInfo>> seqNumberToThread_;
std::map<uint64_t, IRemoteObject *> stubObjects_;
std::map<std::thread::id, std::shared_ptr<SocketThreadLockInfo>> threadLockInfo_;
std::map<uint32_t, std::shared_ptr<DBinderSessionObject>> proxyToSession_;
std::map<uint32_t, std::shared_ptr<DBinderSessionObject>> dbinderSessionObjects_;
std::map<uint32_t, uint64_t> handleToStubIndex_;
std::map<IPCObjectProxy *, sptr<IPCObjectStub>> noticeStub_;
std::map<IRemoteObject *, uint32_t> transTimes_;
std::map<std::thread::id, std::vector<std::shared_ptr<ThreadProcessInfo>>> dataInfoQueue_; // key is threadId
std::map<std::string, std::map<uint64_t, bool>> appInfoToStubIndex_;
std::list<std::thread::id> idleDataThreads_;
std::list<std::shared_ptr<StubRefCountObject>> stubRecvRefs_;
std::list<std::shared_ptr<StubRefCountObject>> stubSendRefs_;
std::list<std::shared_ptr<CommAuthInfo>> commAuth_;
uint32_t dBinderHandle_ = DBINDER_HANDLE_BASE; /* dbinder handle start at 100000 */
uint64_t seqNumber_ = 0;
std::string sessionName_ = std::string("");
uint64_t randNum_;
#endif
};
#ifdef CONFIG_IPC_SINGLE
} // namespace IPC_SINGLE
#endif
} // namespace OHOS
#endif // OHOS_IPC_IPC_PROCESS_SKELETON_H

View File

@ -0,0 +1,74 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_IPC_WORK_THREAD_POOL_H
#define OHOS_IPC_IPC_WORK_THREAD_POOL_H
#include <functional>
#include <thread>
#include <map>
#include <atomic>
#include <mutex>
#include <ipc_workthread.h>
#include "hilog/log.h"
#include "log_tags.h"
namespace OHOS {
#ifdef CONFIG_IPC_SINGLE
namespace IPC_SINGLE {
#endif
class IPCWorkThreadPool {
public:
IPCWorkThreadPool(const IPCWorkThreadPool &) = delete;
IPCWorkThreadPool(IPCWorkThreadPool &&) = delete;
~IPCWorkThreadPool();
IPCWorkThreadPool &operator = (const IPCWorkThreadPool &) = delete;
IPCWorkThreadPool &operator = (IPCWorkThreadPool &&) = delete;
bool SpawnThread(int policy = IPCWorkThread::SPAWN_PASSIVE, int proto = IRemoteObject::IF_PROT_DEFAULT);
bool RemoveThread(const std::string &threadName);
void StopAllThreads();
explicit IPCWorkThreadPool(int maxThreadNum);
int GetMaxThreadNum() const;
void UpdateMaxThreadNum(int maxThreadNum);
int GetSocketIdleThreadNum() const;
int GetSocketTotalThreadNum() const;
private:
static constexpr int PROTO_NUM = 2;
std::string MakeThreadName(int proto);
std::map<std::string, sptr<IPCWorkThread>> threads_;
std::atomic<int> threadSequence_;
int maxThreadNum_;
int idleThreadNum_;
int idleSocketThreadNum_;
std::mutex mutex_;
static constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "IPCWorkThreadPool" };
};
#ifdef CONFIG_IPC_SINGLE
} // namespace IPC_SINGLE
#endif
} // namespace OHOS
#endif // OHOS_IPC_IPC_WORK_THREAD_POOL_H

View File

@ -0,0 +1,63 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_IPC_THREAD_SKELETON_H
#define OHOS_IPC_IPC_THREAD_SKELETON_H
#include <mutex>
#include <pthread.h>
#include <unordered_map>
#include "iremote_invoker.h"
#include "binder_invoker.h"
namespace OHOS {
#ifdef CONFIG_IPC_SINGLE
namespace IPC_SINGLE {
#endif
class IPCThreadSkeleton {
public:
IPCThreadSkeleton();
~IPCThreadSkeleton();
static void TlsDestructor(void *args);
static void MakeTlsKey();
static IPCThreadSkeleton *GetCurrent();
static IRemoteInvoker *GetRemoteInvoker(int proto);
static IRemoteInvoker *GetDefaultInvoker();
static IRemoteInvoker *GetActiveInvoker();
static IRemoteInvoker *GetProxyInvoker(IRemoteObject *object);
// Joint Current thread into IPC Work Group
void JoinWorkThread(int proto);
// Quit current thread from IPC work group.
void StopWorkThread(int proto);
private:
static pthread_key_t TLSKey_;
static pthread_once_t TLSKeyOnce_;
std::unordered_map<int, IRemoteInvoker *> invokers_;
};
#ifdef CONFIG_IPC_SINGLE
} // namespace IPC_SINGLE
#endif
} // namespace OHOS
#endif // OHOS_IPC_IPC_THREAD_SKELETON_H

View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_IPC_WORK_THREAD_H
#define OHOS_IPC_IPC_WORK_THREAD_H
#include <string>
#include <thread>
#include "refbase.h"
#include "hilog/log.h"
#include "iremote_invoker.h"
#include "log_tags.h"
namespace OHOS {
#ifdef CONFIG_IPC_SINGLE
namespace IPC_SINGLE {
#endif
class IPCWorkThread : public virtual RefBase {
public:
enum {
SPAWN_PASSIVE,
SPAWN_ACTIVE,
PROCESS_PASSIVE,
PROCESS_ACTIVE
};
explicit IPCWorkThread(std::string threadName);
~IPCWorkThread();
void ThreadHandler();
void Start(int policy, int proto, std::string threadName);
void StopWorkThread();
int proto_ = IRemoteObject::IF_PROT_DEFAULT;
private:
int policy_ = SPAWN_PASSIVE;
std::thread thread_;
const std::string threadName_;
static constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "IPCWorkThread" };
};
#ifdef CONFIG_IPC_SINGLE
} // namespace IPC_SINGLE
#endif
} // namespace OHOS
#endif // OHOS_IPC_IPC_WORK_THREAD_H

View File

@ -0,0 +1,36 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_STUB_REFCOUNT_OBJECT_H
#define OHOS_IPC_STUB_REFCOUNT_OBJECT_H
#include "iremote_object.h"
namespace OHOS {
class StubRefCountObject {
public:
StubRefCountObject(IRemoteObject *stub, int remotePid, const std::string &deviceId);
virtual ~StubRefCountObject();
IRemoteObject *GetStubObject() const;
int GetRemotePid() const;
std::string GetDeviceId() const;
private:
IRemoteObject *stub_;
int remotePid_;
std::string deviceId_;
};
} // namespace OHOS
#endif // OHOS_IPC_STUB_REFCOUNT_OBJECT_H

View File

@ -0,0 +1,223 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "buffer_object.h"
#include "securec.h"
#include "sys_binder.h"
namespace OHOS {
BufferObject::BufferObject()
{
}
BufferObject::~BufferObject()
{
if (receiveBuffer_ != nullptr) {
delete[] receiveBuffer_;
receiveBuffer_ = nullptr;
}
if (sendBuffer_ != nullptr) {
delete[] sendBuffer_;
sendBuffer_ = nullptr;
}
}
/* update buffer need get mutex first */
void BufferObject::UpdateSendBuffer()
{
if (sendBufferCursorW_ <= sendBufferCursorR_) {
sendBufferCursorW_ = 0;
sendBufferCursorR_ = 0;
return;
}
/* check whether buffer size is enough, if not, move write/read cursor to head */
if (sendBuffSize_ - sendBufferCursorW_ < SOCKET_BUFF_RESERVED_SIZE) {
/* writeCursor always bigger than readCursor */
if (sendBufferCursorW_ - sendBufferCursorR_ < sendBufferCursorR_) {
auto memcpyResult = memmove_s(sendBuffer_, sendBufferCursorW_ - sendBufferCursorR_,
sendBuffer_ + sendBufferCursorR_, sendBufferCursorW_ - sendBufferCursorR_);
if (memcpyResult != EOK) {
sendBufferCursorW_ = 0; // drop data in buffer, if memmove failed
} else {
sendBufferCursorW_ = sendBufferCursorW_ - sendBufferCursorR_;
}
sendBufferCursorR_ = 0;
}
}
}
/* update buffer need get mutex first */
void BufferObject::UpdateReceiveBuffer()
{
if (recvBufferCursorW_ <= recvBufferCursorR_) {
recvBufferCursorR_ = 0;
recvBufferCursorW_ = 0;
return;
}
/* check whether buffer size is enough, if not, move write/read cursor to head */
if (recvBuffSize_ - recvBufferCursorW_ < SOCKET_BUFF_RESERVED_SIZE) {
/* writeCursor always bigger than readCursor */
if (recvBufferCursorW_ - recvBufferCursorR_ < recvBufferCursorR_) {
auto memcpyResult = memmove_s(receiveBuffer_, recvBufferCursorW_ - recvBufferCursorR_,
receiveBuffer_ + recvBufferCursorR_, recvBufferCursorW_ - recvBufferCursorR_);
if (memcpyResult != EOK) {
recvBufferCursorW_ = 0; // drop data in buffer, if memmove failed
} else {
recvBufferCursorW_ = recvBufferCursorW_ - recvBufferCursorR_;
}
recvBufferCursorR_ = 0;
}
}
}
char *BufferObject::GetSendBufferAndLock(uint32_t size)
{
uint32_t needSize = GetNeedBufferSize(size);
if (needSize == 0) {
return nullptr;
}
sendMutex_.lock();
if (needSize > sendBuffSize_) {
char *newBuffer_ = new (std::nothrow) char[needSize];
if (newBuffer_ == nullptr) {
sendMutex_.unlock();
return nullptr;
}
if ((sendBuffer_ != nullptr) && (sendBuffSize_ != 0)) {
int memcpyResult = memcpy_s(newBuffer_, needSize, sendBuffer_, sendBuffSize_);
if (memcpyResult != 0) {
delete[] newBuffer_;
sendMutex_.unlock();
return nullptr;
}
}
delete[] sendBuffer_;
sendBuffer_ = newBuffer_;
sendBuffSize_ = needSize;
}
/* attention: need unlock mutex by caller */
return sendBuffer_;
}
char *BufferObject::GetReceiveBufferAndLock(uint32_t size)
{
uint32_t needSize = GetNeedBufferSize(size);
if (needSize == 0) {
return nullptr;
}
recvMutex_.lock();
if (needSize > recvBuffSize_) {
char *newBuffer_ = new (std::nothrow) char[needSize];
if (newBuffer_ == nullptr) {
recvMutex_.unlock();
return nullptr;
}
if ((receiveBuffer_ != nullptr) && (recvBuffSize_ != 0)) {
int memcpyResult = memcpy_s(newBuffer_, needSize, receiveBuffer_, recvBuffSize_);
if (memcpyResult != 0) {
delete[] newBuffer_;
recvMutex_.unlock();
return nullptr;
}
}
delete[] receiveBuffer_;
receiveBuffer_ = newBuffer_;
recvBuffSize_ = needSize;
}
/* attention: need unlock mutex by caller */
return receiveBuffer_;
}
void BufferObject::ReleaseSendBufferLock()
{
sendMutex_.unlock();
}
void BufferObject::ReleaseReceiveBufferLock()
{
recvMutex_.unlock();
}
ssize_t BufferObject::GetReceiveBufferWriteCursor() const
{
return recvBufferCursorW_;
}
void BufferObject::SetReceiveBufferWriteCursor(ssize_t newWriteCursor)
{
recvBufferCursorW_ = newWriteCursor;
}
ssize_t BufferObject::GetReceiveBufferReadCursor() const
{
return recvBufferCursorR_;
}
void BufferObject::SetReceiveBufferReadCursor(ssize_t newReadCursor)
{
recvBufferCursorR_ = newReadCursor;
}
ssize_t BufferObject::GetSendBufferWriteCursor() const
{
return sendBufferCursorW_;
}
void BufferObject::SetSendBufferWriteCursor(ssize_t newWriteCursor)
{
sendBufferCursorW_ = newWriteCursor;
}
ssize_t BufferObject::GetSendBufferReadCursor() const
{
return sendBufferCursorR_;
}
void BufferObject::SetSendBufferReadCursor(ssize_t newReadCursor)
{
sendBufferCursorR_ = newReadCursor;
}
uint32_t BufferObject::GetNeedBufferSize(uint32_t size) const
{
if (size <= SOCKET_BUFF_SIZE_USER_S) {
return SOCKET_BUFF_SIZE_USER_S;
} else if (size <= SOCKET_BUFF_SIZE_USER_M) {
return SOCKET_BUFF_SIZE_USER_M;
} else if (size <= SOCKET_BUFF_SIZE_USER_L) {
return SOCKET_BUFF_SIZE_USER_L;
} else if (size <= SOCKET_BUFF_SIZE_USER_HUGE) {
return SOCKET_BUFF_SIZE_USER_HUGE;
} else {
return 0;
}
}
uint32_t BufferObject::GetSendBufferSize() const
{
return sendBuffSize_;
}
uint32_t BufferObject::GetRecvBufferSize() const
{
return recvBuffSize_;
}
} // namespace OHOS

View File

@ -0,0 +1,43 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "comm_auth_info.h"
namespace OHOS {
CommAuthInfo::CommAuthInfo(IRemoteObject *stub, int pid, int uid, const std::string &deviceId)
: stub_(stub), remotePid_(pid), remoteUid_(uid), deviceId_(deviceId)
{}
CommAuthInfo::~CommAuthInfo()
{
stub_ = nullptr;
}
const IRemoteObject *CommAuthInfo::GetStubObject() const
{
return stub_;
}
int CommAuthInfo::GetRemotePid() const
{
return remotePid_;
}
int CommAuthInfo::GetRemoteUid() const
{
return remoteUid_;
}
std::string CommAuthInfo::GetRemoteDeviceId() const
{
return deviceId_;
}
} // namespace OHOS

View File

@ -0,0 +1,81 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "databus_session_callback.h"
#include "ipc_thread_skeleton.h"
#include "ipc_process_skeleton.h"
#include "dbinder_databus_invoker.h"
#include "ipc_debug.h"
#include "log_tags.h"
namespace OHOS {
#ifndef TITLE
#define TITLE __PRETTY_FUNCTION__
#endif
static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_RPC, "DatabusSessionCallback" };
#define DBINDER_LOGE(fmt, args...) \
(void)OHOS::HiviewDFX::HiLog::Error(LOG_LABEL, "%{public}s %{public}d: " fmt, TITLE, __LINE__, ##args)
#define DBINDER_LOGI(fmt, args...) \
(void)OHOS::HiviewDFX::HiLog::Info(LOG_LABEL, "%{public}s %{public}d: " fmt, TITLE, __LINE__, ##args)
int DatabusSessionCallback::OnSessionOpened(std::shared_ptr<Session> session)
{
if (session->GetChannelId() < 0) {
DBINDER_LOGE("fail to open session because of wrong channel ID");
return SESSION_WRONG_FD_ERR;
}
if (!session->IsServerSide()) {
DBINDER_LOGI("active end");
return 0;
}
DBINDER_LOGI("passive end");
DBinderDatabusInvoker *invoker =
reinterpret_cast<DBinderDatabusInvoker *>(IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DATABUS));
if (invoker == nullptr) {
DBINDER_LOGE("fail to get invoker");
return SESSION_INVOKER_NULL_ERR;
}
return invoker->OnReceiveNewConnection(session) ? 0 : SESSION_UNOPEN_ERR;
}
void DatabusSessionCallback::OnSessionClosed(std::shared_ptr<Session> session)
{
DBinderDatabusInvoker *invoker =
reinterpret_cast<DBinderDatabusInvoker *>(IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DATABUS));
if (invoker == nullptr) {
DBINDER_LOGE("fail to get invoker");
return;
}
invoker->OnDatabusSessionClosed(session);
}
void DatabusSessionCallback::OnBytesReceived(std::shared_ptr<Session> session, const char *data, ssize_t len)
{
DBinderDatabusInvoker *invoker =
reinterpret_cast<DBinderDatabusInvoker *>(IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DATABUS));
if (invoker == nullptr) {
DBINDER_LOGE("fail to get invoker");
return;
}
invoker->OnMessageAvailable(session, data, len);
}
} // namespace OHOS

View File

@ -0,0 +1,95 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "dbinder_session_object.h"
#include "ipc_process_skeleton.h"
#include "ISessionService.h"
namespace OHOS {
DBinderSessionObject::DBinderSessionObject(std::shared_ptr<Session> session, const std::string &serviceName,
const std::string &serverDeviceId)
: session_(session), serviceName_(serviceName), serverDeviceId_(serverDeviceId)
{}
DBinderSessionObject::~DBinderSessionObject()
{
if (session_ != nullptr) {
std::shared_ptr<ISessionService> manager = ISessionService::GetInstance();
if (manager != nullptr) {
(void)manager->CloseSession(session_);
}
}
session_ = nullptr;
buff_ = nullptr;
}
void DBinderSessionObject::SetBusSession(std::shared_ptr<Session> session)
{
session_ = session;
}
std::shared_ptr<Session> DBinderSessionObject::GetBusSession() const
{
return session_;
}
std::shared_ptr<BufferObject> DBinderSessionObject::GetSessionBuff()
{
if (buff_ == nullptr) {
std::lock_guard<std::mutex> lockGuard(buffMutex_);
if (buff_ == nullptr) {
std::shared_ptr<BufferObject> temp = std::make_shared<BufferObject>();
buff_ = temp;
}
}
return buff_;
}
void DBinderSessionObject::SetServiceName(const std::string &serviceName)
{
serviceName_ = serviceName;
}
std::string DBinderSessionObject::GetServiceName() const
{
return serviceName_;
}
void DBinderSessionObject::SetDeviceId(const std::string &serverDeviceId)
{
serverDeviceId_ = serverDeviceId;
}
std::string DBinderSessionObject::GetDeviceId() const
{
return serverDeviceId_;
}
uint32_t DBinderSessionObject::GetFlatSessionLen()
{
return sizeof(struct FlatDBinderSession);
}
uint32_t DBinderSessionObject::GetSessionHandle() const
{
if (session_ != nullptr) {
return IPCProcessSkeleton::ConvertChannelID2Int(session_->GetChannelId());
}
return 0;
}
} // namespace OHOS

View File

@ -0,0 +1,91 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ipc_file_descriptor.h"
#include "ipc_debug.h"
#include "ipc_thread_skeleton.h"
#include "log_tags.h"
namespace OHOS {
using namespace OHOS::HiviewDFX;
#ifdef CONFIG_IPC_SINGLE
using namespace IPC_SINGLE;
#endif
static constexpr HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "IPCFileDescriptor" };
IPCFileDescriptor::IPCFileDescriptor() : Parcelable(true), fd_(INVALID_FD) {}
IPCFileDescriptor::IPCFileDescriptor(int fd) : Parcelable(true)
{
fd_ = fd;
}
IPCFileDescriptor::~IPCFileDescriptor()
{
fd_ = INVALID_FD;
}
int IPCFileDescriptor::GetFd() const
{
return fd_;
}
void IPCFileDescriptor::SetFd(int fd)
{
fd_ = fd;
}
bool IPCFileDescriptor::Marshalling(Parcel &parcel) const
{
if (fd_ < 0) {
ZLOGE(LABEL, "%s:IPCFileDescriptor: fd %d is invalid", __func__, fd_);
return false;
}
IRemoteInvoker *invoker = IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DEFAULT);
if (invoker != nullptr) {
return invoker->WriteFileDescriptor(parcel, fd_, false);
}
return false;
}
bool IPCFileDescriptor::Marshalling(Parcel &parcel, const sptr<IPCFileDescriptor> &object)
{
IRemoteInvoker *invoker = IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DEFAULT);
if (invoker != nullptr) {
return invoker->WriteFileDescriptor(parcel, object->GetFd(), false);
}
return false;
}
IPCFileDescriptor *IPCFileDescriptor::Unmarshalling(Parcel &parcel)
{
IRemoteInvoker *invoker = IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DEFAULT);
int fd = -1;
if (invoker != nullptr) {
fd = invoker->ReadFileDescriptor(parcel);
}
if (fd < 0) {
return nullptr;
}
return new IPCFileDescriptor(fd);
}
} // namespace OHOS

View File

@ -0,0 +1,660 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ipc_object_proxy.h"
#include "dbinder_error_code.h"
#include "ipc_types.h"
#include "ipc_debug.h"
#include "ipc_thread_skeleton.h"
#include "ipc_process_skeleton.h"
#include "log_tags.h"
#include "securec.h"
#ifndef CONFIG_IPC_SINGLE
#include "dbinder_databus_invoker.h"
#endif
namespace OHOS {
#ifdef CONFIG_IPC_SINGLE
using namespace IPC_SINGLE;
#endif
static constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "IPCObjectProxy" };
IPCObjectProxy::IPCObjectProxy(int handle, std::u16string descriptor, int proto)
: IRemoteObject(std::move(descriptor)), handle_(handle), proto_(proto), isFinishInit_(false), isRemoteDead_(false)
{}
IPCObjectProxy::~IPCObjectProxy()
{
ZLOGW(LABEL, "handle = %{public}u destroyed", handle_);
}
int32_t IPCObjectProxy::GetObjectRefCount()
{
MessageParcel dummy, reply;
MessageOption option;
option.SetFlags(MessageOption::TF_SYNC);
if (SendRequestInner(false, SYNCHRONIZE_REFERENCE, dummy, reply, option) == ERR_NONE) {
return reply.ReadInt32();
}
return 0;
}
int IPCObjectProxy::Dump(int fd, const std::vector<std::u16string> &args)
{
MessageParcel data, reply;
MessageOption option { MessageOption::TF_SYNC };
data.WriteFileDescriptor(fd);
data.WriteString16Vector(args);
return SendRequestInner(false, DUMP_TRANSACTION, data, reply, option);
}
int IPCObjectProxy::SendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
{
if (code != DUMP_TRANSACTION && code > MAX_TRANSACTION_ID) {
return IPC_PROXY_INVALID_CODE_ERR;
}
return SendRequestInner(false, code, data, reply, option);
}
int IPCObjectProxy::SendLocalRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
{
return SendRequestInner(true, code, data, reply, option);
}
int IPCObjectProxy::SendRequestInner(bool isLocal, uint32_t code, MessageParcel &data, MessageParcel &reply,
MessageOption &option)
{
if (IsObjectDead()) {
return ERR_DEAD_OBJECT;
}
IRemoteInvoker *invoker = nullptr;
if (isLocal) {
invoker = IPCThreadSkeleton::GetDefaultInvoker();
} else {
invoker = IPCThreadSkeleton::GetRemoteInvoker(proto_);
}
if (invoker == nullptr) {
ZLOGE(LABEL, "%s: null invoker, type = %d", __func__, proto_);
return ERR_NULL_OBJECT;
}
int status = invoker->SendRequest(handle_, code, data, reply, option);
if (status == ERR_DEAD_OBJECT) {
MarkObjectDied();
}
return status;
}
std::u16string IPCObjectProxy::GetInterfaceDescriptor()
{
std::lock_guard<std::mutex> lockGuard(initMutex_);
if (!remoteDescriptor_.empty()) {
return remoteDescriptor_;
}
if (handle_ == 0) {
ZLOGI(LABEL, "handle == 0, do nothing");
return std::u16string();
}
MessageParcel data, reply;
MessageOption option;
uint32_t err = SendRequestInner(false, INTERFACE_TRANSACTION, data, reply, option);
if (err != ERR_NONE) {
ZLOGE(LABEL, "INTERFACE_TRANSACTION transact return error = %{public}u", err);
return std::u16string();
}
remoteDescriptor_ = reply.ReadString16();
return remoteDescriptor_;
}
std::string IPCObjectProxy::GetPidAndUidInfo()
{
MessageParcel data, reply;
MessageOption option;
uint32_t err = SendRequestInner(false, GET_UIDPID_INFO, data, reply, option);
if (err != ERR_NONE) {
ZLOGE(LABEL, "GetPidAndUidInfo SendRequestInner return error = %{public}u", err);
return std::string("");
}
return reply.ReadString();
}
std::string IPCObjectProxy::GetDataBusName()
{
MessageParcel data, reply;
MessageOption option;
uint32_t err = SendRequestInner(false, GRANT_DATABUS_NAME, data, reply, option);
if (err != ERR_NONE) {
ZLOGE(LABEL, "GetDataBusName transact return error = %{public}u", err);
return std::string("");
}
if (reply.ReadUint32() != IRemoteObject::IF_PROT_DATABUS) {
ZLOGE(LABEL, "GetDataBusName normal binder");
return std::string("");
}
return reply.ReadString();
}
void IPCObjectProxy::OnFirstStrongRef(const void *objectId)
{
return WaitForInit();
}
void IPCObjectProxy::WaitForInit()
{
#ifndef CONFIG_IPC_SINGLE
int type = 0;
#endif
{
bool acquire = true;
std::lock_guard<std::mutex> lockGuard(initMutex_);
if (IsObjectDead()) {
ZLOGI(LABEL, "check a dead proxy, init again");
isRemoteDead_ = false;
isFinishInit_ = false;
acquire = false;
}
// check again is this object been initialized
if (isFinishInit_) {
return;
}
IRemoteInvoker *invoker = IPCThreadSkeleton::GetDefaultInvoker();
if (invoker != nullptr && acquire == true) {
invoker->AcquireHandle(handle_);
}
#ifndef CONFIG_IPC_SINGLE
type = UpdateProto();
#endif
isFinishInit_ = true;
}
#ifndef CONFIG_IPC_SINGLE
if (type == IRemoteObject::IF_PROT_DATABUS) {
IncRefToRemote();
}
#endif
}
void IPCObjectProxy::OnLastStrongRef(const void *objectId)
{
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
ZLOGE(LABEL, "OnLastStrongRef current is null");
return;
}
if (current->DetachObject(this)) {
IRemoteInvoker *invoker = IPCThreadSkeleton::GetDefaultInvoker();
if (invoker != nullptr) {
invoker->ReleaseHandle(handle_);
}
}
#ifndef CONFIG_IPC_SINGLE
ReleaseProto();
#endif
}
/* mutex_ should be called before set or get isRemoteDead_ status */
void IPCObjectProxy::MarkObjectDied()
{
isRemoteDead_ = true;
}
bool IPCObjectProxy::IsObjectDead() const
{
return isRemoteDead_;
}
bool IPCObjectProxy::AddDeathRecipient(const sptr<DeathRecipient> &recipient)
{
std::lock_guard<std::recursive_mutex> lock(mutex_);
if (IsObjectDead()) {
ZLOGI(LABEL, "%s: proxy is already dead", __func__);
return false;
}
bool registerRecipient = false;
if (recipients_.empty()) {
registerRecipient = true;
}
recipients_.push_back(recipient);
if (!registerRecipient || handle_ >= IPCProcessSkeleton::DBINDER_HANDLE_BASE) {
ZLOGI(LABEL, "%s: death recipient is already registered", __func__);
return true;
}
IRemoteInvoker *invoker = IPCThreadSkeleton::GetDefaultInvoker();
if (invoker == nullptr) {
ZLOGE(LABEL, "%s : invoker is null", __func__);
return false;
}
/* 1. Subscribe to death notifications, whether the stub comes from kernel or remote;
* 2. Subscribe to additional death notifications, if remote object.
* If step 1 is failed, do not execute step 2 and return false directly.
* If step 1 is successful but step 2 is failed, return false.
*/
bool status = invoker->AddDeathRecipient(handle_, this);
if (!status) {
ZLOGE(LABEL, "%s: fail to add binder death recipient, status = %d", __func__, status);
#ifndef BUILD_PUBLIC_VERSION
ReportDriverEvent(DbinderErrorCode::COMMON_DRIVER_ERROR, DbinderErrorCode::ERROR_TYPE,
DbinderErrorCode::IPC_DRIVER, DbinderErrorCode::ERROR_CODE, DbinderErrorCode::SET_DEATH_RECIPIENT_FAILURE);
#endif
return status;
}
#ifndef CONFIG_IPC_SINGLE
if (proto_ == IRemoteObject::IF_PROT_DATABUS) {
status = AddDbinderDeathRecipient();
ZLOGE(LABEL, "%s: fail to add dbinder death recipient, status = %d", __func__, status);
#ifndef BUILD_PUBLIC_VERSION
if (!status) {
ReportDriverEvent(DbinderErrorCode::COMMON_DRIVER_ERROR, DbinderErrorCode::ERROR_TYPE,
DbinderErrorCode::RPC_DRIVER, DbinderErrorCode::ERROR_CODE,
DbinderErrorCode::SET_DEATH_RECIPIENT_FAILURE);
}
#endif
}
#endif
return status;
}
bool IPCObjectProxy::RemoveDeathRecipient(const sptr<DeathRecipient> &recipient)
{
std::lock_guard<std::recursive_mutex> lock(mutex_);
bool removeRecipient = false;
if (!IsObjectDead()) {
auto it = find(recipients_.begin(), recipients_.end(), recipient);
if (it != recipients_.end()) {
recipients_.erase(it);
removeRecipient = true;
}
if (!recipients_.empty()) {
removeRecipient = false;
}
}
if ((handle_ >= IPCProcessSkeleton::DBINDER_HANDLE_BASE) && (removeRecipient == true)) {
ZLOGI(LABEL, "%s: death recipient is already unregistered", __func__);
return true;
}
if (removeRecipient) {
IRemoteInvoker *invoker = IPCThreadSkeleton::GetDefaultInvoker();
if (invoker == nullptr) {
ZLOGE(LABEL, "%s : invoker is null", __func__);
return false;
}
bool dbinderStatus = true;
bool binderStatus = invoker->RemoveDeathRecipient(handle_, this);
#ifndef CONFIG_IPC_SINGLE
if (proto_ == IRemoteObject::IF_PROT_DATABUS) {
dbinderStatus = RemoveDbinderDeathRecipient();
}
#endif
if (binderStatus && dbinderStatus) {
return true;
}
}
return false;
}
void IPCObjectProxy::SendObituary()
{
{
std::lock_guard<std::recursive_mutex> lock(mutex_);
MarkObjectDied();
int recipientCount = recipients_.size();
for (int i = 0; i < recipientCount; i++) {
sptr<DeathRecipient> recipient = recipients_[i];
ZLOGW(LABEL, "%s: handle = %{public}u call OnRemoteDied", __func__, handle_);
recipient->OnRemoteDied(this);
}
recipients_.clear();
if (recipientCount > 0) {
IRemoteInvoker *invoker = IPCThreadSkeleton::GetDefaultInvoker();
if (invoker != nullptr) {
invoker->RemoveDeathRecipient(handle_, this);
}
}
}
#ifndef CONFIG_IPC_SINGLE
if (proto_ == IRemoteObject::IF_PROT_DATABUS) {
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
ZLOGE(LABEL, "%s: get current fail", __func__);
return;
}
current->DetachCallbackStubByProxy(this);
}
#endif
}
int IPCObjectProxy::GetProto() const
{
return proto_;
}
int32_t IPCObjectProxy::NoticeServiceDie()
{
MessageParcel data;
MessageParcel reply;
MessageOption option(MessageOption::TF_SYNC);
data.WriteInt32(IRemoteObject::DeathRecipient::NOTICE_DEATH_RECIPIENT);
int status = SendLocalRequest(DBINDER_OBITUARY_TRANSACTION, data, reply, option);
if (status != ERR_NONE || reply.ReadInt32() != ERR_NONE) {
ZLOGE(LABEL, "%s: send local request fail, status = %d", __func__, status);
return IPC_PROXY_TRANSACTION_ERR;
}
return ERR_NONE;
}
int IPCObjectProxy::InvokeListenThread(MessageParcel &data, MessageParcel &reply)
{
MessageOption option;
return SendRequestInner(false, INVOKE_LISTEN_THREAD, data, reply, option);
}
#ifndef CONFIG_IPC_SINGLE
int IPCObjectProxy::UpdateProto()
{
int type = GetSessionFromDBinderService();
SetProto(type);
return type;
}
void IPCObjectProxy::IncRefToRemote()
{
MessageParcel data, reply;
MessageOption option;
int32_t err = SendRequestInner(false, DBINDER_INCREFS_TRANSACTION, data, reply, option);
if (err != ERR_NONE) {
ZLOGE(LABEL, "DBINDER_INCREFS_TRANSACTION transact return error = %{public}d", err);
// do nothing
}
}
void IPCObjectProxy::ReleaseProto()
{
switch (GetProto()) {
case IRemoteObject::IF_PROT_BINDER: {
ZLOGW(LABEL, "it is normal binder, try to delete handle to index");
ReleaseBinderProto();
break;
}
case IRemoteObject::IF_PROT_DATABUS: {
ReleaseDatabusProto();
break;
}
default: {
ZLOGE(LABEL, "ReleaseProto Invalid Type");
break;
}
}
return;
}
void IPCObjectProxy::SetProto(int proto)
{
proto_ = proto;
}
int IPCObjectProxy::GetSessionFromDBinderService()
{
MessageParcel data, reply;
MessageOption option;
uint32_t type = IRemoteObject::IF_PROT_BINDER;
if (CheckHaveSession(type)) {
ZLOGE(LABEL, "GetSessionFromDBinderService type = %u", type);
return type;
}
uint32_t err = SendRequestInner(true, GET_PROTO_INFO, data, reply, option);
if (err != ERR_NONE) {
ZLOGI(LABEL, "GET_PROTO_INFO transact return error = %{public}u", err);
return IRemoteObject::IF_PROT_BINDER;
}
switch (reply.ReadUint32()) {
case IRemoteObject::IF_PROT_BINDER: {
ZLOGW(LABEL, "it is normal binder, not dbinder");
break;
}
case IRemoteObject::IF_PROT_DATABUS: {
if (UpdateDatabusClientSession(handle_, reply)) {
ZLOGW(LABEL, "it is dbinder, not binder");
return IRemoteObject::IF_PROT_DATABUS;
}
break;
}
default: {
ZLOGE(LABEL, "GetSessionFromDBinderService Invalid Type");
break;
}
}
return IRemoteObject::IF_PROT_BINDER;
}
bool IPCObjectProxy::AddDbinderDeathRecipient()
{
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
ZLOGE(LABEL, "%s: get current fail", __func__);
return false;
}
if (current->QueryCallbackStub(this) != nullptr) {
ZLOGW(LABEL, "%s: already attach callback stub", __func__);
return true;
}
sptr<IPCObjectStub> callbackStub = new IPCObjectStub(descriptor_);
if (!current->AttachCallbackStub(this, callbackStub)) {
ZLOGW(LABEL, "%s: already attach new callback stub", __func__);
return false;
}
MessageParcel data;
MessageParcel reply;
MessageOption option(MessageOption::TF_SYNC);
data.WriteInt32(IRemoteObject::DeathRecipient::ADD_DEATH_RECIPIENT);
data.WriteRemoteObject(callbackStub);
int err = SendLocalRequest(DBINDER_OBITUARY_TRANSACTION, data, reply, option);
if (err != ERR_NONE || reply.ReadInt32() != ERR_NONE) {
ZLOGE(LABEL, "%s: send local request fail, err = %d", __func__, err);
(void)current->DetachCallbackStubByProxy(this);
return false;
}
return true;
}
bool IPCObjectProxy::RemoveDbinderDeathRecipient()
{
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
ZLOGE(LABEL, "%s: get current fail", __func__);
return false;
}
sptr<IPCObjectStub> callbackStub = current->QueryCallbackStub(this);
if (callbackStub == nullptr) {
ZLOGE(LABEL, "%s: get callbackStub fail", __func__);
return false;
}
MessageParcel data;
MessageParcel reply;
MessageOption option(MessageOption::TF_SYNC);
data.WriteInt32(IRemoteObject::DeathRecipient::REMOVE_DEATH_RECIPIENT);
data.WriteRemoteObject(callbackStub);
int err = SendLocalRequest(DBINDER_OBITUARY_TRANSACTION, data, reply, option);
if (err != ERR_NONE || reply.ReadInt32() != ERR_NONE) {
ZLOGE(LABEL, "%s: send local request fail, err = %d", __func__, err);
// do nothing, even send request failed
}
return current->DetachCallbackStubByProxy(this);
}
bool IPCObjectProxy::CheckHaveSession(uint32_t &type)
{
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
ZLOGE(LABEL, "IPCProcessSkeleton is null, set type as binder");
return false;
}
std::shared_ptr<DBinderSessionObject> session = current->ProxyQueryDBinderSession(handle_);
if (session == nullptr) {
ZLOGW(LABEL, "no databus session attach to this handle, maybe need update");
return false;
}
type = IRemoteObject::IF_PROT_DATABUS;
return true;
}
bool IPCObjectProxy::UpdateDatabusClientSession(int handle, MessageParcel &reply)
{
DBinderDatabusInvoker *invoker =
reinterpret_cast<DBinderDatabusInvoker *>(IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DATABUS));
if (invoker == nullptr) {
ZLOGE(LABEL, "%s: invoker null", __func__);
return false;
}
uint64_t stubIndex = reply.ReadUint64();
std::string serviceName = reply.ReadString();
std::string peerID = reply.ReadString();
std::string localID = reply.ReadString();
std::string localBusName = reply.ReadString();
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
ZLOGE(LABEL, "%s:current process skeleton is nullptr", __func__);
return false;
}
std::shared_ptr<DBinderSessionObject> connectSession = current->QuerySessionByInfo(serviceName, peerID);
if (connectSession == nullptr) {
connectSession = std::make_shared<DBinderSessionObject>(nullptr, serviceName, peerID);
if (connectSession == nullptr) {
ZLOGE(LABEL, "new server session fail!");
return false;
}
}
if (!current->AttachHandleToIndex(handle, stubIndex)) {
ZLOGE(LABEL, "add stub index err stubIndex = %" PRIu64 ", handle = %d", stubIndex, handle);
return false;
}
if (!current->CreateSoftbusServer(localBusName)) {
ZLOGE(LABEL, "create bus server fail name = %s, localID = %s", localBusName.c_str(), localID.c_str());
return false;
}
bool result = invoker->UpdateClientSession(handle, connectSession);
if (!result) {
ZLOGE(LABEL, "update server session object fail!");
return false;
}
return true;
}
void IPCObjectProxy::ReleaseDatabusProto()
{
if (handle_ == 0) {
ZLOGI(LABEL, "%s:handle == 0, do nothing", __func__);
return;
}
if (GetProto() != IRemoteObject::IF_PROT_DATABUS) {
ZLOGI(LABEL, "not databus dbinder, need do nothing");
return;
}
MessageParcel data, reply;
MessageOption option = { MessageOption::TF_ASYNC };
uint32_t err = SendRequestInner(false, DBINDER_DECREFS_TRANSACTION, data, reply, option);
if (err != ERR_NONE) {
ZLOGE(LABEL, "DBINDER_DECREFS_TRANSACTION transact return error = %{public}u", err);
// do nothing
}
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
ZLOGE(LABEL, "release proto current is null");
return;
}
(void)current->ProxyDetachDBinderSession(handle_);
(void)current->DetachHandleToIndex(handle_);
return;
}
void IPCObjectProxy::ReleaseBinderProto()
{
if (handle_ == 0) {
ZLOGI(LABEL, "%s:handle == 0, do nothing", __func__);
return;
}
if (GetProto() != IRemoteObject::IF_PROT_BINDER) {
ZLOGI(LABEL, "not binder proxy, need do nothing");
return;
}
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
ZLOGE(LABEL, "release proto current is null");
return;
}
(void)current->DetachHandleToIndex(handle_);
return;
}
#endif
} // namespace OHOS

View File

@ -0,0 +1,495 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ipc_object_stub.h"
#include <string>
#include "ipc_types.h"
#include "ipc_debug.h"
#include "ipc_process_skeleton.h"
#include "ipc_thread_skeleton.h"
#include "log_tags.h"
#include "ipc_skeleton.h"
#ifndef CONFIG_IPC_SINGLE
#include "dbinder_databus_invoker.h"
#include "dbinder_error_code.h"
#include "ISessionService.h"
#endif
namespace OHOS {
#ifdef CONFIG_IPC_SINGLE
using namespace IPC_SINGLE;
#endif
using namespace OHOS::HiviewDFX;
static constexpr HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "IPCObjectStub" };
#ifndef CONFIG_IPC_SINGLE
// Authentication information can be added only for processes with system permission.
static constexpr pid_t ALLOWED_UID = 10000;
// Only the samgr can obtain the UID and PID.
static constexpr pid_t SYSTEM_SERVER_UID = 1000;
#endif
static constexpr pid_t SHELL_UID = 2000;
IPCObjectStub::IPCObjectStub(std::u16string descriptor) : IRemoteObject(descriptor) {}
IPCObjectStub::~IPCObjectStub()
{
ZLOGW(LABEL, "IPCObjectStub destroyed");
}
bool IPCObjectStub::IsDeviceIdIllegal(const std::string &deviceID)
{
if (deviceID.empty() || deviceID.length() > DEVICEID_LENGTH) {
return true;
}
return false;
}
int32_t IPCObjectStub::GetObjectRefCount()
{
int kRefCount = 0;
int refCount = GetSptrRefCount();
IRemoteInvoker *invoker = IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DEFAULT);
if (invoker != nullptr) {
kRefCount = invoker->GetObjectRefCount(this);
}
/* the kernel has already acquire the reference
* on this object, so we need to decrement by 1.
*/
if (kRefCount > 0) {
refCount += kRefCount - 1;
}
return refCount;
}
int IPCObjectStub::Dump(int fd, const std::vector<std::u16string> &args)
{
const size_t numArgs = args.size();
ZLOGE(LABEL, "Invalid call on Stub:fd:%d, args:%zu", fd, numArgs);
return ERR_NONE;
}
int IPCObjectStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
{
int result = ERR_NONE;
switch (code) {
#ifndef CONFIG_IPC_SINGLE
case DBINDER_OBITUARY_TRANSACTION: {
if (IPCSkeleton::GetCallingUid() != SYSTEM_SERVER_UID) {
ZLOGE(LABEL, "%s: DBINDER_OBITUARY_TRANSACTION unauthenticated user ", __func__);
result = IPC_STUB_INVALID_DATA_ERR;
break;
}
if (data.ReadInt32() == IRemoteObject::DeathRecipient::NOTICE_DEATH_RECIPIENT) {
result = NoticeServiceDie(data, reply, option);
} else {
result = IPC_STUB_INVALID_DATA_ERR;
}
break;
}
#endif
default:
result = IPC_STUB_UNKNOW_TRANS_ERR;
ZLOGI(LABEL, "unknown OnRemoteRequest code = %{public}u", code);
break;
}
return result;
}
int IPCObjectStub::OnRemoteDump(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
{
int result = ERR_NONE;
int fd = data.ReadFileDescriptor();
std::vector<std::u16string> args;
if (fd != INVALID_FD) {
if (data.ReadString16Vector(&args)) {
result = Dump(fd, args);
}
::close(fd);
} else {
result = IPC_STUB_INVALID_DATA_ERR;
}
return result;
}
int IPCObjectStub::SendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
{
int result = ERR_NONE;
switch (code) {
case PING_TRANSACTION: {
if (!reply.WriteInt32(ERR_NONE)) {
result = IPC_STUB_WRITE_PARCEL_ERR;
}
break;
}
case INTERFACE_TRANSACTION: {
std::u16string descriptor = GetObjectDescriptor();
if (!reply.WriteString16(descriptor)) {
ZLOGE(LABEL, "write to parcel fail");
result = IPC_STUB_WRITE_PARCEL_ERR;
}
break;
}
case SYNCHRONIZE_REFERENCE: {
int refCount = GetObjectRefCount();
// when handle transaction the invoker would try to acquire
// the object's reference to defense the object being released
// so the actual we should decrement the temporary reference.
--refCount;
reply.WriteInt32(refCount);
break;
}
case DUMP_TRANSACTION: {
pid_t uid = IPCSkeleton::GetCallingUid();
if (!IPCSkeleton::IsLocalCalling() || (uid != 0 && uid != SHELL_UID)) {
ZLOGE(LABEL, "do not allow dump");
break;
}
result = OnRemoteDump(code, data, reply, option);
break;
}
#ifndef CONFIG_IPC_SINGLE
case INVOKE_LISTEN_THREAD: {
if (!IPCSkeleton::IsLocalCalling() || IPCSkeleton::GetCallingUid() >= ALLOWED_UID) {
ZLOGE(LABEL, "%s: INVOKE_LISTEN_THREAD unauthenticated user ", __func__);
result = IPC_STUB_INVALID_DATA_ERR;
break;
}
result = InvokerThread(code, data, reply, option);
break;
}
case GET_PROTO_INFO: {
result = ProcessProto(code, data, reply, option);
break;
}
case DBINDER_INCREFS_TRANSACTION: {
if (IPCSkeleton::IsLocalCalling()) {
ZLOGE(LABEL, "%s: cannot be called in same device", __func__);
result = IPC_STUB_INVALID_DATA_ERR;
break;
}
result = IncStubRefs(data, reply);
break;
}
case DBINDER_DECREFS_TRANSACTION: {
if (IPCSkeleton::IsLocalCalling()) {
ZLOGE(LABEL, "%s: cannot be called in same device", __func__);
result = IPC_STUB_INVALID_DATA_ERR;
break;
}
result = DecStubRefs(data, reply);
break;
}
case DBINDER_ADD_COMMAUTH: {
if (IPCSkeleton::IsLocalCalling() || IPCSkeleton::GetCallingUid() >= ALLOWED_UID) {
ZLOGE(LABEL, "%s: DBINDER_ADD_COMMAUTH unauthenticated user ", __func__);
result = IPC_STUB_INVALID_DATA_ERR;
break;
}
result = AddAuthInfo(data, reply);
break;
}
case GET_UIDPID_INFO: {
if (!IPCSkeleton::IsLocalCalling()) {
ZLOGE(LABEL, "GET_UIDPID_INFO message is not from sa manager");
result = IPC_STUB_INVALID_DATA_ERR;
break;
}
std::string sessionName = GetDataBusName();
if (sessionName.empty()) {
ZLOGE(LABEL, "sessionName is empty");
result = IPC_STUB_CREATE_BUS_SERVER_ERR;
break;
}
if (!reply.WriteString(sessionName)) {
ZLOGE(LABEL, "write to parcel fail");
result = IPC_STUB_INVALID_DATA_ERR;
break;
}
break;
}
case GRANT_DATABUS_NAME: {
if (!IPCSkeleton::IsLocalCalling() || getuid() != SYSTEM_SERVER_UID) {
ZLOGE(LABEL, "GRANT_DATABUS_NAME message is excluded in sa manager");
result = IPC_STUB_INVALID_DATA_ERR;
break;
}
result = GrantDataBusName(code, data, reply, option);
break;
}
#endif
default:
result = OnRemoteRequest(code, data, reply, option);
break;
}
return result;
}
void IPCObjectStub::OnFirstStrongRef(const void *objectId)
{
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current != nullptr) {
current->AttachObject(this);
}
}
void IPCObjectStub::OnLastStrongRef(const void *objectId)
{
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current != nullptr) {
current->DetachObject(this);
#ifndef CONFIG_IPC_SINGLE
current->DetachStubRecvRefInfo(this);
current->DetachStubSendRefInfo(this);
(void)current->DetachStubRefTimes(this);
current->DetachCommAuthInfoByStub(this);
uint64_t stubIndex = current->EraseStubIndex(reinterpret_cast<IRemoteObject *>(this));
current->DetachAppInfoToStubIndex(stubIndex);
#endif
}
}
bool IPCObjectStub::AddDeathRecipient(const sptr<DeathRecipient> &recipient)
{
return false;
}
bool IPCObjectStub::RemoveDeathRecipient(const sptr<DeathRecipient> &recipient)
{
return false;
}
pid_t IPCObjectStub::GetCallingPid()
{
return IPCSkeleton::GetCallingPid();
}
pid_t IPCObjectStub::GetCallingUid()
{
return IPCSkeleton::GetCallingUid();
}
int32_t IPCObjectStub::ProcessProto(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
{
int result = ERR_NONE;
ZLOGE(LABEL, "IPCObjectStub::ProcessProto called, type = 0, normal stub object");
if (!reply.WriteUint32(IRemoteObject::IF_PROT_BINDER)) {
ZLOGE(LABEL, "write to parcel fail");
result = IPC_STUB_WRITE_PARCEL_ERR;
}
return result;
}
#ifndef CONFIG_IPC_SINGLE
int32_t IPCObjectStub::InvokerThread(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
{
switch (data.ReadUint32()) {
case IRemoteObject::DATABUS_TYPE: {
if (InvokerDataBusThread(data, reply) != ERR_NONE) {
ZLOGE(LABEL, "Invoker databus thread fail");
return IPC_STUB_INVOKE_THREAD_ERR;
}
break;
}
default: {
ZLOGE(LABEL, "InvokerThread Invalid Type");
return IPC_STUB_INVALID_DATA_ERR;
}
}
return ERR_NONE;
}
int32_t IPCObjectStub::InvokerDataBusThread(MessageParcel &data, MessageParcel &reply)
{
std::string deviceId = data.ReadString();
uint32_t remotePid = data.ReadUint32();
uint32_t remoteUid = data.ReadUint32();
std::string remoteDeviceId = data.ReadString();
std::string sessionName = data.ReadString();
if (IsDeviceIdIllegal(deviceId) || IsDeviceIdIllegal(remoteDeviceId) || sessionName.empty()) {
ZLOGE(LABEL, "%s: device ID is invalid or session name nil", __func__);
return IPC_STUB_INVALID_DATA_ERR;
}
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
ZLOGE(LABEL, "IPCProcessSkeleton is nullptr");
return IPC_STUB_CURRENT_NULL_ERR;
}
if (!current->CreateSoftbusServer(sessionName)) {
ZLOGE(LABEL, "%s: fail to create databus server", __func__);
return IPC_STUB_CREATE_BUS_SERVER_ERR;
}
uint64_t stubIndex = current->AddStubByIndex(this);
if (stubIndex == 0) {
ZLOGE(LABEL, "%s: add stub fail", __func__);
return IPC_STUB_INVALID_DATA_ERR;
}
if (!reply.WriteUint64(stubIndex) || !reply.WriteString(sessionName) || !reply.WriteString(deviceId)) {
ZLOGE(LABEL, "%s: write to parcel fail", __func__);
return IPC_STUB_INVALID_DATA_ERR;
}
if (!current->AttachAppInfoToStubIndex(remotePid, remoteUid, remoteDeviceId, stubIndex)) {
ZLOGE(LABEL, "fail to attach appinfo to stubIndex, maybe attach already");
}
if (!current->AttachCommAuthInfo(this, remotePid, remoteUid, remoteDeviceId)) {
ZLOGE(LABEL, "fail to attach comm auth info");
}
return ERR_NONE;
}
int32_t IPCObjectStub::NoticeServiceDie(MessageParcel &data, MessageParcel &reply, MessageOption &option)
{
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
ZLOGE(LABEL, "%s: current is null", __func__);
return IPC_STUB_CURRENT_NULL_ERR;
}
IPCObjectProxy *ipcProxy = current->QueryCallbackProxy(this);
if (ipcProxy == nullptr) {
ZLOGE(LABEL, "%s: ipc proxy is null", __func__);
return IPC_STUB_INVALID_DATA_ERR;
}
ipcProxy->SendObituary();
if (!current->DetachCallbackStub(this)) {
ZLOGE(LABEL, "%s: fail to detach callback stub", __func__);
// do nothing, RemoveDeathRecipient can delete this too
}
return ERR_NONE;
}
int32_t IPCObjectStub::IncStubRefs(MessageParcel &data, MessageParcel &reply)
{
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
ZLOGE(LABEL, "%s: current is null", __func__);
return IPC_STUB_CURRENT_NULL_ERR;
}
std::string deviceId = IPCSkeleton::GetCallingDeviceID();
if (deviceId.empty()) {
ZLOGE(LABEL, "%s: calling error", __func__);
return IPC_STUB_INVALID_DATA_ERR;
}
if (!current->AttachStubRecvRefInfo(this, IPCSkeleton::GetCallingPid(), deviceId)) {
ZLOGE(LABEL, "%s: attach stub ref info err, already in", __func__);
return ERR_NONE;
}
if (!current->DecStubRefTimes(this)) {
this->IncStrongRef(this);
}
return ERR_NONE;
}
int32_t IPCObjectStub::DecStubRefs(MessageParcel &data, MessageParcel &reply)
{
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
ZLOGE(LABEL, "%s: current is null", __func__);
return IPC_STUB_CURRENT_NULL_ERR;
}
std::string deviceId = IPCSkeleton::GetCallingDeviceID();
current->DetachStubRefInfo(this, IPCSkeleton::GetCallingPid(), deviceId);
return ERR_NONE;
}
int32_t IPCObjectStub::AddAuthInfo(MessageParcel &data, MessageParcel &reply)
{
uint32_t remotePid = data.ReadUint32();
uint32_t remoteUid = data.ReadUint32();
std::string remoteDeviceId = data.ReadString();
if (IsDeviceIdIllegal(remoteDeviceId)) {
ZLOGE(LABEL, "%s: remote deviceId is null", __func__);
return IPC_STUB_INVALID_DATA_ERR;
}
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
ZLOGE(LABEL, "%s: current is null", __func__);
return IPC_STUB_CURRENT_NULL_ERR;
}
if (!current->AttachCommAuthInfo(this, remotePid, remoteUid, remoteDeviceId)) {
ZLOGE(LABEL, "fail to attach comm auth info fail");
return IPC_STUB_INVALID_DATA_ERR;
}
return ERR_NONE;
}
std::string IPCObjectStub::GetDataBusName()
{
sptr<IRemoteObject> object = IPCProcessSkeleton::GetCurrent()->GetSAMgrObject();
if (object == nullptr) {
ZLOGE(LABEL, "get object is null");
return std::string("");
}
IPCObjectProxy *samgr = reinterpret_cast<IPCObjectProxy *>(object.GetRefPtr());
return samgr->GetDataBusName();
}
int32_t IPCObjectStub::GrantDataBusName(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
{
int pid = IPCSkeleton::GetCallingPid();
int uid = IPCSkeleton::GetCallingUid();
std::string sessionName = CreateDatabusName(uid, pid);
if (sessionName.empty()) {
ZLOGE(LABEL, "pid/uid is invalid, pid = {public}%d, uid = {public}%d", pid, uid);
return IPC_STUB_INVALID_DATA_ERR;
}
if (!reply.WriteUint32(IRemoteObject::IF_PROT_DATABUS) || !reply.WriteString(sessionName)) {
ZLOGE(LABEL, "write to parcel fail");
return IPC_STUB_INVALID_DATA_ERR;
}
return ERR_NONE;
}
std::string IPCObjectStub::CreateDatabusName(int uid, int pid)
{
std::shared_ptr<ISessionService> softbusManager = ISessionService::GetInstance();
if (softbusManager == nullptr) {
ZLOGE(LABEL, "fail to get softbus service");
return "";
}
std::string sessionName = "DBinder" + std::to_string(uid) + std::string("_") + std::to_string(pid);
if (softbusManager->GrantPermission(uid, pid, sessionName) != ERR_NONE) {
ZLOGE(LABEL, "fail to Grant Permission softbus name");
return "";
}
return sessionName;
}
#endif
} // namespace OHOS

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,148 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ipc_skeleton.h"
#include "ipc_process_skeleton.h"
#include "ipc_thread_skeleton.h"
namespace OHOS {
#ifdef CONFIG_IPC_SINGLE
using namespace IPC_SINGLE;
#endif
void IPCSkeleton::JoinWorkThread()
{
IPCThreadSkeleton *current = IPCThreadSkeleton::GetCurrent();
if (current != nullptr) {
current->JoinWorkThread(IRemoteObject::IF_PROT_DEFAULT);
}
}
void IPCSkeleton::StopWorkThread()
{
IPCThreadSkeleton *current = IPCThreadSkeleton::GetCurrent();
if (current != nullptr) {
current->StopWorkThread(IRemoteObject::IF_PROT_DEFAULT);
}
}
bool IPCSkeleton::SetContextObject(sptr<IRemoteObject> &object)
{
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current != nullptr) {
return current->SetRegistryObject(object);
}
return false;
}
sptr<IRemoteObject> IPCSkeleton::GetContextObject()
{
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current != nullptr) {
return current->GetRegistryObject();
}
return nullptr;
}
bool IPCSkeleton::SetMaxWorkThreadNum(int maxThreadNum)
{
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current != nullptr) {
// first thread have started at IPCProcessSkeleton instances
return current->SetMaxWorkThread(maxThreadNum);
}
return false;
}
pid_t IPCSkeleton::GetCallingPid()
{
IRemoteInvoker *invoker = IPCThreadSkeleton::GetActiveInvoker();
if (invoker != nullptr) {
return invoker->GetCallerPid();
}
return getpid();
}
pid_t IPCSkeleton::GetCallingUid()
{
IRemoteInvoker *invoker = IPCThreadSkeleton::GetActiveInvoker();
if (invoker != nullptr) {
return invoker->GetCallerUid();
}
return getuid();
}
std::string IPCSkeleton::GetLocalDeviceID()
{
IRemoteInvoker *invoker = IPCThreadSkeleton::GetActiveInvoker();
if (invoker != nullptr) {
return invoker->GetLocalDeviceID();
}
return "";
}
std::string IPCSkeleton::GetCallingDeviceID()
{
IRemoteInvoker *invoker = IPCThreadSkeleton::GetActiveInvoker();
if (invoker != nullptr) {
return invoker->GetCallerDeviceID();
}
return "";
}
IPCSkeleton &IPCSkeleton::GetInstance()
{
static IPCSkeleton skeleton;
return skeleton;
}
bool IPCSkeleton::IsLocalCalling()
{
IRemoteInvoker *invoker = IPCThreadSkeleton::GetActiveInvoker();
if (invoker != nullptr) {
return invoker->IsLocalCalling();
}
return true;
}
int IPCSkeleton::FlushCommands(IRemoteObject *object)
{
IRemoteInvoker *invoker = IPCThreadSkeleton::GetProxyInvoker(object);
if (invoker == nullptr) {
return IPC_SKELETON_NULL_OBJECT_ERR;
}
return invoker->FlushCommands(object);
}
std::string IPCSkeleton::ResetCallingIdentity()
{
IRemoteInvoker *invoker = IPCThreadSkeleton::GetActiveInvoker();
if (invoker != nullptr) {
return invoker->ResetCallingIdentity();
}
return "";
}
bool IPCSkeleton::SetCallingIdentity(std::string &identity)
{
IRemoteInvoker *invoker = IPCThreadSkeleton::GetActiveInvoker();
if (invoker != nullptr) {
return invoker->SetCallingIdentity(identity);
}
return true;
}
} // namespace OHOS

View File

@ -0,0 +1,147 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ipc_thread_pool.h"
#include <unistd.h>
#include <sys/types.h>
#include "ipc_debug.h"
#include "log_tags.h"
namespace OHOS {
#ifdef CONFIG_IPC_SINGLE
namespace IPC_SINGLE {
#endif
static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_IPC, "IPCWorkThreadPool" };
#define DBINDER_LOGI(fmt, args...) (void)OHOS::HiviewDFX::HiLog::Info(LOG_LABEL, "%{public}d: " fmt, __LINE__, ##args)
IPCWorkThreadPool::IPCWorkThreadPool(int maxThreadNum)
: threadSequence_(0),
maxThreadNum_(maxThreadNum + maxThreadNum),
idleThreadNum_(maxThreadNum),
idleSocketThreadNum_(maxThreadNum)
{}
IPCWorkThreadPool::~IPCWorkThreadPool()
{
StopAllThreads();
threads_.clear();
}
void IPCWorkThreadPool::StopAllThreads()
{
std::lock_guard<std::mutex> lock(mutex_);
for (auto it = threads_.begin(); it != threads_.end(); it++) {
it->second->StopWorkThread();
}
}
bool IPCWorkThreadPool::SpawnThread(int policy, int proto)
{
std::lock_guard<std::mutex> lock(mutex_);
if (!(proto == IRemoteObject::IF_PROT_DEFAULT && idleThreadNum_ > 0) &&
!(proto == IRemoteObject::IF_PROT_DATABUS && idleSocketThreadNum_ > 0)) {
return false;
}
std::string threadName = MakeThreadName(proto);
DBINDER_LOGI("SpawnThread Name= %{public}s", threadName.c_str());
if (threads_.find(threadName) == threads_.end()) {
sptr<IPCWorkThread> newThread = sptr<IPCWorkThread>(new IPCWorkThread(threadName));
threads_[threadName] = newThread;
if (proto == IRemoteObject::IF_PROT_DEFAULT) {
idleThreadNum_--;
DBINDER_LOGI("SpawnThread, now idleThreadNum_ =%d", idleThreadNum_);
}
if (proto == IRemoteObject::IF_PROT_DATABUS) {
idleSocketThreadNum_--;
DBINDER_LOGI("SpawnThread, now idleSocketThreadNum_ =%d", idleSocketThreadNum_);
}
newThread->Start(policy, proto, threadName);
return true;
}
return false;
}
std::string IPCWorkThreadPool::MakeThreadName(int proto)
{
int sequence = threadSequence_.fetch_add(1, std::memory_order_relaxed);
if (proto == IRemoteObject::IF_PROT_DATABUS) {
std::string threadName = "DRPC";
return std::to_string(sequence) + threadName;
} else {
std::string threadName = "IPC";
return std::to_string(sequence) + threadName;
}
}
bool IPCWorkThreadPool::RemoveThread(const std::string &threadName)
{
std::lock_guard<std::mutex> lock(mutex_);
auto it = threads_.find(threadName);
if (it != threads_.end()) {
sptr<IPCWorkThread> workThread = it->second;
if (workThread == nullptr) {
return false;
}
if (workThread->proto_ == IRemoteObject::IF_PROT_DEFAULT) {
idleThreadNum_++;
} else if (workThread->proto_ == IRemoteObject::IF_PROT_DATABUS) {
idleSocketThreadNum_++;
}
threads_.erase(it);
DBINDER_LOGI("SpawnThread, now idleThreadNum_ =%d", idleSocketThreadNum_);
return true;
}
return false;
}
int IPCWorkThreadPool::GetSocketIdleThreadNum() const
{
return idleSocketThreadNum_;
}
int IPCWorkThreadPool::GetSocketTotalThreadNum() const
{
return maxThreadNum_ / PROTO_NUM;
}
int IPCWorkThreadPool::GetMaxThreadNum() const
{
return maxThreadNum_ / PROTO_NUM;
}
void IPCWorkThreadPool::UpdateMaxThreadNum(int maxThreadNum)
{
/*
* not support delete thread, because thread is in using
*/
int totalNum = maxThreadNum + maxThreadNum;
std::lock_guard<std::mutex> lock(mutex_);
if (totalNum <= maxThreadNum_) {
return;
}
int diff = totalNum - maxThreadNum_;
maxThreadNum_ = totalNum;
idleThreadNum_ += diff / PROTO_NUM;
idleSocketThreadNum_ += diff / PROTO_NUM;
}
#ifdef CONFIG_IPC_SINGLE
} // namespace IPC_SINGLE
#endif
} // namesapce OHOS

View File

@ -0,0 +1,158 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ipc_thread_skeleton.h"
#include "ipc_debug.h"
#include "dbinder_error_code.h"
#include "log_tags.h"
#include "ipc_object_proxy.h"
namespace OHOS {
#ifdef CONFIG_IPC_SINGLE
namespace IPC_SINGLE {
#endif
using namespace OHOS::HiviewDFX;
pthread_key_t IPCThreadSkeleton::TLSKey_ = 0;
pthread_once_t IPCThreadSkeleton::TLSKeyOnce_ = PTHREAD_ONCE_INIT;
static constexpr HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "IPCThreadSkeleton" };
void IPCThreadSkeleton::TlsDestructor(void *args)
{
auto *current = static_cast<IPCThreadSkeleton *>(args);
auto it = current->invokers_.find(IRemoteObject::IF_PROT_BINDER);
if (it != current->invokers_.end()) {
ZLOGW(LABEL, "thread exit, flush commands");
BinderInvoker *invoker = reinterpret_cast<BinderInvoker *>(it->second);
invoker->FlushCommands(nullptr);
invoker->ExitCurrentThread();
}
delete current;
}
void IPCThreadSkeleton::MakeTlsKey()
{
pthread_key_create(&TLSKey_, IPCThreadSkeleton::TlsDestructor);
}
IPCThreadSkeleton *IPCThreadSkeleton::GetCurrent()
{
IPCThreadSkeleton *current = nullptr;
pthread_once(&TLSKeyOnce_, IPCThreadSkeleton::MakeTlsKey);
void *curTLS = pthread_getspecific(TLSKey_);
if (curTLS != nullptr) {
current = reinterpret_cast<IPCThreadSkeleton *>(curTLS);
} else {
current = new IPCThreadSkeleton();
}
return current;
}
IPCThreadSkeleton::IPCThreadSkeleton()
{
pthread_setspecific(TLSKey_, this);
}
IPCThreadSkeleton::~IPCThreadSkeleton()
{
ZLOGE(LABEL, "IPCThreadSkeleton delete");
for (auto it = invokers_.begin(); it != invokers_.end();) {
delete it->second;
it = invokers_.erase(it);
}
}
IRemoteInvoker *IPCThreadSkeleton::GetRemoteInvoker(int proto)
{
IPCThreadSkeleton *current = IPCThreadSkeleton::GetCurrent();
IRemoteInvoker *invoker = nullptr;
if (current == nullptr) {
return nullptr;
}
auto it = current->invokers_.find(proto);
if (it != current->invokers_.end()) {
invoker = it->second;
} else {
InvokerFactory &factory = InvokerFactory::Get();
invoker = factory.newInstance(proto);
if (invoker == nullptr) {
ZLOGE(LABEL, "invoker is NULL proto = %d", proto);
return nullptr;
}
// non-thread safe, add lock to protect it.
current->invokers_.insert(std::make_pair(proto, invoker));
}
return invoker;
}
IRemoteInvoker *IPCThreadSkeleton::GetActiveInvoker()
{
IRemoteInvoker *binderInvoker = IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_BINDER);
if ((binderInvoker != nullptr) && (binderInvoker->GetStatus() == IRemoteInvoker::ACTIVE_INVOKER)) {
return binderInvoker;
}
#ifndef CONFIG_IPC_SINGLE
IRemoteInvoker *dbinderInvoker = IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DATABUS);
if ((dbinderInvoker != nullptr) && (dbinderInvoker->GetStatus() == IRemoteInvoker::ACTIVE_INVOKER)) {
return dbinderInvoker;
}
#endif
return nullptr;
}
IRemoteInvoker *IPCThreadSkeleton::GetProxyInvoker(IRemoteObject *object)
{
if (object == nullptr) {
ZLOGE(LABEL, "proxy is invalid");
return nullptr;
}
if (!object->IsProxyObject()) {
return nullptr;
}
IPCObjectProxy *proxy = reinterpret_cast<IPCObjectProxy *>(object);
return IPCThreadSkeleton::GetRemoteInvoker(proxy->GetProto());
}
IRemoteInvoker *IPCThreadSkeleton::GetDefaultInvoker()
{
return GetRemoteInvoker(IRemoteObject::IF_PROT_DEFAULT);
}
void IPCThreadSkeleton::JoinWorkThread(int prot)
{
IRemoteInvoker *invoker = GetRemoteInvoker(prot);
if (invoker != nullptr) {
invoker->JoinThread(true);
}
}
void IPCThreadSkeleton::StopWorkThread(int prot)
{
IRemoteInvoker *invoker = GetRemoteInvoker(prot);
if (invoker != nullptr) {
invoker->StopWorkThread();
}
}
#ifdef CONFIG_IPC_SINGLE
} // namespace IPC_SINGLE
#endif
} // namespace OHOS

View File

@ -0,0 +1,94 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ipc_workthread.h"
#include <sys/prctl.h>
#include "ipc_debug.h"
#include "ipc_process_skeleton.h"
#include "ipc_thread_skeleton.h"
#include "log_tags.h"
namespace OHOS {
#ifdef CONFIG_IPC_SINGLE
namespace IPC_SINGLE {
#endif
#ifndef TITLE
#define TITLE __PRETTY_FUNCTION__
#endif
#define DBINDER_LOGI(fmt, args...) \
(void)OHOS::HiviewDFX::HiLog::Info(LABEL, "%{public}s %{public}d: " fmt, TITLE, __LINE__, ##args)
IPCWorkThread::IPCWorkThread(std::string threadName) : threadName_(std::move(threadName)) {}
IPCWorkThread::~IPCWorkThread()
{
StopWorkThread();
}
void IPCWorkThread::ThreadHandler()
{
IRemoteInvoker *invoker = IPCThreadSkeleton::GetRemoteInvoker(proto_);
DBINDER_LOGI("proto_=%d", proto_);
if (invoker != nullptr) {
switch (policy_) {
case SPAWN_PASSIVE:
invoker->JoinThread(false);
break;
case SPAWN_ACTIVE:
invoker->JoinThread(true);
break;
case PROCESS_PASSIVE:
invoker->JoinProcessThread(false);
break;
case PROCESS_ACTIVE:
invoker->JoinProcessThread(true);
break;
default:
DBINDER_LOGI("policy_ = %{public}d", policy_);
break;
}
}
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current != nullptr) {
current->OnThreadTerminated(threadName_);
}
}
void IPCWorkThread::StopWorkThread()
{
IRemoteInvoker *invoker = IPCThreadSkeleton::GetRemoteInvoker(proto_);
if (invoker != nullptr) {
invoker->StopWorkThread();
}
}
void IPCWorkThread::Start(int policy, int proto, std::string threadName)
{
policy_ = policy;
proto_ = proto;
std::thread t(std::bind(&IPCWorkThread::ThreadHandler, this));
std::string wholeName = threadName + std::to_string(getpid()) + "_" + std::to_string(gettid());
DBINDER_LOGI("create thread = %{public}s, policy=%d, proto=%d", wholeName.c_str(), policy, proto);
thread_ = std::move(t);
thread_.detach();
}
#ifdef CONFIG_IPC_SINGLE
} // namespace IPC_SINGLE
#endif
} // namespace OHOS

View File

@ -0,0 +1,79 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "iremote_broker.h"
#include <utility>
#include "ipc_debug.h"
#include "log_tags.h"
namespace OHOS {
[[maybe_unused]] static constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "BrokerRegistration" };
BrokerRegistration &BrokerRegistration::Get()
{
static BrokerRegistration instance;
return instance;
}
BrokerRegistration::~BrokerRegistration()
{
std::lock_guard<std::mutex> lockGuard(creatorMutex_);
for (auto it = creators_.begin(); it != creators_.end();) {
it = creators_.erase(it);
}
}
bool BrokerRegistration::Register(const std::u16string &descriptor, const Constructor &creator)
{
if (descriptor.empty()) {
return false;
}
std::lock_guard<std::mutex> lockGuard(creatorMutex_);
auto it = creators_.find(descriptor);
if (it == creators_.end()) {
return creators_.insert({ descriptor, creator }).second;
}
return false;
}
void BrokerRegistration::Unregister(const std::u16string &descriptor)
{
std::lock_guard<std::mutex> lockGuard(creatorMutex_);
if (!descriptor.empty()) {
auto it = creators_.find(descriptor);
if (it != creators_.end()) {
creators_.erase(it);
}
}
}
sptr<IRemoteBroker> BrokerRegistration::NewInstance(const std::u16string &descriptor, const sptr<IRemoteObject> &object)
{
std::lock_guard<std::mutex> lockGuard(creatorMutex_);
sptr<IRemoteBroker> broker;
if (object != nullptr) {
if (object->IsProxyObject()) {
auto it = creators_.find(descriptor);
if (it != creators_.end()) {
broker = it->second(object);
}
} else {
broker = object->AsInterface().GetRefPtr();
}
}
return broker;
}
} // namespace OHOS

View File

@ -0,0 +1,84 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "iremote_broker.h"
#include "ipc_types.h"
#include "ipc_debug.h"
#include "ipc_object_proxy.h"
#include "ipc_thread_skeleton.h"
namespace OHOS {
#ifdef CONFIG_IPC_SINGLE
using namespace IPC_SINGLE;
#endif
bool IRemoteObject::CheckObjectLegality() const
{
return false;
}
bool IRemoteObject::Marshalling(Parcel &parcel) const
{
IRemoteInvoker *invoker = IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DEFAULT);
if (invoker != nullptr) {
return invoker->FlattenObject(parcel, this);
}
return false;
}
bool IRemoteObject::Marshalling(Parcel &parcel, const sptr<IRemoteObject> &object)
{
IRemoteInvoker *invoker = IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DEFAULT);
if (invoker != nullptr) {
return invoker->FlattenObject(parcel, object);
}
return false;
}
IRemoteObject *IRemoteObject::Unmarshalling(Parcel &parcel)
{
IRemoteInvoker *invoker = IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DEFAULT);
if (invoker != nullptr) {
return invoker->UnflattenObject(parcel);
}
return nullptr;
}
std::u16string IRemoteObject::GetObjectDescriptor() const
{
return descriptor_;
}
sptr<IRemoteBroker> IRemoteObject::AsInterface()
{
return nullptr;
}
bool IRemoteObject::IsProxyObject() const
{
return true;
}
IRemoteObject::IRemoteObject(std::u16string descriptor) : descriptor_(descriptor)
{
ExtendObjectLifetime();
asRemote_ = true;
}
} // namespace OHOS

View File

@ -0,0 +1,46 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "message_option.h"
namespace OHOS {
static constexpr int MAX_WAIT_TIME = 3000;
MessageOption::MessageOption(int flags, int waitTime) : flags_(static_cast<uint32_t>(flags)), waitTime_(waitTime) {}
void MessageOption::SetFlags(int flags)
{
flags_ |= static_cast<uint32_t>(flags);
}
int MessageOption::GetFlags() const
{
return flags_;
}
void MessageOption::SetWaitTime(int waitTime)
{
if (waitTime <= 0) {
waitTime_ = TF_WAIT_TIME;
} else if (waitTime > MAX_WAIT_TIME) {
waitTime_ = MAX_WAIT_TIME;
} else {
waitTime_ = waitTime;
}
}
int MessageOption::GetWaitTime() const
{
return waitTime_;
}
} // namespace OHOS

View File

@ -0,0 +1,327 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "message_parcel.h"
#include <unistd.h>
#include <sys/mman.h>
#include "ipc_debug.h"
#include "iremote_object.h"
#include "ipc_file_descriptor.h"
#include "sys_binder.h"
#include "ashmem.h"
#include "securec.h"
namespace OHOS {
MessageParcel::MessageParcel()
: Parcel(),
writeRawDataFd_(-1),
readRawDataFd_(-1),
kernelMappedWrite_(nullptr),
kernelMappedRead_(nullptr),
rawData_(nullptr),
rawDataSize_(0)
{}
MessageParcel::MessageParcel(Allocator *allocator)
: Parcel(allocator),
writeRawDataFd_(-1),
readRawDataFd_(-1),
kernelMappedWrite_(nullptr),
kernelMappedRead_(nullptr),
rawData_(nullptr),
rawDataSize_(0)
{}
MessageParcel::~MessageParcel()
{
if (kernelMappedWrite_ != nullptr) {
::munmap(kernelMappedWrite_, rawDataSize_);
kernelMappedWrite_ = nullptr;
}
if (kernelMappedRead_ != nullptr) {
::munmap(kernelMappedRead_, rawDataSize_);
kernelMappedRead_ = nullptr;
}
if (readRawDataFd_ > 0) {
::close(readRawDataFd_);
readRawDataFd_ = -1;
}
if (writeRawDataFd_ > 0) {
::close(writeRawDataFd_);
writeRawDataFd_ = -1;
}
ClearFileDescriptor();
rawData_ = nullptr;
rawDataSize_ = 0;
}
bool MessageParcel::WriteRemoteObject(const sptr<IRemoteObject> &object)
{
holders_.push_back(object);
return WriteObject<IRemoteObject>(object);
}
sptr<IRemoteObject> MessageParcel::ReadRemoteObject()
{
return ReadObject<IRemoteObject>();
}
bool MessageParcel::WriteFileDescriptor(int fd)
{
if (fd < 0) {
return false;
}
int dupFd = dup(fd);
if (dupFd < 0) {
return false;
}
sptr<IPCFileDescriptor> descriptor = new IPCFileDescriptor(dupFd);
return WriteObject<IPCFileDescriptor>(descriptor);
}
int MessageParcel::ReadFileDescriptor()
{
sptr<IPCFileDescriptor> descriptor = ReadObject<IPCFileDescriptor>();
if (descriptor == nullptr) {
return -1;
}
int fd = descriptor->GetFd();
if (fd < 0) {
return -1;
}
holders_.push_back(descriptor);
return dup(fd);
}
void MessageParcel::ClearFileDescriptor()
{
binder_size_t *object = reinterpret_cast<binder_size_t *>(GetObjectOffsets());
size_t objectNum = GetOffsetsSize();
uintptr_t data = GetData();
for (size_t i = 0; i < objectNum; i++) {
const flat_binder_object *flat = reinterpret_cast<flat_binder_object *>(data + object[i]);
if (flat->hdr.type == BINDER_TYPE_FD && flat->handle > 0) {
::close(flat->handle);
}
}
}
bool MessageParcel::ContainFileDescriptors() const
{
binder_size_t *object = reinterpret_cast<binder_size_t *>(GetObjectOffsets());
size_t objectNum = GetOffsetsSize();
uintptr_t data = GetData();
for (size_t i = 0; i < objectNum; i++) {
const flat_binder_object *flat = reinterpret_cast<flat_binder_object *>(data + object[i]);
if (flat->hdr.type == BINDER_TYPE_FD) {
return true;
}
}
return false;
}
bool MessageParcel::WriteInterfaceToken(std::u16string name)
{
constexpr int strictModePolicy = 0x100;
constexpr int workSource = 0;
size_t rewindPos = GetWritePosition();
if (!WriteInt32(strictModePolicy)) {
return false;
}
if (!WriteInt32(workSource)) {
if (!RewindWrite(rewindPos)) {
FlushBuffer();
}
return false;
}
return WriteString16(name);
}
std::u16string MessageParcel::ReadInterfaceToken()
{
[[maybe_unused]] int strictModePolicy = ReadInt32();
[[maybe_unused]] int workSource = ReadInt32();
return ReadString16();
}
bool MessageParcel::WriteRawData(const void *data, size_t size)
{
if (data == nullptr || size > MAX_RAWDATA_SIZE) {
return false;
}
if (kernelMappedWrite_ != nullptr) {
return false;
}
if (!WriteInt32(size)) {
return false;
}
if (size <= MIN_RAWDATA_SIZE) {
return WriteUnpadBuffer(data, size);
}
int fd = AshmemCreate("Parcel RawData", size);
if (fd < 0) {
return false;
}
writeRawDataFd_ = fd;
int result = AshmemSetProt(fd, PROT_READ | PROT_WRITE);
if (result < 0) {
return false;
}
void *ptr = ::mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (ptr == MAP_FAILED) {
return false;
}
if (!WriteFileDescriptor(fd)) {
::munmap(ptr, size);
return false;
}
if (memcpy_s(ptr, size, data, size) != EOK) {
::munmap(ptr, size);
return false;
}
kernelMappedWrite_ = ptr;
rawDataSize_ = size;
return true;
}
bool MessageParcel::RestoreRawData(std::shared_ptr<char> rawData, size_t size)
{
if (rawData_ != nullptr || rawData == nullptr) {
return false;
}
rawData_ = rawData;
rawDataSize_ = size;
writeRawDataFd_ = 0;
return true;
}
const void *MessageParcel::ReadRawData(size_t size)
{
int32_t bufferSize = ReadInt32();
if (static_cast<unsigned int>(bufferSize) != size) {
return nullptr;
}
if (static_cast<unsigned int>(bufferSize) <= MIN_RAWDATA_SIZE) {
return ReadUnpadBuffer(size);
}
/* if rawDataFd_ == 0 means rawData is received from remote
*/
if (rawData_ != nullptr && writeRawDataFd_ == 0) {
/* should read fd for move readCursor of parcel */
if (ReadFileDescriptor()) {
// do nothing
}
if (rawDataSize_ != size) {
return nullptr;
}
return rawData_.get();
}
int fd = ReadFileDescriptor();
if (fd < 0) {
return nullptr;
}
readRawDataFd_ = fd;
int ashmemSize = AshmemGetSize(fd);
if (ashmemSize < 0 || size_t(ashmemSize) < size) {
// do not close fd here. fd will be closed in FileDescriptor, ::close(fd)
return nullptr;
}
void *ptr = ::mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0);
if (ptr == MAP_FAILED) {
// do not close fd here. fd will be closed in FileDescriptor, ::close(fd)
return nullptr;
}
kernelMappedRead_ = ptr;
rawDataSize_ = size;
return ptr;
}
const void *MessageParcel::GetRawData() const
{
if (rawData_ != nullptr) {
return rawData_.get();
}
if (kernelMappedWrite_ != nullptr) {
return kernelMappedWrite_;
}
if (kernelMappedRead_ != nullptr) {
return kernelMappedRead_;
}
return nullptr;
}
size_t MessageParcel::GetRawDataSize() const
{
return rawDataSize_;
}
size_t MessageParcel::GetRawDataCapacity() const
{
return MAX_RAWDATA_SIZE;
}
void MessageParcel::WriteNoException()
{
WriteInt32(0);
}
int32_t MessageParcel::ReadException()
{
int32_t errorCode = ReadInt32();
if (errorCode != 0) {
ReadString16();
}
return errorCode;
}
bool MessageParcel::WriteAshmem(sptr<Ashmem> ashmem)
{
int fd = ashmem->GetAshmemFd();
int32_t size = ashmem->GetAshmemSize();
if (fd < 0 || size <= 0) {
return false;
}
if (!WriteFileDescriptor(fd) || !WriteInt32(size)) {
return false;
}
return true;
}
sptr<Ashmem> MessageParcel::ReadAshmem()
{
int fd = ReadFileDescriptor();
if (fd < 0) {
return nullptr;
}
int32_t size = ReadInt32();
if (size <= 0) {
::close(fd);
return nullptr;
}
return new Ashmem(fd, size);
}
} // namespace OHOS

View File

@ -0,0 +1,25 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "peer_holder.h"
namespace OHOS {
PeerHolder::PeerHolder(const sptr<IRemoteObject> &object) : remoteObject_(object) {}
sptr<IRemoteObject> PeerHolder::Remote()
{
return remoteObject_;
}
} // namespace OHOS

View File

@ -0,0 +1,43 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "stub_refcount_object.h"
namespace OHOS {
StubRefCountObject::StubRefCountObject(IRemoteObject *stub, int remotePid, const std::string &deviceId)
: stub_(stub), remotePid_(remotePid), deviceId_(deviceId)
{
}
StubRefCountObject::~StubRefCountObject()
{
stub_ = nullptr;
}
IRemoteObject *StubRefCountObject::GetStubObject() const
{
return stub_;
}
int StubRefCountObject::GetRemotePid() const
{
return remotePid_;
}
std::string StubRefCountObject::GetDeviceId() const
{
return deviceId_;
}
} // namespace OHOS

View File

@ -0,0 +1,68 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_JNI_HELPERS_H
#define OHOS_IPC_JNI_HELPERS_H
#include <jni.h>
namespace OHOS {
class JNIEnvHelper {
public:
JNIEnvHelper();
~JNIEnvHelper();
JNIEnv *Get();
JNIEnv *operator->();
static void nativeInit(JavaVM *vm);
private:
JNIEnvHelper(const JNIEnvHelper &) = delete;
JNIEnvHelper &operator = (const JNIEnvHelper &) = delete;
private:
JNIEnv *env_;
bool nativeThread_;
static JavaVM *javaVm_;
};
void JniHelperThrowException(JNIEnv *env, const char *className, const char *msg);
void JniHelperThrowNullPointerException(JNIEnv *env, const char *msg);
void JniHelperThrowIllegalStateException(JNIEnv *env, const char *msg);
/*
* JNI may throws exception when native code call java scenario.
* we should convert local exception to native status code.
* Check and clear local exception.
*/
jboolean JniHelperCheckAndClearLocalException(JNIEnv *env);
/*
* Get an int file descriptor from a java.io.FileDescriptor
*/
int JniHelperJavaIoGetFdFromFileDescriptor(JNIEnv *env, jobject fileDescriptor);
/*
* Set the descriptor of a java.io.FileDescriptor
*/
void JniHelperJavaIoSetFdToFileDescriptor(JNIEnv *env, jobject fileDescriptor, int value);
/*
* Create a java.io.FileDescriptor given an integer fd
*/
jobject JniHelperJavaIoCreateFileDescriptor(JNIEnv *env, int fd);
int JniHelperRegisterNativeMethods(JNIEnv *env);
} // namespace OHOS
#endif // OHOS_IPC_JNI_HELPERS_H

View File

@ -0,0 +1,27 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_JNI_REMOTE_OBJECT_H
#define OHOS_IPC_JNI_REMOTE_OBJECT_H
#include <jni.h>
#include "refbase.h"
#include "iremote_object.h"
namespace OHOS {
jobject GetJObjectFromRemoteObject(JNIEnv *env, const sptr<IRemoteObject> &val);
sptr<IRemoteObject> GetRemoteObjectFromJObject(JNIEnv *env, jobject obj);
} // namespace OHOS
#endif // OHOS_IPC_JNI_REMOTE_OBJECT_H

View File

@ -0,0 +1,59 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_JNI_MESSAGE_OPTION_H
#define OHOS_IPC_JNI_MESSAGE_OPTION_H
#include <jni.h>
#include <memory>
#include "message_option.h"
namespace OHOS {
/*
* Get flags field from ohos.rpc.MessageOption.
*/
int JavaOhosRpcMessageOptionGetFlags(JNIEnv *env, jobject object);
/*
* Set flags to ohos.rpc.MessageOption
*/
void JavaOhosRpcMessageOptionSetFlags(JNIEnv *env, jobject object, int flags);
/*
* Get wait time field from ohos.rpc.MessageOption.
*/
int JavaOhosRpcMessageOptionGetWaitTime(JNIEnv *env, jobject object);
/*
* Set wait time to ohos.rpc.MessageOption
*/
void JavaOhosRpcMessageOptionSetWaitTime(JNIEnv *env, jobject object, int waitTime);
/*
* Create java object for ohos.rpc.MessageOption.
*/
jobject JavaOhosRpcMessageOptionNewJavaObject(JNIEnv *env, int flags, int waitTime);
/*
* Get and create native instance of ohos.rpc.MessageOption.
*/
MessageOptionPtr JavaOhosRpcMessageOptionGetNative(JNIEnv *env, jobject object);
/*
* register native methods for ohos.rpc.MessageOption.
*/
int JavaOhosRpcMessageOptionRegisterNativeMethods(JNIEnv *env);
} // namespace OHOS
#endif // OHOS_IPC_JNI_MESSAGE_OPTION_H

View File

@ -0,0 +1,158 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_JNI_MESSAGE_PARCEL_H
#define OHOS_IPC_JNI_MESSAGE_PARCEL_H
#include <jni.h>
#include "message_parcel.h"
namespace OHOS {
/*
* register native methods for ohos.rpc.MessageParcel.
*/
int JavaOhosRpcMessageParcelRegisterNativeMethods(JNIEnv *env);
/*
* Get Native Message Parcel instance of ohos/rpc/MessageParcel
*/
MessageParcel *JavaOhosRpcMessageParcelGetNative(JNIEnv *env, jobject object);
} // namespace OHOS
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeNewObject
* Signature: (J)J;
*/
jlong JNICALL Java_ohos_rpc_MessageParcel_nativeNewObject(JNIEnv *env, jobject object, jlong nativeObject);
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeFreeObject
* Signature: (J)V;
*/
void JNICALL Java_ohos_rpc_MessageParcel_nativeFreeObject(JNIEnv *env, jobject object, jlong nativeObject);
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeWriteRemoteObject
* Signature: (Lohos/rpc/IRemoteObject)Z
*/
jboolean JNICALL Java_ohos_rpc_MessageParcel_nativeWriteRemoteObject(JNIEnv *env, jobject parcel, jobject object);
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeReadRemoteObject
* Signature: ()Lohos/rpc/IRemoteObject;
*/
jobject JNICALL Java_ohos_rpc_MessageParcel_nativeReadRemoteObject(JNIEnv *env, jobject object);
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeWriteFileDescriptor
* Signature: (LJava/io/FileDescriptor;)Z
*/
jboolean JNICALL Java_ohos_rpc_MessageParcel_nativeWriteFileDescriptor(JNIEnv *env, jobject object, jobject descriptor);
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeReadFileDescriptor
* Signature: ()LJava/io/FileDescriptor;
*/
jobject JNICALL Java_ohos_rpc_MessageParcel_nativeReadFileDescriptor(JNIEnv *env, jobject object);
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeWriteInterfaceToken
* Signature: (LJava/io/String;)Z
*/
jboolean JNICALL Java_ohos_rpc_MessageParcel_nativeWriteInterfaceToken(JNIEnv *env, jobject object, jstring name,
jint len);
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeReadInterfaceToken
* Signature: ()LJava/io/String;
*/
jobject JNICALL Java_ohos_rpc_MessageParcel_nativeReadInterfaceToken(JNIEnv *env, jobject object);
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeWriteRawData
* Signature: ()LJava/io/String;
*/
jboolean JNICALL Java_ohos_rpc_MessageParcel_nativeWriteRawData(JNIEnv *env, jobject object, jobject rawData,
jint size);
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeReadRawData
* Signature: ()LJava/io/String;
*/
jbyteArray JNICALL Java_ohos_rpc_MessageParcel_nativeReadRawData(JNIEnv *env, jobject object, jint size);
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeGetRawDataCapacity
* Signature: (V)I;
*/
jint JNICALL Java_ohos_rpc_MessageParcel_nativeGetRawDataCapacity(JNIEnv *env, jobject object);
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeCloseFileDescriptor
* Signature: (LJava/io/FileDescriptor;)V
*/
void JNICALL Java_ohos_rpc_MessageParcel_nativeCloseFileDescriptor(JNIEnv *env, jobject object, jobject descriptor);
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeDupFileDescriptor
* Signature: (LJava/io/FileDescriptor;)LJava/io/FileDescriptor;
*/
jobject JNICALL Java_ohos_rpc_MessageParcel_nativeDupFileDescriptor(JNIEnv *env, jobject object, jobject descriptor);
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeContainFileDescriptors
* Signature: ()Z;
*/
jboolean JNICALL Java_ohos_rpc_MessageParcel_nativeContainFileDescriptors(JNIEnv *env, jobject object);
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeWriteAshmem
* Signature: (J)Z
*/
jboolean JNICALL Java_ohos_rpc_MessageParcel_nativeWriteAshmem(JNIEnv *env, jobject object, jlong id);
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeReadAshmem
* Signature: (V)J
*/
jlong JNICALL Java_ohos_rpc_MessageParcel_nativeReadAshmem(JNIEnv *env, jobject object);
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeReleaseAshmem
* Signature: (J)V
*/
void JNICALL Java_ohos_rpc_MessageParcel_nativeReleaseAshmem(JNIEnv *env, jobject object, jlong id);
#ifdef __cplusplus
}
#endif
#endif // OHOS_IPC_JNI_MESSAGE_PARCEL_H

View File

@ -0,0 +1,181 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_JNI_REMOTE_OBJECT_H
#define OHOS_IPC_JNI_REMOTE_OBJECT_H
#include <jni.h>
#include "refbase.h"
#include "iremote_object.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: ohos.rpc.IPCSkeleton
* Method: nativeGetContextObject
* Signature: (V)Lohos/rpc/IRemoteObject;
*/
jobject JNICALL Java_ohos_rpc_IPCSkeleton_nativeGetContextObject(JNIEnv *env, jclass clazz);
/*
* Class: ohos.rpc.IPCSkeleton
* Method: nativeGetCallingPid
* Signature: (V)I
*/
jint JNICALL Java_ohos_rpc_IPCSkeleton_nativeGetCallingPid(JNIEnv *env, jclass clazz);
/*
* Class: ohos.rpc.IPCSkeleton
* Method: nativeGetCallingUid
* Signature: (V)I
*/
jint JNICALL Java_ohos_rpc_IPCSkeleton_nativeGetCallingUid(JNIEnv *env, jclass clazz);
/*
* Class: ohos.rpc.IPCSkeleton
* Method: nativeGetCallingDeviceID
* Signature: (V)Lohos/rpc/IRemoteObject;
*/
jstring JNICALL Java_ohos_rpc_IPCSkeleton_nativeGetCallingDeviceID(JNIEnv *env, jclass clazz);
/*
* Class: ohos.rpc.IPCSkeleton
* Method: nativeGetLocalDeviceID
* Signature: (V)Lohos/rpc/IRemoteObject;
*/
jstring JNICALL Java_ohos_rpc_IPCSkeleton_nativeGetLocalDeviceID(JNIEnv *env, jclass clazz);
/*
* Class: ohos.rpc.IPCSkeleton
* Method: nativeIsLocalCalling
* Signature: (V)Z
*/
jboolean JNICALL Java_ohos_rpc_IPCSkeleton_nativeIsLocalCalling(JNIEnv *env, jclass clazz);
/*
* Class: ohos.rpc.IPCSkeleton
* Method: nativeFlushCommands
* Signature: (Lohos/rpc/IRemoteObject;)I;
*/
jint JNICALL Java_ohos_rpc_IPCSkeleton_nativeFlushCommands(JNIEnv *env, jclass clazz, jobject object);
/*
* Class: ohos.rpc.IPCSkeleton
* Method: nativeResetCallingIdentity
* Signature: (Lohos/rpc/IRemoteObject;)I;
*/
jstring JNICALL Java_ohos_rpc_IPCSkeleton_nativeResetCallingIdentity(JNIEnv *env, jclass clazz);
/*
* Class: ohos.rpc.IPCSkeleton
* Method: nativeSetCallingIdentity
* Signature: (Lohos/rpc/IRemoteObject;)I;
*/
jboolean JNICALL Java_ohos_rpc_IPCSkeleton_nativeSetCallingIdentity(JNIEnv *env, jclass clazz, jstring identity,
jint len);
/*
* Class: ohos.rpc.RemoteObject
* Method: nativeGetObjectHolder
* Signature: (Ljava/lang/String;I)J
*/
jlong JNICALL Java_ohos_rpc_RemoteObject_nativeGetObjectHolder(JNIEnv *env, jclass clazz, jstring value, jint len);
/*
* Free local Object Holder of RemoteObject.
* Class: ohos.rpc.RemoteObject
* Method: nativeFreeObjectHolder
* Signature: (J)V
*/
void JNICALL Java_ohos_rpc_RemoteObject_nativeFreeObjectHolder(JNIEnv *env, jclass clazz, jlong holder);
/*
* Get calling pid from native.
* Class: ohos.rpc.RemoteObject
* Method: nativeGetCallingPid
* Signature: (V)I
*/
jint JNICALL Java_ohos_rpc_RemoteObject_nativeGetCallingPid(JNIEnv *env, jclass object);
/*
* Get calling UID from native.
* Class: ohos.rpc.RemoteObject
* Method: nativeGetCallingUid
* Signature: (V)I
*/
jint JNICALL Java_ohos_rpc_RemoteObject_nativeGetCallingUid(JNIEnv *env, jclass object);
/*
* Class: ohos_rpc_RemoteProxy
* Method: nativeFreeProxyHolder
* Signature: (J)V
*/
void JNICALL Java_ohos_rpc_RemoteProxy_nativeFreeProxyHolder(JNIEnv *env, jclass clazz, jlong holder);
/*
* Class: ohos.rpc.RemoteProxy
* Method: nativeSendRequest
* Signature: (ILohos/rpc/MessageParcel;Lohos/rpc/Parcel;Lohos/rpc/MessageOption;)Z
*/
jboolean JNICALL Java_ohos_rpc_RemoteProxy_nativeSendRequest(JNIEnv *env, jobject object, jint code, jobject data,
jobject reply, jobject option);
/*
* Class: ohos.rpc.RemoteProxy
* Method: nativeAddDeathRecipient
* Signature: (Lohos/rpc/IRemoteObject$DeathRecipient;I)Z
*/
jboolean JNICALL Java_ohos_rpc_RemoteProxy_nativeAddDeathRecipient(JNIEnv *env, jobject clazz, jobject recipient,
jint flags);
/*
* Class: ohos.rpc.RemoteProxy
* Method: nativeRemoveDeathRecipient
* Signature: (Lohos/rpc/IRemoteObject$DeathRecipient;I)Z
*/
jboolean JNICALL Java_ohos_rpc_RemoteProxy_nativeRemoveDeathRecipient(JNIEnv *env, jobject clazz, jobject recipient,
jint flags);
/*
* Class: ohos_rpc_RemoteProxy
* Method: nativeGetInterfaceDescriptor
* Signature: ()Ljava/lang/String;
*/
jstring JNICALL Java_ohos_rpc_RemoteProxy_nativeGetInterfaceDescriptor(JNIEnv *env, jobject clazz);
/*
* Class: ohos.rpc.RemoteProxy
* Method: nativeIsObjectDead
* Signature: (V)Z
*/
jboolean JNICALL Java_ohos_rpc_RemoteProxy_nativeIsObjectDead(JNIEnv *env, jobject object);
/*
* Class: ohos.rpc.RemoteProxy
* Method: nativeGetHandle
* Signature: (V)J
*/
jlong JNICALL Java_ohos_rpc_RemoteProxy_nativeGetHandle(JNIEnv *env, jobject object);
#ifdef __cplusplus
}
#endif
namespace OHOS {
sptr<IRemoteObject> Java_ohos_rpc_getNativeRemoteObject(JNIEnv *env, jobject object);
jobject Java_ohos_rpc_getJavaRemoteObject(JNIEnv *env, const sptr<IRemoteObject> target);
} // namespace OHOS
#endif // OHOS_IPC_JNI_REMOTE_OBJECT_H

View File

@ -0,0 +1,176 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "jni_helper.h"
#include "ipc_debug.h"
#include "jni_help.h"
#include "ohos_rpc_remote_object.h"
#include "log_tags.h"
namespace OHOS {
using namespace OHOS::HiviewDFX;
struct JFileDescriptor {
jclass klazz;
jmethodID fileDescriptorCtor;
jfieldID descriptorField;
} g_jFileDescriptor;
static constexpr HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "IPCJniHelper" };
JavaVM *JNIEnvHelper::javaVm_ = nullptr;
// The JavaVM is a representation of the virtual machine on the JNI layer,
// one process has only one JavaVM, and all the threads share a JavaVM.
// JNIEnv is in effect only on the thread that it is created,
// cannot be passed across threads, different threads are independent of each other.
// In order to implement cross-threading calls, we need to transform between JNIENV and JavaVM
JNIEnvHelper::JNIEnvHelper() : env_ { nullptr }, nativeThread_ { false }
{
if (javaVm_->GetEnv(reinterpret_cast<void **>(&env_), JNI_VERSION_1_4) == JNI_EDETACHED) {
javaVm_->AttachCurrentThread(reinterpret_cast<void **>(&env_), nullptr);
nativeThread_ = true;
}
}
void JNIEnvHelper::nativeInit(JavaVM *vm)
{
if (javaVm_ != nullptr) {
ZLOGE(LABEL, "Failed to init vm, javaVm_ has been initialized");
return;
}
javaVm_ = vm;
}
JNIEnvHelper::~JNIEnvHelper()
{
if (nativeThread_) {
javaVm_->DetachCurrentThread();
}
}
JNIEnv *JNIEnvHelper::Get()
{
return env_;
}
JNIEnv *JNIEnvHelper::operator->()
{
return env_;
}
void JniHelperThrowException(JNIEnv *env, const char *className, const char *msg)
{
jclass clazz = env->FindClass(className);
if (!clazz) {
ZLOGE(LABEL, "Unable to find exception class %s", className);
/* ClassNotFoundException now pending */
return;
}
if (env->ThrowNew(clazz, msg) != JNI_OK) {
ZLOGE(LABEL, "Failed throwing '%s' '%s'", className, msg);
/* an exception, most likely OOM, will now be pending */
}
env->DeleteLocalRef(clazz);
}
void JniHelperThrowNullPointerException(JNIEnv *env, const char *msg)
{
JniHelperThrowException(env, "java/lang/NullPointerException", msg);
}
void JniHelperThrowIllegalStateException(JNIEnv *env, const char *msg)
{
JniHelperThrowException(env, "java/lang/IllegalStateException", msg);
}
/*
* Get an int file descriptor from a java.io.FileDescriptor
*/
int JniHelperJavaIoGetFdFromFileDescriptor(JNIEnv *env, jobject fileDescriptor)
{
return env->GetIntField(fileDescriptor, g_jFileDescriptor.descriptorField);
}
/*
* Set the descriptor of a java.io.FileDescriptor
*/
void JniHelperJavaIoSetFdToFileDescriptor(JNIEnv *env, jobject fileDescriptor, int value)
{
env->SetIntField(fileDescriptor, g_jFileDescriptor.descriptorField, value);
}
/*
* JNI may throws exception when native code call java scenario.
* we should convert local exception to native status code.
* Check and clear local exception.
*/
jboolean JniHelperCheckAndClearLocalException(JNIEnv *env)
{
jthrowable exception = env->ExceptionOccurred();
if (exception != nullptr) {
ZLOGE(LABEL, "clean up JNI local ref");
// clean up JNI local ref -- we don't return to Java code
env->ExceptionDescribe(); // for debug perpose.
env->ExceptionClear();
env->DeleteLocalRef(exception);
return JNI_TRUE;
}
return JNI_FALSE;
}
/*
* Create a java.io.FileDescriptor given an integer fd
*/
jobject JniHelperJavaIoCreateFileDescriptor(JNIEnv *env, int fd)
{
jobject descriptor = env->NewObject(g_jFileDescriptor.klazz, g_jFileDescriptor.fileDescriptorCtor);
JniHelperJavaIoSetFdToFileDescriptor(env, descriptor, fd);
return descriptor;
}
int JniHelperRegisterNativeMethods(JNIEnv *env)
{
g_jFileDescriptor.klazz = (jclass)env->NewGlobalRef(env->FindClass("java/io/FileDescriptor"));
if (g_jFileDescriptor.klazz == nullptr) {
return -1;
}
g_jFileDescriptor.fileDescriptorCtor = env->GetMethodID(g_jFileDescriptor.klazz, "<init>", "()V");
if (g_jFileDescriptor.fileDescriptorCtor == nullptr) {
env->DeleteGlobalRef(g_jFileDescriptor.klazz);
return -1;
}
g_jFileDescriptor.descriptorField = env->GetFieldID(g_jFileDescriptor.klazz, "descriptor", "I");
if (g_jFileDescriptor.descriptorField == nullptr) {
env->DeleteGlobalRef(g_jFileDescriptor.klazz);
return -1;
}
return 0;
}
jobject JNIHelperGetJavaRemoteObject(JNIEnv *env, const sptr<IRemoteObject> &target)
{
if (env == nullptr) {
return nullptr;
}
return Java_ohos_rpc_getJavaRemoteObject(env, target);
}
} // namespace OHOS

View File

@ -0,0 +1,138 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ohos_rpc_message_option.h"
#include "ipc_debug.h"
#include "log_tags.h"
namespace OHOS {
struct JMessageOption {
jclass klazz;
jfieldID flagsField;
jfieldID waitTimeField;
jmethodID initMethod;
} g_jMessageOption;
static constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "IPCJni" };
/*
* Get flags field from ohos.rpc.MessageOption.
*/
int JavaOhosRpcMessageOptionGetFlags(JNIEnv *env, jobject object)
{
ZLOGI(LABEL, "%s", __func__);
if (g_jMessageOption.flagsField != nullptr) {
return env->GetIntField(object, g_jMessageOption.flagsField);
}
return 0;
}
/*
* Get wait time field from ohos.rpc.MessageOption.
*/
int JavaOhosRpcMessageOptionGetWaitTime(JNIEnv *env, jobject object)
{
ZLOGI(LABEL, "%s", __func__);
if (g_jMessageOption.waitTimeField != nullptr) {
return env->GetIntField(object, g_jMessageOption.waitTimeField);
}
return 0;
}
/*
* Set flags to ohos.rpc.MessageOption
*/
void JavaOhosRpcMessageOptionSetFlags(JNIEnv *env, jobject object, int flags)
{
ZLOGI(LABEL, "%s", __func__);
env->SetIntField(object, g_jMessageOption.flagsField, flags);
}
/*
* Set wait time to ohos.rpc.MessageOption
*/
void JavaOhosRpcMessageOptionSetWaitTime(JNIEnv *env, jobject object, int waitTime)
{
ZLOGI(LABEL, "%s", __func__);
env->SetIntField(object, g_jMessageOption.waitTimeField, waitTime);
}
/*
* Create java object for ohos.rpc.MessageOption.
*/
jobject JavaOhosRpcMessageOptionNewJavaObject(JNIEnv *env, int flags, int waitTime)
{
ZLOGI(LABEL, "%s", __func__);
jobject option = env->NewObject(g_jMessageOption.klazz, g_jMessageOption.initMethod, flags, waitTime);
return option;
}
/*
* Get and create native instance of ohos.rpc.MessageOption.
*/
MessageOptionPtr JavaOhosRpcMessageOptionGetNative(JNIEnv *env, jobject object)
{
ZLOGI(LABEL, "%s", __func__);
int flags = JavaOhosRpcMessageOptionGetFlags(env, object);
int waitTime = JavaOhosRpcMessageOptionGetWaitTime(env, object);
auto option = std::make_shared<MessageOption>();
option->SetFlags(flags);
option->SetWaitTime(waitTime);
return option;
}
/*
* register native methods fopr ohos.rpc.MessageOption.
*/
int JavaOhosRpcMessageOptionRegisterNativeMethods(JNIEnv *env)
{
ZLOGI(LABEL, "%s", __func__);
jclass klazz = (jclass)env->NewGlobalRef(env->FindClass("ohos/rpc/MessageOption"));
if (klazz == nullptr) {
ZLOGE(LABEL, "could not find class for MessageOption");
return -1;
}
g_jMessageOption.klazz = (jclass)env->NewGlobalRef(klazz);
g_jMessageOption.initMethod = env->GetMethodID(g_jMessageOption.klazz, "<init>", "(II)V");
if (g_jMessageOption.initMethod == nullptr) {
ZLOGE(LABEL, "could not get initMethod from MessageOption");
if (g_jMessageOption.klazz != nullptr) {
env->DeleteGlobalRef(g_jMessageOption.klazz);
}
env->DeleteGlobalRef(klazz);
return -1;
}
g_jMessageOption.flagsField = env->GetFieldID(g_jMessageOption.klazz, "mFlags", "I");
if (g_jMessageOption.flagsField == nullptr) {
ZLOGE(LABEL, "could not get flags fields from MessageOption");
if (g_jMessageOption.klazz != nullptr) {
env->DeleteGlobalRef(g_jMessageOption.klazz);
}
env->DeleteGlobalRef(klazz);
return -1;
}
g_jMessageOption.waitTimeField = env->GetFieldID(g_jMessageOption.klazz, "mWaitTime", "I");
if (g_jMessageOption.waitTimeField == nullptr) {
ZLOGE(LABEL, "could not get mWaitTime fields from MessageOption");
if (g_jMessageOption.klazz != nullptr) {
env->DeleteGlobalRef(g_jMessageOption.klazz);
}
env->DeleteGlobalRef(klazz);
return -1;
}
return 0;
}
} // namespace OHOS

View File

@ -0,0 +1,519 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ohos_rpc_message_parcel.h"
#include <unistd.h>
#include <securec.h>
#include "ipc_debug.h"
#include "jni_helper.h"
#include "ohos_utils_parcel.h"
#include "ohos_rpc_remote_object.h"
#include "ipc_file_descriptor.h"
#include "log_tags.h"
#include "jkit_utils.h"
#include <ashmem.h>
using namespace OHOS;
using namespace OHOS::HiviewDFX;
namespace OHOS {
struct JMessageParcel {
jclass klazz;
jfieldID nativeObject;
jfieldID nativeObjectOwner;
} g_jMessageParcel;
static constexpr HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "IPCJni" };
class AshmemSmartPointWrapper {
public:
explicit AshmemSmartPointWrapper(const sptr<Ashmem> &ashmem) : ashmem_(ashmem)
{
if (ashmem == nullptr) {
ZLOGE(LABEL, "%s: ashmem is null", __func__);
}
}
~AshmemSmartPointWrapper() = default;
const sptr<Ashmem> &GetAshmem() const
{
return ashmem_;
}
private:
// make sure this is immutable
sptr<Ashmem> const ashmem_;
};
/*
* Get Native Message Parcel instance of zindaneos/rpc/MessageParcel
*/
MessageParcel *JavaOhosRpcMessageParcelGetNative(JNIEnv *env, jobject object)
{
ZLOGI(LABEL, "%s", __func__);
jlong nativeObject = env->GetLongField(object, g_jMessageParcel.nativeObject);
return reinterpret_cast<MessageParcel *>(nativeObject);
}
sptr<Ashmem> Java_ohos_rpc_Ashmem_getSptrAshmem(JNIEnv *env, jobject object, jlong id)
{
if (id == 0) {
return nullptr;
}
AshmemSmartPointWrapper *wrapper = reinterpret_cast<AshmemSmartPointWrapper *>(id);
return wrapper->GetAshmem();
}
static const JNINativeMethod sMethods[] = {
/* Name, Signature, FunctionPointer */
{ "nativeNewObject", "(J)J", (void *)Java_ohos_rpc_MessageParcel_nativeNewObject },
{ "nativeFreeObject", "(J)V", (void *)Java_ohos_rpc_MessageParcel_nativeFreeObject },
{ "nativeWriteRemoteObject", "(Lohos/rpc/IRemoteObject;)Z",
(void *)Java_ohos_rpc_MessageParcel_nativeWriteRemoteObject },
{ "nativeReadRemoteObject", "()Lohos/rpc/IRemoteObject;",
(void *)Java_ohos_rpc_MessageParcel_nativeReadRemoteObject },
{ "nativeWriteFileDescriptor", "(Ljava/io/FileDescriptor;)Z",
(void *)Java_ohos_rpc_MessageParcel_nativeWriteFileDescriptor },
{ "nativeReadFileDescriptor", "()Ljava/io/FileDescriptor;",
(void *)Java_ohos_rpc_MessageParcel_nativeReadFileDescriptor },
{ "nativeWriteInterfaceToken", "(Ljava/lang/String;I)Z",
(void *)Java_ohos_rpc_MessageParcel_nativeWriteInterfaceToken },
{ "nativeReadInterfaceToken", "()Ljava/lang/String;",
(void *)Java_ohos_rpc_MessageParcel_nativeReadInterfaceToken },
{ "nativeWriteRawData", "([BI)Z", (void *)Java_ohos_rpc_MessageParcel_nativeWriteRawData },
{ "nativeReadRawData", "(I)[B", (void *)Java_ohos_rpc_MessageParcel_nativeReadRawData },
{ "nativeGetRawDataCapacity", "()I", (void *)Java_ohos_rpc_MessageParcel_nativeGetRawDataCapacity },
{ "nativeCloseFileDescriptor", "(Ljava/io/FileDescriptor;)V",
(void *)Java_ohos_rpc_MessageParcel_nativeCloseFileDescriptor },
{ "nativeDupFileDescriptor", "(Ljava/io/FileDescriptor;)Ljava/io/FileDescriptor;",
(void *)Java_ohos_rpc_MessageParcel_nativeDupFileDescriptor },
{ "nativeContainFileDescriptors", "()Z", (void *)Java_ohos_rpc_MessageParcel_nativeContainFileDescriptors },
{ "nativeWriteAshmem", "(J)Z", (void *)Java_ohos_rpc_MessageParcel_nativeWriteAshmem },
{ "nativeReadAshmem", "()J", (void *)Java_ohos_rpc_MessageParcel_nativeReadAshmem },
{ "nativeReleaseAshmem", "(J)V", (void *)Java_ohos_rpc_MessageParcel_nativeReleaseAshmem },
};
/*
* register native methods fopr ohos.rpc.MessageParcel.
*/
int JavaOhosRpcMessageParcelRegisterNativeMethods(JNIEnv *env)
{
ZLOGI(LABEL, "%s", __func__);
jclass klazz = (jclass)env->NewGlobalRef(env->FindClass("ohos/rpc/MessageParcel"));
if (klazz == nullptr) {
ZLOGE(LABEL, "could not find class for MessageParcel");
return -1;
}
g_jMessageParcel.klazz = (jclass)env->NewGlobalRef(klazz);
g_jMessageParcel.nativeObject = env->GetFieldID(g_jMessageParcel.klazz, "mNativeObject", "J");
if (g_jMessageParcel.nativeObject == nullptr) {
ZLOGE(LABEL, "could not Get mNativeObject field for MessageParcel");
if (g_jMessageParcel.klazz != nullptr) {
env->DeleteGlobalRef(g_jMessageParcel.klazz);
}
env->DeleteGlobalRef(klazz);
return -1;
}
g_jMessageParcel.nativeObjectOwner = env->GetFieldID(g_jMessageParcel.klazz, "mOwnsNativeObject", "Z");
if (g_jMessageParcel.nativeObjectOwner == nullptr) {
ZLOGE(LABEL, "could not Get mOwnsNativeObject field for MessageParcel");
if (g_jMessageParcel.klazz != nullptr) {
env->DeleteGlobalRef(g_jMessageParcel.klazz);
}
env->DeleteGlobalRef(klazz);
return -1;
}
return JkitRegisterNativeMethods(env, "ohos/rpc/MessageParcel", sMethods, NUM_METHODS(sMethods));
}
} // namespace OHOS
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeWriteRemoteObject
* Signature: (Lohos/rpc/IRemoteObject;)Z
*/
jboolean JNICALL Java_ohos_rpc_MessageParcel_nativeWriteRemoteObject(JNIEnv *env, jobject parcel, jobject object)
{
ZLOGI(LABEL, "%s", __func__);
MessageParcel *nativeParcel = JavaOhosRpcMessageParcelGetNative(env, parcel);
if (nativeParcel == nullptr) {
ZLOGE(LABEL, "could not get native parcel for marshalling");
return JNI_FALSE;
}
sptr<IRemoteObject> target = Java_ohos_rpc_getNativeRemoteObject(env, object);
if (target != nullptr) {
if (nativeParcel->WriteRemoteObject(target)) {
return JNI_TRUE;
}
}
return JNI_FALSE;
}
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeReadRemoteObject
* Signature: ()Lohos/rpc/IRemoteObject;
*/
jobject JNICALL Java_ohos_rpc_MessageParcel_nativeReadRemoteObject(JNIEnv *env, jobject object)
{
ZLOGI(LABEL, "%s", __func__);
MessageParcel *nativeParcel = JavaOhosRpcMessageParcelGetNative(env, object);
if (nativeParcel == nullptr) {
ZLOGE(LABEL, "could not get native parcel for unmarshalling");
return nullptr;
}
return Java_ohos_rpc_getJavaRemoteObject(env, nativeParcel->ReadRemoteObject());
}
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeWriteFileDescriptor
* Signature: (Ljava/io/FileDescriptor;)Z
*/
jboolean JNICALL Java_ohos_rpc_MessageParcel_nativeWriteFileDescriptor(JNIEnv *env, jobject object, jobject descriptor)
{
ZLOGI(LABEL, "%s", __func__);
MessageParcel *nativeParcel = JavaOhosRpcMessageParcelGetNative(env, object);
if (nativeParcel == nullptr) {
ZLOGE(LABEL, "could not get native parcel for marshalling");
return JNI_FALSE;
}
int fd = JniHelperJavaIoGetFdFromFileDescriptor(env, descriptor);
return fd > 0 ? nativeParcel->WriteFileDescriptor(fd) : JNI_FALSE;
}
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeReadFileDescriptor
* Signature: ()Ljava/io/FileDescriptor;
*/
jobject JNICALL Java_ohos_rpc_MessageParcel_nativeReadFileDescriptor(JNIEnv *env, jobject object)
{
ZLOGI(LABEL, "%s", __func__);
MessageParcel *nativeParcel = JavaOhosRpcMessageParcelGetNative(env, object);
if (nativeParcel == nullptr) {
ZLOGE(LABEL, "unable to get native parcel");
return nullptr;
}
int fd = nativeParcel->ReadFileDescriptor();
if (fd != INVALID_FD) {
return JniHelperJavaIoCreateFileDescriptor(env, fd);
}
ZLOGE(LABEL, "Got invalid fd from parcel");
return nullptr;
}
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeContainFileDescriptors
* Signature: ()Z;
*/
jboolean JNICALL Java_ohos_rpc_MessageParcel_nativeContainFileDescriptors(JNIEnv *env, jobject object)
{
ZLOGI(LABEL, "%s", __func__);
MessageParcel *nativeParcel = JavaOhosRpcMessageParcelGetNative(env, object);
if (nativeParcel == nullptr) {
ZLOGE(LABEL, "unable to get native parcel");
return JNI_FALSE;
}
bool result = nativeParcel->ContainFileDescriptors();
return result ? JNI_TRUE : JNI_FALSE;
}
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeWriteInterfaceToken
* Signature: (Ljava/lang/String;I)Z
*/
jboolean JNICALL Java_ohos_rpc_MessageParcel_nativeWriteInterfaceToken(JNIEnv *env, jobject object, jstring name,
jint len)
{
ZLOGI(LABEL, "%s", __func__);
MessageParcel *nativeParcel = JavaOhosRpcMessageParcelGetNative(env, object);
if (nativeParcel == nullptr) {
ZLOGE(LABEL, "could not get native parcel for marshalling");
return JNI_FALSE;
}
bool result = false;
const jchar *u16chars = env->GetStringCritical(name, 0);
if (u16chars != nullptr) {
const auto *u16Str = reinterpret_cast<const char16_t *>(u16chars);
result = nativeParcel->WriteInterfaceToken(std::u16string(u16Str, len));
env->ReleaseStringCritical(name, u16chars);
}
return result ? JNI_TRUE : JNI_FALSE;
}
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeReadInterfaceToken
* Signature: ()Ljava/lang/String;
*/
jobject JNICALL Java_ohos_rpc_MessageParcel_nativeReadInterfaceToken(JNIEnv *env, jobject object)
{
ZLOGI(LABEL, "%s", __func__);
MessageParcel *nativeParcel = JavaOhosRpcMessageParcelGetNative(env, object);
if (nativeParcel == nullptr) {
ZLOGE(LABEL, "could not get native parcel for marshalling");
return JNI_FALSE;
}
std::u16string name = nativeParcel->ReadInterfaceToken();
return env->NewString(reinterpret_cast<const jchar *>(name.data()), name.size());
}
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeWriteRawData
* Signature: ([BI)Z
*/
jboolean JNICALL Java_ohos_rpc_MessageParcel_nativeWriteRawData(JNIEnv *env, jobject object, jobject rawData, jint size)
{
MessageParcel *nativeParcel = JavaOhosRpcMessageParcelGetNative(env, object);
if (nativeParcel == nullptr) {
ZLOGE(LABEL, "could not get native parcel for raw data");
return JNI_FALSE;
}
jbyte *ptr = static_cast<jbyte *>(env->GetPrimitiveArrayCritical(static_cast<jarray>(rawData), 0));
if (ptr == nullptr) {
return JNI_FALSE;
}
bool result = nativeParcel->WriteRawData(ptr, size);
env->ReleasePrimitiveArrayCritical(static_cast<jarray>(rawData), ptr, 0);
return result ? JNI_TRUE : JNI_FALSE;
}
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeReadRawData
* Signature: (I)[B
*/
jbyteArray JNICALL Java_ohos_rpc_MessageParcel_nativeReadRawData(JNIEnv *env, jobject object, jint size)
{
MessageParcel *nativeParcel = JavaOhosRpcMessageParcelGetNative(env, object);
if (nativeParcel == nullptr) {
ZLOGE(LABEL, "could not get native parcel for rawData");
return nullptr;
}
const void *rawData = nativeParcel->ReadRawData(size);
if (rawData == nullptr) {
ZLOGE(LABEL, "read raw data failed");
return nullptr;
}
jbyteArray bytes = env->NewByteArray(size);
if (bytes == nullptr) {
ZLOGE(LABEL, "NewByteArray failed");
return nullptr;
}
jbyte *ptr = static_cast<jbyte *>(env->GetPrimitiveArrayCritical(bytes, 0));
if (ptr != nullptr) {
int result = memcpy_s(ptr, size, rawData, size);
env->ReleasePrimitiveArrayCritical(bytes, ptr, 0);
if (result != 0) {
ZLOGE(LABEL, "copy raw data failed");
env->DeleteLocalRef(bytes);
return nullptr;
}
}
return bytes;
}
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeGetRawDataCapacity
* Signature: ()I;
*/
jint JNICALL Java_ohos_rpc_MessageParcel_nativeGetRawDataCapacity(JNIEnv *env, jobject object)
{
MessageParcel *nativeParcel = JavaOhosRpcMessageParcelGetNative(env, object);
if (nativeParcel == nullptr) {
ZLOGE(LABEL, "could not get native parcel for rawData");
return 0;
}
return static_cast<jint>(nativeParcel->GetRawDataCapacity());
}
/*
* Set mOwnsNativeObject filed to ohos.rpc.MessageParcel
*/
void JavaOhosRpcMessageOptionSetNativeObjectOwner(JNIEnv *env, jobject object, jboolean value)
{
ZLOGI(LABEL, "%s", __func__);
env->SetBooleanField(object, g_jMessageParcel.nativeObjectOwner, value);
}
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeNewObject
* Signature: (J)J;
*/
jlong JNICALL Java_ohos_rpc_MessageParcel_nativeNewObject(JNIEnv *env, jobject object, jlong nativeObject)
{
ZLOGI(LABEL, "%s", __func__);
MessageParcel *nativeMessageParcel = nullptr;
if (nativeObject != 0) {
nativeMessageParcel = reinterpret_cast<MessageParcel *>(nativeObject);
JavaOhosRpcMessageOptionSetNativeObjectOwner(env, object, JNI_FALSE);
} else {
JavaOhosRpcMessageOptionSetNativeObjectOwner(env, object, JNI_TRUE);
nativeMessageParcel = new MessageParcel();
}
if (nativeMessageParcel == nullptr) {
return 0L;
}
jclass superClass = env->GetSuperclass(g_jMessageParcel.klazz);
if (superClass == nullptr) {
ZLOGE(LABEL, "get supper class for MessageParcel failed");
delete nativeMessageParcel;
return 0L;
}
jmethodID superInit = env->GetMethodID(superClass, "<init>", "(J)V");
if (superInit == nullptr) {
ZLOGE(LABEL, "get supper method for MessageParcel failed");
delete nativeMessageParcel;
return 0L;
}
Parcel *nativeParcel = static_cast<Parcel *>(nativeMessageParcel);
ZLOGI(LABEL, "intSuperClass's native holder:%s", __func__);
env->CallNonvirtualVoidMethod(object, superClass, superInit, reinterpret_cast<jlong>(nativeParcel));
return reinterpret_cast<jlong>(nativeMessageParcel);
}
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeFreeObject
* Signature: (J)V;
*/
void JNICALL Java_ohos_rpc_MessageParcel_nativeFreeObject(JNIEnv *env, jobject object, jlong nativeObject)
{
ZLOGI(LABEL, "%s", __func__);
std::unique_ptr<MessageParcel> nativeParcel(reinterpret_cast<MessageParcel *>(nativeObject));
}
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeCloseFileDescriptor
* Signature: (Ljava/io/FileDescriptor;)V
*/
void JNICALL Java_ohos_rpc_MessageParcel_nativeCloseFileDescriptor(JNIEnv *env, jobject object, jobject descriptor)
{
ZLOGI(LABEL, "%s", __func__);
if (descriptor != nullptr) {
int fd = JniHelperJavaIoGetFdFromFileDescriptor(env, descriptor);
if (fd != INVALID_FD) {
close(fd);
JniHelperJavaIoSetFdToFileDescriptor(env, descriptor, INVALID_FD);
}
}
}
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeDupFileDescriptor
* Signature: (Ljava/io/FileDescriptor;)Ljava/io/FileDescriptor;
*/
jobject JNICALL Java_ohos_rpc_MessageParcel_nativeDupFileDescriptor(JNIEnv *env, jobject object, jobject descriptor)
{
ZLOGI(LABEL, "%s", __func__);
if (descriptor != nullptr) {
int fd = JniHelperJavaIoGetFdFromFileDescriptor(env, descriptor);
int dupFd = INVALID_FD;
if (fd != INVALID_FD) {
dupFd = dup(fd);
}
if (dupFd != INVALID_FD) {
return JniHelperJavaIoCreateFileDescriptor(env, dupFd);
}
}
return nullptr;
}
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeWriteAshmem
* Signature: (J)Z
*/
jboolean JNICALL Java_ohos_rpc_MessageParcel_nativeWriteAshmem(JNIEnv *env, jobject object, jlong id)
{
ZLOGI(LABEL, "%s", __func__);
MessageParcel *nativeParcel = JavaOhosRpcMessageParcelGetNative(env, object);
if (nativeParcel == nullptr) {
ZLOGE(LABEL, "could not get native parcel for raw data");
return JNI_FALSE;
}
sptr<Ashmem> ashmem = Java_ohos_rpc_Ashmem_getSptrAshmem(env, object, id);
if (ashmem == nullptr) {
ZLOGE(LABEL, "%s: ashmem=null", __func__);
return JNI_FALSE;
}
bool result = nativeParcel->WriteAshmem(ashmem);
return result ? JNI_TRUE : JNI_FALSE;
}
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeReadAshmem
* Signature: (V)J
*/
jlong JNICALL Java_ohos_rpc_MessageParcel_nativeReadAshmem(JNIEnv *env, jobject object)
{
ZLOGI(LABEL, "%s", __func__);
MessageParcel *nativeParcel = JavaOhosRpcMessageParcelGetNative(env, object);
if (nativeParcel == nullptr) {
ZLOGE(LABEL, "could not get native parcel for rawData");
return 0;
}
sptr<Ashmem> nativeAshmem = nativeParcel->ReadAshmem();
if (nativeAshmem == nullptr) {
ZLOGE(LABEL, "read raw data failed");
return 0;
}
// memory is released in Java_ohos_rpc_MessageParcel_nativeReleaseAshmem
AshmemSmartPointWrapper *wrapper = new AshmemSmartPointWrapper(nativeAshmem);
return reinterpret_cast<jlong>(wrapper);
}
/*
* Class: ohos.rpc.MessageParcel
* Method: nativeReleaseAshmem
* Signature: (J)V
*/
void JNICALL Java_ohos_rpc_MessageParcel_nativeReleaseAshmem(JNIEnv *env, jobject object, jlong id)
{
ZLOGI(LABEL, "%s", __func__);
if (id == 0) {
return;
}
std::unique_ptr<AshmemSmartPointWrapper> nativeParcel(reinterpret_cast<AshmemSmartPointWrapper *>(id));
}

View File

@ -0,0 +1,982 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ohos_rpc_remote_object.h"
#include <mutex>
#include <set>
#include "ipc_debug.h"
#include "jni_helper.h"
#include "ohos_utils_parcel.h"
#include "ohos_rpc_message_option.h"
#include "ohos_rpc_message_parcel.h"
#include "ipc_object_stub.h"
#include "ipc_object_proxy.h"
#include "ipc_thread_skeleton.h"
#include "ipc_skeleton.h"
#include "ipc_types.h"
#include "log_tags.h"
#include "jkit_utils.h"
using namespace OHOS;
using namespace OHOS::HiviewDFX;
namespace OHOS {
static constexpr HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "IPCJni" };
class JDeathRecipientList;
class JRemoteObjectHolder;
struct JRemoteObjectDesc {
jclass klass;
jmethodID methodDispatchRequest;
jfieldID fieldNativeHolder;
jmethodID methodDispatchDump;
};
struct JRemoteProxyDesc {
jclass klass;
jmethodID methodGetInstance;
jmethodID methodSendObituary;
jfieldID fieldNativeData;
};
class JRemoteProxyHolder {
public:
JRemoteProxyHolder();
~JRemoteProxyHolder();
sptr<JDeathRecipientList> list_;
sptr<IRemoteObject> object_;
};
/*
* the native RemoteObject act as bridger between java and native.
* It received the request from client and pass it Java Layer.
*/
class JRemoteObject : public IPCObjectStub {
public:
JRemoteObject(jobject object, const std::u16string &descriptor);
~JRemoteObject() override;
bool CheckObjectLegality() const override;
int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override;
int OnRemoteDump(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override;
jobject GetJObject() const;
private:
jobject object_;
};
/*
* To ensure a better consistency of the life time of
* Java IPC Object and native object we designed
* a container to save the native object.
*/
class JRemoteObjectHolder : public RefBase {
public:
explicit JRemoteObjectHolder(const std::u16string &descriptor);
~JRemoteObjectHolder();
sptr<JRemoteObject> Get(jobject object);
private:
std::mutex mutex_;
std::u16string descriptor_;
sptr<JRemoteObject> cachedObject_;
};
/*
* the native DeathRecipient container.
* As an recipient of Obituary of service death.
* and pass the message to Java Layer.
*/
class JDeathRecipient : public IRemoteObject::DeathRecipient {
public:
explicit JDeathRecipient(jobject object);
void OnRemoteDied(const wptr<IRemoteObject> &object) override;
bool Matches(jobject object);
protected:
virtual ~JDeathRecipient();
private:
std::mutex mutex_;
jobject refObject_;
jweak weakRefObject_ {};
};
/*
* the native DeathRecipient container
*/
class JDeathRecipientList : public RefBase {
std::set<sptr<JDeathRecipient>> set_;
std::mutex mutex_;
public:
JDeathRecipientList();
~JDeathRecipientList();
bool Add(const sptr<JDeathRecipient> &recipient);
bool Remove(const sptr<JDeathRecipient> &recipient);
sptr<JDeathRecipient> Find(jobject recipient);
};
// Global variable definition.
static JRemoteProxyHolder *g_cachedProxyHolder;
static struct JRemoteObjectDesc g_jRemoteStub;
static struct JRemoteProxyDesc g_jRemoteProxy;
static std::mutex g_proxyMutex_;
static bool g_ipcNativeMethodsLoaded = false;
JRemoteObject::JRemoteObject(jobject object, const std::u16string &descriptor) : IPCObjectStub(descriptor)
{
JNIEnvHelper env;
if (env.Get() != nullptr && object != nullptr) {
object_ = env->NewGlobalRef(object);
} else {
object_ = nullptr;
}
}
bool JRemoteObject::CheckObjectLegality() const
{
return true;
}
JRemoteObject::~JRemoteObject()
{
JNIEnvHelper env;
if (env.Get() != nullptr && object_ != nullptr) {
env->DeleteGlobalRef(object_);
}
}
jobject JRemoteObject::GetJObject() const
{
return object_;
}
int JRemoteObject::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
{
JNIEnvHelper env;
if (env.Get() == nullptr) {
return ERR_TRANSACTION_FAILED;
}
if (code == DUMP_TRANSACTION) {
ZLOGE(LABEL, "DUMP_TRANSACTION data size:%zu", data.GetReadableBytes());
}
jobject javaOption = JavaOhosRpcMessageOptionNewJavaObject(env.Get(), option.GetFlags(), option.GetWaitTime());
jboolean res = env->CallBooleanMethod(object_, g_jRemoteStub.methodDispatchRequest, code,
reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(&reply), javaOption);
env->DeleteLocalRef(javaOption);
if (JniHelperCheckAndClearLocalException(env.Get())) {
ZLOGE(LABEL, "OnRemoteRequest found exception, res:%{public}d", res);
return ERR_UNKNOWN_TRANSACTION;
}
if (code == SYSPROPS_TRANSACTION) {
int result = IPCObjectStub::OnRemoteRequest(code, data, reply, option);
if (result != ERR_NONE) {
ZLOGE(LABEL, "OnRemoteRequest res:%{public}d", result);
return ERR_INVALID_DATA;
}
}
if (!res) {
ZLOGE(LABEL, "OnRemoteRequest res:%{public}d", res);
return ERR_UNKNOWN_TRANSACTION;
}
return ERR_NONE;
}
int JRemoteObject::OnRemoteDump(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
{
JNIEnvHelper env;
if (env.Get() == nullptr) {
return ERR_TRANSACTION_FAILED;
}
jobject javaOption = JavaOhosRpcMessageOptionNewJavaObject(env.Get(), option.GetFlags(), option.GetWaitTime());
jboolean res = env->CallBooleanMethod(object_, g_jRemoteStub.methodDispatchDump, code,
reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(&reply), javaOption);
if (JniHelperCheckAndClearLocalException(env.Get())) {
res = JNI_FALSE;
}
env->DeleteLocalRef(javaOption);
ZLOGI(LABEL, "OnRemoteDump res:%d", res);
return res ? ERR_NONE : ERR_UNKNOWN_TRANSACTION;
}
JRemoteObjectHolder::JRemoteObjectHolder(const std::u16string &descriptor)
: descriptor_(descriptor), cachedObject_(nullptr)
{}
JRemoteObjectHolder::~JRemoteObjectHolder()
{
// free the reference of object.
cachedObject_ = nullptr;
}
sptr<JRemoteObject> JRemoteObjectHolder::Get(jobject object)
{
std::lock_guard<std::mutex> lockGuard(mutex_);
// grab an strong reference to the object,
// so it will not be freed util this reference released.
sptr<JRemoteObject> remoteObject = nullptr;
if (cachedObject_ != nullptr) {
remoteObject = cachedObject_;
}
if (remoteObject == nullptr) {
remoteObject = new JRemoteObject(object, descriptor_);
cachedObject_ = remoteObject;
}
return remoteObject;
}
JRemoteProxyHolder::JRemoteProxyHolder() : list_(nullptr), object_(nullptr) {}
JRemoteProxyHolder::~JRemoteProxyHolder()
{
list_ = nullptr;
object_ = nullptr;
}
JDeathRecipient::JDeathRecipient(jobject object)
{
JNIEnvHelper env;
if (env.Get() != nullptr) {
refObject_ = env->NewGlobalRef(object);
} else {
refObject_ = nullptr;
}
}
void JDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object)
{
ZLOGI(LABEL, "OnRemoteDied called");
if (refObject_ == nullptr) {
ZLOGE(LABEL, "Object has already removed");
return;
}
JNIEnvHelper env;
if (env.Get() == nullptr) {
return;
}
env->CallStaticVoidMethod(g_jRemoteProxy.klass, g_jRemoteProxy.methodSendObituary, refObject_);
JniHelperCheckAndClearLocalException(env.Get());
weakRefObject_ = env->NewWeakGlobalRef(refObject_);
env->DeleteGlobalRef(refObject_);
std::lock_guard<std::mutex> lockGuard(mutex_);
refObject_ = nullptr;
}
bool JDeathRecipient::Matches(jobject object)
{
JNIEnvHelper env;
if (env.Get() == nullptr) {
return false;
}
bool result = false;
if (object != nullptr) {
std::lock_guard<std::mutex> lockGuard(mutex_);
if (refObject_ != nullptr) {
result = env->IsSameObject(object, refObject_);
}
} else {
if (weakRefObject_ == nullptr) {
return false;
}
jobject me = env->NewLocalRef(weakRefObject_);
result = env->IsSameObject(object, me);
env->DeleteLocalRef(me);
}
return result;
}
JDeathRecipient::~JDeathRecipient()
{
JNIEnvHelper env;
if (env.Get() != nullptr) {
if (refObject_ != nullptr) {
env->DeleteGlobalRef(refObject_);
} else {
if (weakRefObject_ != nullptr) {
env->DeleteWeakGlobalRef(weakRefObject_);
}
}
}
}
JDeathRecipientList::JDeathRecipientList() {}
JDeathRecipientList::~JDeathRecipientList()
{
std::lock_guard<std::mutex> lockGuard(mutex_);
set_.clear();
}
bool JDeathRecipientList::Add(const sptr<JDeathRecipient> &recipient)
{
std::lock_guard<std::mutex> lockGuard(mutex_);
auto ret = set_.insert(recipient);
return ret.second;
}
bool JDeathRecipientList::Remove(const sptr<JDeathRecipient> &recipient)
{
std::lock_guard<std::mutex> lockGuard(mutex_);
return (set_.erase(recipient) > 0);
}
sptr<JDeathRecipient> JDeathRecipientList::Find(jobject recipient)
{
std::lock_guard<std::mutex> lockGuard(mutex_);
for (auto it = set_.begin(); it != set_.end(); it++) {
if ((*it)->Matches(recipient)) {
return *it;
}
}
return nullptr;
}
JRemoteProxyHolder *Java_ohos_rpc_getRemoteProxyHolder(JNIEnv *env, jobject object)
{
return reinterpret_cast<JRemoteProxyHolder *>(env->GetLongField(object, g_jRemoteProxy.fieldNativeData));
}
jobject Java_ohos_rpc_getJavaRemoteObject(JNIEnv *env, const sptr<IRemoteObject> target)
{
ZLOGI(LABEL, "%s", __func__);
if (target == nullptr) {
ZLOGE(LABEL, "RemoteObject is null");
return nullptr;
}
if (target->CheckObjectLegality()) {
ZLOGI(LABEL, "native Get RemoteObject");
auto object = static_cast<JRemoteObject *>(target.GetRefPtr());
return object->GetJObject();
}
std::lock_guard<std::mutex> lockGuard(g_proxyMutex_);
JRemoteProxyHolder *cachedHolder = g_cachedProxyHolder;
if (cachedHolder == nullptr) {
cachedHolder = new JRemoteProxyHolder();
}
jobject object = env->CallStaticObjectMethod(g_jRemoteProxy.klass, g_jRemoteProxy.methodGetInstance,
reinterpret_cast<jlong>(cachedHolder));
if (JniHelperCheckAndClearLocalException(env)) {
if (g_cachedProxyHolder == nullptr) {
delete cachedHolder;
}
return nullptr;
}
JRemoteProxyHolder *objectHolder = Java_ohos_rpc_getRemoteProxyHolder(env, object);
// If the objects holder is same as the cached holder it should be a new create holder.
if (cachedHolder == objectHolder) {
objectHolder->object_ = target;
objectHolder->list_ = new JDeathRecipientList();
g_cachedProxyHolder = nullptr;
} else {
g_cachedProxyHolder = cachedHolder;
}
return object;
}
sptr<IRemoteObject> Java_ohos_rpc_getNativeRemoteObject(JNIEnv *env, jobject object)
{
ZLOGI(LABEL, "%s", __func__);
if (object != nullptr) {
if (env->IsInstanceOf(object, g_jRemoteStub.klass)) {
JRemoteObjectHolder *holder =
reinterpret_cast<JRemoteObjectHolder *>(env->GetLongField(object, g_jRemoteStub.fieldNativeHolder));
return holder != nullptr ? holder->Get(object) : nullptr;
}
if (env->IsInstanceOf(object, g_jRemoteProxy.klass)) {
JRemoteProxyHolder *holder = Java_ohos_rpc_getRemoteProxyHolder(env, object);
return holder != nullptr ? holder->object_ : nullptr;
}
}
return nullptr;
}
} // namespace OHOS
/*
* Class: ohos.rpc.IPCSkeleton
* Method: nativeGetContextObject
* Signature: ()Lohos/rpc/IRemoteObject;
*/
jobject JNICALL Java_ohos_rpc_IPCSkeleton_nativeGetContextObject(JNIEnv *env, jclass clazz)
{
ZLOGI(LABEL, "%s", __func__);
sptr<IRemoteObject> object = IPCSkeleton::GetContextObject();
if (object == nullptr) {
ZLOGE(LABEL, "fatal error, could not get registry object");
return nullptr;
}
return Java_ohos_rpc_getJavaRemoteObject(env, object);
}
/*
* Class: ohos.rpc.IPCSkeleton
* Method: nativeGetCallingPid
* Signature: ()I;
*/
jint JNICALL Java_ohos_rpc_IPCSkeleton_nativeGetCallingPid(JNIEnv *env, jclass clazz)
{
pid_t pid = IPCSkeleton::GetCallingPid();
return static_cast<jint>(pid);
}
/*
* Class: ohos.rpc.IPCSkeleton
* Method: nativeGetCallingUid
* Signature: ()I;
*/
jint JNICALL Java_ohos_rpc_IPCSkeleton_nativeGetCallingUid(JNIEnv *env, jclass clazz)
{
uid_t uid = IPCSkeleton::GetCallingUid();
return static_cast<jint>(uid);
}
/*
* Class: ohos.rpc.IPCSkeleton
* Method: nativeGetCallingDeviceID
* Signature: (V)Ljava/lang/String;
*/
jstring JNICALL Java_ohos_rpc_IPCSkeleton_nativeGetCallingDeviceID(JNIEnv *env, jclass clazz)
{
std::string deviceId = IPCSkeleton::GetCallingDeviceID();
return env->NewStringUTF(deviceId.c_str());
}
/*
* Class: ohos.rpc.IPCSkeleton
* Method: nativeGetLocalDeviceID
* Signature: (V)Ljava/lang/String;
*/
jstring JNICALL Java_ohos_rpc_IPCSkeleton_nativeGetLocalDeviceID(JNIEnv *env, jclass clazz)
{
std::string deviceId = IPCSkeleton::GetLocalDeviceID();
return env->NewStringUTF(deviceId.c_str());
}
/*
* Class: ohos.rpc.IPCSkeleton
* Method: nativeIsLocalCalling
* Signature: ()Z;
*/
jboolean JNICALL Java_ohos_rpc_IPCSkeleton_nativeIsLocalCalling(JNIEnv *env, jclass clazz)
{
return (IPCSkeleton::IsLocalCalling() == true) ? JNI_TRUE : JNI_FALSE;
}
/*
* Class: ohos.rpc.IPCSkeleton
* Method: nativeIsLocalCalling
* Signature: (Lohos/rpc/IRemoteObject;)I;
*/
jint JNICALL Java_ohos_rpc_IPCSkeleton_nativeFlushCommands(JNIEnv *env, jclass clazz, jobject object)
{
sptr<IRemoteObject> target = Java_ohos_rpc_getNativeRemoteObject(env, object);
return static_cast<jint>(IPCSkeleton::FlushCommands(target));
}
/*
* Class: ohos.rpc.IPCSkeleton
* Method: nativeResetCallingIdentity
* Signature: ()Ljava/lang/String;
*/
jstring JNICALL Java_ohos_rpc_IPCSkeleton_nativeResetCallingIdentity(JNIEnv *env, jclass clazz)
{
std::string identity = IPCSkeleton::ResetCallingIdentity();
return env->NewStringUTF(identity.c_str());
}
/*
* Class: ohos.rpc.IPCSkeleton
* Method: nativeSetCallingIdentity
* Signature: ((Ljava/lang/String;I)Z
*/
jboolean JNICALL Java_ohos_rpc_IPCSkeleton_nativeSetCallingIdentity(JNIEnv *env, jclass clazz, jstring identity,
jint len)
{
const char *identityUtf = env->GetStringUTFChars(identity, JNI_FALSE);
if (identityUtf != nullptr) {
std::string token = std::string(identityUtf, len);
env->ReleaseStringUTFChars(identity, identityUtf);
return (IPCSkeleton::SetCallingIdentity(token) == true) ? JNI_TRUE : JNI_FALSE;
}
return JNI_FALSE;
}
/*
* Class: ohos.rpc.RemoteObject
* Method: nativeGetObjectHolder
* Signature: (Ljava/lang/String;I)J
*/
jlong JNICALL Java_ohos_rpc_RemoteObject_nativeGetObjectHolder(JNIEnv *env, jclass clazz, jstring value, jint len)
{
std::u16string descriptor = std::u16string();
if (value != nullptr) {
const jchar *jcharStr = env->GetStringCritical(value, 0);
if (jcharStr != nullptr) {
descriptor.assign(reinterpret_cast<const char16_t *>(jcharStr), reinterpret_cast<int32_t>(len));
env->ReleaseStringCritical(value, jcharStr);
}
}
return (jlong)(new JRemoteObjectHolder(descriptor));
}
/*
* Get calling pid from native.
* Class: ohos.rpc.RemoteObject
* Method: nativeGetCallingPid
* Signature: ()I
*/
jint JNICALL Java_ohos_rpc_RemoteObject_nativeGetCallingPid(JNIEnv *env, jclass object)
{
sptr<IRemoteObject> nativeObject = Java_ohos_rpc_getNativeRemoteObject(env, object);
if ((nativeObject != nullptr) && (!nativeObject->IsProxyObject())) {
IPCObjectStub *target = reinterpret_cast<IPCObjectStub *>(nativeObject.GetRefPtr());
return target->GetCallingPid();
}
return getpid();
}
/*
* Get calling uid from native.
* Class: ohos.rpc.RemoteObject
* Method: nativeGetCallingUid
* Signature: ()I
*/
jint JNICALL Java_ohos_rpc_RemoteObject_nativeGetCallingUid(JNIEnv *env, jclass object)
{
sptr<IRemoteObject> nativeObject = Java_ohos_rpc_getNativeRemoteObject(env, object);
if ((nativeObject != nullptr) && (!nativeObject->IsProxyObject())) {
IPCObjectStub *target = reinterpret_cast<IPCObjectStub *>(nativeObject.GetRefPtr());
return target->GetCallingUid();
}
return getuid();
}
/*
* Free local Object Holder of RemoteObject.
* Class: ohos.rpc.RemoteObject
* Method: nativeFreeObjectHolder
* Signature: (J)V
*/
void JNICALL Java_ohos_rpc_RemoteObject_nativeFreeObjectHolder(JNIEnv *env, jclass clazz, jlong holder)
{
// Delegate sptr to manage memory,
// it will automatically release managed memory when the life cycle ends.
ZLOGI(LABEL, "Call Free Object Holder");
std::unique_ptr<JRemoteObjectHolder> nativeHolder(reinterpret_cast<JRemoteObjectHolder *>(holder));
}
/*
* Free local Object Holder of RemoteObject.
* Class: ohos.rpc.RemoteProxy
* Method: nativeFreeProxyHolder
* Signature: (J)V
*/
void JNICALL Java_ohos_rpc_RemoteProxy_nativeFreeProxyHolder(JNIEnv *env, jclass clazz, jlong holder)
{
// Delegate sptr to manage memory,
// it will automatically release managed memory when the life cycle ends.
ZLOGI(LABEL, "Call Free Proxy Holder");
std::unique_ptr<JRemoteProxyHolder> nativeHolder(reinterpret_cast<JRemoteProxyHolder *>(holder));
}
/*
* Class: ohos.rpc.RemoteProxy
* Method: nativeSendRequest
* Signature: (ILohos/rpc/MessageParcel;Lohos/rpc/Parcel;Lohos/rpc/MessageOption;)Z
*/
jboolean JNICALL Java_ohos_rpc_RemoteProxy_nativeSendRequest(JNIEnv *env, jobject object, jint code, jobject data,
jobject reply, jobject option)
{
ZLOGI(LABEL, "%s", __func__);
MessageParcel *nativeData = JavaOhosRpcMessageParcelGetNative(env, data);
if (nativeData == nullptr) {
JniHelperThrowNullPointerException(env, "data field is null");
return JNI_FALSE;
}
MessageParcel *nativeReply = JavaOhosRpcMessageParcelGetNative(env, reply);
if (nativeReply == nullptr) {
ZLOGE(LABEL, "Fail to get native parcel for reply");
return JNI_FALSE;
}
MessageOptionPtr nativeOption = JavaOhosRpcMessageOptionGetNative(env, option);
if (nativeOption == nullptr) {
ZLOGE(LABEL, "Fail to get native parcel for reply");
return JNI_FALSE;
}
JRemoteProxyHolder *holder = Java_ohos_rpc_getRemoteProxyHolder(env, object);
if (holder == nullptr) {
JniHelperThrowIllegalStateException(env, "Proxy has been finalized!");
return JNI_FALSE;
}
sptr<IRemoteObject> target = holder->object_;
if (target == nullptr) {
ZLOGE(LABEL, "Invalid proxy object");
return JNI_FALSE;
}
int result = target->SendRequest(code, *nativeData, *nativeReply, *nativeOption.get());
ZLOGI(LABEL, "nativeSendRequest result %d", result);
return (result == ERR_NONE) ? JNI_TRUE : JNI_FALSE;
}
/*
* Class: ohos.rpc.RemoteProxy
* Method: nativeAddDeathRecipient
* Signature: (Lohos/rpc/IRemoteObject$DeathRecipient;I)Z
*/
jboolean JNICALL Java_ohos_rpc_RemoteProxy_nativeAddDeathRecipient(JNIEnv *env, jobject object, jobject recipient,
jint flags)
{
if (recipient == nullptr) {
JniHelperThrowNullPointerException(env, "the recipient is null");
return JNI_FALSE;
}
JRemoteProxyHolder *holder = Java_ohos_rpc_getRemoteProxyHolder(env, object);
if (holder == nullptr) {
JniHelperThrowIllegalStateException(env, "Proxy has been finalized!");
return JNI_FALSE;
}
sptr<IRemoteObject> target = holder->object_;
if ((target == nullptr) || !target->IsProxyObject()) {
ZLOGE(LABEL, "could not add recipient from invalid target");
return JNI_FALSE;
}
sptr<JDeathRecipient> nativeRecipient = new JDeathRecipient(recipient);
if (target->AddDeathRecipient(nativeRecipient)) {
JDeathRecipientList *list = holder->list_;
return (list->Add(nativeRecipient) ? JNI_TRUE : JNI_FALSE);
}
return JNI_FALSE;
}
/*
* Class: ohos.rpc.RemoteProxy
* Method: nativeRemoveDeathRecipient
* Signature: (Lohos/rpc/IRemoteObject$DeathRecipient;I)Z
*/
jboolean JNICALL Java_ohos_rpc_RemoteProxy_nativeRemoveDeathRecipient(JNIEnv *env, jobject object, jobject recipient,
jint flags)
{
if (recipient == nullptr) {
JniHelperThrowNullPointerException(env, "the recipient is null");
return JNI_FALSE;
}
JRemoteProxyHolder *holder = Java_ohos_rpc_getRemoteProxyHolder(env, object);
if (holder == nullptr) {
JniHelperThrowIllegalStateException(env, "Proxy has been finalized!");
return JNI_FALSE;
}
sptr<IRemoteObject> target = holder->object_;
if ((target == nullptr) || !target->IsProxyObject()) {
ZLOGE(LABEL, "could not remove recipient from invalid target");
return JNI_FALSE;
}
// list should not be null here, it should be alloc at create proxy object.
sptr<JDeathRecipientList> list = holder->list_;
sptr<JDeathRecipient> nativeRecipient = list->Find(recipient);
if (nativeRecipient == nullptr) {
ZLOGE(LABEL, "recipient not found");
return JNI_FALSE;
}
target->RemoveDeathRecipient(nativeRecipient);
return (list->Remove(nativeRecipient) ? JNI_TRUE : JNI_FALSE);
}
/*
* Class: ohos.rpc.RemoteProxy
* Method: nativeGetInterfaceDescriptor
* Signature: ()Ljava/lang/String;
*/
jstring JNICALL Java_ohos_rpc_RemoteProxy_nativeGetInterfaceDescriptor(JNIEnv *env, jobject object)
{
JRemoteProxyHolder *holder = Java_ohos_rpc_getRemoteProxyHolder(env, object);
if (holder == nullptr) {
JniHelperThrowIllegalStateException(env, "Proxy has been finalized!");
return env->NewStringUTF("");
}
IPCObjectProxy *target = reinterpret_cast<IPCObjectProxy *>(holder->object_.GetRefPtr());
if (target == nullptr) {
ZLOGE(LABEL, "Invalid proxy object");
return env->NewStringUTF("");
}
std::u16string remoteDescriptor = target->GetInterfaceDescriptor();
return env->NewStringUTF(Str16ToStr8(remoteDescriptor).c_str());
}
/*
* Class: ohos.rpc.RemoteProxy
* Method: nativeIsObjectDead
* Signature: ()Z
*/
jboolean JNICALL Java_ohos_rpc_RemoteProxy_nativeIsObjectDead(JNIEnv *env, jobject object)
{
JRemoteProxyHolder *holder = Java_ohos_rpc_getRemoteProxyHolder(env, object);
if (holder == nullptr) {
JniHelperThrowIllegalStateException(env, "Proxy has been finalized!");
return JNI_TRUE;
}
IPCObjectProxy *target = reinterpret_cast<IPCObjectProxy *>(holder->object_.GetRefPtr());
if (target == nullptr) {
ZLOGE(LABEL, "Invalid proxy object");
return JNI_TRUE;
}
return (target->IsObjectDead() == true) ? JNI_TRUE : JNI_FALSE;
}
/*
* Class: ohos.rpc.RemoteProxy
* Method: nativeGetHandle
* Signature: ()J
*/
jlong JNICALL Java_ohos_rpc_RemoteProxy_nativeGetHandle(JNIEnv *env, jobject object)
{
JRemoteProxyHolder *holder = Java_ohos_rpc_getRemoteProxyHolder(env, object);
if (holder == nullptr) {
JniHelperThrowIllegalStateException(env, "Proxy has been finalized!");
return 0;
}
IPCObjectProxy *target = reinterpret_cast<IPCObjectProxy *>(holder->object_.GetRefPtr());
if (target == nullptr) {
ZLOGE(LABEL, "Invalid proxy object");
return 0;
}
return (jlong)target->GetHandle();
}
static const JNINativeMethod sMethods[] = {
/* Name, Signature, FunctionPointer */
{ "nativeGetContextObject", "()Lohos/rpc/IRemoteObject;",
(void *)Java_ohos_rpc_IPCSkeleton_nativeGetContextObject },
{ "nativeGetCallingPid", "()I", (void *)Java_ohos_rpc_IPCSkeleton_nativeGetCallingPid },
{ "nativeGetCallingUid", "()I", (void *)Java_ohos_rpc_IPCSkeleton_nativeGetCallingUid },
{ "nativeGetCallingDeviceID", "()Ljava/lang/String;", (void *)Java_ohos_rpc_IPCSkeleton_nativeGetCallingDeviceID },
{ "nativeGetLocalDeviceID", "()Ljava/lang/String;", (void *)Java_ohos_rpc_IPCSkeleton_nativeGetLocalDeviceID },
{ "nativeIsLocalCalling", "()Z", (void *)Java_ohos_rpc_IPCSkeleton_nativeIsLocalCalling },
{ "nativeFlushCommands", "(Lohos/rpc/IRemoteObject;)I", (void *)Java_ohos_rpc_IPCSkeleton_nativeFlushCommands },
{ "nativeResetCallingIdentity", "()Ljava/lang/String;",
(void *)Java_ohos_rpc_IPCSkeleton_nativeResetCallingIdentity },
{ "nativeSetCallingIdentity", "(Ljava/lang/String;I)Z",
(void *)Java_ohos_rpc_IPCSkeleton_nativeSetCallingIdentity },
};
static const JNINativeMethod sObjectMethods[] = {
/* Name, Signature, FunctionPointer */
{ "nativeGetObjectHolder", "(Ljava/lang/String;I)J", (void *)Java_ohos_rpc_RemoteObject_nativeGetObjectHolder },
{ "nativeFreeObjectHolder", "(J)V", (void *)Java_ohos_rpc_RemoteObject_nativeFreeObjectHolder },
{ "nativeGetCallingPid", "()I", (void *)Java_ohos_rpc_RemoteObject_nativeGetCallingPid },
{ "nativeGetCallingUid", "()I", (void *)Java_ohos_rpc_RemoteObject_nativeGetCallingUid },
};
static const JNINativeMethod sProxyMethods[] = {
/* Name, Signature, FunctionPointer */
{ "nativeFreeProxyHolder", "(J)V", (void *)Java_ohos_rpc_RemoteProxy_nativeFreeProxyHolder },
{ "nativeGetInterfaceDescriptor", "()Ljava/lang/String;",
(void *)Java_ohos_rpc_RemoteProxy_nativeGetInterfaceDescriptor },
{ "nativeSendRequest", "(ILohos/rpc/MessageParcel;Lohos/rpc/MessageParcel;Lohos/rpc/MessageOption;)Z",
(void *)Java_ohos_rpc_RemoteProxy_nativeSendRequest },
{ "nativeAddDeathRecipient", "(Lohos/rpc/IRemoteObject$DeathRecipient;I)Z",
(void *)Java_ohos_rpc_RemoteProxy_nativeAddDeathRecipient },
{ "nativeRemoveDeathRecipient", "(Lohos/rpc/IRemoteObject$DeathRecipient;I)Z",
(void *)Java_ohos_rpc_RemoteProxy_nativeRemoveDeathRecipient },
{ "nativeIsObjectDead", "()Z", (void *)Java_ohos_rpc_RemoteProxy_nativeIsObjectDead },
{ "nativeGetHandle", "()J", (void *)Java_ohos_rpc_RemoteProxy_nativeGetHandle }
};
int JavaOhosRpcIpcSkeletonRegisterNativeMethods(JNIEnv *env)
{
return JkitRegisterNativeMethods(env, "ohos/rpc/IPCSkeleton", sMethods, NUM_METHODS(sMethods));
}
int JavaOhosRpcRemoteObjectRegisterNativeMethods(JNIEnv *env)
{
jclass clazz = env->FindClass("ohos/rpc/RemoteObject");
if (clazz == nullptr) {
ZLOGE(LABEL, "Could not find class:RemoteObject");
return -1;
}
g_jRemoteStub.klass = (jclass)env->NewGlobalRef(clazz);
if (g_jRemoteStub.klass == nullptr) {
ZLOGE(LABEL, "JRemoteObject NewGlobalRef failed");
return -1;
}
g_jRemoteStub.methodDispatchRequest = env->GetMethodID(clazz, "dispatchRequest", "(IJJLohos/rpc/MessageOption;)Z");
if (g_jRemoteStub.methodDispatchRequest == nullptr) {
ZLOGE(LABEL, "JRemoteObject get method execTransact failed");
env->DeleteGlobalRef(g_jRemoteStub.klass);
return -1;
}
g_jRemoteStub.methodDispatchDump = env->GetMethodID(clazz, "dispatchDump", "(IJJLohos/rpc/MessageOption;)Z");
if (g_jRemoteStub.methodDispatchDump == nullptr) {
ZLOGE(LABEL, "JRemoteObject get method execTransact failed");
env->DeleteGlobalRef(g_jRemoteStub.klass);
return -1;
}
g_jRemoteStub.fieldNativeHolder = env->GetFieldID(clazz, "mNativeHolder", "J");
if (g_jRemoteStub.fieldNativeHolder == nullptr) {
ZLOGE(LABEL, "JRemoteObject get field mNativeHolder failed");
env->DeleteGlobalRef(g_jRemoteStub.klass);
return -1;
}
return JkitRegisterNativeMethods(env, "ohos/rpc/RemoteObject", sObjectMethods, NUM_METHODS(sObjectMethods));
}
int JavaOhosRpcRemoteProxyRegisterNativeMethods(JNIEnv *env)
{
jclass clazz = env->FindClass("ohos/rpc/RemoteProxy");
if (clazz == nullptr) {
ZLOGE(LABEL, "Could not find class:RemoteProxy");
return -1;
}
g_jRemoteProxy.klass = (jclass)env->NewGlobalRef(clazz);
g_jRemoteProxy.methodGetInstance = env->GetStaticMethodID(clazz, "getInstance", "(J)Lohos/rpc/RemoteProxy;");
if (g_jRemoteProxy.methodGetInstance == nullptr) {
ZLOGE(LABEL, "JRemoteProxy get method getInstance failed");
env->DeleteGlobalRef(g_jRemoteProxy.klass);
return -1;
}
g_jRemoteProxy.methodSendObituary =
env->GetStaticMethodID(clazz, "sendObituary", "(Lohos/rpc/IRemoteObject$DeathRecipient;)V");
if (g_jRemoteProxy.methodSendObituary == nullptr) {
env->DeleteGlobalRef(g_jRemoteProxy.klass);
ZLOGE(LABEL, "JRemoteProxy get method sendObituary failed");
return -1;
}
g_jRemoteProxy.fieldNativeData = env->GetFieldID(clazz, "mNativeData", "J");
if (g_jRemoteProxy.fieldNativeData == nullptr) {
env->DeleteGlobalRef(g_jRemoteProxy.klass);
ZLOGE(LABEL, "JRemoteProxy get field mNativeData failed");
return -1;
}
return JkitRegisterNativeMethods(env, "ohos/rpc/RemoteProxy", sProxyMethods, NUM_METHODS(sProxyMethods));
}
int RegisterJavaRpcNativeMethods(JNIEnv *env)
{
if (JniHelperRegisterNativeMethods(env) < 0) {
ZLOGE(LABEL, "Register JniHelper Native Methods failed");
return -1;
}
if (JavaOhosRpcMessageOptionRegisterNativeMethods(env) < 0) {
ZLOGE(LABEL, "Register MessageOption Native Methods failed");
return -1;
}
if (JavaOhosRpcMessageParcelRegisterNativeMethods(env) < 0) {
ZLOGE(LABEL, "Register MessageParcel Native Methods failed");
return -1;
}
if (JavaOhosRpcIpcSkeletonRegisterNativeMethods(env) < 0) {
ZLOGE(LABEL, "Register IPCSkeleton Native Methods failed");
return -1;
}
if (JavaOhosRpcRemoteObjectRegisterNativeMethods(env) < 0) {
ZLOGE(LABEL, "Register JRemoteObject Native Methods failed");
return -1;
}
if (JavaOhosRpcRemoteProxyRegisterNativeMethods(env) < 0) {
ZLOGE(LABEL, "Register JRemoteProxy Native Methods failed");
return -1;
}
if (Java_ohos_utils_Parcel_registerNativeMethods(env) < 0) {
ZLOGE(LABEL, "Register JParcel Native Methods failed");
return -1;
}
return 0;
}
jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
if (vm == nullptr) {
return -1;
}
if (!g_ipcNativeMethodsLoaded) {
JNIEnv *env = NULL;
if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_4) != JNI_OK) {
return -1;
}
if (RegisterJavaRpcNativeMethods(env) < 0) {
return -1;
}
JNIEnvHelper::nativeInit(vm);
g_ipcNativeMethodsLoaded = true;
}
return JNI_VERSION_1_4;
}

View File

@ -0,0 +1,48 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_BINDER_CONNECTOR_H
#define OHOS_IPC_BINDER_CONNECTOR_H
#include <string>
#include <mutex>
namespace OHOS {
#ifdef CONFIG_IPC_SINGLE
namespace IPC_SINGLE {
#endif
class BinderConnector {
public:
static BinderConnector *GetInstance();
BinderConnector(const std::string &deviceName);
~BinderConnector();
int WriteBinder(unsigned long request, void *value);
void ExitCurrentThread(unsigned long request);
bool IsDriverAlive();
private:
static BinderConnector *instance_;
static std::mutex skeletonMutex;
bool OpenDriver();
int driverFD_;
void *vmAddr_;
const std::string deviceName_;
};
#ifdef CONFIG_IPC_SINGLE
} // namespace IPC_SINGLE
#endif
} // namespace OHOS
#endif // OHOS_IPC_BINDER_CONNECTOR_H

View File

@ -0,0 +1,30 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_BINDER_DEBUG_H
#define OHOS_IPC_BINDER_DEBUG_H
#include "ipc_debug.h"
namespace OHOS {
class BinderDebug : public ErrorBase {
public:
BinderDebug() = default;
~BinderDebug() = default;
static const std::string &ToString(int value);
virtual ErrorMap &GetErrorMap() override;
};
} // namespace OHOS
#endif // OHOS_IPC_BINDER_DEBUG_H

View File

@ -0,0 +1,154 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_BINDER_INVOKER_H
#define OHOS_IPC_BINDER_INVOKER_H
#include <unistd.h>
#include <sys/types.h>
#include "binder_connector.h"
#include "iremote_invoker.h"
#include "invoker_factory.h"
namespace OHOS {
#ifdef CONFIG_IPC_SINGLE
namespace IPC_SINGLE {
#endif
class BinderInvoker : public IRemoteInvoker {
public:
class BinderAllocator : public DefaultAllocator {
void Dealloc(void *data) override;
friend BinderInvoker;
};
BinderInvoker();
~BinderInvoker() = default;
bool AcquireHandle(int32_t handle) override;
bool ReleaseHandle(int32_t handle) override;
bool PingService(int32_t handle) override;
bool AddDeathRecipient(int32_t handle, void *cookie) override;
bool RemoveDeathRecipient(int32_t handle, void *cookie) override;
int GetObjectRefCount(const IRemoteObject *object) override;
bool SetMaxWorkThread(int maxThreadNum) override;
void JoinThread(bool initiative) override;
void JoinProcessThread(bool initiative) override;
void FreeBuffer(void *data) override;
void StopWorkThread() override;
bool SetRegistryObject(sptr<IRemoteObject> &object) override;
int SendRequest(int handle, uint32_t code, MessageParcel &data, MessageParcel &reply,
MessageOption &option) override;
int SendReply(MessageParcel &reply, uint32_t flags, int32_t result) override;
bool FlattenObject(Parcel &parcel, const IRemoteObject *object) const override;
IRemoteObject *UnflattenObject(Parcel &parcel) override;
int ReadFileDescriptor(Parcel &parcel) override;
bool WriteFileDescriptor(Parcel &parcel, int fd, bool takeOwnership) override;
pid_t GetCallerPid() const override;
uid_t GetCallerUid() const override;
uint32_t GetStatus() const override;
bool IsLocalCalling() override;
void SetStatus(uint32_t status);
std::string GetLocalDeviceID() override;
std::string GetCallerDeviceID() const override;
int FlushCommands(IRemoteObject *object) override;
std::string ResetCallingIdentity() override;
bool SetCallingIdentity(std::string &identity) override;
void ExitCurrentThread();
#ifndef CONFIG_IPC_SINGLE
int TranslateProxy(uint32_t handle, uint32_t flag) override;
int TranslateStub(binder_uintptr_t cookie, binder_uintptr_t ptr, uint32_t flag, int cmd) override;
sptr<IRemoteObject> GetSAMgrObject() override;
#endif
protected:
bool isMainWorkThread;
bool stopWorkThread;
pid_t callerPid_;
pid_t callerUid_;
private:
int TransactWithDriver(bool doRead = true);
bool WriteTransaction(int cmd, uint32_t flags, int32_t handle, uint32_t code, const MessageParcel &data,
const int *status);
int WaitForCompletion(MessageParcel *reply = nullptr, int32_t *acquireResult = nullptr);
void OnAttemptAcquire();
void OnRemoveRecipientDone();
void StartWorkLoop();
void OnBinderDied();
void OnAcquireObject(uint32_t cmd);
void OnReleaseObject(uint32_t cmd);
void OnTransaction(const uint8_t *);
int HandleCommands(uint32_t cmd);
int HandleReply(MessageParcel *reply);
private:
DISALLOW_COPY_AND_MOVE(BinderInvoker);
static constexpr int IPC_DEFAULT_PARCEL_SIZE = 256;
Parcel input_;
Parcel output_;
BinderConnector *binderConnector_;
uint32_t status_;
static inline InvokerDelegator<BinderInvoker> delegator_ = { IRemoteObject::IF_PROT_BINDER };
};
#ifdef CONFIG_IPC_SINGLE
} // namespace IPC_SINGLE
#endif
} // namespace OHOS
#endif // OHOS_IPC_BINDER_INVOKER_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,111 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_DBINDER_DATABUS_INVOKER_H
#define OHOS_IPC_DBINDER_DATABUS_INVOKER_H
#include <unistd.h>
#include <sys/types.h>
#include "hilog/log.h"
#include "dbinder_base_invoker.h"
#include "invoker_factory.h"
#include "dbinder_session_object.h"
#include "sys_binder.h"
#include "Session.h"
#include "ISessionService.h"
using Communication::SoftBus::ISessionService;
using Communication::SoftBus::Session;
namespace OHOS {
class DBinderDatabusInvoker : public DBinderBaseInvoker<DBinderSessionObject> {
public:
DBinderDatabusInvoker();
~DBinderDatabusInvoker();
bool AcquireHandle(int32_t handle) override;
bool ReleaseHandle(int32_t handle) override;
void JoinThread(bool initiative) override;
void JoinProcessThread(bool initiative) override;
void StopWorkThread() override;
bool FlattenObject(Parcel &parcel, const IRemoteObject *object) const override;
IRemoteObject *UnflattenObject(Parcel &parcel) override;
int ReadFileDescriptor(Parcel &parcel) override;
bool WriteFileDescriptor(Parcel &parcel, int fd, bool takeOwnership) override;
pid_t GetCallerPid() const override;
uid_t GetCallerUid() const override;
uint32_t GetStatus() const override;
bool IsLocalCalling() override;
std::string GetLocalDeviceID() override;
std::string GetCallerDeviceID() const override;
bool UpdateClientSession(uint32_t handle, std::shared_ptr<DBinderSessionObject> sessionObject) override;
std::shared_ptr<DBinderSessionObject> QueryClientSessionObject(uint32_t databusHandle) override;
std::shared_ptr<DBinderSessionObject> QueryServerSessionObject(uint32_t handle) override;
std::shared_ptr<DBinderSessionObject> CreateServerSessionObject(binder_uintptr_t binder, uint64_t &stubIndex,
std::shared_ptr<DBinderSessionObject> sessionObject) override;
int FlushCommands(IRemoteObject *object) override;
bool OnDatabusSessionClosed(std::shared_ptr<Session> session);
bool OnReceiveNewConnection(std::shared_ptr<Session> session);
std::string ResetCallingIdentity() override;
bool SetCallingIdentity(std::string &identity) override;
int TranslateProxy(uint32_t handle, uint32_t flag) override;
int TranslateStub(binder_uintptr_t cookie, binder_uintptr_t ptr, uint32_t flag, int cmd) override;
void OnMessageAvailable(std::shared_ptr<Session> session, const char *data, ssize_t len);
private:
bool CreateProcessThread() override;
int OnSendMessage(std::shared_ptr<DBinderSessionObject> sessionOfPeer) override;
int OnSendRawData(std::shared_ptr<DBinderSessionObject> session, const void *data, size_t size) override;
std::shared_ptr<DBinderSessionObject> NewSessionOfBinderProxy(uint32_t handle,
std::shared_ptr<DBinderSessionObject> session) override;
std::shared_ptr<DBinderSessionObject> QuerySessionOfBinderProxy(uint32_t handle,
std::shared_ptr<DBinderSessionObject> session) override;
uint32_t FlattenSession(char *sessionOffset, const std::shared_ptr<DBinderSessionObject> connectSession,
uint64_t stubIndex) override;
std::shared_ptr<DBinderSessionObject> UnFlattenSession(char *sessionOffset, uint64_t &stubIndex) override;
uint32_t QueryHandleBySession(std::shared_ptr<DBinderSessionObject> session, uint64_t stubIndex) override;
virtual uint64_t GetSeqNum() const override;
virtual void SetSeqNum(uint64_t seq) override;
virtual uint32_t GetClientFd() const override;
virtual void SetClientFd(uint32_t fd) override;
virtual void SetCallerPid(pid_t pid) override;
virtual void SetCallerUid(pid_t uid) override;
virtual void SetStatus(uint32_t status) override;
virtual void SetCallerDeviceID(const std::string &deviceId) override;
virtual int CheckAndSetCallerInfo(uint32_t listenFd, uint64_t stubIndex) override;
uint32_t HasRawDataPackage(const char *data, ssize_t len);
uint32_t HasCompletePackage(const char *data, uint32_t readCursor, ssize_t len);
void OnRawDataAvailable(std::shared_ptr<Session> session, const char *data, uint32_t dataSize);
uint64_t MakeStubIndexByRemoteObject(IRemoteObject *stubObject);
std::shared_ptr<DBinderSessionObject> MakeDefaultServerSessionObject();
bool ConnectRemoteObject2Session(IRemoteObject *stubObject, uint64_t stubIndex,
const std::shared_ptr<DBinderSessionObject> sessionObject);
bool AuthSession2Proxy(uint32_t handle, const std::shared_ptr<DBinderSessionObject> Session);
private:
DISALLOW_COPY_AND_MOVE(DBinderDatabusInvoker);
bool stopWorkThread_;
pid_t callerPid_;
pid_t callerUid_;
std::string callerDeviceID_;
uint64_t seqNumber_ = 0;
uint32_t clientFd_ = 0;
uint32_t status_;
static inline InvokerDelegator<DBinderDatabusInvoker> DBinderDatabusDelegator_ = { IRemoteObject::IF_PROT_DATABUS };
};
} // namespace OHOS
#endif // OHOS_IPC_DBINDER_DATABUS_INVOKER_H

View File

@ -0,0 +1,42 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_HITRACE_INVOKER_H
#define OHOS_IPC_HITRACE_INVOKER_H
#include "hitrace/trace.h"
#include "iremote_object.h"
namespace OHOS {
class HitraceInvoker {
public:
static bool IsClientTraced(int32_t handle, uint32_t flags, const HiviewDFX::HiTraceId &traceId);
static HiviewDFX::HiTraceId TraceClientSend(int32_t handle, uint32_t code, Parcel &data, uint32_t &flags,
const HiviewDFX::HiTraceId &traceId);
static void TraceClientReceieve(int32_t handle, uint32_t code, uint32_t flags, const HiviewDFX::HiTraceId &traceId,
const HiviewDFX::HiTraceId &childId);
static void RecoveryDataAndFlag(Parcel &data, uint32_t &flags, size_t oldReadPosition, uint8_t idLen);
static bool TraceServerReceieve(int32_t handle, uint32_t code, Parcel &data, uint32_t &flags);
static void TraceServerSend(int32_t handle, uint32_t code, bool isServerTraced, uint32_t flags);
private:
static const int PADDED_SIZE_OF_PARCEL = 4;
};
} // namespace OHOS
#endif // OHOS_IPC_HITRACE_INVOKER_H

View File

@ -0,0 +1,70 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_INVOKER_FACTORY_H
#define OHOS_IPC_INVOKER_FACTORY_H
#include <functional>
#include <unordered_map>
#include "iremote_invoker.h"
namespace OHOS {
#ifdef CONFIG_IPC_SINGLE
namespace IPC_SINGLE {
#endif
class InvokerFactory {
public:
using InvokerCreator = std::function<IRemoteInvoker *()>;
static InvokerFactory &Get();
bool Register(int protocol, InvokerCreator creator);
void Unregister(int protocol);
IRemoteInvoker *newInstance(int protocol);
private:
InvokerFactory &operator = (const InvokerFactory &) = delete;
InvokerFactory(const InvokerFactory &) = delete;
InvokerFactory();
~InvokerFactory();
static bool isAvailable_;
std::mutex factoryMutex_;
std::unordered_map<int, InvokerCreator> creators_;
};
template <typename T> class InvokerDelegator {
public:
InvokerDelegator(int prot);
~InvokerDelegator();
private:
int prot_;
InvokerDelegator &operator = (const InvokerDelegator &) = delete;
InvokerDelegator(const InvokerDelegator &) = delete;
};
template <typename T> InvokerDelegator<T>::InvokerDelegator(int prot)
{
prot_ = prot;
InvokerFactory::Get().Register(prot, []() { return static_cast<IRemoteInvoker *>(new T()); });
}
template <typename T> InvokerDelegator<T>::~InvokerDelegator()
{
InvokerFactory::Get().Unregister(prot_);
}
#ifdef CONFIG_IPC_SINGLE
} // namespace IPC_SINGLE
#endif
} // namespace OHOS
#endif // OHOS_IPC_INVOKER_FACTORY_H

View File

@ -0,0 +1,40 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_INVOKER_RAWDATA_H
#define OHOS_IPC_INVOKER_RAWDATA_H
#include <unistd.h>
#include <memory>
#include <sys/types.h>
#include <cinttypes>
#include "nocopyable.h"
namespace OHOS {
class InvokerRawData {
public:
DISALLOW_COPY_AND_MOVE(InvokerRawData);
explicit InvokerRawData(size_t size);
~InvokerRawData();
std::shared_ptr<char> GetData() const;
size_t GetSize() const;
private:
std::shared_ptr<char> data_;
size_t size_;
};
} // namespace OHOS
#endif // OHOS_IPC_INVOKER_RAWDATA_H

View File

@ -0,0 +1,105 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_IREMOTE_INVOKER_H
#define OHOS_IPC_IREMOTE_INVOKER_H
#include <unistd.h>
#include <sys/types.h>
#include "parcel.h"
#include "sys_binder.h"
#include "iremote_object.h"
#include "ipc_file_descriptor.h"
namespace OHOS {
#ifdef CONFIG_IPC_SINGLE
namespace IPC_SINGLE {
#endif
class IRemoteInvoker {
public:
enum {
IDLE_INVOKER,
ACTIVE_INVOKER,
};
virtual ~IRemoteInvoker() = default;
virtual bool AcquireHandle(int32_t handle) = 0;
virtual bool ReleaseHandle(int32_t handle) = 0;
virtual bool PingService(int32_t handle) = 0;
virtual int SendReply(MessageParcel &reply, uint32_t flags, int32_t result) = 0;
virtual int SendRequest(int handle, uint32_t code, MessageParcel &data, MessageParcel &reply,
MessageOption &option) = 0;
virtual bool AddDeathRecipient(int32_t handle, void *cookie) = 0;
virtual int GetObjectRefCount(const IRemoteObject *object) = 0;
virtual bool RemoveDeathRecipient(int32_t handle, void *cookie) = 0;
virtual bool SetMaxWorkThread(int maxThreadNum) = 0;
virtual void JoinThread(bool initiative) = 0;
virtual void JoinProcessThread(bool initiative) = 0;
virtual void StopWorkThread() = 0;
virtual void FreeBuffer(void *data) = 0;
virtual bool SetRegistryObject(sptr<IRemoteObject> &object) = 0;
virtual pid_t GetCallerPid() const = 0;
virtual uid_t GetCallerUid() const = 0;
virtual uint32_t GetStatus() const = 0;
virtual bool IsLocalCalling() = 0;
virtual std::string GetLocalDeviceID() = 0;
virtual std::string GetCallerDeviceID() const = 0;
virtual bool FlattenObject(Parcel &parcel, const IRemoteObject *object) const = 0;
virtual IRemoteObject *UnflattenObject(Parcel &parcel) = 0;
virtual int ReadFileDescriptor(Parcel &parcel) = 0;
virtual bool WriteFileDescriptor(Parcel &parcel, int fd, bool takeOwnership) = 0;
virtual int FlushCommands(IRemoteObject *object) = 0;
virtual std::string ResetCallingIdentity() = 0;
virtual bool SetCallingIdentity(std::string &identity) = 0;
#ifndef CONFIG_IPC_SINGLE
virtual sptr<IRemoteObject> GetSAMgrObject() = 0;
virtual int TranslateProxy(uint32_t handle, uint32_t flag) = 0;
virtual int TranslateStub(binder_uintptr_t cookie, binder_uintptr_t ptr, uint32_t flag, int cmd) = 0;
#endif
};
#ifdef CONFIG_IPC_SINGLE
} // namespace IPC_SINGLE
#endif
} // namespace OHOS
#endif // OHOS_IPC_IREMOTE_INVOKER_H

View File

@ -0,0 +1,270 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_SYS_BINDER_H
#define OHOS_IPC_SYS_BINDER_H
#include <sys/types.h>
#ifndef _UAPI_LINUX_BINDER_H
#define _UAPI_LINUX_BINDER_H
#include <linux/types.h>
#include <linux/ioctl.h>
#ifndef B_PACK_CHARS
#define B_PACK_CHARS(c1, c2, c3, c4) ((((c1) << 24)) | (((c2) << 16)) | (((c3) << 8)) | (c4))
#endif
#define B_TYPE_LARGE 0x85
enum {
BINDER_TYPE_BINDER = B_PACK_CHARS('s', 'b', '*', B_TYPE_LARGE),
BINDER_TYPE_WEAK_BINDER = B_PACK_CHARS('w', 'b', '*', B_TYPE_LARGE),
BINDER_TYPE_HANDLE = B_PACK_CHARS('s', 'h', '*', B_TYPE_LARGE),
BINDER_TYPE_WEAK_HANDLE = B_PACK_CHARS('w', 'h', '*', B_TYPE_LARGE),
BINDER_TYPE_FD = B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE),
BINDER_TYPE_FDA = B_PACK_CHARS('f', 'd', 'a', B_TYPE_LARGE),
BINDER_TYPE_PTR = B_PACK_CHARS('p', 't', '*', B_TYPE_LARGE),
};
enum {
FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff,
FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100,
FLAT_BINDER_FLAG_TXN_SECURITY_CTX = 0x1000,
};
#ifdef BINDER_IPC_32BIT
typedef __u32 binder_size_t;
typedef __u32 binder_uintptr_t;
#else
typedef __u64 binder_size_t;
typedef __u64 binder_uintptr_t;
#endif
struct binder_object_header {
__u32 type;
};
struct flat_binder_object {
struct binder_object_header hdr;
__u32 flags;
union {
binder_uintptr_t binder;
__u32 handle;
};
binder_uintptr_t cookie;
};
struct binder_fd_object {
struct binder_object_header hdr;
__u32 pad_flags;
union {
binder_uintptr_t pad_binder;
__u32 fd;
};
binder_uintptr_t cookie;
};
struct binder_buffer_object {
struct binder_object_header hdr;
__u32 flags;
binder_uintptr_t buffer;
binder_size_t length;
binder_size_t parent;
binder_size_t parent_offset;
};
enum {
BINDER_BUFFER_FLAG_HAS_PARENT = 0x01,
};
struct binder_fd_array_object {
struct binder_object_header hdr;
__u32 pad;
binder_size_t num_fds;
binder_size_t parent;
binder_size_t parent_offset;
};
struct binder_write_read {
binder_size_t write_size;
binder_size_t write_consumed;
binder_uintptr_t write_buffer;
binder_size_t read_size;
binder_size_t read_consumed;
binder_uintptr_t read_buffer;
};
struct binder_version {
__s32 protocol_version;
};
#ifdef BINDER_IPC_32BIT
#define BINDER_CURRENT_PROTOCOL_VERSION 7
#else
#define BINDER_CURRENT_PROTOCOL_VERSION 8
#endif
struct binder_node_debug_info {
binder_uintptr_t ptr;
binder_uintptr_t cookie;
__u32 has_strong_ref;
__u32 has_weak_ref;
};
struct binder_node_info_for_ref {
__u32 handle;
__u32 strong_count;
__u32 weak_count;
__u32 reserved1;
__u32 reserved2;
__u32 reserved3;
};
#define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read)
#define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, __s64)
#define BINDER_SET_MAX_THREADS _IOW('b', 5, __u32)
#define BINDER_SET_IDLE_PRIORITY _IOW('b', 6, __s32)
#define BINDER_SET_CONTEXT_MGR _IOW('b', 7, __s32)
#define BINDER_THREAD_EXIT _IOW('b', 8, __s32)
#define BINDER_VERSION _IOWR('b', 9, struct binder_version)
#define BINDER_GET_NODE_DEBUG_INFO _IOWR('b', 11, struct binder_node_debug_info)
#define BINDER_GET_NODE_INFO_FOR_REF _IOWR('b', 12, struct binder_node_info_for_ref)
#define BINDER_SET_CONTEXT_MGR_EXT _IOW('b', 13, struct flat_binder_object)
#define BINDER_GET_NODE_REFCOUNT _IOWR('b', 17, struct binder_ptr_count)
#define BINDER_TRANSLATE_HANDLE _IOWR('b', 18, __u32)
enum transaction_flags {
TF_ONE_WAY = 0x01,
TF_ROOT_OBJECT = 0x04,
TF_STATUS_CODE = 0x08,
TF_ACCEPT_FDS = 0x10,
TF_HITRACE = 0x80, // add flag for hitrace
};
struct binder_transaction_data {
union {
__u32 handle;
binder_uintptr_t ptr;
} target;
binder_uintptr_t cookie;
__u32 code;
__u32 flags;
pid_t sender_pid;
uid_t sender_euid;
binder_size_t data_size;
binder_size_t offsets_size;
union {
struct {
binder_uintptr_t buffer;
binder_uintptr_t offsets;
} ptr;
__u8 buf[8];
} data;
};
struct binder_transaction_data_secctx {
struct binder_transaction_data transaction_data;
binder_uintptr_t secctx;
};
struct binder_transaction_data_sg {
struct binder_transaction_data transaction_data;
binder_size_t buffers_size;
};
struct binder_ptr_cookie {
binder_uintptr_t ptr;
binder_uintptr_t cookie;
};
struct binder_handle_cookie {
__u32 handle;
binder_uintptr_t cookie;
} __attribute__((__packed__));
struct binder_pri_desc {
__s32 priority;
__u32 desc;
};
struct binder_pri_ptr_cookie {
__s32 priority;
binder_uintptr_t ptr;
binder_uintptr_t cookie;
};
enum binder_driver_return_protocol {
BR_ERROR = _IOR('r', 0, __s32),
BR_OK = _IO('r', 1),
BR_TRANSACTION_SEC_CTX = _IOR('r', 2, struct binder_transaction_data_secctx),
BR_TRANSACTION = _IOR('r', 2, struct binder_transaction_data),
BR_REPLY = _IOR('r', 3, struct binder_transaction_data),
BR_ACQUIRE_RESULT = _IOR('r', 4, __s32),
BR_DEAD_REPLY = _IO('r', 5),
BR_TRANSACTION_COMPLETE = _IO('r', 6),
BR_INCREFS = _IOR('r', 7, struct binder_ptr_cookie),
BR_ACQUIRE = _IOR('r', 8, struct binder_ptr_cookie),
BR_RELEASE = _IOR('r', 9, struct binder_ptr_cookie),
BR_DECREFS = _IOR('r', 10, struct binder_ptr_cookie),
BR_ATTEMPT_ACQUIRE = _IOR('r', 11, struct binder_pri_ptr_cookie),
BR_NOOP = _IO('r', 12),
BR_SPAWN_LOOPER = _IO('r', 13),
BR_FINISHED = _IO('r', 14),
BR_DEAD_BINDER = _IOR('r', 15, binder_uintptr_t),
BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, binder_uintptr_t),
BR_FAILED_REPLY = _IO('r', 17),
BR_RELEASE_NODE = _IO('r', 18),
};
enum binder_driver_command_protocol {
BC_TRANSACTION = _IOW('c', 0, struct binder_transaction_data),
BC_REPLY = _IOW('c', 1, struct binder_transaction_data),
BC_ACQUIRE_RESULT = _IOW('c', 2, __s32),
BC_FREE_BUFFER = _IOW('c', 3, binder_uintptr_t),
BC_INCREFS = _IOW('c', 4, __u32),
BC_ACQUIRE = _IOW('c', 5, __u32),
BC_RELEASE = _IOW('c', 6, __u32),
BC_DECREFS = _IOW('c', 7, __u32),
BC_INCREFS_DONE = _IOW('c', 8, struct binder_ptr_cookie),
BC_ACQUIRE_DONE = _IOW('c', 9, struct binder_ptr_cookie),
BC_ATTEMPT_ACQUIRE = _IOW('c', 10, struct binder_pri_desc),
BC_REGISTER_LOOPER = _IO('c', 11),
BC_ENTER_LOOPER = _IO('c', 12),
BC_EXIT_LOOPER = _IO('c', 13),
BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14, struct binder_handle_cookie),
BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct binder_handle_cookie),
BC_DEAD_BINDER_DONE = _IOW('c', 16, binder_uintptr_t),
BC_TRANSACTION_SG = _IOW('c', 17, struct binder_transaction_data_sg),
BC_REPLY_SG = _IOW('c', 18, struct binder_transaction_data_sg),
BC_SEND_RAWDATA = _IOW('c', 20, __u32),
};
#endif /* * _UAPI_LINUX_BINDER_H * */
static const int DBINDER_MAGICWORD = 0X4442494E;
static const int ENCRYPT_HEAD_LEN = 28;
static const int DEVICEID_LENGTH = 64;
static const int PID_LEN = 32;
static const int VERSION_NUM = 1;
enum {
BINDER_TYPE_REMOTE_BINDER = B_PACK_CHARS('r', 'b', '*', B_TYPE_LARGE),
BINDER_TYPE_REMOTE_HANDLE = B_PACK_CHARS('r', 'h', '*', B_TYPE_LARGE),
ZBINDER_TYPE_REMOTE_NODE = B_PACK_CHARS('r', 'n', '*', B_TYPE_LARGE),
ZBINDER_TYPE_NODE = B_PACK_CHARS('s', 'n', '*', B_TYPE_LARGE),
BINDER_TYPE_FDR = B_PACK_CHARS('f', 'd', 'r', B_TYPE_LARGE),
};
struct binder_ptr_count {
binder_uintptr_t ptr;
uint32_t count;
};
struct dbinder_transaction_data {
__u32 sizeOfSelf;
__u32 magic;
__u32 version;
int cmd;
__u32 code;
__u32 flags;
__u64 cookie;
__u64 seqNumber;
binder_size_t buffer_size;
binder_size_t offsets_size;
binder_uintptr_t offsets;
unsigned char buffer[0];
};
#endif // OHOS_IPC_SYS_BINDER_H

View File

@ -0,0 +1,147 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "binder_connector.h"
#include <fcntl.h>
#include <unistd.h>
#include <mutex>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include "hilog/log.h"
#include "ipc_types.h"
#include "ipc_debug.h"
#include "dbinder_error_code.h"
#include "log_tags.h"
namespace OHOS {
#ifdef CONFIG_IPC_SINGLE
namespace IPC_SINGLE {
#endif
static constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "BinderConnector" };
std::mutex BinderConnector::skeletonMutex;
constexpr int SZ_1_M = 1048576;
constexpr int DOUBLE = 2;
static const int IPC_MMAP_SIZE = (SZ_1_M - sysconf(_SC_PAGE_SIZE) * DOUBLE);
#if (defined CONFIG_DUAL_FRAMEWORK)
static const std::string DRIVER_NAME = std::string("/dev/binder");
#else
static const std::string DRIVER_NAME = std::string("/dev/zbinder");
#endif /* CONFIG_DUAL_FRAMEWORK */
BinderConnector *BinderConnector::instance_ = nullptr;
BinderConnector::BinderConnector(const std::string &deviceName)
: driverFD_(-1), vmAddr_(MAP_FAILED), deviceName_(deviceName)
{}
BinderConnector::~BinderConnector()
{
if (vmAddr_ != MAP_FAILED) {
munmap(vmAddr_, IPC_MMAP_SIZE);
vmAddr_ = MAP_FAILED;
}
if (driverFD_ >= 0) {
close(driverFD_);
driverFD_ = -1;
}
};
bool BinderConnector::IsDriverAlive()
{
return driverFD_ >= 0;
}
bool BinderConnector::OpenDriver()
{
int fd = open(deviceName_.c_str(), O_RDWR);
if (fd < 0) {
ZLOGE(LABEL, "%s:fail to open", __func__);
#ifndef BUILD_PUBLIC_VERSION
ReportEvent(DbinderErrorCode::KERNEL_DRIVER_ERROR, DbinderErrorCode::ERROR_CODE,
DbinderErrorCode::OPEN_IPC_DRIVER_FAILURE);
#endif
return false;
}
ZLOGI(LABEL, "%s:succ to open, fd=%d", __func__, fd);
driverFD_ = fd;
vmAddr_ = mmap(0, IPC_MMAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, driverFD_, 0);
if (vmAddr_ == MAP_FAILED) {
ZLOGE(LABEL, "%s:fail to mmap\n", __func__);
close(driverFD_);
driverFD_ = -1;
#ifndef BUILD_PUBLIC_VERSION
ReportEvent(DbinderErrorCode::KERNEL_DRIVER_ERROR, DbinderErrorCode::ERROR_CODE,
DbinderErrorCode::OPEN_IPC_DRIVER_FAILURE);
#endif
return false;
}
return true;
}
int BinderConnector::WriteBinder(unsigned long request, void *value)
{
int err = -EINTR;
while (err == -EINTR) {
if (ioctl(driverFD_, request, value) >= 0) {
err = ERR_NONE;
} else {
err = -errno;
}
if (err == -EINTR) {
ZLOGE(LABEL, "%s:ioctl_binder returned EINTR", __func__);
#ifndef BUILD_PUBLIC_VERSION
ReportEvent(DbinderErrorCode::KERNEL_DRIVER_ERROR, DbinderErrorCode::ERROR_CODE,
DbinderErrorCode::WRITE_IPC_DRIVER_FAILURE);
#endif
}
}
return err;
}
void BinderConnector::ExitCurrentThread(unsigned long request)
{
if (driverFD_ > 0) {
ioctl(driverFD_, request, 0);
}
}
BinderConnector *BinderConnector::GetInstance()
{
if (instance_ == nullptr) {
std::lock_guard<std::mutex> lockGuard(skeletonMutex);
if (instance_ == nullptr) {
BinderConnector *temp = new BinderConnector(DRIVER_NAME);
if (!temp->OpenDriver()) {
delete temp;
temp = nullptr;
}
instance_ = temp;
}
}
return instance_;
}
#ifdef CONFIG_IPC_SINGLE
} // namespace IPC_SINGLE
#endif
} // namespace OHOS

View File

@ -0,0 +1,65 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "binder_debug.h"
#include "sys_binder.h"
namespace OHOS {
const std::string &BinderDebug::ToString(int value)
{
static BinderDebug instance;
return instance.GetErrorDesc(value);
}
ErrorMap &BinderDebug::GetErrorMap()
{
static ErrorMap errorMap = { { BR_ERROR, "BR_ERROR" },
{ BR_OK, "BR_OK" },
{ BR_TRANSACTION, "BR_TRANSACTION" },
{ BR_REPLY, "BR_REPLY" },
{ BR_ACQUIRE_RESULT, "BR_ACQUIRE_RESULT" },
{ BR_DEAD_REPLY, "BR_DEAD_REPLY" },
{ BR_TRANSACTION_COMPLETE, "BR_TRANSACTION_COMPLETE" },
{ BR_INCREFS, "BR_INCREFS" },
{ BR_ACQUIRE, "BR_ACQUIRE" },
{ BR_RELEASE, "BR_RELEASE" },
{ BR_DECREFS, "BR_DECREFS" },
{ BR_ATTEMPT_ACQUIRE, "BR_ATTEMPT_ACQUIRE" },
{ BR_NOOP, "BR_NOOP" },
{ BR_SPAWN_LOOPER, "BR_SPAWN_LOOPER" },
{ BR_FINISHED, "BR_FINISHED" },
{ BR_DEAD_BINDER, "BR_DEAD_BINDER" },
{ BR_CLEAR_DEATH_NOTIFICATION_DONE, "BR_CLEAR_DEATH_NOTIFICATION_DONE" },
{ BR_FAILED_REPLY, "BR_FAILED_REPLY" },
{ BC_TRANSACTION, "BC_TRANSACTION" },
{ BC_REPLY, "BC_REPLY" },
{ BC_ACQUIRE_RESULT, "BC_ACQUIRE_RESULT" },
{ BC_FREE_BUFFER, "BC_FREE_BUFFER" },
{ BC_INCREFS, "BC_INCREFS" },
{ BC_ACQUIRE, "BC_ACQUIRE" },
{ BC_RELEASE, "BC_RELEASE" },
{ BC_DECREFS, "BC_DECREFS" },
{ BC_INCREFS_DONE, "BC_INCREFS_DONE" },
{ BC_ACQUIRE_DONE, "BC_ACQUIRE_DONE" },
{ BC_ATTEMPT_ACQUIRE, "BC_ATTEMPT_ACQUIRE" },
{ BC_REGISTER_LOOPER, "BC_REGISTER_LOOPER" },
{ BC_ENTER_LOOPER, "BC_ENTER_LOOPER" },
{ BC_EXIT_LOOPER, "BC_EXIT_LOOPER" },
{ BC_REQUEST_DEATH_NOTIFICATION, "BC_REQUEST_DEATH_NOTIFICATION" },
{ BC_CLEAR_DEATH_NOTIFICATION, "BC_CLEAR_DEATH_NOTIFICATION" },
{ BC_DEAD_BINDER_DONE, "BC_DEAD_BINDER_DONE" } };
return errorMap;
}
} // namespace OHOS

View File

@ -0,0 +1,951 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "binder_invoker.h"
#include "string_ex.h"
#include "sys_binder.h"
#include "hilog/log.h"
#include "binder_debug.h"
#include "ipc_object_stub.h"
#include "ipc_object_proxy.h"
#include "ipc_process_skeleton.h"
#include "ipc_thread_skeleton.h"
#ifndef CONFIG_STANDARD_SYSTEM
#include "hitrace_invoker.h"
#endif
#include "dbinder_error_code.h"
#include "log_tags.h"
namespace OHOS {
#ifdef CONFIG_IPC_SINGLE
namespace IPC_SINGLE {
#endif
using namespace OHOS::HiviewDFX;
static constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "BinderInvoker" };
enum {
GET_SERVICE_TRANSACTION = 0x1,
CHECK_SERVICE_TRANSACTION,
ADD_SERVICE_TRANSACTION,
};
BinderInvoker::BinderInvoker()
: isMainWorkThread(false), stopWorkThread(false), callerPid_(getpid()), callerUid_(getuid()), status_(0)
{
input_.SetDataCapacity(IPC_DEFAULT_PARCEL_SIZE);
binderConnector_ = BinderConnector::GetInstance();
}
bool BinderInvoker::AcquireHandle(int32_t handle)
{
size_t rewindPos = output_.GetWritePosition();
if (!output_.WriteUint32(BC_ACQUIRE)) {
return false;
}
if (!output_.WriteInt32(handle)) {
if (!output_.RewindWrite(rewindPos)) {
output_.FlushBuffer();
}
return false;
}
/* invoke remote to receive acquire handle event, don't care ping result */
if (handle != 0) {
(void)PingService(handle);
}
ZLOGI(LABEL, "Acquire Handle %{public}d", handle);
return true;
}
bool BinderInvoker::ReleaseHandle(int32_t handle)
{
size_t rewindPos = output_.GetWritePosition();
if (!output_.WriteUint32(BC_RELEASE)) {
return false;
}
if (!output_.WriteInt32(handle)) {
if (!output_.RewindWrite(rewindPos)) {
output_.FlushBuffer();
}
return false;
}
ZLOGI(LABEL, "Release Handle %{public}d", handle);
FlushCommands(nullptr);
return true;
}
int BinderInvoker::SendRequest(int handle, uint32_t code, MessageParcel &data, MessageParcel &reply,
MessageOption &option)
{
int error = ERR_NONE;
uint32_t flags = option.GetFlags();
ZLOGI(LABEL, "%{public}s: handle=%d ,flags:%d", __func__, handle, flags);
MessageParcel &newData = const_cast<MessageParcel &>(data);
size_t oldWritePosition = newData.GetWritePosition();
#ifndef CONFIG_STANDARD_SYSTEM
HiTraceId traceId = HiTrace::GetId();
// set client send trace point if trace is enabled
HiTraceId childId = HitraceInvoker::TraceClientSend(handle, code, newData, flags, traceId);
#endif
if (!WriteTransaction(BC_TRANSACTION, flags, handle, code, data, nullptr)) {
newData.RewindWrite(oldWritePosition);
ZLOGE(LABEL, "WriteTransaction ERROR");
#ifndef BUILD_PUBLIC_VERSION
ReportDriverEvent(DbinderErrorCode::COMMON_DRIVER_ERROR, DbinderErrorCode::ERROR_TYPE,
DbinderErrorCode::IPC_DRIVER, DbinderErrorCode::ERROR_CODE, DbinderErrorCode::TRANSACT_DATA_FAILURE);
#endif
return IPC_INVOKER_WRITE_TRANS_ERR;
}
if ((flags & TF_ONE_WAY) != 0) {
error = WaitForCompletion(nullptr);
} else {
error = WaitForCompletion(&reply);
}
#ifndef CONFIG_STANDARD_SYSTEM
HitraceInvoker::TraceClientReceieve(handle, code, flags, traceId, childId);
#endif
// restore Parcel data
newData.RewindWrite(oldWritePosition);
ZLOGI(LABEL, "%{public}s: handle=%d result = %{public}d", __func__, handle, error);
return error;
}
bool BinderInvoker::AddDeathRecipient(int32_t handle, void *cookie)
{
ZLOGI(LABEL, "BinderInvoker::AddDeathRecipient for handle:%d", handle);
size_t rewindPos = output_.GetWritePosition();
if (!output_.WriteInt32(BC_REQUEST_DEATH_NOTIFICATION)) {
ZLOGE(LABEL, "fail to write command field:%d", handle);
return false;
}
if (!output_.WriteInt32(handle)) {
if (!output_.RewindWrite(rewindPos)) {
output_.FlushBuffer();
}
return false;
}
if (!output_.WritePointer((uintptr_t)cookie)) {
/* rewind written size notification and handle. */
if (!output_.RewindWrite(rewindPos)) {
output_.FlushBuffer();
}
return false;
}
// pass in nullptr directly
int error = FlushCommands(nullptr);
if (error == ERR_NONE) {
auto *proxy = reinterpret_cast<IPCObjectProxy *>(cookie);
if (proxy != nullptr) {
proxy->IncStrongRef(this);
}
}
return error == ERR_NONE;
}
bool BinderInvoker::RemoveDeathRecipient(int32_t handle, void *cookie)
{
size_t rewindPos = output_.GetWritePosition();
if (!output_.WriteInt32(BC_CLEAR_DEATH_NOTIFICATION)) {
return false;
}
if (!output_.WriteInt32(handle)) {
if (!output_.RewindWrite(rewindPos)) {
output_.FlushBuffer();
}
return false;
}
if (!output_.WritePointer((uintptr_t)cookie)) {
if (!output_.RewindWrite(rewindPos)) {
output_.FlushBuffer();
}
return false;
}
// pass in nullptr directly
int error = FlushCommands(nullptr);
if (error != ERR_NONE) {
ZLOGE(LABEL, "Remove Death Recipient handle =%{public}d result = %{public}d", handle, error);
return false;
}
return true;
}
int BinderInvoker::GetObjectRefCount(const IRemoteObject *object)
{
if ((binderConnector_ == nullptr) || (!binderConnector_->IsDriverAlive())) {
return 0;
}
struct binder_ptr_count refs;
refs.ptr = reinterpret_cast<uintptr_t>(object);
int error = binderConnector_->WriteBinder(BINDER_GET_NODE_REFCOUNT, &refs);
if (error != ERR_NONE) {
ZLOGE(LABEL, "GetSRefCount error = %{public}d", error);
return 0;
}
return refs.count;
}
#ifndef CONFIG_IPC_SINGLE
int BinderInvoker::TranslateProxy(uint32_t handle, uint32_t flag)
{
binder_node_debug_info info {};
if ((binderConnector_ == nullptr) || (!binderConnector_->IsDriverAlive())) {
return -IPC_INVOKER_CONNECT_ERR;
}
info.has_strong_ref = handle;
info.has_weak_ref = flag;
ZLOGI(LABEL, "TranslateProxy input handle = %{public}u", info.has_strong_ref);
int error = binderConnector_->WriteBinder(BINDER_TRANSLATE_HANDLE, &info);
if (error == ERR_NONE && info.has_strong_ref > 0) {
ZLOGI(LABEL, "TranslateProxy get new handle = %{public}u", info.has_strong_ref);
return info.has_strong_ref;
}
ZLOGE(LABEL, "failed to translateProxy input handle = %{public}u", info.has_strong_ref);
return -IPC_INVOKER_TRANSLATE_ERR;
}
int BinderInvoker::TranslateStub(binder_uintptr_t cookie, binder_uintptr_t ptr, uint32_t flag, int cmd)
{
binder_node_debug_info info {};
if ((binderConnector_ == nullptr) || (!binderConnector_->IsDriverAlive())) {
return -IPC_INVOKER_CONNECT_ERR;
}
info.cookie = cookie;
info.ptr = ptr;
info.has_weak_ref = cmd;
info.has_strong_ref = flag;
int error = binderConnector_->WriteBinder(BINDER_TRANSLATE_HANDLE, &info);
if (error == ERR_NONE && info.has_strong_ref > 0) {
ZLOGI(LABEL, "TranslateStub get new handle = %{public}u", info.has_strong_ref);
return info.has_strong_ref;
}
ZLOGE(LABEL, "failed to TranslateStub");
return -IPC_INVOKER_TRANSLATE_ERR;
}
sptr<IRemoteObject> BinderInvoker::GetSAMgrObject()
{
return nullptr;
}
#endif
bool BinderInvoker::SetMaxWorkThread(int maxThreadNum)
{
if ((binderConnector_ == nullptr) || (!binderConnector_->IsDriverAlive())) {
ZLOGE(LABEL, "%{public}s driver died", __func__);
return false;
}
int error = binderConnector_->WriteBinder(BINDER_SET_MAX_THREADS, &maxThreadNum);
if (error != ERR_NONE) {
ZLOGE(LABEL, "SetMaxWorkThread error = %{public}d", error);
return false;
}
return true;
}
int BinderInvoker::FlushCommands(IRemoteObject *object)
{
if ((binderConnector_ == nullptr) || (!binderConnector_->IsDriverAlive())) {
ZLOGE(LABEL, "driver is died");
return IPC_INVOKER_CONNECT_ERR;
}
int error = TransactWithDriver(false);
if (error != ERR_NONE) {
ZLOGE(LABEL, "fail to flush commands with error = %{public}d", error);
}
if (output_.GetDataSize() > 0) {
error = TransactWithDriver(false);
ZLOGE(LABEL, "flush commands again with return value = %{public}d", error);
}
if (error != ERR_NONE || output_.GetDataSize() > 0) {
ZLOGE(LABEL, "flush commands with error = %{public}d, left data size = %{public}zu", error,
output_.GetDataSize());
}
return error;
}
void BinderInvoker::ExitCurrentThread()
{
if ((binderConnector_ == nullptr) || (!binderConnector_->IsDriverAlive())) {
ZLOGE(LABEL, "%{public}s driver died when exit current thread", __func__);
return;
}
binderConnector_->ExitCurrentThread(BINDER_THREAD_EXIT);
}
void BinderInvoker::StartWorkLoop()
{
int error;
do {
error = TransactWithDriver();
if (error < ERR_NONE && error != -ECONNREFUSED && error != -EBADF) {
ZLOGE(LABEL, "returned unexpected error %d, aborting", error);
abort();
}
uint32_t cmd = input_.ReadUint32();
int userError = HandleCommands(cmd);
if ((userError == -ERR_TIMED_OUT || userError == IPC_INVOKER_INVALID_DATA_ERR) && !isMainWorkThread) {
break;
}
} while (error != -ECONNREFUSED && error != -EBADF && !stopWorkThread);
}
int BinderInvoker::SendReply(MessageParcel &reply, uint32_t flags, int32_t result)
{
int error = WriteTransaction(BC_REPLY, flags, -1, 0, reply, &result);
if (error < ERR_NONE) {
return error;
}
return WaitForCompletion();
}
void BinderInvoker::OnBinderDied()
{
uintptr_t cookie = input_.ReadPointer();
auto *proxy = reinterpret_cast<IPCObjectProxy *>(cookie);
ZLOGI(LABEL, "%s", __func__);
if (proxy != nullptr) {
proxy->SendObituary();
}
size_t rewindPos = output_.GetWritePosition();
if (!output_.WriteInt32(BC_DEAD_BINDER_DONE)) {
return;
}
if (!output_.WritePointer((uintptr_t)cookie)) {
if (!output_.RewindWrite(rewindPos)) {
output_.FlushBuffer();
}
}
}
void BinderInvoker::OnAcquireObject(uint32_t cmd)
{
bool ParcelResult = false;
uintptr_t refsPointer = input_.ReadPointer();
uintptr_t objectPointer = input_.ReadPointer();
RefBase *refs = reinterpret_cast<IRemoteObject *>(refsPointer);
if ((refs == nullptr) || (!objectPointer)) {
ZLOGE(LABEL, "OnAcquireObject FAIL!");
return;
}
ZLOGI(LABEL, "OnAcquireObject refcount=%{public}d", refs->GetSptrRefCount());
size_t rewindPos = output_.GetWritePosition();
if (cmd == BR_ACQUIRE) {
refs->IncStrongRef(this);
ParcelResult = output_.WriteInt32(BC_ACQUIRE_DONE);
} else {
refs->IncWeakRef(this);
ParcelResult = output_.WriteInt32(BC_INCREFS_DONE);
}
if (!ParcelResult || !output_.WritePointer(refsPointer)) {
if (!output_.RewindWrite(rewindPos)) {
output_.FlushBuffer();
}
return;
}
if (!output_.WritePointer(objectPointer)) {
if (!output_.RewindWrite(rewindPos)) {
output_.FlushBuffer();
}
}
}
void BinderInvoker::OnReleaseObject(uint32_t cmd)
{
uintptr_t refsPointer = input_.ReadPointer();
uintptr_t objectPointer = input_.ReadPointer();
auto *refs = reinterpret_cast<IRemoteObject *>(refsPointer);
auto *object = reinterpret_cast<IRemoteObject *>(objectPointer);
if ((refs == nullptr) || (object == nullptr)) {
ZLOGE(LABEL, "OnReleaseObject FAIL!");
return;
}
ZLOGI(LABEL, "OnReleaseObject refcount=%{public}d", refs->GetSptrRefCount());
if (cmd == BR_RELEASE) {
refs->DecStrongRef(this);
} else {
refs->DecWeakRef(this);
}
}
void BinderInvoker::OnTransaction(const uint8_t *buffer)
{
const binder_transaction_data *tr = reinterpret_cast<const binder_transaction_data *>(buffer);
auto data = std::make_unique<MessageParcel>(new BinderAllocator());
data->ParseFrom(tr->data.ptr.buffer, tr->data_size);
if (tr->offsets_size > 0) {
data->InjectOffsets(tr->data.ptr.offsets, tr->offsets_size / sizeof(binder_size_t));
}
#ifndef CONFIG_STANDARD_SYSTEM
uint32_t &newflags = const_cast<uint32_t &>(tr->flags);
int isServerTraced = HitraceInvoker::TraceServerReceieve(tr->target.handle, tr->code, *data, newflags);
#endif
const pid_t oldPid = callerPid_;
const auto oldUid = static_cast<const uid_t>(callerUid_);
callerPid_ = tr->sender_pid;
callerUid_ = tr->sender_euid;
SetStatus(IRemoteInvoker::ACTIVE_INVOKER);
int error = ERR_DEAD_OBJECT;
sptr<IRemoteObject> targetObject;
if (tr->target.ptr != 0) {
auto *refs = reinterpret_cast<IRemoteObject *>(tr->target.ptr);
if ((refs != nullptr) && (tr->cookie) && (refs->AttemptIncStrongRef(this))) {
targetObject = reinterpret_cast<IPCObjectStub *>(tr->cookie);
targetObject->DecStrongRef(this);
}
} else {
targetObject = IPCProcessSkeleton::GetCurrent()->GetRegistryObject();
}
MessageParcel reply;
MessageOption option;
uint32_t flagValue = static_cast<uint32_t>(tr->flags) & ~static_cast<uint32_t>(MessageOption::TF_ACCEPT_FDS);
if (targetObject != nullptr) {
option.SetFlags(static_cast<int>(flagValue));
error = targetObject->SendRequest(tr->code, *data, reply, option);
}
#ifndef CONFIG_STANDARD_SYSTEM
HitraceInvoker::TraceServerSend(tr->target.handle, tr->code, isServerTraced, newflags);
#endif
if (!(flagValue & TF_ONE_WAY)) {
SendReply(reply, 0, error);
}
callerPid_ = oldPid;
callerUid_ = oldUid;
SetStatus(IRemoteInvoker::IDLE_INVOKER);
}
void BinderInvoker::OnAttemptAcquire()
{
bool success = false;
uintptr_t refsPtr = input_.ReadPointer();
uintptr_t objectPtr = input_.ReadPointer();
auto *refs = reinterpret_cast<IRemoteObject *>(refsPtr);
size_t rewindPos = output_.GetWritePosition();
if ((refs != nullptr) && (!objectPtr)) {
ZLOGI(LABEL, "OnAttemptAcquire refcount=%{public}d", refs->GetSptrRefCount());
success = refs->AttemptIncStrongRef(this);
}
if (!output_.WriteUint32(BC_ACQUIRE_RESULT)) {
return;
}
if (!output_.WriteUint32((uint32_t)success)) {
if (!output_.RewindWrite(rewindPos)) {
output_.FlushBuffer();
}
}
}
void BinderInvoker::OnRemoveRecipientDone()
{
uintptr_t cookie = input_.ReadPointer();
auto *proxy = reinterpret_cast<IPCObjectProxy *>(cookie);
if (proxy != nullptr) {
proxy->DecStrongRef(this);
}
}
int BinderInvoker::HandleReply(MessageParcel *reply)
{
const size_t readSize = sizeof(binder_transaction_data);
const uint8_t *buffer = input_.ReadBuffer(readSize);
if (buffer == nullptr) {
ZLOGE(LABEL, "HandleReply read tr failed");
return IPC_INVOKER_INVALID_DATA_ERR;
}
const binder_transaction_data *tr = reinterpret_cast<const binder_transaction_data *>(buffer);
if (reply == nullptr) {
ZLOGI(LABEL, "no need reply, free the buffer");
FreeBuffer(reinterpret_cast<void *>(tr->data.ptr.buffer));
return IPC_INVOKER_INVALID_REPLY_ERR;
}
if (tr->flags & TF_STATUS_CODE) {
int32_t status = *reinterpret_cast<const int32_t *>(tr->data.ptr.buffer);
ZLOGI(LABEL, "received status code:%{public}d, free the buffer", status);
FreeBuffer(reinterpret_cast<void *>(tr->data.ptr.buffer));
return status;
}
if (tr->data_size > 0) {
auto allocator = new BinderAllocator();
if (!reply->SetAllocator(allocator)) {
ZLOGI(LABEL, "SetAllocator failed");
delete allocator;
FreeBuffer(reinterpret_cast<void*>(tr->data.ptr.buffer));
return IPC_INVOKER_INVALID_DATA_ERR;
}
reply->ParseFrom(tr->data.ptr.buffer, tr->data_size);
}
if (tr->offsets_size > 0) {
reply->InjectOffsets(tr->data.ptr.offsets, tr->offsets_size / sizeof(binder_size_t));
reply->SetClearFdFlag();
}
return ERR_NONE;
}
int BinderInvoker::HandleCommands(uint32_t cmd)
{
int error = ERR_NONE;
ZLOGI(LABEL, "HandleCommands:cmd=[%u]:%{public}s\n", cmd, BinderDebug::ToString(cmd).c_str());
switch (cmd) {
case BR_ERROR:
error = input_.ReadInt32();
break;
case BR_ACQUIRE:
case BR_INCREFS:
OnAcquireObject(cmd);
break;
case BR_RELEASE:
case BR_DECREFS:
OnReleaseObject(cmd);
break;
case BR_ATTEMPT_ACQUIRE:
OnAttemptAcquire();
break;
case BR_TRANSACTION: {
const uint8_t *buffer = input_.ReadBuffer(sizeof(binder_transaction_data));
if (buffer == nullptr) {
error = IPC_INVOKER_INVALID_DATA_ERR;
break;
}
OnTransaction(buffer);
break;
}
case BR_SPAWN_LOOPER: {
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current != nullptr) {
current->SpawnThread();
}
break;
}
case BR_FINISHED:
error = -ERR_TIMED_OUT;
break;
case BR_DEAD_BINDER:
OnBinderDied();
break;
case BR_CLEAR_DEATH_NOTIFICATION_DONE:
OnRemoveRecipientDone();
break;
case BR_OK:
case BR_NOOP:
break;
default:
error = IPC_INVOKER_ON_TRANSACT_ERR;
break;
}
if (error != ERR_NONE) {
ZLOGE(LABEL, "HandleCommands cmd = %{public}u(%{public}s), error = %{public}d", cmd,
BinderDebug::ToString(cmd).c_str(), error);
}
return error;
}
void BinderInvoker::JoinThread(bool initiative)
{
isMainWorkThread = initiative;
output_.WriteUint32(initiative ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
StartWorkLoop();
output_.WriteUint32(BC_EXIT_LOOPER);
// pass in nullptr directly
FlushCommands(nullptr);
ZLOGE(LABEL, "Current Thread %d is leaving", getpid());
}
void BinderInvoker::JoinProcessThread(bool initiative) {}
int BinderInvoker::TransactWithDriver(bool doRead)
{
if ((binderConnector_ == nullptr) || (!binderConnector_->IsDriverAlive())) {
ZLOGE(LABEL, "%{public}s: Binder Driver died", __func__);
return IPC_INVOKER_CONNECT_ERR;
}
binder_write_read bwr;
const bool readAvail = input_.GetReadableBytes() == 0;
const size_t outAvail = (!doRead || readAvail) ? output_.GetDataSize() : 0;
bwr.write_size = (binder_size_t)outAvail;
bwr.write_buffer = output_.GetData();
if (doRead && readAvail) {
bwr.read_size = input_.GetDataCapacity();
bwr.read_buffer = input_.GetData();
} else {
bwr.read_size = 0;
bwr.read_buffer = 0;
}
if ((bwr.write_size == 0) && (bwr.read_size == 0)) {
return ERR_NONE;
}
bwr.write_consumed = 0;
bwr.read_consumed = 0;
ZLOGI(LABEL, "TransactWithDriver write_size:%lld, read_size:%lld\n", bwr.write_size, bwr.read_size);
int error = binderConnector_->WriteBinder(BINDER_WRITE_READ, &bwr);
if (bwr.write_consumed > 0) {
if (bwr.write_consumed < output_.GetDataSize()) {
// we still have some bytes not been handled.
} else {
output_.FlushBuffer();
}
}
if (bwr.read_consumed > 0) {
input_.SetDataSize(bwr.read_consumed);
input_.RewindRead(0);
}
if (error != ERR_NONE) {
ZLOGE(LABEL, "TransactWithDriver result = %{public}d\n", error);
}
return error;
}
bool BinderInvoker::WriteTransaction(int cmd, uint32_t flags, int32_t handle, uint32_t code, const MessageParcel &data,
const int32_t *status)
{
binder_transaction_data tr {};
tr.target.handle = (uint32_t)handle;
tr.code = code;
tr.flags = flags;
tr.flags |= TF_ACCEPT_FDS;
if (data.GetDataSize() > 0) {
// Send this parcel's data through the binder.
tr.data_size = data.GetDataSize();
tr.data.ptr.buffer = (binder_uintptr_t)data.GetData();
tr.offsets_size = data.GetOffsetsSize() * sizeof(binder_size_t);
tr.data.ptr.offsets = data.GetObjectOffsets();
} else if (status != nullptr) {
// Send this parcel's status through the binder.
tr.flags |= TF_STATUS_CODE;
tr.data_size = sizeof(int32_t);
tr.data.ptr.buffer = reinterpret_cast<uintptr_t>(status);
tr.offsets_size = 0;
tr.data.ptr.offsets = 0;
}
if (!output_.WriteInt32(cmd)) {
ZLOGE(LABEL, "WriteTransaction Command failure");
return false;
}
return output_.WriteBuffer(&tr, sizeof(binder_transaction_data));
}
int BinderInvoker::WaitForCompletion(MessageParcel *reply, int32_t *acquireResult)
{
uint32_t cmd;
bool continueLoop = true;
int error = ERR_NONE;
while (continueLoop) {
if ((error = TransactWithDriver()) < ERR_NONE) {
break;
}
if (input_.GetReadableBytes() == 0) {
continue;
}
cmd = input_.ReadUint32();
switch (cmd) {
case BR_TRANSACTION_COMPLETE: {
if (reply == nullptr && acquireResult == nullptr) {
continueLoop = false;
}
break;
}
case BR_DEAD_REPLY: // fall-through
case BR_FAILED_REPLY: {
error = cmd;
if (acquireResult != nullptr) {
*acquireResult = cmd;
}
continueLoop = false;
break;
}
case BR_ACQUIRE_RESULT: {
int32_t result = input_.ReadInt32();
if (acquireResult != nullptr) {
*acquireResult = result ? ERR_NONE : ERR_INVALID_OPERATION;
continueLoop = false;
}
break;
}
case BR_REPLY: {
error = HandleReply(reply);
if (error != IPC_INVOKER_INVALID_REPLY_ERR) {
continueLoop = false;
break;
}
error = ERR_NONE;
break;
}
default: {
error = HandleCommands(cmd);
if (error != ERR_NONE) {
continueLoop = false;
}
break;
}
}
}
return error;
}
void BinderInvoker::StopWorkThread()
{
stopWorkThread = true;
}
bool BinderInvoker::PingService(int32_t handle)
{
MessageParcel data, reply;
MessageOption option;
int result = SendRequest(handle, PING_TRANSACTION, data, reply, option);
return (result == ERR_NONE);
}
bool BinderInvoker::SetRegistryObject(sptr<IRemoteObject> &object)
{
if ((binderConnector_ == nullptr) || (!binderConnector_->IsDriverAlive())) {
return false;
}
if (object->IsProxyObject()) {
ZLOGE(LABEL, "%{public}s: set wrong object!", __func__);
return false;
}
Parcel dummy;
int result = binderConnector_->WriteBinder(BINDER_SET_CONTEXT_MGR, &dummy);
if (result != ERR_NONE) {
ZLOGE(LABEL, "%{public}s:set registry fail, driver error %{public}d", __func__, result);
return false;
}
return true;
}
void BinderInvoker::FreeBuffer(void *data)
{
size_t rewindPos = output_.GetWritePosition();
if (!output_.WriteUint32(BC_FREE_BUFFER)) {
return;
}
if (!output_.WritePointer((uintptr_t)data)) {
if (!output_.RewindWrite(rewindPos)) {
output_.FlushBuffer();
}
}
}
void BinderInvoker::BinderAllocator::Dealloc(void *data)
{
IRemoteInvoker *invoker = IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DEFAULT);
if (invoker != nullptr) {
invoker->FreeBuffer(data);
}
}
pid_t BinderInvoker::GetCallerPid() const
{
return callerPid_;
}
uid_t BinderInvoker::GetCallerUid() const
{
return callerUid_;
}
uint32_t BinderInvoker::GetStatus() const
{
return status_;
}
void BinderInvoker::SetStatus(uint32_t status)
{
status_ = status;
}
std::string BinderInvoker::GetLocalDeviceID()
{
return "";
}
std::string BinderInvoker::GetCallerDeviceID() const
{
return "";
}
bool BinderInvoker::IsLocalCalling()
{
return true;
}
bool BinderInvoker::FlattenObject(Parcel &parcel, const IRemoteObject *object) const
{
if (object == nullptr) {
return false;
}
flat_binder_object flat;
if (object->IsProxyObject()) {
const IPCObjectProxy *proxy = reinterpret_cast<const IPCObjectProxy *>(object);
const int32_t handle = proxy ? proxy->GetHandle() : -1;
flat.hdr.type = BINDER_TYPE_HANDLE;
flat.binder = 0;
flat.handle = (uint32_t)handle;
flat.cookie = proxy ? static_cast<binder_uintptr_t>(proxy->GetProto()) : 0;
} else {
flat.hdr.type = BINDER_TYPE_BINDER;
flat.binder = reinterpret_cast<uintptr_t>(object);
flat.cookie = flat.binder;
}
flat.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
bool status = parcel.WriteBuffer(&flat, sizeof(flat_binder_object));
if (!status) {
ZLOGE(LABEL, "Fail to flatten object");
#ifndef BUILD_PUBLIC_VERSION
ReportDriverEvent(DbinderErrorCode::COMMON_DRIVER_ERROR, DbinderErrorCode::ERROR_TYPE,
DbinderErrorCode::IPC_DRIVER, DbinderErrorCode::ERROR_CODE, DbinderErrorCode::FLATTEN_OBJECT_FAILURE);
#endif
}
return status;
}
IRemoteObject *BinderInvoker::UnflattenObject(Parcel &parcel)
{
const uint8_t *buffer = parcel.ReadBuffer(sizeof(flat_binder_object));
if (buffer == nullptr) {
ZLOGE(LABEL, "UnflattenObject null object buffer");
return nullptr;
}
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
return nullptr;
}
IRemoteObject *remoteObject = nullptr;
auto *flat = reinterpret_cast<const flat_binder_object *>(buffer);
switch (flat->hdr.type) {
case BINDER_TYPE_BINDER: {
remoteObject = reinterpret_cast<IRemoteObject *>(flat->cookie);
if (!current->IsContainsObject(remoteObject)) {
remoteObject = nullptr;
}
break;
}
case BINDER_TYPE_REMOTE_HANDLE:
case BINDER_TYPE_HANDLE: {
remoteObject = current->FindOrNewObject(flat->handle);
break;
}
default:
ZLOGE(LABEL, "%s: unknown binder type %u", __func__, flat->hdr.type);
remoteObject = nullptr;
break;
}
return remoteObject;
}
int BinderInvoker::ReadFileDescriptor(Parcel &parcel)
{
int fd = -1;
const uint8_t *buffer = parcel.ReadBuffer(sizeof(flat_binder_object));
if (buffer == nullptr) {
ZLOGE(LABEL, "UnflattenObject null object buffer");
return fd;
}
auto *flat = reinterpret_cast<const flat_binder_object *>(buffer);
if (flat->hdr.type == BINDER_TYPE_FD || flat->hdr.type == BINDER_TYPE_FDR) {
fd = flat->handle;
ZLOGW(LABEL, "%s:%d : fd = %d", __func__, __LINE__, fd);
} else {
ZLOGE(LABEL, "%s: unknown binder type %u", __func__, flat->hdr.type);
}
return fd;
}
bool BinderInvoker::WriteFileDescriptor(Parcel &parcel, int fd, bool takeOwnership)
{
flat_binder_object flat;
flat.hdr.type = BINDER_TYPE_FD;
flat.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
flat.binder = 0; // Don't pass uninitialized stack data to a remote process
flat.handle = fd;
flat.cookie = takeOwnership ? 1 : 0;
ZLOGW(LABEL, "%s(%d) write fd : %d", __func__, __LINE__, fd);
return parcel.WriteBuffer(&flat, sizeof(flat_binder_object));
}
std::string BinderInvoker::ResetCallingIdentity()
{
int64_t identity = (static_cast<int64_t>(callerUid_) << PID_LEN) | callerPid_;
callerUid_ = getuid();
callerPid_ = getpid();
return std::to_string(identity);
}
bool BinderInvoker::SetCallingIdentity(std::string &identity)
{
if (identity.empty()) {
return false;
}
int64_t token = std::atoll(identity.c_str());
callerUid_ = static_cast<int>(token >> PID_LEN);
callerPid_ = static_cast<int>(token);
return true;
}
#ifdef CONFIG_IPC_SINGLE
} // namespace IPC_SINGLE
#endif
} // namespace OHOS

View File

@ -0,0 +1,892 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "dbinder_databus_invoker.h"
#include <cinttypes>
#include "string_ex.h"
#include "securec.h"
#include "sys_binder.h"
#include "ipc_object_stub.h"
#include "ipc_object_proxy.h"
#include "ipc_process_skeleton.h"
#include "ipc_thread_skeleton.h"
#include "ipc_debug.h"
#include "log_tags.h"
#include "databus_session_callback.h"
namespace OHOS {
using namespace OHOS::HiviewDFX;
#ifndef TITLE
#define TITLE __PRETTY_FUNCTION__
#endif
static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_RPC, "DBinderDatabusInvoker" };
#define DBINDER_LOGE(fmt, args...) \
(void)OHOS::HiviewDFX::HiLog::Error(LOG_LABEL, "%{public}s %{public}d: " fmt, TITLE, __LINE__, ##args)
#define DBINDER_LOGI(fmt, args...) \
(void)OHOS::HiviewDFX::HiLog::Info(LOG_LABEL, "%{public}s %{public}d: " fmt, TITLE, __LINE__, ##args)
DBinderDatabusInvoker::DBinderDatabusInvoker()
: stopWorkThread_(false), callerPid_(getpid()), callerUid_(getuid()), callerDeviceID_(""), status_(0)
{
DBINDER_LOGI("Create DBinderDatabusInvoker");
}
DBinderDatabusInvoker::~DBinderDatabusInvoker()
{
DBINDER_LOGI("Clean DBinderDatabusInvoker");
}
bool DBinderDatabusInvoker::AcquireHandle(int32_t handle)
{
DBINDER_LOGI("Acquire Handle %{public}d", handle);
return true;
}
bool DBinderDatabusInvoker::ReleaseHandle(int32_t handle)
{
DBINDER_LOGI("Release Handle %{public}d", handle);
return true;
}
std::shared_ptr<DBinderSessionObject> DBinderDatabusInvoker::NewSessionOfBinderProxy(uint32_t handle,
std::shared_ptr<DBinderSessionObject> remoteSession)
{
if (remoteSession == nullptr) {
DBINDER_LOGE("remote session is nullptr");
return nullptr;
}
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
DBINDER_LOGE("current ipc process skeleton is nullptr");
return nullptr;
}
IPCObjectProxy *ipcProxy = reinterpret_cast<IPCObjectProxy *>(current->FindOrNewObject(handle));
if (ipcProxy == nullptr) {
DBINDER_LOGE("attempt to send a invalid handle = %u", handle);
return nullptr;
}
if (ipcProxy->GetProto() != IRemoteObject::IF_PROT_BINDER) {
DBINDER_LOGE("attempt to send a distributed proxy, handle = %u", handle);
return nullptr;
}
std::string sessionName = ipcProxy->GetPidAndUidInfo();
if (sessionName.empty()) {
DBINDER_LOGE("get bus name error");
return nullptr;
}
std::shared_ptr<Session> session = remoteSession->GetBusSession();
if (session == nullptr) {
DBINDER_LOGE("get databus session fail");
return nullptr;
}
MessageParcel data, reply;
if (!data.WriteUint32(IRemoteObject::DATABUS_TYPE) || !data.WriteString(current->GetLocalDeviceID()) ||
!data.WriteUint32(session->GetPeerPid()) || !data.WriteUint32(session->GetPeerUid()) ||
!data.WriteString(session->GetPeerDeviceId()) || !data.WriteString(sessionName)) {
DBINDER_LOGE("write to parcel fail");
return nullptr;
}
int err = ipcProxy->InvokeListenThread(data, reply);
if (err != ERR_NONE) {
DBINDER_LOGE("start service listen error = %d", err);
return nullptr;
}
uint64_t stubIndex = reply.ReadUint64();
if (stubIndex == 0) {
DBINDER_LOGE("stubindex error = %" PRIu64 "", stubIndex);
return nullptr;
}
if (!current->AttachHandleToIndex(handle, stubIndex)) {
DBINDER_LOGE("add stub index err stubIndex = %" PRIu64 ", handle = %u", stubIndex, handle);
// do nothing, Sending an object repeatedly
}
std::string serverName = reply.ReadString();
std::string deviceId = reply.ReadString();
DBINDER_LOGI("NewSessionOfBinderProxy serverName= %s", serverName.c_str());
std::shared_ptr<DBinderSessionObject> connectSession =
std::make_shared<DBinderSessionObject>(nullptr, serverName, deviceId);
if (connectSession == nullptr) {
DBINDER_LOGE("new server session fail!");
return nullptr;
}
return connectSession;
}
bool DBinderDatabusInvoker::AuthSession2Proxy(uint32_t handle,
const std::shared_ptr<DBinderSessionObject> databusSession)
{
if (databusSession == nullptr) {
DBINDER_LOGE("remote session is nullptr");
return false;
}
std::shared_ptr<Session> session = databusSession->GetBusSession();
if (session == nullptr) {
DBINDER_LOGE("get databus session fail");
return false;
}
MessageParcel data, reply;
MessageOption option;
if (!data.WriteUint32(session->GetPeerPid()) || !data.WriteUint32(session->GetPeerUid()) ||
!data.WriteString(session->GetPeerDeviceId())) {
DBINDER_LOGE("write to MessageParcel fail");
return false;
}
uint32_t err = SendRequest(handle, DBINDER_ADD_COMMAUTH, data, reply, option);
if (err != ERR_NONE) {
DBINDER_LOGE("send auth info to remote fail");
return false;
}
return true;
}
std::shared_ptr<DBinderSessionObject> DBinderDatabusInvoker::QuerySessionOfBinderProxy(uint32_t handle,
std::shared_ptr<DBinderSessionObject> session)
{
if (AuthSession2Proxy(handle, session) != true) {
DBINDER_LOGE("auth handle =%{public}u to session failed", handle);
return nullptr;
}
return QueryServerSessionObject(handle);
}
std::shared_ptr<DBinderSessionObject> DBinderDatabusInvoker::QueryClientSessionObject(uint32_t databusHandle)
{
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
DBINDER_LOGE("current ipc process skeleton is nullptr");
return nullptr;
}
std::shared_ptr<DBinderSessionObject> sessionOfPeer = current->StubQueryDBinderSession(databusHandle);
if (sessionOfPeer == nullptr) {
DBINDER_LOGE("no session attach to this proxy = %{public}u", databusHandle);
return nullptr;
}
return sessionOfPeer;
}
std::shared_ptr<DBinderSessionObject> DBinderDatabusInvoker::QueryServerSessionObject(uint32_t handle)
{
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
DBINDER_LOGE("current ipc process skeleton is nullptr");
return nullptr;
}
std::shared_ptr<DBinderSessionObject> sessionOfPeer = current->ProxyQueryDBinderSession(handle);
if (sessionOfPeer == nullptr) {
DBINDER_LOGI("no session attach to this handle = %{public}u", handle);
return nullptr;
}
return sessionOfPeer;
}
bool DBinderDatabusInvoker::OnReceiveNewConnection(std::shared_ptr<Session> session)
{
uint32_t handle = IPCProcessSkeleton::ConvertChannelID2Int(session->GetChannelId());
if (handle == 0) {
return false;
}
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
DBINDER_LOGE("current ipc process skeleton is nullptr");
return false;
}
if (!current->QueryIsAuth(session->GetPeerPid(), session->GetPeerUid(), session->GetPeerDeviceId())) {
DBINDER_LOGE("remote device is not auth");
return false;
}
std::shared_ptr<DBinderSessionObject> sessionObject =
std::make_shared<DBinderSessionObject>(session, session->GetPeerSessionName(), session->GetPeerDeviceId());
if (!current->StubAttachDBinderSession(handle, sessionObject)) {
DBINDER_LOGE("attach session to process skeleton failed, handle =%u", handle);
}
return true;
}
bool DBinderDatabusInvoker::CreateProcessThread()
{
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
DBINDER_LOGE("current ipc process skeleton is nullptr");
return false;
}
/* epoll thread obtained one thread, so idle thread must more than 1 */
if (current->GetSocketIdleThreadNum() > 0) {
current->SpawnThread(IPCWorkThread::PROCESS_PASSIVE, IRemoteObject::IF_PROT_DATABUS);
DBINDER_LOGI("create Process thread success");
return true;
}
DBINDER_LOGE("no idle socket thread left, fail to CreateProcessThread");
return false;
}
void DBinderDatabusInvoker::OnRawDataAvailable(std::shared_ptr<Session> session, const char *data, uint32_t dataSize)
{
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
DBINDER_LOGE("current ipc process skeleton is nullptr");
return;
}
uint32_t rawDataSize = dataSize - sizeof(dbinder_transaction_data);
if (rawDataSize > 0 && rawDataSize <= MAX_RAWDATA_SIZE - sizeof(dbinder_transaction_data)) {
std::shared_ptr<InvokerRawData> invokerRawData = std::make_shared<InvokerRawData>(rawDataSize);
if (memcpy_s(invokerRawData->GetData().get(), rawDataSize, data + sizeof(dbinder_transaction_data),
rawDataSize) != EOK) {
DBINDER_LOGE("memcpy_s failed , size = %u", rawDataSize);
return;
}
if (!current->AttachRawData(IPCProcessSkeleton::ConvertChannelID2Int(session->GetChannelId()),
invokerRawData)) {
return;
}
}
return;
}
/*
* Write 64K=SOCKET_BUFF_SIZE
* +------------------+-------------------------+----------------|
* |0<---processed--->|Read <----need process-->|<--idle buffer-->
* -cursor
*
* when idle buffer less 1k, move need process to buffer head, then update R/W cursor
* when idle buffer can not put a full package, also move need process package to buffer head
*/
void DBinderDatabusInvoker::OnMessageAvailable(std::shared_ptr<Session> session, const char *data, ssize_t len)
{
if (session == nullptr || data == nullptr || len > static_cast<ssize_t>(MAX_RAWDATA_SIZE) ||
len < static_cast<ssize_t>(sizeof(dbinder_transaction_data))) {
DBINDER_LOGE("session has wrong inputs");
return;
}
uint32_t packageSize = HasRawDataPackage(data, len);
if (packageSize > 0) {
// Only one set of big data can be transferred at a time.
return OnRawDataAvailable(session, data, packageSize);
}
uint32_t handle = IPCProcessSkeleton::ConvertChannelID2Int(session->GetChannelId());
uint32_t readSize = 0;
do {
packageSize = HasCompletePackage(data, readSize, len);
if (packageSize > 0) {
StartProcessLoop(handle, data + readSize, packageSize);
readSize += packageSize;
} else {
// If the current is abnormal, the subsequent is no longer processed.
break;
}
} while (readSize + sizeof(dbinder_transaction_data) < static_cast<uint32_t>(len));
}
int DBinderDatabusInvoker::OnSendMessage(std::shared_ptr<DBinderSessionObject> sessionOfPeer)
{
if (sessionOfPeer == nullptr) {
DBINDER_LOGE("sessionOfPeer is null");
return -RPC_DATABUS_INVOKER_INVALID_DATA_ERR;
}
std::shared_ptr<Session> session = sessionOfPeer->GetBusSession();
if (session == nullptr) {
DBINDER_LOGE("databus session is null");
return -RPC_DATABUS_INVOKER_INVALID_DATA_ERR;
}
std::shared_ptr<BufferObject> sessionBuff = sessionOfPeer->GetSessionBuff();
if (sessionBuff == nullptr) {
DBINDER_LOGE("databus session buff is null");
return -RPC_DATABUS_INVOKER_INVALID_DATA_ERR;
}
char *sendBuffer = sessionBuff->GetSendBufferAndLock(SOCKET_DEFAULT_BUFF_SIZE);
/* session buffer contain mutex, need release mutex */
if (sendBuffer == nullptr) {
DBINDER_LOGE("buffer alloc failed in session");
return -RPC_DATABUS_INVOKER_INVALID_DATA_ERR;
}
sessionBuff->UpdateSendBuffer();
size_t writeCursor = sessionBuff->GetSendBufferWriteCursor();
size_t readCursor = sessionBuff->GetSendBufferReadCursor();
if (writeCursor <= readCursor) {
sessionBuff->ReleaseSendBufferLock();
return -RPC_DATABUS_INVOKER_INVALID_DATA_ERR;
}
size_t size = writeCursor - readCursor;
int ret = session->SendBytes(static_cast<const void *>(sendBuffer + readCursor), static_cast<ssize_t>(size));
if (ret == 0) {
readCursor += size;
sessionBuff->SetSendBufferReadCursor(readCursor);
sessionBuff->SetSendBufferWriteCursor(writeCursor);
} else {
DBINDER_LOGE("ret = %{public}d, send buffer failed with length = %{public}zu, send in next time", ret, size);
}
sessionBuff->ReleaseSendBufferLock();
return ret;
}
int DBinderDatabusInvoker::OnSendRawData(std::shared_ptr<DBinderSessionObject> session, const void *data, size_t size)
{
if (session == nullptr) {
DBINDER_LOGE("sessionOfPeer is null");
return -RPC_DATABUS_INVOKER_INVALID_DATA_ERR;
}
std::shared_ptr<Session> dataBusSession = session->GetBusSession();
if (dataBusSession == nullptr) {
DBINDER_LOGE("databus session is null");
return -RPC_DATABUS_INVOKER_INVALID_DATA_ERR;
}
int ret = dataBusSession->SendBytes(data, size);
if (ret != 0) {
DBINDER_LOGE("ret = %{public}d, send buffer overflow with length = %{public}zu", ret, size);
}
return ret;
}
void DBinderDatabusInvoker::JoinThread(bool initiative) {}
void DBinderDatabusInvoker::JoinProcessThread(bool initiative)
{
std::thread::id threadId = std::this_thread::get_id();
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
DBINDER_LOGE("current ipc process skeleton is nullptr");
return;
}
std::shared_ptr<ThreadProcessInfo> processInfo = nullptr;
do {
current->AddDataThreadInWait(threadId);
while ((processInfo = current->PopDataInfoFromThread(threadId)) != nullptr) {
OnTransaction(processInfo);
}
} while (!stopWorkThread_);
}
void DBinderDatabusInvoker::StopWorkThread()
{
stopWorkThread_ = true;
}
uint32_t DBinderDatabusInvoker::FlattenSession(char *sessionOffset,
const std::shared_ptr<DBinderSessionObject> connectSession, uint64_t stubIndex)
{
FlatDBinderSession *flatSession = reinterpret_cast<FlatDBinderSession *>(sessionOffset);
flatSession->stubIndex = stubIndex;
flatSession->deviceIdLength = connectSession->GetDeviceId().length();
if (flatSession->deviceIdLength == 0 || flatSession->deviceIdLength > DEVICEID_LENGTH) {
DBINDER_LOGE("wrong devices id");
return 0;
}
int memcpyResult = memcpy_s(flatSession->deviceId, DEVICEID_LENGTH, connectSession->GetDeviceId().data(),
flatSession->deviceIdLength);
if (memcpyResult != 0) {
DBINDER_LOGE("memcpy_s failed , ID Size = %hu", flatSession->deviceIdLength);
return 0;
}
flatSession->deviceId[flatSession->deviceIdLength] = '\0';
flatSession->serviceNameLength = connectSession->GetServiceName().length();
if (flatSession->serviceNameLength == 0 || flatSession->serviceNameLength > SERVICENAME_LENGTH) {
DBINDER_LOGE("wrong service name");
return 0;
}
memcpyResult = memcpy_s(flatSession->serviceName, SERVICENAME_LENGTH, connectSession->GetServiceName().data(),
flatSession->serviceNameLength);
if (memcpyResult != 0) {
DBINDER_LOGE("memcpy_s failed , name Size = %hu", flatSession->serviceNameLength);
return 0;
}
flatSession->serviceName[flatSession->serviceNameLength] = '\0';
DBINDER_LOGI("serviceName = %s, stubIndex = %" PRIu64 "", flatSession->serviceName, flatSession->stubIndex);
return sizeof(struct FlatDBinderSession);
}
std::shared_ptr<DBinderSessionObject> DBinderDatabusInvoker::UnFlattenSession(char *sessionOffset, uint64_t &stubIndex)
{
FlatDBinderSession *flatSession = reinterpret_cast<FlatDBinderSession *>(sessionOffset);
/* force end true string length */
flatSession->deviceId[DEVICEID_LENGTH] = '\0';
flatSession->serviceName[SERVICENAME_LENGTH] = '\0';
DBINDER_LOGI("serviceName = %s, stubIndex = %" PRIu64 "", flatSession->serviceName, flatSession->stubIndex);
stubIndex = flatSession->stubIndex;
if (stubIndex == 0) {
DBINDER_LOGE("stubIndex err");
return nullptr;
}
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
DBINDER_LOGE("current process skeleton is nullptr");
return nullptr;
}
std::shared_ptr<DBinderSessionObject> sessionObject =
current->QuerySessionByInfo(flatSession->serviceName, flatSession->deviceId);
if (sessionObject != nullptr) {
return sessionObject;
}
return std::make_shared<DBinderSessionObject>(nullptr, flatSession->serviceName, flatSession->deviceId);
}
bool DBinderDatabusInvoker::FlattenObject(Parcel &parcel, const IRemoteObject *object) const
{
return true;
}
IRemoteObject *DBinderDatabusInvoker::UnflattenObject(Parcel &parcel)
{
return nullptr;
}
int DBinderDatabusInvoker::ReadFileDescriptor(Parcel &parcel)
{
return -1;
}
bool DBinderDatabusInvoker::WriteFileDescriptor(Parcel &parcel, int fd, bool takeOwnership)
{
return true;
}
bool DBinderDatabusInvoker::UpdateClientSession(uint32_t handle, std::shared_ptr<DBinderSessionObject> sessionObject)
{
DBINDER_LOGI("update client session enter");
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
DBINDER_LOGE("current process skeleton is nullptr");
return false;
}
std::shared_ptr<ISessionService> manager = ISessionService::GetInstance();
if (manager == nullptr) {
DBINDER_LOGE("fail to get softbus manager");
return false;
}
std::string sessionName = current->GetDatabusName();
if (sessionName.empty()) {
DBINDER_LOGE("fail to get session name");
return false;
}
std::shared_ptr<Session> session = manager->OpenSession(sessionName, sessionObject->GetServiceName(),
sessionObject->GetDeviceId(), std::string(""), Session::TYPE_BYTES);
if (session == nullptr) {
DBINDER_LOGE("get databus session fail");
return false;
}
sessionObject->SetBusSession(session);
if (!current->ProxyAttachDBinderSession(handle, sessionObject)) {
DBINDER_LOGE("fail to attach session");
return false;
}
return true;
}
bool DBinderDatabusInvoker::OnDatabusSessionClosed(std::shared_ptr<Session> session)
{
if (session == nullptr) {
DBINDER_LOGE("databus session to be closed is nullptr");
return false;
}
/* means close socket */
DBINDER_LOGI("close databus session, own session name = %{public}s, peer session name = %{public}s",
session->GetMySessionName().c_str(), session->GetPeerSessionName().c_str());
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
DBINDER_LOGE("current ipc process skeleton is nullptr");
return false;
}
if (current->StubDetachDBinderSession(IPCProcessSkeleton::ConvertChannelID2Int(session->GetChannelId()))) {
current->DetachStubRefInfo(session->GetPeerPid(), session->GetPeerDeviceId());
// No need to clear proxy objects
return true;
}
std::vector<uint32_t> proxy;
if (!current->QueryProxyBySessionHandle(IPCProcessSkeleton::ConvertChannelID2Int(session->GetChannelId()), proxy)) {
return false;
}
if (proxy.empty()) {
DBINDER_LOGE("proxy handle is empty");
return false;
}
for (auto it = proxy.begin(); it != proxy.end(); ++it) {
std::u16string descriptor = current->MakeHandleDescriptor(*it);
IRemoteObject *remoteObject = current->QueryObject(descriptor);
if (remoteObject != nullptr) {
IPCObjectProxy *remoteProxy = reinterpret_cast<IPCObjectProxy *>(remoteObject);
if (remoteProxy->IsSubscribeDeathNotice()) {
remoteProxy->SendObituary();
}
(void)current->ProxyDetachDBinderSession(*it);
(void)current->DetachHandleToIndex(*it);
}
}
DBINDER_LOGI("closet socket sussess");
return true;
}
uint32_t DBinderDatabusInvoker::QueryHandleBySession(std::shared_ptr<DBinderSessionObject> session, uint64_t stubIndex)
{
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
DBINDER_LOGE("current ipc process skeleton is nullptr");
return 0;
}
return current->QueryHandleByDatabusSession(session->GetServiceName(), session->GetDeviceId(), stubIndex);
}
uint64_t DBinderDatabusInvoker::GetSeqNum() const
{
return seqNumber_;
}
void DBinderDatabusInvoker::SetSeqNum(uint64_t seq)
{
seqNumber_ = seq;
}
uint32_t DBinderDatabusInvoker::GetClientFd() const
{
return clientFd_;
}
void DBinderDatabusInvoker::SetClientFd(uint32_t fd)
{
clientFd_ = fd;
}
pid_t DBinderDatabusInvoker::GetCallerPid() const
{
return callerPid_;
}
void DBinderDatabusInvoker::SetStatus(uint32_t status)
{
status_ = status;
}
uint32_t DBinderDatabusInvoker::GetStatus() const
{
return status_;
}
void DBinderDatabusInvoker::SetCallerPid(pid_t pid)
{
callerPid_ = pid;
}
uid_t DBinderDatabusInvoker::GetCallerUid() const
{
return callerUid_;
}
void DBinderDatabusInvoker::SetCallerUid(pid_t uid)
{
callerUid_ = uid;
}
void DBinderDatabusInvoker::SetCallerDeviceID(const std::string &deviceId)
{
callerDeviceID_ = deviceId;
}
bool DBinderDatabusInvoker::IsLocalCalling()
{
return false;
}
int DBinderDatabusInvoker::CheckAndSetCallerInfo(uint32_t listenFd, uint64_t stubIndex)
{
std::shared_ptr<DBinderSessionObject> sessionObject = QueryClientSessionObject(listenFd);
if (sessionObject == nullptr) {
DBINDER_LOGE("session is not exist for listenFd = %u", listenFd);
return RPC_DATABUS_INVOKER_INVALID_DATA_ERR;
}
std::shared_ptr<Session> session = sessionObject->GetBusSession();
if (session == nullptr) {
DBINDER_LOGE("get databus session fail");
return RPC_DATABUS_INVOKER_INVALID_DATA_ERR;
}
int pid = session->GetPeerPid();
int uid = session->GetPeerUid();
std::string deviceId = session->GetPeerDeviceId();
if (uid < 0 || deviceId.length() > DEVICEID_LENGTH) {
DBINDER_LOGE("user id and device id error");
return RPC_DATABUS_INVOKER_INVALID_DATA_ERR;
}
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
DBINDER_LOGE("current process skeleton is nullptr");
return IPC_SKELETON_ERR;
}
if (current->QueryAppInfoToStubIndex(pid, uid, deviceId, stubIndex) == false) {
DBINDER_LOGE("stub index is NOT belong to caller,serviceName = %{public}s, listenFd = %{public}u",
deviceId.c_str(), listenFd);
return RPC_DATABUS_INVOKER_INVALID_STUB_INDEX;
}
callerPid_ = pid;
callerUid_ = uid;
callerDeviceID_ = deviceId;
return ERR_NONE;
}
std::string DBinderDatabusInvoker::GetLocalDeviceID()
{
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
DBINDER_LOGE("current process skeleton is nullptr");
return "";
}
return current->GetLocalDeviceID();
}
std::string DBinderDatabusInvoker::GetCallerDeviceID() const
{
return callerDeviceID_;
}
uint64_t DBinderDatabusInvoker::MakeStubIndexByRemoteObject(IRemoteObject *stubObject)
{
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
DBINDER_LOGE("IPCProcessSkeleton is nullptr");
return 0;
}
if (!current->IsContainsObject(stubObject)) {
DBINDER_LOGE("fail to find stub");
return 0;
}
uint64_t stubIndex = current->AddStubByIndex(stubObject);
if (!stubIndex) {
DBINDER_LOGE("fail to add stub");
return 0;
}
return stubIndex;
}
std::shared_ptr<DBinderSessionObject> DBinderDatabusInvoker::MakeDefaultServerSessionObject()
{
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
DBINDER_LOGE("IPCProcessSkeleton is nullptr");
return nullptr;
}
std::string serviceName = current->GetDatabusName();
if (serviceName.empty()) {
DBINDER_LOGE("fail to get databus name");
return nullptr;
}
std::shared_ptr<DBinderSessionObject> connectSession =
std::make_shared<DBinderSessionObject>(nullptr, serviceName, current->GetLocalDeviceID());
if (connectSession == nullptr) {
DBINDER_LOGE("new server session fail!");
return nullptr;
}
return connectSession;
}
bool DBinderDatabusInvoker::ConnectRemoteObject2Session(IRemoteObject *stubObject, uint64_t stubIndex,
const std::shared_ptr<DBinderSessionObject> sessionObject)
{
if (sessionObject == nullptr) {
DBINDER_LOGE("session object is nullptr");
return false;
}
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
DBINDER_LOGE("IPCProcessSkeleton is nullptr");
return false;
}
std::shared_ptr<Session> session = sessionObject->GetBusSession();
if (session == nullptr) {
DBINDER_LOGE("get databus session fail");
return false;
}
int peerPid = session->GetPeerPid();
int peerUid = session->GetPeerUid();
std::string deviceId = session->GetPeerDeviceId();
if (!current->AttachAppInfoToStubIndex(peerPid, peerUid, deviceId, stubIndex)) {
DBINDER_LOGI("fail to attach appinfo to stub index, when proxy call we check appinfo");
// attempt attach again, if failed, do nothing
}
if (!current->AttachCommAuthInfo(stubObject, peerPid, peerUid, deviceId)) {
DBINDER_LOGI("fail to attach comm auth info, maybe attached already");
// attempt attach again, if failed, do nothing
}
if (current->AttachStubSendRefInfo(stubObject, peerPid, deviceId)) {
if (!current->IncStubRefTimes(stubObject)) {
DBINDER_LOGE("Inc Stub RefTimes fail");
current->DetachCommAuthInfo(stubObject, peerPid, peerUid, deviceId);
current->DetachAppInfoToStubIndex(peerPid, peerUid, deviceId, stubIndex);
return false;
}
stubObject->IncStrongRef(this);
}
return true;
}
std::shared_ptr<DBinderSessionObject> DBinderDatabusInvoker::CreateServerSessionObject(binder_uintptr_t binder,
uint64_t &stubIndex, std::shared_ptr<DBinderSessionObject> sessionObject)
{
IRemoteObject *stubObject = reinterpret_cast<IPCObjectStub *>(binder);
if (stubObject == nullptr) {
DBINDER_LOGE("binder is nullptr");
return nullptr;
}
stubIndex = MakeStubIndexByRemoteObject(stubObject);
if (stubIndex == 0) {
DBINDER_LOGE("fail to add stub");
return nullptr;
}
if (ConnectRemoteObject2Session(stubObject, stubIndex, sessionObject) != true) {
DBINDER_LOGE("fail to connect stub to session");
return nullptr;
}
return MakeDefaultServerSessionObject();
}
int DBinderDatabusInvoker::FlushCommands(IRemoteObject *object)
{
if (object == nullptr || !object->IsProxyObject()) {
DBINDER_LOGE("proxy is invalid");
return RPC_DATABUS_INVOKER_INVALID_DATA_ERR;
}
IPCObjectProxy *proxy = reinterpret_cast<IPCObjectProxy *>(object);
std::shared_ptr<DBinderSessionObject> session = QueryServerSessionObject(proxy->GetHandle());
if (session == nullptr) {
DBINDER_LOGE("session is nullptr");
return RPC_DATABUS_INVOKER_INVALID_DATA_ERR;
}
(void)OnSendMessage(session);
return ERR_NONE;
}
std::string DBinderDatabusInvoker::ResetCallingIdentity()
{
std::string token = std::to_string(((static_cast<int64_t>(callerUid_) << PID_LEN) | callerPid_));
std::string identity = callerDeviceID_ + token;
callerUid_ = getuid();
callerPid_ = getpid();
callerDeviceID_ = GetLocalDeviceID();
return identity;
}
bool DBinderDatabusInvoker::SetCallingIdentity(std::string &identity)
{
if (identity.empty() || identity.length() <= DEVICEID_LENGTH) {
return false;
}
std::string deviceId = identity.substr(0, DEVICEID_LENGTH);
int64_t token = std::atoll(identity.substr(DEVICEID_LENGTH, identity.length() - DEVICEID_LENGTH).c_str());
callerUid_ = static_cast<int>(token >> PID_LEN);
callerPid_ = static_cast<int>(token);
callerDeviceID_ = deviceId;
return true;
}
int DBinderDatabusInvoker::TranslateProxy(uint32_t handle, uint32_t flag)
{
return -IPC_INVOKER_TRANSLATE_ERR;
}
int DBinderDatabusInvoker::TranslateStub(binder_uintptr_t cookie, binder_uintptr_t ptr, uint32_t flag, int cmd)
{
return -IPC_INVOKER_TRANSLATE_ERR;
}
uint32_t DBinderDatabusInvoker::HasRawDataPackage(const char *data, ssize_t len)
{
const dbinder_transaction_data *tr = reinterpret_cast<const dbinder_transaction_data *>(data);
if ((tr->magic == DBINDER_MAGICWORD) && (tr->cmd == BC_SEND_RAWDATA) &&
(tr->sizeOfSelf == static_cast<uint32_t>(len))) {
if (tr->sizeOfSelf > MAX_RAWDATA_SIZE) {
return MAX_RAWDATA_SIZE;
}
return tr->sizeOfSelf;
}
return 0;
}
uint32_t DBinderDatabusInvoker::HasCompletePackage(const char *data, uint32_t readCursor, ssize_t len)
{
const dbinder_transaction_data *tr = reinterpret_cast<const dbinder_transaction_data *>(data + readCursor);
if ((tr->magic == DBINDER_MAGICWORD) &&
(tr->sizeOfSelf <= SOCKET_MAX_BUFF_SIZE + sizeof(dbinder_transaction_data)) &&
(readCursor + tr->sizeOfSelf <= static_cast<uint32_t>(len)) && CheckTransactionData(tr)) {
return tr->sizeOfSelf;
}
return 0;
}
} // namespace OHOS

View File

@ -0,0 +1,140 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "hitrace_invoker.h"
#include <sys/types.h>
#include "hilog/log.h"
#include "hitrace/trace.h"
#include "sys_binder.h"
#include "ipc_debug.h"
#include "log_tags.h"
namespace OHOS {
// the value should be equal to the set of parcel
using namespace OHOS::HiviewDFX;
static const HiLogLabel TRACE_LABEL = { LOG_CORE, LOG_ID_IPC, "BinderHiTrace" };
bool HitraceInvoker::IsClientTraced(int32_t handle, uint32_t flags, const HiTraceId &traceId)
{
return (traceId.IsValid() && (handle != 0) &&
((flags & TF_ONE_WAY) ? traceId.IsFlagEnabled(HITRACE_FLAG_INCLUDE_ASYNC) : true));
}
HiTraceId HitraceInvoker::TraceClientSend(int32_t handle, uint32_t code, Parcel &data, uint32_t &flags,
const HiTraceId &traceId)
{
HiTraceId childId = traceId;
bool isClientTraced = IsClientTraced(handle, flags, traceId);
if (isClientTraced) {
childId = HiTrace::CreateSpan();
// add childid to parcel data
uint8_t idBytes[HITRACE_ID_LEN];
int idLen = childId.ToBytes(idBytes, HITRACE_ID_LEN);
if (idLen != HITRACE_ID_LEN) {
ZLOGE(TRACE_LABEL, "%{public}s:idLen not correct", __func__);
return childId;
}
size_t oldWritePosition = data.GetWritePosition();
if (!data.WriteBuffer(idBytes, idLen)) {
ZLOGE(TRACE_LABEL, "%{public}s:Write idBytes fail", __func__);
// restore Parcel data
data.RewindWrite(oldWritePosition);
return childId;
}
// padded size of traceid
if (!data.WriteUint8(data.GetWritePosition() - oldWritePosition)) {
ZLOGE(TRACE_LABEL, "%{public}s:Write idLen fail", __func__);
// restore Parcel data
data.RewindWrite(oldWritePosition);
return childId;
}
// tracepoint: CS(Client Send)
HiTrace::Tracepoint(HITRACE_TP_CS, childId, "%s handle=%d,code=%u", (flags & TF_ONE_WAY) ? "ASYNC" : "SYNC",
handle, code);
flags |= TF_HITRACE;
}
return childId;
}
void HitraceInvoker::TraceClientReceieve(int32_t handle, uint32_t code, uint32_t flags, const HiTraceId &traceId,
const HiTraceId &childId)
{
if (!(flags & TF_HITRACE)) {
return;
}
bool isClientTraced = IsClientTraced(handle, flags, traceId);
if (isClientTraced) {
if (!(flags & TF_ONE_WAY)) {
// restore thread trace id
HiTrace::SetId(traceId);
// tracepoint: CR(Client Receive)
HiTrace::Tracepoint(HITRACE_TP_CR, childId, "%s handle=%d,code=%u", "SYNC", handle, code);
}
}
}
void HitraceInvoker::RecoveryDataAndFlag(Parcel &data, uint32_t &flags, size_t oldReadPosition, uint8_t idLen)
{
// restore data
data.RewindRead(oldReadPosition);
// padded size(4 bytes) of uint8_t
data.SetDataSize(data.GetDataSize() - PADDED_SIZE_OF_PARCEL - idLen);
flags &= ~(uint32_t)TF_HITRACE;
}
bool HitraceInvoker::TraceServerReceieve(int32_t handle, uint32_t code, Parcel &data, uint32_t &flags)
{
bool isServerTraced = (flags & TF_HITRACE) != 0;
if (isServerTraced) {
size_t oldReadPosition = data.GetReadPosition();
// padded size(4 bytes) of uint8_t
data.RewindRead(data.GetDataSize() - PADDED_SIZE_OF_PARCEL);
// the padded size of traceid
uint8_t idLen = data.ReadUint8();
if (idLen >= sizeof(HiTraceIdStruct)) {
// padded size(4 bytes) of uint8_t
data.RewindRead(data.GetDataSize() - PADDED_SIZE_OF_PARCEL - idLen);
const uint8_t *idBytes = data.ReadUnpadBuffer(sizeof(HiTraceIdStruct));
if (idBytes == nullptr) {
ZLOGE(TRACE_LABEL, "%{public}s:idBytes is null", __func__);
isServerTraced = 0;
RecoveryDataAndFlag(data, flags, oldReadPosition, idLen);
return isServerTraced;
}
HiTraceId traceId(idBytes, sizeof(HiTraceIdStruct));
HiTrace::SetId(traceId);
// tracepoint: SR(Server Receive)
HiTrace::Tracepoint(HITRACE_TP_SR, traceId, "%s handle=%d,code=%u", (flags & TF_ONE_WAY) ? "ASYNC" : "SYNC",
handle, code);
}
RecoveryDataAndFlag(data, flags, oldReadPosition, idLen);
}
return isServerTraced;
}
void HitraceInvoker::TraceServerSend(int32_t handle, uint32_t code, bool isServerTraced, uint32_t flags)
{
if (isServerTraced) {
// tracepoint: SS(Server Send)
HiTrace::Tracepoint(HITRACE_TP_SS, HiTrace::GetId(), "%s handle=%d,code=%u",
(flags & TF_ONE_WAY) ? "ASYNC" : "SYNC", handle, code);
}
HiTrace::ClearId();
}
} // namespace OHOS

View File

@ -0,0 +1,87 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "invoker_factory.h"
#include <utility>
namespace OHOS {
#ifdef CONFIG_IPC_SINGLE
namespace IPC_SINGLE {
#endif
bool InvokerFactory::isAvailable_ = true;
InvokerFactory::InvokerFactory() {}
InvokerFactory::~InvokerFactory()
{
isAvailable_ = false;
creators_.clear();
}
InvokerFactory &InvokerFactory::Get()
{
static InvokerFactory instance;
return instance;
}
bool InvokerFactory::Register(int protocol, InvokerCreator creator)
{
if (isAvailable_ != true) {
return false;
}
std::lock_guard<std::mutex> lockGuard(factoryMutex_);
/* check isAvailable_ == true again when a thread take mutex */
if (isAvailable_ != true) {
return false;
}
return creators_.insert(std::make_pair(protocol, creator)).second;
}
void InvokerFactory::Unregister(int protocol)
{
if (isAvailable_ != true) {
return;
}
std::lock_guard<std::mutex> lockGuard(factoryMutex_);
/* check isAvailable_ == true again when a thread take mutex */
if (isAvailable_ != true) {
return;
}
(void)creators_.erase(protocol);
}
IRemoteInvoker *InvokerFactory::newInstance(int protocol)
{
if (isAvailable_ != true) {
return nullptr;
}
std::lock_guard<std::mutex> lockGuard(factoryMutex_);
/* check isAvailable_ == true again when a thread take mutex */
if (isAvailable_ != true) {
return nullptr;
}
auto it = creators_.find(protocol);
if (it != creators_.end() && (it->second != nullptr)) {
return it->second();
}
return nullptr;
}
#ifdef CONFIG_IPC_SINGLE
} // namespace IPC_SINGLE
#endif
} // namespace OHOS

View File

@ -0,0 +1,40 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "invoker_rawdata.h"
namespace OHOS {
InvokerRawData::InvokerRawData(size_t size)
{
/* size is guaranteed by caller, in MessageParcel max size is 1G */
data_.reset(reinterpret_cast<char *>(::operator new(size)));
size_ = size;
}
InvokerRawData::~InvokerRawData()
{
data_ = nullptr;
}
std::shared_ptr<char> InvokerRawData::GetData() const
{
return data_;
}
size_t InvokerRawData::GetSize() const
{
return size_;
}
} // namespace OHOS

22
ipc/native/test/BUILD.gn Executable file
View File

@ -0,0 +1,22 @@
# Copyright (C) 2021 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//build/test.gni")
#################################group#########################################
group("unittest") {
testonly = true
deps = [ "unittest/common:unittest" ]
}
###############################################################################

View File

@ -0,0 +1,82 @@
# Copyright (C) 2021 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//build/test.gni")
SUBSYSTEM_DIR = "//foundation/communication/ipc"
IPC_TEST_ROOT = "//foundation/communication/ipc/ipc/test"
MODULE_OUTPUT_PATH = "ipc"
ohos_unittest("IPCNativeUnitTest") {
module_out_path = MODULE_OUTPUT_PATH
include_dirs = [ "//utils/system/safwk/native/include" ]
sources = [ "ipc_core_unittest.cpp" ]
configs = [
"$SUBSYSTEM_DIR:ipc_util_config",
"$IPC_TEST_ROOT:ipc_test_config",
]
deps = [
"$IPC_TEST_ROOT/auxiliary/native:TestAssistance",
"//third_party/googletest:gtest_main",
"//utils/native/base:utils",
]
external_deps = [
"ipc:ipc_core",
"hiviewdfx_hilog_native:libhilog",
"samgr_L2:samgr_proxy",
]
resource_config_file =
"//foundation/communication/ipc/test/resource/ipc/ohos_test.xml"
}
ohos_unittest("IPCFileDescOpsTest") {
module_out_path = MODULE_OUTPUT_PATH
sources = [ "ipc_file_desc_unittest.cpp" ]
configs = [
"$SUBSYSTEM_DIR:ipc_util_config",
"$IPC_TEST_ROOT:ipc_test_config",
]
deps = [
"$IPC_TEST_ROOT/auxiliary/native:TestAssistance",
"//third_party/googletest:gtest_main",
"//utils/native/base:utils",
]
external_deps = [
"ipc:ipc_core",
"hiviewdfx_hilog_native:libhilog",
]
resource_config_file =
"//foundation/communication/ipc/test/resource/ipc/ohos_test.xml"
}
###############################################################################
group("unittest") {
testonly = true
deps = [
":IPCFileDescOpsTest",
":IPCNativeUnitTest",
]
}
###############################################################################

View File

@ -0,0 +1,489 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <gtest/gtest.h>
#include "ipc_debug.h"
#include "ipc_skeleton.h"
#include "ipc_object_proxy.h"
#include "test_service_skeleton.h"
#include "test_service.h"
#include "test_service_command.h"
#include "test_service_client.h"
#include "ipc_test_helper.h"
#include "iservice_registry.h"
#include "if_system_ability_manager.h"
#include "iservice_registry.h"
#include "system_ability_definition.h"
#include "log_tags.h"
#ifndef CONFIG_STANDARD_SYSTEM
#include "jni_help.h"
#endif
using namespace testing::ext;
using namespace OHOS;
using namespace OHOS::HiviewDFX;
static constexpr int MAX_TEST_COUNT = 1000;
static constexpr bool SUPPORT_ZBINDER = false;
class IPCNativeUnitTest : public testing::Test {
public:
static void SetUpTestCase(void);
static void TearDownTestCase(void);
static constexpr HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "IPCUnitTest" };
private:
static inline IPCTestHelper *g_globalHelper = { nullptr };
};
void IPCNativeUnitTest::SetUpTestCase()
{
if (g_globalHelper == nullptr) {
g_globalHelper = new IPCTestHelper();
bool res = g_globalHelper->PrepareTestSuite();
ASSERT_TRUE(res);
}
}
void IPCNativeUnitTest::TearDownTestCase()
{
if (g_globalHelper != nullptr) {
bool res = g_globalHelper->TearDownTestSuite();
ASSERT_TRUE(res);
delete g_globalHelper;
g_globalHelper = nullptr;
}
}
/**
* @tc.name: DeathRecipient001
* @tc.desc: The Stub should not support AddDeathRecipient
* @tc.type: FUNC
*/
HWTEST_F(IPCNativeUnitTest, DeathRecipient001, TestSize.Level1)
{
sptr<IPCObjectStub> testStub = new IPCObjectStub(u"testStub");
bool res = testStub->AddDeathRecipient(nullptr);
EXPECT_FALSE(res);
}
/**
* @tc.name: DeathRecipient002
* @tc.desc: The Stub should not support RemoveDeathRecipient
* @tc.type: FUNC
*/
HWTEST_F(IPCNativeUnitTest, DeathRecipient002, TestSize.Level1)
{
sptr<IPCObjectStub> testStub = new IPCObjectStub(u"testStub");
bool res = testStub->RemoveDeathRecipient(nullptr);
EXPECT_FALSE(res);
}
/**
* @tc.name: DumpTest001
* @tc.desc: The Stub should not support Dump
* @tc.type: FUNC
*/
HWTEST_F(IPCNativeUnitTest, DumpTest001, TestSize.Level1)
{
sptr<IPCObjectStub> testStub = new IPCObjectStub(u"testStub");
std::vector<std::u16string> args;
args.push_back(u"test");
int res = testStub->Dump(0, args);
EXPECT_EQ(res, 0);
}
/**
* @tc.name: ProxyJudgment001
* @tc.desc: act as stub role, should return false
* @tc.type: FUNC
*/
HWTEST_F(IPCNativeUnitTest, ProxyJudgment001, TestSize.Level1)
{
sptr<IPCObjectStub> testStub = new IPCObjectStub(u"testStub");
bool res = testStub->IsProxyObject();
EXPECT_FALSE(res);
}
#ifndef CONFIG_STANDARD_SYSTEM
/**
* @tc.name: ProxyJudgment002
* @tc.desc: act as proxy role, should return true
* @tc.type: FUNC
*/
HWTEST_F(IPCNativeUnitTest, ProxyJudgment002, TestSize.Level1)
{
sptr<IRemoteObject> remote = SystemAbilityManagerClient::GetInstance().GetRegistryRemoteObject();
ASSERT_TRUE(remote != nullptr);
EXPECT_TRUE(remote->IsProxyObject());
}
/**
* @tc.name: RemoteId001.
* @tc.desc:
* @tc.type: FUNC
*/
HWTEST_F(IPCNativeUnitTest, RemoteId001, TestSize.Level1)
{
sptr<IRemoteObject> remote = SystemAbilityManagerClient::GetInstance().GetRegistryRemoteObject();
ASSERT_TRUE(remote != nullptr);
IPCObjectProxy *proxy = reinterpret_cast<IPCObjectProxy *>(remote.GetRefPtr());
ASSERT_TRUE(proxy != nullptr);
int remoteId = proxy->GetHandle();
EXPECT_GE(remoteId, 0);
}
#endif
/**
* @tc.name: ProxyJudgment003
* @tc.desc: transform interface instance to object.
* @tc.type: FUNC
*/
HWTEST_F(IPCNativeUnitTest, ProxyJudgment003, TestSize.Level1)
{
auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
ASSERT_TRUE(saMgr != nullptr);
sptr<IRemoteObject> asObject = saMgr->AsObject();
ASSERT_TRUE(asObject != nullptr);
}
/**
* @tc.name: ProxyJudgment004
* @tc.desc: Press test to validate Get Register instance..
* @tc.type: FUNC
*/
HWTEST_F(IPCNativeUnitTest, ProxyJudgment004, TestSize.Level1)
{
std::vector<sptr<ISystemAbilityManager>> registryObjs;
registryObjs.resize(100);
for (int i = 0; i < 100; i++) {
registryObjs[i] = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
ASSERT_TRUE(registryObjs[i] != nullptr);
}
}
/**
* @tc.name: MaxWorkThread001
* @tc.desc: when multi-transaction called,
* the driver will spawn new thread.but it should not exceed the max num.
* @tc.type: FUNC
*/
HWTEST_F(IPCNativeUnitTest, MaxWorkThread001, TestSize.Level1)
{
IPCTestHelper helper;
IPCSkeleton::SetMaxWorkThreadNum(8);
std::vector<pid_t> childPids;
helper.GetChildPids(childPids);
ASSERT_GE(childPids.size(), (const unsigned long)1);
}
/**
* @tc.name: SyncTransaction001
* @tc.desc: Test IPC data transaction.
* @tc.type: FUNC
*/
HWTEST_F(IPCNativeUnitTest, SyncTransaction001, TestSize.Level1)
{
IPCTestHelper helper;
bool res = helper.StartTestApp(IPCTestHelper::IPC_TEST_SERVER);
ASSERT_TRUE(res);
auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
ASSERT_TRUE(saMgr != nullptr);
// test get service and call it
sptr<IRemoteObject> service = saMgr->GetSystemAbility(IPC_TEST_SERVICE);
sptr<ITestService> testService = iface_cast<ITestService>(service);
ASSERT_TRUE(testService != nullptr);
if (service->IsProxyObject()) {
int reply = 0;
ZLOGI(LABEL, "Got Proxy node");
TestServiceProxy *proxy = static_cast<TestServiceProxy *>(testService.GetRefPtr());
int ret = proxy->TestSyncTransaction(2019, reply);
EXPECT_EQ(ret, 0);
EXPECT_EQ(reply, 9102);
} else {
ZLOGI(LABEL, "Got Stub node");
}
}
/**
* @tc.name: AsyncTransaction001
* @tc.desc: Test IPC data transaction.
* @tc.type: FUNC
* @tc.require: AR000DPV5F
*/
HWTEST_F(IPCNativeUnitTest, AsyncTransaction001, TestSize.Level1)
{
IPCTestHelper helper;
bool res = helper.StartTestApp(IPCTestHelper::IPC_TEST_SERVER);
ASSERT_TRUE(res);
auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
ASSERT_TRUE(saMgr != nullptr);
sptr<IRemoteObject> service = saMgr->GetSystemAbility(IPC_TEST_SERVICE);
sptr<ITestService> testService = iface_cast<ITestService>(service);
ASSERT_TRUE(testService != nullptr);
ZLOGI(LABEL, "Get test.service OK\n");
if (service->IsProxyObject()) {
ZLOGI(LABEL, "Got Proxy node\n");
TestServiceProxy *proxy = static_cast<TestServiceProxy *>(testService.GetRefPtr());
int reply = 0;
int ret = proxy->TestAsyncTransaction(2019, reply);
EXPECT_EQ(ret, ERR_NONE);
} else {
ZLOGI(LABEL, "Got Stub node\n");
}
}
/**
* @tc.name: SyncTransaction002
* @tc.desc: Test IPC data transaction.
* @tc.type: FUNC
* @tc.require: AR000DPV5E
*/
HWTEST_F(IPCNativeUnitTest, SyncTransaction002, TestSize.Level1)
{
int refCount = 0;
IPCTestHelper helper;
sptr<TestService> stub = new TestService();
auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
ASSERT_TRUE(saMgr != nullptr);
refCount = stub->GetObjectRefCount();
EXPECT_EQ(refCount, 1);
int result = saMgr->AddSystemAbility(IPC_TEST_SERVICE, new TestService());
EXPECT_EQ(result, ERR_NONE);
refCount = stub->GetObjectRefCount();
if (SUPPORT_ZBINDER) {
EXPECT_GE(refCount, 2);
} else {
EXPECT_GE(refCount, 1);
}
bool res = helper.StartTestApp(IPCTestHelper::IPC_TEST_CLIENT);
ASSERT_TRUE(res);
refCount = stub->GetObjectRefCount();
if (SUPPORT_ZBINDER) {
EXPECT_GE(refCount, 3);
} else {
EXPECT_GE(refCount, 1);
}
helper.StopTestApp(IPCTestHelper::IPC_TEST_CLIENT);
refCount = stub->GetObjectRefCount();
if (SUPPORT_ZBINDER) {
EXPECT_GE(refCount, 2);
} else {
EXPECT_GE(refCount, 1);
}
}
/**
* @tc.name: SyncTransaction003
* @tc.desc: Test IPC data transaction.
* @tc.type: FUNC
* @tc.require: AR000DPV5F
*/
HWTEST_F(IPCNativeUnitTest, SyncTransaction003, TestSize.Level1)
{
int refCount = 0;
IPCTestHelper helper;
bool res = helper.StartTestApp(IPCTestHelper::IPC_TEST_SERVER);
ASSERT_TRUE(res);
auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
ASSERT_TRUE(saMgr != nullptr);
sptr<IRemoteObject> proxy = saMgr->GetSystemAbility(IPC_TEST_SERVICE);
ASSERT_TRUE(proxy != nullptr);
refCount = proxy->GetObjectRefCount();
if (SUPPORT_ZBINDER) {
EXPECT_GE(refCount, 2);
} else {
EXPECT_GE(refCount, 1);
}
res = helper.StartTestApp(IPCTestHelper::IPC_TEST_CLIENT);
ASSERT_TRUE(res);
refCount = proxy->GetObjectRefCount();
if (SUPPORT_ZBINDER) {
EXPECT_GE(refCount, 3);
} else {
EXPECT_GE(refCount, 1);
}
helper.StopTestApp(IPCTestHelper::IPC_TEST_CLIENT);
refCount = proxy->GetObjectRefCount();
if (SUPPORT_ZBINDER) {
EXPECT_GE(refCount, 2);
} else {
EXPECT_GE(refCount, 1);
}
}
/**
* @tc.name: SyncTransaction004
* @tc.desc: Test IPC data transaction.
* @tc.type: FUNC
* @tc.require: AR000DPV5E
*/
HWTEST_F(IPCNativeUnitTest, SyncTransaction004, TestSize.Level1)
{
IPCTestHelper helper;
bool res = helper.StartTestApp(IPCTestHelper::IPC_TEST_SERVER);
ASSERT_TRUE(res);
res = helper.StartTestApp(IPCTestHelper::IPC_TEST_CLIENT, static_cast<int>(TestCommand::TEST_CMD_LOOP_TRANSACTION));
ASSERT_TRUE(res);
std::unique_ptr<TestServiceClient> testClient = std::make_unique<TestServiceClient>();
int result = testClient->ConnectService();
ASSERT_EQ(result, 0);
int count = testClient->StartLoopTest(MAX_TEST_COUNT);
EXPECT_EQ(count, MAX_TEST_COUNT);
}
/**
* @tc.name: SyncTransaction005
* @tc.desc: Test get context object.
* @tc.type: FUNC
* @tc.require: SR000DFJQF AR000DFJQG
*/
HWTEST_F(IPCNativeUnitTest, SyncTransaction005, TestSize.Level1)
{
sptr<IRemoteObject> remote = IPCSkeleton::GetContextObject();
ASSERT_TRUE(remote != nullptr);
}
/**
* @tc.name: SyncTransaction006
* @tc.desc: Test set context object.
* @tc.type: FUNC
* @tc.require: SR000DFJQF AR000DFJQG
*/
HWTEST_F(IPCNativeUnitTest, SyncTransaction006, TestSize.Level1)
{
sptr<IRemoteObject> remoteObj = IPCSkeleton::GetContextObject();
ASSERT_TRUE(remoteObj != nullptr);
bool ret = IPCSkeleton::SetContextObject(remoteObj);
ASSERT_FALSE(ret);
}
#ifndef CONFIG_STANDARD_SYSTEM
/**
* @tc.name: SyncTransaction007
* @tc.desc: Test get context object through jni.
* @tc.type: FUNC
* @tc.require: SR000DFJQF AR000DFJQG
*/
HWTEST_F(IPCNativeUnitTest, SyncTransaction007, TestSize.Level1)
{
JNIEnv *env = nullptr;
sptr<IRemoteObject> remoteObj = IPCSkeleton::GetContextObject();
ASSERT_TRUE(remoteObj != nullptr);
jobject testObj = JNIHelperGetJavaRemoteObject(env, remoteObj);
ASSERT_TRUE(testObj == nullptr);
}
#endif
/**
* @tc.name: SyncTransaction008
* @tc.desc: Test write and read interface token in MessageParcel.
* @tc.type: FUNC
* @tc.require: SR000DFJQF AR000DFJQG
*/
HWTEST_F(IPCNativeUnitTest, SyncTransaction008, TestSize.Level1)
{
MessageParcel parcel;
std::u16string descriptor = u"TokenDescriptor";
parcel.WriteInterfaceToken(descriptor);
std::u16string readDescriptor = parcel.ReadInterfaceToken();
ASSERT_EQ(readDescriptor, descriptor);
}
/**
* @tc.name: SyncTransaction009
* @tc.desc: Test IPC stub data Normal release.
* @tc.type: FUNC
*/
HWTEST_F(IPCNativeUnitTest, SyncTransaction009, TestSize.Level1)
{
IPCTestHelper helper;
bool res = helper.StartTestApp(IPCTestHelper::IPC_TEST_SERVER);
ASSERT_TRUE(res);
auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
ASSERT_TRUE(saMgr != nullptr);
sptr<IRemoteObject> service = saMgr->GetSystemAbility(IPC_TEST_SERVICE);
sptr<ITestService> testService = iface_cast<ITestService>(service);
ASSERT_TRUE(testService != nullptr);
ZLOGI(LABEL, "Get test.service OK\n");
if (service->IsProxyObject()) {
ZLOGI(LABEL, "Got Proxy node\n");
TestServiceProxy *proxy = static_cast<TestServiceProxy *>(testService.GetRefPtr());
int reply = 0;
int ret = proxy->TestAsyncTransaction(2019, reply);
EXPECT_EQ(ret, ERR_NONE);
} else {
ZLOGI(LABEL, "Got Stub node\n");
}
}
/**
* @tc.name: SyncTransaction010
* @tc.desc: Test write and read exception.
* @tc.type: FUNC
* @tc.require: AR000E1QEG
*/
HWTEST_F(IPCNativeUnitTest, SyncTransaction010, TestSize.Level1)
{
MessageParcel parcel;
parcel.WriteNoException();
ASSERT_EQ(parcel.ReadException(), 0);
}
/**
* @tc.name: MessageOptionTest001
* @tc.desc: Test set waiting time.
* @tc.type: FUNC
* @tc.require: AR000ER7PF
*/
HWTEST_F(IPCNativeUnitTest, MessageOptionTest001, TestSize.Level1)
{
MessageOption messageOption;
ASSERT_EQ(messageOption.GetWaitTime(), MessageOption::TF_WAIT_TIME);
messageOption.SetWaitTime(-1);
ASSERT_EQ(messageOption.GetWaitTime(), MessageOption::TF_WAIT_TIME);
}

View File

@ -0,0 +1,93 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <gtest/gtest.h>
#include "ipc_debug.h"
#include "ipc_file_descriptor.h"
#include "log_tags.h"
namespace OHOS {
using namespace testing::ext;
using namespace OHOS;
using namespace OHOS::HiviewDFX;
class IPCFileDescOpsTest : public testing::Test {
public:
static void SetUpTestCase(void);
static void TearDownTestCase(void);
void SetUp();
void TearDown();
public:
static constexpr HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "IPCFdTest" };
};
void IPCFileDescOpsTest::SetUp() {}
void IPCFileDescOpsTest::TearDown() {}
void IPCFileDescOpsTest::SetUpTestCase() {}
void IPCFileDescOpsTest::TearDownTestCase() {}
HWTEST_F(IPCFileDescOpsTest, fd_parcelable_001, TestSize.Level1)
{
int testFdNum;
testFdNum = open("/data/test/fd_unit_test.txt", O_RDWR | O_APPEND | O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO);
if (testFdNum == -1) {
ZLOGI(LABEL, "%s(%d):open failed.", __func__, __LINE__);
}
ASSERT_TRUE(testFdNum >= 0);
Parcel parcel(nullptr);
sptr<IPCFileDescriptor> wdesc = new IPCFileDescriptor(testFdNum);
bool result = false;
result = parcel.WriteObject<IPCFileDescriptor>(wdesc);
EXPECT_EQ(true, result);
sptr<IPCFileDescriptor> rdesc = parcel.ReadObject<IPCFileDescriptor>();
ASSERT_TRUE(rdesc != nullptr);
EXPECT_EQ(testFdNum, rdesc->GetFd());
close(testFdNum);
}
HWTEST_F(IPCFileDescOpsTest, fd_parcelable_002, TestSize.Level1)
{
int invalidFdNum = -2;
Parcel parcel(nullptr);
sptr<IPCFileDescriptor> wdesc = new IPCFileDescriptor(invalidFdNum);
bool result = false;
result = parcel.WriteObject<IPCFileDescriptor>(wdesc);
EXPECT_EQ(false, result);
IPCFileDescriptor *rdesc = parcel.ReadObject<IPCFileDescriptor>();
EXPECT_EQ(nullptr, rdesc);
}
HWTEST_F(IPCFileDescOpsTest, fd_parcelable_003, TestSize.Level1)
{
int fd = 9876;
IPCFileDescriptor fdesc;
fdesc.SetFd(fd);
EXPECT_EQ(fd, fdesc.GetFd());
}
} // namespace OHOS

View File

@ -0,0 +1,414 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <unistd.h>
#include <sys/time.h>
#include <iostream>
#include <string>
#include <sstream>
#include <regex>
#include <chrono>
#include <securec.h>
#include <gtest/gtest.h>
#include "ipc_debug.h"
#include "hitrace/trace.h"
#include "ipc_skeleton.h"
#include "ipc_object_proxy.h"
#include "test_service_skeleton.h"
#include "test_service.h"
#include "ipc_test_helper.h"
#include "binder_connector.h"
#include "if_system_ability_manager.h"
#include "iservice_registry.h"
#include "system_ability_definition.h"
#include "log_tags.h"
using namespace testing::ext;
using namespace OHOS;
using namespace OHOS::HiviewDFX;
static constexpr HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_IPC, "BinderTraceUnitTest" };
class BinderTraceTest : public testing::Test {
public:
static void SetUpTestCase(void);
static void TearDownTestCase(void);
private:
static IPCTestHelper *g_helper;
};
IPCTestHelper *BinderTraceTest::g_helper = nullptr;
void BinderTraceTest::SetUpTestCase()
{
if (g_helper == nullptr) {
g_helper = new IPCTestHelper();
bool res = g_helper->PrepareTestSuite();
ASSERT_TRUE(res);
}
}
void BinderTraceTest::TearDownTestCase()
{
if (g_helper != nullptr) {
bool res = g_helper->TearDownTestSuite();
ASSERT_TRUE(res);
delete g_helper;
g_helper = nullptr;
}
}
static std::string HitraceLongToString(unsigned long data)
{
std::string result;
constexpr int BUFFER_SIZE = 16;
char str[BUFFER_SIZE] = {0};
if (sprintf_s(str, sizeof(str), "%lx", data) <= 0) {
return result;
}
result = str;
return result;
}
static std::string BinderTraceGetRemainLog(const std::string &tag)
{
std::string logMsgs;
std::string remainLogMsgs;
constexpr int BUFFER_SIZE = 1024;
FILE *fp = popen("/system/bin/hilog -x -z 4096", "re");
bool findTag = false;
if (fp != nullptr) {
char buf[BUFFER_SIZE] = {0};
size_t n;
n = fread(buf, 1, sizeof(buf), fp);
while (n > 0) {
logMsgs.append(buf, n);
n = fread(buf, 1, sizeof(buf), fp);
}
pclose(fp);
} else {
return remainLogMsgs;
}
std::stringstream ss(logMsgs);
std::string str;
while (!ss.eof()) {
getline(ss, str);
if (findTag == false && str.find(tag) != std::string::npos) {
findTag = true;
}
if (findTag == true) {
remainLogMsgs.append(str);
}
}
return remainLogMsgs;
}
static int BinderTraceCheckLog(const std::string &remainLogMsgs, const std::string &checkItem,
const std::string &chainId)
{
std::stringstream rss(remainLogMsgs);
std::string str;
std::regex re(checkItem);
while (!rss.eof()) {
getline(rss, str);
if (std::regex_search(str, re) == true && str.find(chainId) != std::string::npos) {
return 1;
}
}
return 0;
}
static std::string PrintTagLog(const std::string &tag)
{
struct timeval tv = {};
constexpr int SEC_TO_USEC = 1000000;
gettimeofday(&tv, nullptr);
long long timeStamp = tv.tv_sec * SEC_TO_USEC + tv.tv_usec;
std::string strTimeStamp;
std::stringstream ss;
ss << timeStamp;
ss >> strTimeStamp;
std::string logTag = strTimeStamp + tag;
HiLog::Info(LOG_LABEL, "%s\n", logTag.c_str());
return logTag;
}
HWTEST_F(BinderTraceTest, Sync001, TestSize.Level1)
{
HiTraceId getId = HiTrace::GetId();
EXPECT_EQ(0, getId.IsValid());
HiTraceId traceId = HiTrace::Begin("ipc hitrace", 0);
std::string chainId = HitraceLongToString(traceId.GetChainId());
EXPECT_NE(0UL, chainId.size());
IPCTestHelper helper;
bool res = helper.StartTestApp(IPCTestHelper::IPC_TEST_SERVER);
ASSERT_TRUE(res);
auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
ASSERT_TRUE(saMgr != nullptr);
sptr<IRemoteObject> service = saMgr->GetSystemAbility(IPC_TEST_SERVICE);
sptr<ITestService> testService = iface_cast<ITestService>(service);
ASSERT_TRUE(testService != nullptr);
HiLog::Info(LOG_LABEL, "Get test.service OK\n");
std::string logTag = PrintTagLog(":BinderTraceTest_Sync001");
if (service->IsProxyObject()) {
HiLog::Info(LOG_LABEL, "Got Proxy node\n");
TestServiceProxy *proxy = static_cast<TestServiceProxy *>(testService.GetRefPtr());
int reply = 0;
int ret = proxy->TestSyncTransaction(2019, reply);
EXPECT_EQ(ret, NO_ERROR);
EXPECT_EQ(reply, 9102);
} else {
HiLog::Info(LOG_LABEL, "Got Stub node\n");
}
getId = HiTrace::GetId();
EXPECT_EQ(1, getId.IsValid());
HiTrace::End(traceId);
getId = HiTrace::GetId();
EXPECT_EQ(0, getId.IsValid());
std::string remainLogMsgs = BinderTraceGetRemainLog(logTag);
EXPECT_EQ(0, BinderTraceCheckLog(remainLogMsgs, "HITRACE_TP_CS", chainId));
EXPECT_EQ(0, BinderTraceCheckLog(remainLogMsgs, "HITRACE_TP_SR", chainId));
EXPECT_EQ(0, BinderTraceCheckLog(remainLogMsgs, "HITRACE_TP_SS", chainId));
EXPECT_EQ(0, BinderTraceCheckLog(remainLogMsgs, "HITRACE_TP_CR", chainId));
}
HWTEST_F(BinderTraceTest, Sync002, TestSize.Level1)
{
const std::string HITRACE_TP_CS_LOG =
"\\[[a-f0-9]{1,16}, 0, 0\\] <HITRACE_TP_CS,chain=[0-9a-f]{1,16},span=[0-9a-f]{1,16},pspan=";
const std::string HITRACE_TP_SR_LOG =
"\\[[a-f0-9]{1,16}, [a-f0-9]{1,16}, 0\\] <HITRACE_TP_SR,chain=[0-9a-f]{1,16},span=[0-9a-f]{1,16},pspan=";
const std::string HITRACE_TP_SS_LOG =
"\\[[a-f0-9]{1,16}, [a-f0-9]{1,16}, 0\\] <HITRACE_TP_SS,chain=[0-9a-f]{1,16},span=[0-9a-f]{1,16},pspan=";
const std::string HITRACE_TP_CR_LOG =
"\\[[a-f0-9]{1,16}, 0, 0\\] <HITRACE_TP_CR,chain=[0-9a-f]{1,16},span=[0-9a-f]{1,16},pspan=";
HiTraceId getId = HiTrace::GetId();
EXPECT_EQ(0, getId.IsValid());
HiTraceId traceId = HiTrace::Begin("ipc hitrace", HITRACE_FLAG_TP_INFO);
std::string chainId = HitraceLongToString(traceId.GetChainId());
EXPECT_NE(0UL, chainId.size());
IPCTestHelper helper;
bool res = helper.StartTestApp(IPCTestHelper::IPC_TEST_SERVER);
ASSERT_TRUE(res);
auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
ASSERT_TRUE(saMgr != nullptr);
sptr<IRemoteObject> service = saMgr->GetSystemAbility(IPC_TEST_SERVICE);
sptr<ITestService> testService = iface_cast<ITestService>(service);
ASSERT_TRUE(testService != nullptr);
HiLog::Info(LOG_LABEL, "Get test.service OK\n");
std::string logTag = PrintTagLog(":BinderTraceTest_Sync002");
if (service->IsProxyObject()) {
HiLog::Info(LOG_LABEL, "Got Proxy node\n");
TestServiceProxy *proxy = static_cast<TestServiceProxy *>(testService.GetRefPtr());
int reply = 0;
int ret = proxy->TestSyncTransaction(2019, reply);
EXPECT_EQ(ret, NO_ERROR);
EXPECT_EQ(reply, 9102);
} else {
HiLog::Info(LOG_LABEL, "Got Stub node\n");
}
getId = HiTrace::GetId();
EXPECT_EQ(1, getId.IsValid());
HiTrace::End(traceId);
getId = HiTrace::GetId();
EXPECT_EQ(0, getId.IsValid());
}
HWTEST_F(BinderTraceTest, Sync003, TestSize.Level1)
{
const std::string HITRACE_TP_CS_LOG = "\\[[a-f0-9]{1,16}\\] <HITRACE_TP_CS,chain=[0-9a-f]{1,16},span=0,pspan=";
const std::string HITRACE_TP_SR_LOG = "\\[[a-f0-9]{1,16}\\] <HITRACE_TP_SR,chain=[0-9a-f]{1,16},span=0,pspan=";
const std::string HITRACE_TP_SS_LOG = "\\[[a-f0-9]{1,16}\\] <HITRACE_TP_SS,chain=[0-9a-f]{1,16},span=0,pspan=";
const std::string HITRACE_TP_CR_LOG = "\\[[a-f0-9]{1,16}\\] <HITRACE_TP_CR,chain=[0-9a-f]{1,16},span=0,pspan=";
HiTraceId getId = HiTrace::GetId();
EXPECT_EQ(0, getId.IsValid());
HiTraceId traceId = HiTrace::Begin("ipc hitrace", HITRACE_FLAG_TP_INFO | HITRACE_FLAG_DONOT_CREATE_SPAN);
std::string chainId = HitraceLongToString(traceId.GetChainId());
EXPECT_NE(0UL, chainId.size());
IPCTestHelper helper;
bool res = helper.StartTestApp(IPCTestHelper::IPC_TEST_SERVER);
ASSERT_TRUE(res);
auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
ASSERT_TRUE(saMgr != nullptr);
sptr<IRemoteObject> service = saMgr->GetSystemAbility(IPC_TEST_SERVICE);
sptr<ITestService> testService = iface_cast<ITestService>(service);
ASSERT_TRUE(testService != nullptr);
HiLog::Info(LOG_LABEL, "Get test.service OK\n");
std::string logTag = PrintTagLog(":BinderTraceTest_Sync003");
if (service->IsProxyObject()) {
HiLog::Info(LOG_LABEL, "Got Proxy node\n");
TestServiceProxy *proxy = static_cast<TestServiceProxy *>(testService.GetRefPtr());
int reply = 0;
int ret = proxy->TestSyncTransaction(2019, reply);
EXPECT_EQ(ret, NO_ERROR);
EXPECT_EQ(reply, 9102);
} else {
HiLog::Info(LOG_LABEL, "Got Stub node\n");
}
getId = HiTrace::GetId();
EXPECT_EQ(1, getId.IsValid());
HiTrace::End(traceId);
getId = HiTrace::GetId();
EXPECT_EQ(0, getId.IsValid());
}
HWTEST_F(BinderTraceTest, Async001, TestSize.Level1)
{
HiTraceId getId = HiTrace::GetId();
EXPECT_EQ(0, getId.IsValid());
HiTraceId traceId = HiTrace::Begin("ipc hitrace", HITRACE_FLAG_INCLUDE_ASYNC);
std::string chainId = HitraceLongToString(traceId.GetChainId());
EXPECT_NE(0UL, chainId.size());
IPCTestHelper helper;
bool res = helper.StartTestApp(IPCTestHelper::IPC_TEST_SERVER);
ASSERT_TRUE(res);
auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
ASSERT_TRUE(saMgr != nullptr);
sptr<IRemoteObject> service = saMgr->GetSystemAbility(IPC_TEST_SERVICE);
sptr<ITestService> testService = iface_cast<ITestService>(service);
ASSERT_TRUE(testService != nullptr);
HiLog::Info(LOG_LABEL, "Get test.service OK\n");
std::string logTag = PrintTagLog(":BinderTraceTest_Async001");
if (service->IsProxyObject()) {
HiLog::Info(LOG_LABEL, "Got Proxy node\n");
TestServiceProxy *proxy = static_cast<TestServiceProxy *>(testService.GetRefPtr());
int ret = proxy->TestAsyncTransaction(2019);
EXPECT_EQ(ret, ERR_NONE);
} else {
HiLog::Info(LOG_LABEL, "Got Stub node\n");
}
getId = HiTrace::GetId();
EXPECT_EQ(1, getId.IsValid());
HiTrace::End(traceId);
getId = HiTrace::GetId();
EXPECT_EQ(0, getId.IsValid());
std::string remainLogMsgs = BinderTraceGetRemainLog(logTag);
EXPECT_EQ(0, BinderTraceCheckLog(remainLogMsgs, "HITRACE_TP_CS", chainId));
EXPECT_EQ(0, BinderTraceCheckLog(remainLogMsgs, "HITRACE_TP_SR", chainId));
EXPECT_EQ(0, BinderTraceCheckLog(remainLogMsgs, "HITRACE_TP_SS", chainId));
EXPECT_EQ(0, BinderTraceCheckLog(remainLogMsgs, "HITRACE_TP_CR", chainId));
}
HWTEST_F(BinderTraceTest, Async002, TestSize.Level1)
{
const std::string HITRACE_TP_CS_LOG =
"\\[[a-f0-9]{1,16}, 0, 0\\] <HITRACE_TP_CS,chain=[0-9a-f]{1,16},span=[0-9a-f]{1,16},pspan=";
const std::string HITRACE_TP_SR_LOG =
"\\[[a-f0-9]{1,16}, [a-f0-9]{1,16}, 0\\] <HITRACE_TP_SR,chain=[0-9a-f]{1,16},span=[0-9a-f]{1,16},pspan=";
HiTraceId getId = HiTrace::GetId();
EXPECT_EQ(0, getId.IsValid());
HiTraceId traceId = HiTrace::Begin("ipc hitrace", HITRACE_FLAG_TP_INFO | HITRACE_FLAG_INCLUDE_ASYNC);
std::string chainId = HitraceLongToString(traceId.GetChainId());
EXPECT_NE(0UL, chainId.size());
IPCTestHelper helper;
bool res = helper.StartTestApp(IPCTestHelper::IPC_TEST_SERVER);
ASSERT_TRUE(res);
auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
ASSERT_TRUE(saMgr != nullptr);
sptr<IRemoteObject> service = saMgr->GetSystemAbility(IPC_TEST_SERVICE);
sptr<ITestService> testService = iface_cast<ITestService>(service);
ASSERT_TRUE(testService != nullptr);
HiLog::Info(LOG_LABEL, "Get test.service OK\n");
std::string logTag = PrintTagLog(":BinderTraceTest_Async002");
if (service->IsProxyObject()) {
HiLog::Info(LOG_LABEL, "Got Proxy node\n");
TestServiceProxy *proxy = static_cast<TestServiceProxy *>(testService.GetRefPtr());
int ret = proxy->TestAsyncTransaction(2019, 1);
EXPECT_EQ(ret, ERR_NONE);
} else {
HiLog::Info(LOG_LABEL, "Got Stub node\n");
}
getId = HiTrace::GetId();
EXPECT_EQ(1, getId.IsValid());
HiTrace::End(traceId);
getId = HiTrace::GetId();
EXPECT_EQ(0, getId.IsValid());
}
HWTEST_F(BinderTraceTest, Async003, TestSize.Level1)
{
const std::string HITRACE_TP_CS_LOG = "\\[[a-f0-9]{1,16}\\] <HITRACE_TP_CS,chain=[0-9a-f]{1,16},span=0,pspan=";
const std::string HITRACE_TP_SR_LOG = "\\[[a-f0-9]{1,16}\\] <HITRACE_TP_SR,chain=[0-9a-f]{1,16},span=0,pspan=";
HiTraceId getId = HiTrace::GetId();
EXPECT_EQ(0, getId.IsValid());
HiTraceId traceId = HiTrace::Begin("ipc hitrace",
HITRACE_FLAG_TP_INFO | HITRACE_FLAG_INCLUDE_ASYNC | HITRACE_FLAG_DONOT_CREATE_SPAN);
std::string chainId = HitraceLongToString(traceId.GetChainId());
EXPECT_NE(0UL, chainId.size());
IPCTestHelper helper;
bool res = helper.StartTestApp(IPCTestHelper::IPC_TEST_SERVER);
ASSERT_TRUE(res);
auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
ASSERT_TRUE(saMgr != nullptr);
sptr<IRemoteObject> service = saMgr->GetSystemAbility(IPC_TEST_SERVICE);
sptr<ITestService> testService = iface_cast<ITestService>(service);
ASSERT_TRUE(testService != nullptr);
HiLog::Info(LOG_LABEL, "Get test.service OK\n");
std::string logTag = PrintTagLog(":BinderTraceTest_Async003");
if (service->IsProxyObject()) {
HiLog::Info(LOG_LABEL, "Got Proxy node\n");
TestServiceProxy *proxy = static_cast<TestServiceProxy *>(testService.GetRefPtr());
int ret = proxy->TestAsyncTransaction(2019, 1);
EXPECT_EQ(ret, ERR_NONE);
} else {
HiLog::Info(LOG_LABEL, "Got Stub node\n");
}
getId = HiTrace::GetId();
EXPECT_EQ(1, getId.IsValid());
HiTrace::End(traceId);
getId = HiTrace::GetId();
EXPECT_EQ(0, getId.IsValid());
}

33
ipc/test/BUILD.gn Executable file
View File

@ -0,0 +1,33 @@
# Copyright (C) 2021 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//build/test.gni")
SUBSYSTEM_DIR = "//foundation/communication/ipc"
IPC_TEST_ROOT = "//foundation/communication/ipc/ipc/test"
config("ipc_test_config") {
include_dirs = [
"//utils/native/base/include",
"$IPC_TEST_ROOT/auxiliary/native/include",
"$SUBSYSTEM_DIR/utils/include",
"$SUBSYSTEM_DIR/ipc/native/src/mock/include",
]
}
#################################group#########################################
group("moduletest") {
testonly = true
deps = [ "moduletest/native:moduletest" ]
}
###############################################################################

View File

@ -0,0 +1,157 @@
# Copyright (C) 2021 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//build/ohos.gni")
SUBSYSTEM_DIR = "//foundation/communication/ipc"
IPC_TEST_ROOT = "//foundation/communication/ipc/ipc/test"
ohos_shared_library("ipc_test_helper") {
include_dirs = [ "//utils/system/safwk/native/include" ]
sources = [
"./src/assist_test_service.cpp",
"./src/foo_service.cpp",
"./src/ipc_test_helper.cpp",
"./src/test_service.cpp",
"./src/test_service_client.cpp",
"./src/test_service_skeleton.cpp",
]
configs = [
"$IPC_TEST_ROOT:ipc_test_config",
"$SUBSYSTEM_DIR:ipc_util_config",
]
deps = [ "//utils/native/base:utils" ]
external_deps = [
"ipc:ipc_core",
"hiviewdfx_hilog_native:libhilog",
"samgr_L2:samgr_proxy",
]
part_name = "ipc"
subsystem_name = "communication"
}
ohos_executable("ipc_server_test") {
sources = [ "./src/main_server.cpp" ]
configs = [
"$SUBSYSTEM_DIR:ipc_util_config",
"$IPC_TEST_ROOT:ipc_test_config",
]
deps = [
":ipc_test_helper",
"//utils/native/base:utils",
]
external_deps = [
"ipc:ipc_core",
"hiviewdfx_hilog_native:libhilog",
"samgr_L2:samgr_proxy",
]
part_name = "ipc"
subsystem_name = "communication"
}
ohos_executable("ipc_client_test") {
sources = [ "./src/main_client.cpp" ]
configs = [
"$SUBSYSTEM_DIR:ipc_util_config",
"$IPC_TEST_ROOT:ipc_test_config",
]
deps = [
":ipc_test_helper",
"//utils/native/base:utils",
]
external_deps = [
"ipc:ipc_core",
"hiviewdfx_hilog_native:libhilog",
"samgr_L2:samgr_proxy",
]
part_name = "ipc"
subsystem_name = "communication"
}
ohos_shared_library("ipc_test_helper_extra") {
include_dirs = [ "//utils/system/safwk/native/include" ]
sources = [
"./src/assist_test_service.cpp",
"./src/foo_service.cpp",
"./src/ipc_test_helper.cpp",
"./src/test_service.cpp",
"./src/test_service_client.cpp",
"./src/test_service_skeleton.cpp",
]
cflags = [ "-DIPCSERVERTESTEXTRA" ]
configs = [
"$IPC_TEST_ROOT:ipc_test_config",
"$SUBSYSTEM_DIR:ipc_util_config",
]
deps = [ "//utils/native/base:utils" ]
external_deps = [
"ipc:ipc_core",
"hiviewdfx_hilog_native:libhilog",
"samgr_L2:samgr_proxy",
]
part_name = "ipc"
subsystem_name = "communication"
}
ohos_executable("ipc_server_test_extra") {
sources = [ "./src/main_server.cpp" ]
configs = [
"$SUBSYSTEM_DIR:ipc_util_config",
"$IPC_TEST_ROOT:ipc_test_config",
]
deps = [
":ipc_test_helper_extra",
"//utils/native/base:utils",
]
external_deps = [
"ipc:ipc_core",
"hiviewdfx_hilog_native:libhilog",
"samgr_L2:samgr_proxy",
]
part_name = "ipc"
subsystem_name = "communication"
}
###############################################################################
group("TestAssistance") {
testonly = true
deps = [
":ipc_client_test",
":ipc_server_test",
":ipc_server_test_extra",
":ipc_test_helper",
]
}
###############################################################################

View File

@ -0,0 +1,137 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_ASSIST_TEST_SERVICE_H
#define OHOS_ASSIST_TEST_SERVICE_H
#include "iremote_broker.h"
#include "iremote_proxy.h"
namespace OHOS {
class IAssistTestService : public IRemoteBroker {
public:
enum {
TEST_PARCEL_INT32 = 0,
TEST_PARCEL_UINT32,
TEST_PARCEL_INT64,
TEST_PARCEL_UINT64,
TEST_PARCEL_FLOAT,
TEST_PARCEL_DOUBLE,
TEST_PARCEL_UINTPTR,
TEST_PARCEL_BOOL,
TEST_PARCEL_CHAR,
TEST_PARCEL_BYTE,
TEST_PARCEL_CSTRING = 10,
TEST_PARCEL_STRING8,
TEST_PARCEL_STRING16,
TEST_PARCEL_STRONGBINDER,
TEST_PARCEL_WEAKBINDER,
TEST_PARCEL_UINT8_FROM_UINT16,
WRITE_BYTEVECTOR_UNIQUE_PRT_INT8_CODE,
TEST_PARCEL_INT8_VECTOR,
WRITE_BYTEVECTOR_UNIQUE_PRT_U_INT8_CODE,
TEST_PARCEL_UINT8_VECTOR,
WRITE_INT32_VECTOR_UNIQUE_PRT_CODE = 20,
TEST_PARCEL_INT32_VECTOR,
WRITE_INT64_VECTOR_UNIQUE_PRT_CODE,
TEST_PARCEL_INT64_VECTOR,
WRITE_UINT64_VECTOR_UNIQUE_PRT_CODE,
TEST_PARCEL_UINT64_VECTOR,
WRITE_FLOAT_UNIQUE_PTR_CODE,
TEST_PARCEL_FLOAT_VECTOR,
WRITE_DOUBLE_UNIQUE_PTR_CODE,
TEST_PARCEL_DOUBLE_VECTOR,
WRITE_BOOL_UNIQUE_PTR_CODE = 30,
TEST_PARCEL_BOOL_VECTOR,
WRITE_CHAR_UNIQUE_PTR_CODE,
TEST_PARCEL_CHAR_VECTOR,
WRITE_STRING16_VECTOR_UNIQUE_PTR_CODE,
TEST_PARCEL_STRING16_VECTOR,
WRITE_UTF8_VECTOR_FROM_UNT16_VECTOR_UNIQUE_PTR_CODE,
WRITE_UTF8_VECTOR_FROM_UNT16_VECTOR_VECTOR_CODE,
WRITE_STRONGBINDERVECTOR_UNIQUE_PTR_CODE,
WRITE_STRONGBINDERVECTOR_VECTOR_CODE,
WRITE_MAP_CODE = 40,
WRITE_NULLABLE_MAP_CODE,
WRITE_NATIVE_HANDLE_CODE,
WRITE_EXCEPTION_CODE,
WRITE_FILE_DESCRIPTOR_CODE,
WRITE_PARCEL_FILE_DESCRIPTOR_CODE,
WRITE_UNIQUE_FILE_DESCRIPTOR_CODE,
WRITE_UNIQUE_FILE_DESCRIPTOR_VECTOR_UNIQUE_PTR_CODE,
WRITE_UNIQUE_FILE_DESCRIPTOR_VECTOR_VECTOR_CODE = 48,
WRITE_INVALID,
};
public:
IAssistTestService() = default;
virtual ~IAssistTestService() = default;
virtual bool TestParcelBool(bool value) = 0;
virtual int16_t TestParcelChar(int16_t value) = 0;
virtual int32_t TestParcelInt32(int32_t value) = 0;
virtual int64_t TestParcelInt64(int64_t value) = 0;
virtual uint8_t TestParcelByte(uint8_t value) = 0;
virtual uint32_t TestParcelUint32(uint32_t value) = 0;
virtual uint64_t TestParcelUint64(uint64_t value) = 0;
virtual float TestParcelFloat(float value) = 0;
virtual double TestParcelDouble(double value) = 0;
virtual const char *TestParcelCString(const char *value) = 0;
virtual const std::string TestParcelString(const std::string& value) = 0;
virtual const std::u16string TestParcelString16(const std::u16string& val) = 0;
virtual bool TestParcelBoolVector() = 0;
virtual bool TestParcelInt8Vector() = 0;
virtual bool TestParcelUint8Vector() = 0;
virtual bool TestParcelCharVector() = 0;
virtual bool TestParcelInt64Vector() = 0;
virtual bool TestParcelUint64Vector() = 0;
virtual bool TestParcelInt32Vector() = 0;
virtual bool TestParcelFloatVector() = 0;
virtual bool TestParcelDoubleVector() = 0;
virtual bool TestParcelString16Vector() = 0;
public:
DECLARE_INTERFACE_DESCRIPTOR(u"test.ipc.IAssistTestService");
};
class AssistTestServiceProxy : public IRemoteProxy<IAssistTestService> {
public:
explicit AssistTestServiceProxy(const sptr<IRemoteObject>& object);
~AssistTestServiceProxy();
bool TestParcelBool(bool value) override;
int16_t TestParcelChar(int16_t value) override;
int32_t TestParcelInt32(int32_t value) override;
int64_t TestParcelInt64(int64_t value) override;
uint8_t TestParcelByte(uint8_t value) override;
uint32_t TestParcelUint32(uint32_t value) override;
uint64_t TestParcelUint64(uint64_t value) override;
float TestParcelFloat(float value) override;
double TestParcelDouble(double value) override;
const char *TestParcelCString(const char *value) override;
const std::string TestParcelString(const std::string& value) override;
const std::u16string TestParcelString16(const std::u16string& val) override;
bool TestParcelBoolVector() override;
bool TestParcelInt8Vector() override;
bool TestParcelUint8Vector() override;
bool TestParcelCharVector() override;
bool TestParcelInt64Vector() override;
bool TestParcelUint64Vector() override;
bool TestParcelInt32Vector() override;
bool TestParcelFloatVector() override;
bool TestParcelDoubleVector() override;
bool TestParcelString16Vector() override;
private:
static inline BrokerDelegator<AssistTestServiceProxy> delegator_;
};
} // namespace OHOS
#endif // OHOS_ASSIST_TEST_SERVICE_H

View File

@ -0,0 +1,77 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_FOO_SERVICE_H
#define OHOS_IPC_FOO_SERVICE_H
#include <mutex>
#include <condition_variable>
#include "iremote_broker.h"
#include "iremote_proxy.h"
#include "iremote_stub.h"
#include "hilog/log.h"
#include "log_tags.h"
namespace OHOS {
class IFoo : public IRemoteBroker {
public:
enum FooInterFaceId {
GET_FOO_NAME = 0,
SEND_ASYNC_REPLY = 1,
SEND_WRONG_REPLY = 2,
};
virtual std::string GetFooName() = 0;
virtual void SendAsyncReply(int &reply) = 0;
virtual int TestNestingSend(int sendCode) = 0;
public:
DECLARE_INTERFACE_DESCRIPTOR(u"test.ipc.IFoo");
};
class FooStub : public IRemoteStub<IFoo> {
public:
virtual ~FooStub();
virtual int OnRemoteRequest(uint32_t code,
MessageParcel &data, MessageParcel &reply, MessageOption &option) override;
std::string GetFooName() override;
void SendAsyncReply(int &reply) override;
int WaitForAsyncReply(int timeout);
static void CleanDecTimes();
static int GetDecTimes();
int TestNestingSend(int sendCode) override;
public:
static std::mutex decTimeMutex_;
static int decTimes_;
private:
int asyncReply_ = { 0 };
std::mutex mutex_;
std::condition_variable cv_;
static constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "FooStub" };
};
class FooProxy : public IRemoteProxy<IFoo> {
public:
explicit FooProxy(const sptr<IRemoteObject> &impl);
~FooProxy() = default;
std::string GetFooName() override;
void SendAsyncReply(int &reply) override;
int TestNestingSend(int sendCode) override;
private:
static constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "FooProxy" };
static inline BrokerDelegator<FooProxy> delegator_;
};
} // namespace OHOS
#endif // OHOS_IPC_FOO_SERVICE_H

View File

@ -0,0 +1,76 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_TEST_HELPER_H
#define OHOS_IPC_TEST_HELPER_H
#include <map>
#include <mutex>
#include <string>
#include <dirent.h>
#include <iostream>
#include <sys/types.h>
#include "ipc_debug.h"
#include "log_tags.h"
namespace OHOS {
const static int INVALID_PID = -1;
class IPCTestHelper {
public:
enum {
IPC_TEST_SAMGR,
IPC_TEST_SERVER,
IPC_TEST_CLIENT,
IPC_TEST_MSG_SERVER,
IPC_TEST_MSG_CLIENT,
IPC_TEST_SERVER_EXTRA,
IPC_TEST_NONE = 0xFF,
};
IPCTestHelper() = default;
~IPCTestHelper();
static const std::string &GetTestAppName(int appId);
pid_t GetPidByName(std::string task_name);
bool GetChildPids(std::vector<pid_t> &childPids);
pid_t StartExecutable(std::string name, std::string args = "");
bool StopExecutable(pid_t pid);
bool StopExecutable(std::string name);
bool PrepareTestSuite();
bool TearDownTestSuite();
void AddTestAppPid(const std::string &appName, const int &pid);
void RemoveTestAppPid(const std::string &appName);
bool StartTestApp(int appId, const int &cmdId = 0);
bool StopTestApp(int appId);
pid_t GetTestAppPid(int appId);
pid_t GetPid();
uid_t GetUid();
long GetCurrentTimeMs();
private:
std::mutex mutex_;
std::map<std::string, pid_t> testPids_;
static constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "IPCTestHelper" };
};
} // namespace OHOS
#endif // OHOS_IPC_TEST_HELPER_H

View File

@ -0,0 +1,122 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_RPC_TEST_TESTHELP_H
#define OHOS_RPC_TEST_TESTHELP_H
#include <jni.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: ohos_rpc_test_TestHelper
* Method: nativeNewInstance
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_ohos_rpc_test_TestHelper_nativeNewInstance(
JNIEnv *env, jclass clazz);
/*
* Class: ohos_rpc_test_TestHelper
* Method: nativeFreeInstance
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_ohos_rpc_test_TestHelper_nativeFreeInstance(
JNIEnv *env, jobject object, jlong);
/*
* Class: ohos_rpc_test_TestHelper
* Method: nativePrepareTestSuite
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_ohos_rpc_test_TestHelper_nativePrepareTestSuite(
JNIEnv *env, jobject object);
/*
* Class: ohos_rpc_test_TestHelper
* Method: nativeTearDownTestSuite
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_ohos_rpc_test_TestHelper_nativeTearDownTestSuite(
JNIEnv *env, jobject object);
/*
* Class: ohos_rpc_test_TestHelper
* Method: nativeStartTestServer
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL Java_ohos_rpc_test_TestHelper_nativeStartTestApp(
JNIEnv *env, jobject object, jint appId, jint commandId);
/*
* Class: ohos_rpc_test_TestHelper
* Method: StopTestApp
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL Java_ohos_rpc_test_TestHelper_nativeStopTestApp(
JNIEnv *env, jobject object, jlong appId);
/*
* Class: ohos_rpc_test_TestHelper
* Method: nativeGetTestServerPid
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_ohos_rpc_test_TestHelper_nativeGetTestAppPid(
JNIEnv *env, jobject object, jint appId);
/*
* Class: ohos_rpc_test_TestHelper
* Method: nativeGetUid
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_ohos_rpc_test_TestHelper_nativeGetUid(
JNIEnv *env, jobject object);
/*
* Class: ohos_rpc_test_TestHelper
* Method: nativeGetPid
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_ohos_rpc_test_TestHelper_nativeGetPid(
JNIEnv *env, jobject object);
/*
* Class: ohos_rpc_test_TestHelper
* Method: nativeStartExecutable
* Signature: (Ljava/lang/String;I)Z
*/
JNIEXPORT jboolean JNICALL Java_ohos_rpc_test_TestHelper_nativeStartExecutable(
JNIEnv *env, jobject object, jstring, jint);
/*
* Class: ohos_rpc_test_TestHelper
* Method: nativeStopExecutable
* Signature: (Ljava/lang/String;I)Z
*/
JNIEXPORT jboolean JNICALL Java_ohos_rpc_test_TestHelper_nativeStopExecutable(
JNIEnv *env, jobject object, jstring string, jint length);
/*
* Class: ohos_rpc_test_TestHelper
* Method: nativeRunCommand
* Signature: (Ljava/lang/String;I)Z
*/
JNIEXPORT jboolean JNICALL Java_ohos_rpc_test_TestHelper_nativeRunCommand(
JNIEnv *env, jobject object, jstring string, jint length);
#ifdef __cplusplus
}
#endif
#endif // OHOS_RPC_TEST_TESTHELP_H

View File

@ -0,0 +1,54 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_TEST_SERVICE_H
#define OHOS_IPC_TEST_SERVICE_H
#include "hilog/log.h"
#include "log_tags.h"
#include "test_service_skeleton.h"
namespace OHOS {
class TestService : public TestServiceStub {
public:
TestService();
~TestService();
static int Instantiate();
int TestSyncTransaction(int data, int &rep, int delayTime = 0) override;
int TestAsyncTransaction(int data, int timeout = 0) override;
int TestAsyncCallbackTrans(int data, int &reply, int timeout) override;
int TestPingService(const std::u16string &serviceName) override;
int TestGetFileDescriptor() override;
int TestStringTransaction(const std::string& data) override;
int TestZtraceTransaction(std::string& send, std::string& reply, int len) override;
void TestDumpService() override;
int TestRawDataTransaction(int length, int &reply) override;
int TestRawDataReply(int length) override;
sptr<IFoo> TestGetFooService() override;
int Dump(int fd, const std::vector<std::u16string>& args) override;
int TestCallingUidPid() override;
int TestFlushAsyncCalls(int count, int length) override;
int TestMultipleProcesses(int data, int &rep, int delayTime) override;
std::u16string TestAshmem(sptr<Ashmem> ashmem, int32_t contentSize) override;
void TestAsyncDumpService() override;
int TestNestingSend(int sendCode, int &replyCode) override;
private:
int testFd_;
static constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "TestService" };
};
} // namespace OHOS
#endif // OHOS_IPC_TEST_SERVICE_H

View File

@ -0,0 +1,48 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_TEST_SERVICE_CLIENT_H
#define OHOS_IPC_TEST_SERVICE_CLIENT_H
#include <vector>
#include <string>
#include "test_service_skeleton.h"
#include "log_tags.h"
namespace OHOS {
struct TraceParam {
int dataSize;
int testTimes;
int sleepUs;
};
class TestServiceClient {
public:
int ConnectService();
void StartSyncTransaction();
void StartSyncDelayReply();
void StartAsyncTransaction();
void StartPingService();
void StartGetFooService();
int StartLoopTest(int maxCount);
void StartDumpService();
void StartTestFileDescriptor();
void StartAsyncDumpService();
private:
static constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "TestServiceClient" };
sptr<ITestService> testService_;
};
} // namespace OHOS
#endif // OHOS_IPC_TEST_SERVICE_CLIENT_H

View File

@ -0,0 +1,31 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_TEST_SERVICE_COMMAND_H
#define OHOS_IPC_TEST_SERVICE_COMMAND_H
enum class TestCommand : int {
TEST_CMD_NONE = 0,
TEST_CMD_SYNC_TRANS = 1,
TEST_CMD_ASYNC_TRANS = 2,
TEST_CMD_PING_SERVICE = 3,
TEST_CMD_GET_FOO_SERVICE = 4,
TEST_CMD_TRANS_FILE_DESC = 5,
TEST_CMD_TRANSACTION = 6,
TEST_CMD_DUMP_SERVICE = 8,
TEST_CMD_LOOP_TRANSACTION = 9,
TEST_CMD_ASYNC_DUMP_SERVICE = 10,
};
#endif // OHOS_IPC_TEST_SERVICE_COMMAND_H

View File

@ -0,0 +1,122 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_TEST_SERVICE_SKELETON_H
#define OHOS_TEST_SERVICE_SKELETON_H
#include "ipc_debug.h"
#include "iremote_broker.h"
#include "iremote_stub.h"
#include "iremote_proxy.h"
#include "foo_service.h"
#include "ipc_file_descriptor.h"
#include "log_tags.h"
namespace OHOS {
class ITestService : public IRemoteBroker {
public:
enum {
TRANS_ID_SYNC_TRANSACTION = 1,
TRANS_ID_ASYNC_TRANSACTION = 2,
TRANS_ID_PING_SERVICE = 3,
TRANS_ID_GET_FOO_SERVICE = 4,
TRANS_ID_TRANSACT_FILE_DESC = 5,
TRANS_ID_STRING_TRANSACTION = 6,
TRANS_ID_ZTRACE_TRANSACTION = 7,
TRANS_ID_LOOP_TRANSACTION = 8,
TRANS_ID_DUMP_SERVICE = 9,
TRANS_ID_RAWDATA_TRANSACTION = 10,
TRANS_ID_RAWDATA_REPLY = 11,
TRANS_ID_CALLING_UID_PID = 12,
TRANS_ID_FLUSH_ASYNC_CALLS = 13,
TRANS_ID_MULTIPLE_PROCESSES = 14,
TRANS_ID_ASHMEM = 15,
TRANS_ID_ASYNC_DUMP_SERVICE = 16,
TRANS_ID_NESTING_SEND = 17,
};
public:
virtual int TestSyncTransaction(int data, int &reply, int delayTime = 0) = 0;
virtual int TestAsyncTransaction(int data, int timeout = 0) = 0;
virtual int TestAsyncCallbackTrans(int data, int &reply, int timeout = 0) = 0;
virtual int TestGetFileDescriptor() = 0;
virtual int TestPingService(const std::u16string &serviceName) = 0;
virtual int TestStringTransaction(const std::string &data) = 0;
virtual int TestZtraceTransaction(std::string &send, std::string &reply, int len) = 0;
virtual void TestDumpService() = 0;
virtual int TestRawDataTransaction(int length, int &reply) = 0;
virtual int TestRawDataReply(int length) = 0;
virtual sptr<IFoo> TestGetFooService() = 0;
virtual int TestCallingUidPid() = 0;
virtual int TestFlushAsyncCalls(int count, int length) = 0;
virtual int TestMultipleProcesses(int data, int &rep, int delayTime) = 0;
virtual std::u16string TestAshmem(sptr<Ashmem> ashmem, int32_t contentSize) = 0;
virtual void TestAsyncDumpService() = 0;
virtual int TestNestingSend(int sendCode, int &replyCode) = 0;
public:
DECLARE_INTERFACE_DESCRIPTOR(u"test.ipc.ITestService");
};
class TestServiceStub : public IRemoteStub<ITestService> {
public:
virtual int OnRemoteRequest(uint32_t code,
MessageParcel &data, MessageParcel &reply, MessageOption &option) override;
private:
static constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "TestServiceStub" };
int TransferRawData(MessageParcel &data, MessageParcel &reply);
int ReplyRawData(MessageParcel &data, MessageParcel &reply);
void TransferToNextProcess(MessageParcel &data, MessageParcel &reply);
void ReadAshmem(MessageParcel &data, MessageParcel &reply);
};
class TestServiceProxy : public IRemoteProxy<ITestService> {
public:
explicit TestServiceProxy(const sptr<IRemoteObject> &impl);
~TestServiceProxy() = default;
int TestSyncTransaction(int data, int &reply, int delayTime = 0) override;
int TestAsyncTransaction(int data, int timeout = 0) override;
int TestAsyncCallbackTrans(int data, int &reply, int timeout = 0) override;
int TestPingService(const std::u16string &serviceName) override;
int TestGetFileDescriptor() override;
int TestStringTransaction(const std::string &data) override;
int TestZtraceTransaction(std::string &send, std::string &reply, int len) override;
void TestDumpService() override;
int TestRawDataTransaction(int length, int &reply) override;
int TestRawDataReply(int length) override;
sptr<IFoo> TestGetFooService() override;
int TestCallingUidPid() override;
int TestFlushAsyncCalls(int count, int length) override;
int TestMultipleProcesses(int data, int &rep, int delayTime) override;
std::u16string TestAshmem(sptr<Ashmem> ashmem, int32_t contentSize) override;
void TestAsyncDumpService() override;
int TestNestingSend(int sendCode, int &replyCode) override;
private:
static inline BrokerDelegator<TestServiceProxy> delegator_;
static constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "TestServiceProxy" };
};
class TestDeathRecipient : public IRemoteObject::DeathRecipient {
public:
virtual void OnRemoteDied(const wptr<IRemoteObject> &remote);
TestDeathRecipient();
virtual ~TestDeathRecipient();
static bool GotDeathRecipient();
static bool gotDeathRecipient_;
private:
static constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "TestDeathRecipient" };
};
} // namespace OHOS
#endif // OHOS_TEST_SERVICE_SKELETON_H

View File

@ -0,0 +1,391 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ipc_types.h"
#include "assist_test_service.h"
namespace OHOS {
AssistTestServiceProxy::AssistTestServiceProxy(const sptr<IRemoteObject>& object)
: IRemoteProxy<IAssistTestService>(object)
{
}
AssistTestServiceProxy::~AssistTestServiceProxy()
{
}
bool AssistTestServiceProxy::TestParcelBool(bool value)
{
MessageParcel data, reply;
MessageOption option;
data.WriteBool(value);
int res = Remote()->SendRequest(TEST_PARCEL_BOOL, data, reply, option);
return (res == ERR_NONE) ? reply.ReadBool() : false;
}
int16_t AssistTestServiceProxy::TestParcelChar(int16_t value)
{
MessageParcel data, reply;
MessageOption option;
data.WriteInt16(value);
int res = Remote()->SendRequest(TEST_PARCEL_CHAR, data, reply, option);
return (res == ERR_NONE) ? reply.ReadInt16() : 0;
}
int32_t AssistTestServiceProxy::TestParcelInt32(int32_t value)
{
MessageParcel data, reply;
MessageOption option;
data.WriteInt32(value);
int res = Remote()->SendRequest(TEST_PARCEL_INT32, data, reply, option);
return (res == ERR_NONE) ? reply.ReadInt32() : 0;
}
int64_t AssistTestServiceProxy::TestParcelInt64(int64_t value)
{
MessageParcel data, reply;
MessageOption option;
data.WriteInt64(value);
int res = Remote()->SendRequest(TEST_PARCEL_INT64, data, reply, option);
return (res == ERR_NONE) ? reply.ReadInt64() : 0;
}
uint8_t AssistTestServiceProxy::TestParcelByte(uint8_t value)
{
MessageParcel data, reply;
MessageOption option;
data.WriteUint8(value);
int res = Remote()->SendRequest(TEST_PARCEL_BYTE, data, reply, option);
return (res == ERR_NONE) ? reply.ReadUint8() : 0;
}
uint32_t AssistTestServiceProxy::TestParcelUint32(uint32_t value)
{
MessageParcel data, reply;
MessageOption option;
data.WriteUint32(value);
int res = Remote()->SendRequest(TEST_PARCEL_UINT32, data, reply, option);
return (res == ERR_NONE) ? reply.ReadUint32() : 0;
}
uint64_t AssistTestServiceProxy::TestParcelUint64(uint64_t value)
{
MessageParcel data, reply;
MessageOption option;
data.WriteUint64(value);
int res = Remote()->SendRequest(TEST_PARCEL_UINT64, data, reply, option);
return (res == ERR_NONE) ? reply.ReadUint64() : 0;
}
float AssistTestServiceProxy::TestParcelFloat(float value)
{
MessageParcel data, reply;
MessageOption option;
data.WriteFloat(value);
int res = Remote()->SendRequest(TEST_PARCEL_FLOAT, data, reply, option);
return (res == ERR_NONE) ? reply.ReadFloat() : 0;
}
double AssistTestServiceProxy::TestParcelDouble(double value)
{
MessageParcel data, reply;
MessageOption option;
data.WriteDouble(value);
int res = Remote()->SendRequest(TEST_PARCEL_DOUBLE, data, reply, option);
return (res == ERR_NONE) ? reply.ReadDouble() : 0;
}
const char *AssistTestServiceProxy::TestParcelCString(const char *value)
{
MessageParcel data, reply;
MessageOption option;
data.WriteCString(value);
int res = Remote()->SendRequest(TEST_PARCEL_CSTRING, data, reply, option);
return (res == ERR_NONE) ? reply.ReadCString() : nullptr;
}
const std::string AssistTestServiceProxy::TestParcelString(const std::string& value)
{
MessageParcel data, reply;
MessageOption option;
data.WriteString(value);
int res = Remote()->SendRequest(TEST_PARCEL_STRING8, data, reply, option);
return (res == ERR_NONE) ? reply.ReadString() : std::string();
}
const std::u16string AssistTestServiceProxy::TestParcelString16(const std::u16string& value)
{
MessageParcel data, reply;
MessageOption option;
data.WriteString16(value);
int res = Remote()->SendRequest(TEST_PARCEL_STRING16, data, reply, option);
return (res == ERR_NONE) ? reply.ReadString16() : std::u16string();
}
bool AssistTestServiceProxy::TestParcelBoolVector()
{
MessageParcel data, reply;
MessageOption option;
std::vector<bool> readBoolVector;
std::vector<bool> writeBoolVector = { false, false, true, false, true };
data.WriteBoolVector(writeBoolVector);
if (Remote()->SendRequest(TEST_PARCEL_BOOL_VECTOR, data, reply, option) != ERR_NONE) {
return false;
}
if (!reply.ReadBoolVector(&readBoolVector)) {
return false;
}
for (size_t i = 0; i < writeBoolVector.size(); i++) {
if (writeBoolVector[i] != readBoolVector[i]) {
bool write = writeBoolVector[i];
bool read = readBoolVector[i];
printf("index:%zu write:%d, read:%d\n", i, write, read);
return false;
}
}
return true;
}
bool AssistTestServiceProxy::TestParcelInt8Vector()
{
MessageParcel data, reply;
MessageOption option;
std::vector<int8_t> readInt8Vector;
std::vector<int8_t> writeInt8Vector = { 0x01, 0x10, -0x20, 0x30, 0x40 };
data.WriteInt8Vector(writeInt8Vector);
int res = Remote()->SendRequest(TEST_PARCEL_INT8_VECTOR, data, reply, option);
if (res != ERR_NONE) {
return false;
}
if (!reply.ReadInt8Vector(&readInt8Vector)) {
return false;
}
for (size_t i = 0; i < writeInt8Vector.size(); i++) {
if (writeInt8Vector[i] != readInt8Vector[i]) {
return false;
}
}
return true;
}
bool AssistTestServiceProxy::TestParcelUint8Vector()
{
MessageParcel data, reply;
MessageOption option;
std::vector<uint8_t> readUint8Vector;
std::vector<uint8_t> writeUint8Vector = { 0xA1, 0xA1, 0xA2, 0x30, 0x40 };
data.WriteUInt8Vector(writeUint8Vector);
if (Remote()->SendRequest(TEST_PARCEL_UINT8_VECTOR, data, reply, option) != ERR_NONE) {
return false;
}
if (!reply.ReadUInt8Vector(&readUint8Vector)) {
return false;
}
for (size_t i = 0; i < writeUint8Vector.size(); i++) {
if (writeUint8Vector[i] != readUint8Vector[i]) {
return false;
}
}
return true;
}
bool AssistTestServiceProxy::TestParcelCharVector()
{
MessageParcel data, reply;
MessageOption option;
std::vector<int16_t> readInt16Vector;
std::vector<int16_t> writeInt16Vector = { 0x1234, -0x2345, 0x3456, -0x4567, 0x5678 };
data.WriteInt16Vector(writeInt16Vector);
if (Remote()->SendRequest(TEST_PARCEL_CHAR_VECTOR, data, reply, option) != ERR_NONE) {
return false;
}
if (!reply.ReadInt16Vector(&readInt16Vector)) {
return false;
}
for (size_t i = 0; i < writeInt16Vector.size(); i++) {
if (writeInt16Vector[i] != readInt16Vector[i]) {
return false;
}
}
return true;
}
bool AssistTestServiceProxy::TestParcelInt64Vector()
{
MessageParcel data, reply;
MessageOption option;
std::vector<int64_t> readInt64Vector;
std::vector<int64_t> writeInt64Vector = { 0x1234567887654321, -0x2345678998765432 };
data.WriteInt64Vector(writeInt64Vector);
if (Remote()->SendRequest(TEST_PARCEL_INT64_VECTOR, data, reply, option) != ERR_NONE) {
return false;
}
if (!reply.ReadInt64Vector(&readInt64Vector)) {
return false;
}
for (size_t i = 0; i < writeInt64Vector.size(); i++) {
if (writeInt64Vector[i] != readInt64Vector[i]) {
return false;
}
}
return true;
}
bool AssistTestServiceProxy::TestParcelUint64Vector()
{
MessageParcel data, reply;
MessageOption option;
std::vector<uint64_t> readUint64Vector;
std::vector<uint64_t> writeUint64Vector = { 0x1234567887654321, 0x2345678998765432 };
data.WriteUInt64Vector(writeUint64Vector);
if (Remote()->SendRequest(TEST_PARCEL_UINT64_VECTOR, data, reply, option) != ERR_NONE) {
return false;
}
bool result = reply.ReadUInt64Vector(&readUint64Vector);
if (result != true) {
return false;
}
for (size_t i = 0; i < writeUint64Vector.size(); i++) {
if (writeUint64Vector[i] != readUint64Vector[i]) {
return false;
}
}
return true;
}
bool AssistTestServiceProxy::TestParcelInt32Vector()
{
MessageParcel data, reply;
MessageOption option;
std::vector<int32_t> readInt32Vector;
std::vector<int32_t> writeInt32Vector = { 0x12345678, -0x23456789, 0x34567890, -0x45678901 };;
data.WriteInt32Vector(writeInt32Vector);
if (Remote()->SendRequest(TEST_PARCEL_INT32_VECTOR, data, reply, option) != ERR_NONE) {
return false;
}
if (!reply.ReadInt32Vector(&readInt32Vector)) {
return false;
}
for (size_t i = 0; i < writeInt32Vector.size(); i++) {
if (writeInt32Vector[i] != readInt32Vector[i]) {
return false;
}
}
return true;
}
bool AssistTestServiceProxy::TestParcelFloatVector()
{
MessageParcel data, reply;
MessageOption option;
std::vector<float> readFloatVector;
std::vector<float> writeFloatVector{ 11221.132313, 11221.45678 };
data.WriteFloatVector(writeFloatVector);
if (Remote()->SendRequest(TEST_PARCEL_FLOAT_VECTOR, data, reply, option) != ERR_NONE) {
return false;
}
if (!reply.ReadFloatVector(&readFloatVector)) {
return false;
}
for (size_t i = 0; i < writeFloatVector.size(); i++) {
if (writeFloatVector[i] != readFloatVector[i]) {
return false;
}
}
return true;
}
bool AssistTestServiceProxy::TestParcelDoubleVector()
{
MessageParcel data, reply;
MessageOption option;
std::vector<double> readDoubleVector;
std::vector<double> writeDoubleVector{ 1122.132313, 1122.45678 };
data.WriteDoubleVector(writeDoubleVector);
if (Remote()->SendRequest(TEST_PARCEL_DOUBLE_VECTOR, data, reply, option) != ERR_NONE) {
return false;
}
if (!reply.ReadDoubleVector(&readDoubleVector)) {
return false;
}
for (size_t i = 0; i < writeDoubleVector.size(); i++) {
if (writeDoubleVector[i] != readDoubleVector[i]) {
return false;
}
}
return true;
}
bool AssistTestServiceProxy::TestParcelString16Vector()
{
MessageParcel data, reply;
MessageOption option;
std::vector<std::u16string> readString16Vector;
std::vector<std::u16string> writeString16Vector{
u"test", u"test for", u"test for write", u"test for write vector"
};
data.WriteString16Vector(writeString16Vector);
if (Remote()->SendRequest(TEST_PARCEL_STRING16_VECTOR, data, reply, option) != ERR_NONE) {
return false;
}
if (!reply.ReadString16Vector(&readString16Vector)) {
return false;
}
for (size_t i = 0; i < writeString16Vector.size(); i++) {
if (writeString16Vector[i].compare(readString16Vector[i])) {
return false;
}
}
return true;
}
} // namespace OHOS

View File

@ -0,0 +1,129 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "foo_service.h"
#include "ipc_debug.h"
#include "ipc_types.h"
namespace OHOS {
std::mutex FooStub::decTimeMutex_;
int FooStub::decTimes_ = 0;
int FooStub::OnRemoteRequest(uint32_t code,
MessageParcel& data, MessageParcel& reply, MessageOption& option)
{
int result = ERR_NONE;
switch (code) {
case GET_FOO_NAME: {
ZLOGI(LABEL, "%{public}s:called\n", __func__);
reply.WriteString(GetFooName());
break;
}
case SEND_ASYNC_REPLY: {
int32_t replyData = data.ReadInt32();
SendAsyncReply(replyData);
break;
}
case SEND_WRONG_REPLY: {
return TestNestingSend(data.ReadInt32());
}
default:
result = ERR_TRANSACTION_FAILED;
break;
}
return result;
}
std::string FooStub::GetFooName()
{
return "ReallFoo";
}
int FooStub::WaitForAsyncReply(int timeout)
{
asyncReply_ = 0;
std::unique_lock<std::mutex> lck(mutex_);
cv_.wait_for(lck, std::chrono::milliseconds(timeout), [&]() {
return asyncReply_ != 0;
});
return asyncReply_;
}
void FooStub::SendAsyncReply(int &replyValue)
{
std::unique_lock<std::mutex> lck(mutex_);
asyncReply_ = replyValue;
cv_.notify_all();
}
FooStub::~FooStub()
{
std::unique_lock<std::mutex> lck(decTimeMutex_);
decTimes_++;
}
void FooStub::CleanDecTimes()
{
std::unique_lock<std::mutex> lck(decTimeMutex_);
decTimes_ = 0;
}
int FooStub::GetDecTimes()
{
std::unique_lock<std::mutex> lck(decTimeMutex_);
return decTimes_;
}
int FooStub::TestNestingSend(int sendCode)
{
return sendCode;
}
FooProxy::FooProxy(const sptr<IRemoteObject> &impl)
: IRemoteProxy<IFoo>(impl)
{
}
std::string FooProxy::GetFooName()
{
ZLOGI(LABEL, "%{public}s:called\n", __func__);
MessageParcel data, reply;
MessageOption option;
Remote()->SendRequest(GET_FOO_NAME, data, reply, option);
return reply.ReadString();
}
void FooProxy::SendAsyncReply(int &replyValue)
{
ZLOGI(LABEL, "%{public}s:called\n", __func__);
MessageParcel data, reply;
MessageOption option = { MessageOption::TF_ASYNC };
data.WriteInt32(replyValue);
Remote()->SendRequest(SEND_ASYNC_REPLY, data, reply, option);
}
int FooProxy::TestNestingSend(int sendCode)
{
MessageOption option;
MessageParcel dataParcel, replyParcel;
if (!dataParcel.WriteInt32(sendCode)) {
return -1;
}
int error = Remote()->SendRequest(SEND_WRONG_REPLY, dataParcel, replyParcel, option);
ZLOGE(LABEL, "send foo result = %{public}d", error);
return error;
}
} // namespace OHOS

View File

@ -0,0 +1,337 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ipc_test_helper.h"
#include <vector>
#include <csignal>
#include <fstream>
#include <string>
#include <securec.h>
#include <sys/time.h>
#include <unistd.h>
#include "ipc_debug.h"
#include "test_service_client.h"
using namespace OHOS::HiviewDFX;
namespace OHOS {
static const int MAX_NAME_LEN = 256;
static const int MAX_BUFFER_SIZE = 1024;
static const int SLEEP_TIME = 500000; // ms
static const int SECOND_TO_MS = 1000;
static const int ONE_SECOND = 1; // seconds
static const int MAX_CHECK_COUNT = 10;
static const int SIG_KILL = 9;
const std::string &IPCTestHelper::GetTestAppName(int appId)
{
static std::map<unsigned int, std::string> appNames = {
{ IPC_TEST_NONE, ""},
{ IPC_TEST_SAMGR, "samgr" },
{ IPC_TEST_SERVER, "ipc_server_test" },
{ IPC_TEST_SERVER_EXTRA, "ipc_server_test_extra" },
{ IPC_TEST_CLIENT, "ipc_client_test" },
{ IPC_TEST_MSG_SERVER, "ipcmsg_server" },
{ IPC_TEST_MSG_CLIENT, "ipcmsg_client" },
};
if (appNames.count(appId)) {
return appNames[appId];
}
return appNames[IPC_TEST_NONE];
}
IPCTestHelper::~IPCTestHelper()
{
TearDownTestSuite();
}
pid_t IPCTestHelper::GetPidByName(std::string task_name)
{
struct dirent *ptr = nullptr;
FILE *fp = nullptr;
char filepath[MAX_NAME_LEN + 1];
char curTaskName[MAX_NAME_LEN + 1];
char buf[MAX_BUFFER_SIZE];
pid_t pid = INVALID_PID;
DIR *dir = opendir("/proc");
if (dir == nullptr) {
return pid;
}
for (;;) {
ptr = readdir(dir);
if (ptr == nullptr) {
break;
}
if ((strcmp(ptr->d_name, ".") == 0) ||
(strcmp(ptr->d_name, "..") == 0) ||
(ptr->d_type != DT_DIR)) {
continue;
}
if (sprintf_s(filepath, sizeof(filepath), "/proc/%s/status", ptr->d_name) <= 0) {
ZLOGE(LABEL, "format file failed");
closedir(dir);
return INVALID_PID;
}
fp = fopen(filepath, "r");
if (fp == nullptr) {
continue;
}
if (fgets(buf, MAX_BUFFER_SIZE - 1, fp) == nullptr) {
fclose(fp);
continue;
}
if (sscanf_s(buf, "%*s %s", curTaskName, sizeof(curTaskName)) <= 0) {
ZLOGE(LABEL, "could not find current task");
}
if (!strcmp(task_name.c_str(), curTaskName)) {
if (sscanf_s(ptr->d_name, "%d", &pid) <= 0) {
ZLOGE(LABEL, "could not find target task");
}
}
fclose(fp);
}
closedir(dir);
return pid;
}
bool IPCTestHelper::GetChildPids(std::vector<pid_t> &childPids)
{
pid_t current = getpid();
ZLOGI(LABEL, "current pid %d\n", current);
const std::string taskPath = "/proc/" + std::to_string(current) + "/task";
DIR *dir = opendir(taskPath.c_str());
if (dir == nullptr) {
return false;
}
struct dirent *ptr = nullptr;
for (;;) {
ptr = readdir(dir);
if (ptr == nullptr) {
break;
}
if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0)) {
continue;
}
if (ptr->d_type != DT_DIR) {
continue;
}
pid_t child = std::stoi(ptr->d_name);
if (child == current) {
continue;
}
childPids.push_back(child);
ZLOGI(LABEL, "child pid %d", child);
}
closedir(dir);
return true;
}
pid_t IPCTestHelper::StartExecutable(std::string name, std::string args)
{
pid_t execPid;
int checkCount = 0;
const char *ld_library_path = getenv("LD_LIBRARY_PATH");
if (ld_library_path != nullptr) {
unsetenv("LD_LIBRARY_PATH");
}
std::string cmd1 = "chmod +x /system/bin/" + name;
int res = system(cmd1.c_str());
ZLOGI(LABEL, "%s, res = %d\n", cmd1.c_str(), res);
// kill the program if the program is already exist.
execPid = GetPidByName(name);
StopExecutable(execPid);
std::string cmd2 = name + " " + args + "&";
res = system(cmd2.c_str());
if (ld_library_path != nullptr) {
setenv("LD_LIBRARY_PATH", ld_library_path, 1);
}
ZLOGI(LABEL, "%s res = %d\n", cmd2.c_str(), res);
do {
execPid = GetPidByName(name);
sleep(ONE_SECOND);
if (execPid != INVALID_PID) {
break;
}
} while (checkCount++ < MAX_CHECK_COUNT);
ZLOGI(LABEL, "start %s done, pid:%d\n", name.c_str(), execPid);
return execPid;
}
bool IPCTestHelper::StopExecutable(pid_t pid)
{
if (pid != INVALID_PID) {
ZLOGI(LABEL, "kill pid = %d\n", pid);
kill(pid, SIG_KILL);
}
return true;
}
bool IPCTestHelper::StopExecutable(std::string name)
{
pid_t pid = GetPidByName(name);
if (pid != INVALID_PID) {
ZLOGI(LABEL, "%s pid = %d, kill it\n", name.c_str(), pid);
kill(pid, SIG_KILL);
}
return true;
}
bool IPCTestHelper::PrepareTestSuite()
{
pid_t pid = GetTestAppPid(IPC_TEST_SAMGR);
if (pid == INVALID_PID) {
usleep(SLEEP_TIME);
pid = StartTestApp(IPC_TEST_SAMGR);
ZLOGI(LABEL, "StartSystemServer done");
}
return (pid != INVALID_PID);
}
bool IPCTestHelper::TearDownTestSuite()
{
for (auto it = testPids_.begin(); it != testPids_.end();) {
ZLOGI(LABEL, "kill %s", it->first.c_str());
StopExecutable(it->second);
it = testPids_.erase(it);
}
return true;
}
void IPCTestHelper::AddTestAppPid(const std::string &appName, const int &pid)
{
std::lock_guard<std::mutex> auto_lock(mutex_);
testPids_.insert(std::make_pair(appName, pid));
}
void IPCTestHelper::RemoveTestAppPid(const std::string &appName)
{
std::lock_guard<std::mutex> auto_lock(mutex_);
auto it = testPids_.find(appName);
if (it != testPids_.end()) {
testPids_.erase(appName);
}
}
bool IPCTestHelper::StartTestApp(int appId, const int &cmdId)
{
int pid = INVALID_PID;
std::string appName = GetTestAppName(appId);
if (!appName.empty()) {
if (cmdId > 0) {
pid = StartExecutable(appName, std::to_string(cmdId));
} else {
pid = StartExecutable(appName);
}
}
if (pid != INVALID_PID) {
RemoveTestAppPid(appName); // should remove it if exist;
AddTestAppPid(appName, pid);
}
ZLOGI(LABEL, "StartTestApp:%d cmdId=%d pid = %d", appId, cmdId, pid);
return (pid != INVALID_PID);
}
bool IPCTestHelper::StopTestApp(int appId)
{
std::string appName = GetTestAppName(appId);
if (appName.empty()) {
return false;
}
pid_t pid = GetTestAppPid(appId);
if (pid != INVALID_PID) {
pid = StopExecutable(pid);
RemoveTestAppPid(appName);
usleep(SLEEP_TIME);
}
return (pid != INVALID_PID);
}
pid_t IPCTestHelper::GetTestAppPid(int appId)
{
ZLOGE(LABEL, "GetTestAppPid appId=%d", appId);
int pid = INVALID_PID;
std::string appName = GetTestAppName(appId);
if (appName.empty()) {
return INVALID_PID;
}
auto it = testPids_.find(appName);
if (it != testPids_.end()) {
pid = it->second;
} else {
pid = GetPidByName(appName);
}
ZLOGE(LABEL, "GetTestAppPid return pid=%d", pid);
return pid;
}
pid_t IPCTestHelper::GetPid()
{
pid_t pid = getpid();
ZLOGI(LABEL, "return pid=%{public}d", pid);
return pid;
}
uid_t IPCTestHelper::GetUid()
{
uid_t uid = getuid();
ZLOGI(LABEL, "return uid=%{public}d", uid);
return uid;
}
long IPCTestHelper::GetCurrentTimeMs()
{
struct timeval tv;
gettimeofday(&tv, nullptr);
return tv.tv_sec * SECOND_TO_MS + tv.tv_usec / SECOND_TO_MS;
}
} // namespace OHOS

View File

@ -0,0 +1,101 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <string>
#include <cerrno>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "ipc_debug.h"
#include "ipc_skeleton.h"
#include "test_service_command.h"
#include "test_service_client.h"
#include "test_service_skeleton.h"
#include "if_system_ability_manager.h"
#include "log_tags.h"
using namespace OHOS;
using namespace OHOS::HiviewDFX;
static constexpr HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "IPCTestClient" };
std::vector<std::string> GetArgvOptions(int argc, char **argv)
{
std::vector<std::string> argvOptions;
for (int i = 1; i < argc; i++) {
argvOptions.emplace_back(std::string(argv[i]));
}
return argvOptions;
}
int main(int argc, char *argv[])
{
int result = 0;
TestCommand commandId = TestCommand::TEST_CMD_SYNC_TRANS;
if (argc > 1) {
commandId = { atoi(argv[1]) };
} else {
ZLOGE(LABEL, "unknown command");
}
std::vector<std::string> argvOptions;
argvOptions = GetArgvOptions(argc, argv);
std::unique_ptr<TestServiceClient> testClient = std::make_unique<TestServiceClient>();
if (testClient->ConnectService()) {
return -1;
}
ZLOGE(LABEL, "commandId= : %{public}d", commandId);
switch (commandId) {
case TestCommand::TEST_CMD_SYNC_TRANS:
testClient->StartSyncTransaction();
break;
case TestCommand::TEST_CMD_ASYNC_TRANS: {
testClient->StartAsyncTransaction();
break;
}
case TestCommand::TEST_CMD_PING_SERVICE: {
testClient->StartPingService();
break;
}
case TestCommand::TEST_CMD_GET_FOO_SERVICE: {
testClient->StartGetFooService();
break;
}
case TestCommand::TEST_CMD_TRANS_FILE_DESC: {
testClient->StartTestFileDescriptor();
break;
}
case TestCommand::TEST_CMD_LOOP_TRANSACTION: {
constexpr int maxTestCount = 1000;
testClient->StartLoopTest(maxTestCount);
break;
}
case TestCommand::TEST_CMD_DUMP_SERVICE: {
testClient->StartDumpService();
break;
}
case TestCommand::TEST_CMD_ASYNC_DUMP_SERVICE: {
testClient->StartAsyncDumpService();
break;
}
default:
ZLOGI(LABEL, "main arg error");
break;
}
ZLOGE(LABEL, "get from service: %{public}d", result);
IPCSkeleton::JoinWorkThread();
return 0;
}

View File

@ -0,0 +1,31 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ipc_debug.h"
#include "ipc_skeleton.h"
#include "test_service.h"
#include "log_tags.h"
using namespace OHOS;
using namespace OHOS::HiviewDFX;
[[maybe_unused]]static constexpr HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "IPCTestServer" };
int main(int argc __attribute__((unused)), char **argv __attribute__((unused)))
{
TestService::Instantiate();
ZLOGI(LABEL, "call StartThreadPool");
IPCSkeleton::JoinWorkThread();
}

Some files were not shown because too many files have changed in this diff Show More