mirror of
https://gitee.com/openharmony/communication_ipc
synced 2024-11-22 23:40:24 +00:00
update OpenHarmony 2.0 Canary
This commit is contained in:
parent
b201636188
commit
483c66de10
15
.gitattributes
vendored
Normal file
15
.gitattributes
vendored
Normal 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
43
BUILD.gn
Executable 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
178
LICENSE
Executable 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
|
||||
|
36
README.en.md
36
README.en.md
@ -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
275
README.md
Normal file → Executable file
@ -1,37 +1,262 @@
|
||||
# communication_ipc
|
||||
# communication\_ipc<a name="EN-US_TOPIC_0000001103602398"></a>
|
||||
|
||||
#### 介绍
|
||||
Inter-process communication (IPC) and Remote Procedure Call (RPC) | 跨进程通信与跨设备的远程过程调用
|
||||
- [Introduction](#section11660541593)
|
||||
- [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
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
## Architecture<a name="section1950291414611"></a>
|
||||
|
||||
#### 使用说明
|
||||
**Figure 1** IPC architecture<a name="fig312319321710"></a>
|
||||
![](figures/ipc-architecture.png "ipc-architecture")
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
## Directory Structure<a name="section161941989596"></a>
|
||||
|
||||
#### 参与贡献
|
||||
```
|
||||
/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 本仓库
|
||||
2. 新建 Feat_xxx 分支
|
||||
3. 提交代码
|
||||
4. 新建 Pull Request
|
||||
## Constraints<a name="section119744591305"></a>
|
||||
|
||||
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<IRemoteObject> 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 &data, MessageParcel &reply, MessageOption &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 "> </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
264
README_zh.md
Executable 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>
|
||||
|
||||
IPC(Inter-Process Communication)与RPC(Remote Procedure Call)机制用于实现跨进程通信,不同的是前者使用Binder驱动,用于设备内的跨进程通信,而后者使用软总线驱动,用于跨设备跨进程通信。IPC和RPC通常采用客户端-服务器(Client-Server)模型,服务请求方(Client)可获取提供服务提供方(Server)的代理 (Proxy),并通过此代理读写数据来实现进程间的数据通信。通常,Server会先注册系统能力(System Ability)到系统能力管理者(System Ability Manager,缩写SAMgr)中,SAMgr负责管理这些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<IRemoteObject> 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 &data, MessageParcel &reply, MessageOption &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 "> </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)、接收FD(TF\_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
BIN
figures/ipc-architecture.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 7.7 KiB |
67
interfaces/innerkits/ipc_core/BUILD.gn
Executable file
67
interfaces/innerkits/ipc_core/BUILD.gn
Executable 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"
|
||||
}
|
38
interfaces/innerkits/ipc_core/include/ipc_file_descriptor.h
Executable file
38
interfaces/innerkits/ipc_core/include/ipc_file_descriptor.h
Executable 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
|
117
interfaces/innerkits/ipc_core/include/ipc_object_proxy.h
Executable file
117
interfaces/innerkits/ipc_core/include/ipc_object_proxy.h
Executable 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
|
84
interfaces/innerkits/ipc_core/include/ipc_object_stub.h
Executable file
84
interfaces/innerkits/ipc_core/include/ipc_object_stub.h
Executable 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
|
59
interfaces/innerkits/ipc_core/include/ipc_skeleton.h
Executable file
59
interfaces/innerkits/ipc_core/include/ipc_skeleton.h
Executable 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
|
122
interfaces/innerkits/ipc_core/include/ipc_types.h
Executable file
122
interfaces/innerkits/ipc_core/include/ipc_types.h
Executable 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
|
109
interfaces/innerkits/ipc_core/include/iremote_broker.h
Executable file
109
interfaces/innerkits/ipc_core/include/iremote_broker.h
Executable 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 ®istration = BrokerRegistration::Get();
|
||||
registration.Register(descriptor, BrokerCreator<T>());
|
||||
}
|
||||
|
||||
template <typename T> BrokerDelegator<T>::~BrokerDelegator()
|
||||
{
|
||||
const std::u16string descriptor = T::GetDescriptor();
|
||||
BrokerRegistration ®istration = BrokerRegistration::Get();
|
||||
registration.Unregister(descriptor);
|
||||
}
|
||||
|
||||
template <typename INTERFACE> inline sptr<INTERFACE> iface_cast(const sptr<IRemoteObject> &object)
|
||||
{
|
||||
const std::u16string descriptor = INTERFACE::GetDescriptor();
|
||||
BrokerRegistration ®istration = BrokerRegistration::Get();
|
||||
sptr<IRemoteBroker> broker = registration.NewInstance(descriptor, object);
|
||||
return static_cast<INTERFACE *>(broker.GetRefPtr());
|
||||
}
|
||||
} // namespace OHOS
|
||||
#endif // OHOS_IPC_IREMOTE_BROKER_H
|
86
interfaces/innerkits/ipc_core/include/iremote_object.h
Executable file
86
interfaces/innerkits/ipc_core/include/iremote_object.h
Executable 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
|
43
interfaces/innerkits/ipc_core/include/iremote_proxy.h
Executable file
43
interfaces/innerkits/ipc_core/include/iremote_proxy.h
Executable 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
|
44
interfaces/innerkits/ipc_core/include/iremote_stub.h
Executable file
44
interfaces/innerkits/ipc_core/include/iremote_stub.h
Executable 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
|
26
interfaces/innerkits/ipc_core/include/jni_help.h
Executable file
26
interfaces/innerkits/ipc_core/include/jni_help.h
Executable 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
|
43
interfaces/innerkits/ipc_core/include/message_option.h
Executable file
43
interfaces/innerkits/ipc_core/include/message_option.h
Executable 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
|
67
interfaces/innerkits/ipc_core/include/message_parcel.h
Executable file
67
interfaces/innerkits/ipc_core/include/message_parcel.h
Executable 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
|
34
interfaces/innerkits/ipc_core/include/peer_holder.h
Executable file
34
interfaces/innerkits/ipc_core/include/peer_holder.h
Executable 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
|
58
interfaces/innerkits/ipc_single/BUILD.gn
Executable file
58
interfaces/innerkits/ipc_single/BUILD.gn
Executable 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"
|
||||
}
|
66
interfaces/innerkits/libdbinder/BUILD.gn
Executable file
66
interfaces/innerkits/libdbinder/BUILD.gn
Executable 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"
|
||||
}
|
194
interfaces/innerkits/libdbinder/include/dbinder_service.h
Executable file
194
interfaces/innerkits/libdbinder/include/dbinder_service.h
Executable 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
|
51
interfaces/innerkits/libdbinder/include/dbinder_service_stub.h
Executable file
51
interfaces/innerkits/libdbinder/include/dbinder_service_stub.h
Executable 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
|
76
ipc/native/src/core/include/buffer_object.h
Executable file
76
ipc/native/src/core/include/buffer_object.h
Executable 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
|
39
ipc/native/src/core/include/comm_auth_info.h
Executable file
39
ipc/native/src/core/include/comm_auth_info.h
Executable 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
|
42
ipc/native/src/core/include/databus_session_callback.h
Executable file
42
ipc/native/src/core/include/databus_session_callback.h
Executable 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
|
144
ipc/native/src/core/include/dbinder_error_code.h
Executable file
144
ipc/native/src/core/include/dbinder_error_code.h
Executable 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
|
70
ipc/native/src/core/include/dbinder_session_object.h
Executable file
70
ipc/native/src/core/include/dbinder_session_object.h
Executable 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
|
62
ipc/native/src/core/include/ipc_debug.h
Executable file
62
ipc/native/src/core/include/ipc_debug.h
Executable 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
|
258
ipc/native/src/core/include/ipc_process_skeleton.h
Executable file
258
ipc/native/src/core/include/ipc_process_skeleton.h
Executable 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
|
74
ipc/native/src/core/include/ipc_thread_pool.h
Executable file
74
ipc/native/src/core/include/ipc_thread_pool.h
Executable 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
|
63
ipc/native/src/core/include/ipc_thread_skeleton.h
Executable file
63
ipc/native/src/core/include/ipc_thread_skeleton.h
Executable 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
|
60
ipc/native/src/core/include/ipc_workthread.h
Executable file
60
ipc/native/src/core/include/ipc_workthread.h
Executable 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
|
36
ipc/native/src/core/include/stub_refcount_object.h
Executable file
36
ipc/native/src/core/include/stub_refcount_object.h
Executable 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
|
223
ipc/native/src/core/source/buffer_object.cpp
Executable file
223
ipc/native/src/core/source/buffer_object.cpp
Executable 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
|
43
ipc/native/src/core/source/comm_auth_info.cpp
Executable file
43
ipc/native/src/core/source/comm_auth_info.cpp
Executable 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
|
81
ipc/native/src/core/source/databus_session_callback.cpp
Executable file
81
ipc/native/src/core/source/databus_session_callback.cpp
Executable 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
|
95
ipc/native/src/core/source/dbinder_session_object.cpp
Executable file
95
ipc/native/src/core/source/dbinder_session_object.cpp
Executable 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
|
91
ipc/native/src/core/source/ipc_file_descriptor.cpp
Executable file
91
ipc/native/src/core/source/ipc_file_descriptor.cpp
Executable 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
|
660
ipc/native/src/core/source/ipc_object_proxy.cpp
Executable file
660
ipc/native/src/core/source/ipc_object_proxy.cpp
Executable 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
|
495
ipc/native/src/core/source/ipc_object_stub.cpp
Executable file
495
ipc/native/src/core/source/ipc_object_stub.cpp
Executable 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
|
1229
ipc/native/src/core/source/ipc_process_skeleton.cpp
Executable file
1229
ipc/native/src/core/source/ipc_process_skeleton.cpp
Executable file
File diff suppressed because it is too large
Load Diff
148
ipc/native/src/core/source/ipc_skeleton.cpp
Executable file
148
ipc/native/src/core/source/ipc_skeleton.cpp
Executable 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
|
147
ipc/native/src/core/source/ipc_thread_pool.cpp
Executable file
147
ipc/native/src/core/source/ipc_thread_pool.cpp
Executable 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
|
||||
|
158
ipc/native/src/core/source/ipc_thread_skeleton.cpp
Executable file
158
ipc/native/src/core/source/ipc_thread_skeleton.cpp
Executable 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
|
94
ipc/native/src/core/source/ipc_workthread.cpp
Executable file
94
ipc/native/src/core/source/ipc_workthread.cpp
Executable 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
|
79
ipc/native/src/core/source/iremote_broker.cpp
Executable file
79
ipc/native/src/core/source/iremote_broker.cpp
Executable 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
|
84
ipc/native/src/core/source/iremote_object.cpp
Executable file
84
ipc/native/src/core/source/iremote_object.cpp
Executable 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
|
46
ipc/native/src/core/source/message_option.cpp
Executable file
46
ipc/native/src/core/source/message_option.cpp
Executable 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
|
327
ipc/native/src/core/source/message_parcel.cpp
Executable file
327
ipc/native/src/core/source/message_parcel.cpp
Executable 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
|
25
ipc/native/src/core/source/peer_holder.cpp
Executable file
25
ipc/native/src/core/source/peer_holder.cpp
Executable 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
|
43
ipc/native/src/core/source/stub_refcount_object.cpp
Executable file
43
ipc/native/src/core/source/stub_refcount_object.cpp
Executable 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
|
68
ipc/native/src/jni/include/jni_helper.h
Executable file
68
ipc/native/src/jni/include/jni_helper.h
Executable 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
|
27
ipc/native/src/jni/include/jni_remote_object.h
Executable file
27
ipc/native/src/jni/include/jni_remote_object.h
Executable 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
|
59
ipc/native/src/jni/include/ohos_rpc_message_option.h
Executable file
59
ipc/native/src/jni/include/ohos_rpc_message_option.h
Executable 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
|
158
ipc/native/src/jni/include/ohos_rpc_message_parcel.h
Executable file
158
ipc/native/src/jni/include/ohos_rpc_message_parcel.h
Executable 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
|
181
ipc/native/src/jni/include/ohos_rpc_remote_object.h
Executable file
181
ipc/native/src/jni/include/ohos_rpc_remote_object.h
Executable 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
|
176
ipc/native/src/jni/source/jni_helper.cpp
Executable file
176
ipc/native/src/jni/source/jni_helper.cpp
Executable 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
|
138
ipc/native/src/jni/source/ohos_rpc_message_option.cpp
Executable file
138
ipc/native/src/jni/source/ohos_rpc_message_option.cpp
Executable 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
|
519
ipc/native/src/jni/source/ohos_rpc_message_parcel.cpp
Executable file
519
ipc/native/src/jni/source/ohos_rpc_message_parcel.cpp
Executable 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));
|
||||
}
|
982
ipc/native/src/jni/source/ohos_rpc_remote_object.cpp
Executable file
982
ipc/native/src/jni/source/ohos_rpc_remote_object.cpp
Executable 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;
|
||||
}
|
48
ipc/native/src/mock/include/binder_connector.h
Executable file
48
ipc/native/src/mock/include/binder_connector.h
Executable 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
|
30
ipc/native/src/mock/include/binder_debug.h
Executable file
30
ipc/native/src/mock/include/binder_debug.h
Executable 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
|
154
ipc/native/src/mock/include/binder_invoker.h
Executable file
154
ipc/native/src/mock/include/binder_invoker.h
Executable 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
|
1022
ipc/native/src/mock/include/dbinder_base_invoker.h
Executable file
1022
ipc/native/src/mock/include/dbinder_base_invoker.h
Executable file
File diff suppressed because it is too large
Load Diff
111
ipc/native/src/mock/include/dbinder_databus_invoker.h
Executable file
111
ipc/native/src/mock/include/dbinder_databus_invoker.h
Executable 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
|
42
ipc/native/src/mock/include/hitrace_invoker.h
Executable file
42
ipc/native/src/mock/include/hitrace_invoker.h
Executable 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
|
70
ipc/native/src/mock/include/invoker_factory.h
Executable file
70
ipc/native/src/mock/include/invoker_factory.h
Executable 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
|
40
ipc/native/src/mock/include/invoker_rawdata.h
Executable file
40
ipc/native/src/mock/include/invoker_rawdata.h
Executable 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
|
105
ipc/native/src/mock/include/iremote_invoker.h
Executable file
105
ipc/native/src/mock/include/iremote_invoker.h
Executable 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
|
270
ipc/native/src/mock/include/sys_binder.h
Executable file
270
ipc/native/src/mock/include/sys_binder.h
Executable 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
|
147
ipc/native/src/mock/source/binder_connector.cpp
Executable file
147
ipc/native/src/mock/source/binder_connector.cpp
Executable 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
|
65
ipc/native/src/mock/source/binder_debug.cpp
Executable file
65
ipc/native/src/mock/source/binder_debug.cpp
Executable 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
|
951
ipc/native/src/mock/source/binder_invoker.cpp
Executable file
951
ipc/native/src/mock/source/binder_invoker.cpp
Executable 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
|
892
ipc/native/src/mock/source/dbinder_databus_invoker.cpp
Executable file
892
ipc/native/src/mock/source/dbinder_databus_invoker.cpp
Executable 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
|
140
ipc/native/src/mock/source/hitrace_invoker.cpp
Executable file
140
ipc/native/src/mock/source/hitrace_invoker.cpp
Executable 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
|
87
ipc/native/src/mock/source/invoker_factory.cpp
Executable file
87
ipc/native/src/mock/source/invoker_factory.cpp
Executable 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
|
40
ipc/native/src/mock/source/invoker_rawdata.cpp
Executable file
40
ipc/native/src/mock/source/invoker_rawdata.cpp
Executable 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
22
ipc/native/test/BUILD.gn
Executable 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" ]
|
||||
}
|
||||
###############################################################################
|
82
ipc/native/test/unittest/common/BUILD.gn
Executable file
82
ipc/native/test/unittest/common/BUILD.gn
Executable 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",
|
||||
]
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
|
489
ipc/native/test/unittest/common/ipc_core_unittest.cpp
Executable file
489
ipc/native/test/unittest/common/ipc_core_unittest.cpp
Executable 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);
|
||||
}
|
93
ipc/native/test/unittest/common/ipc_file_desc_unittest.cpp
Executable file
93
ipc/native/test/unittest/common/ipc_file_desc_unittest.cpp
Executable 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
|
414
ipc/native/test/unittest/common/ipc_hitrace_unittest.cpp
Executable file
414
ipc/native/test/unittest/common/ipc_hitrace_unittest.cpp
Executable 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
33
ipc/test/BUILD.gn
Executable 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" ]
|
||||
}
|
||||
###############################################################################
|
157
ipc/test/auxiliary/native/BUILD.gn
Executable file
157
ipc/test/auxiliary/native/BUILD.gn
Executable 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",
|
||||
]
|
||||
}
|
||||
###############################################################################
|
137
ipc/test/auxiliary/native/include/assist_test_service.h
Executable file
137
ipc/test/auxiliary/native/include/assist_test_service.h
Executable 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
|
77
ipc/test/auxiliary/native/include/foo_service.h
Executable file
77
ipc/test/auxiliary/native/include/foo_service.h
Executable 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
|
||||
|
76
ipc/test/auxiliary/native/include/ipc_test_helper.h
Executable file
76
ipc/test/auxiliary/native/include/ipc_test_helper.h
Executable 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
|
122
ipc/test/auxiliary/native/include/ohos_rpc_test_testhelper.h
Executable file
122
ipc/test/auxiliary/native/include/ohos_rpc_test_testhelper.h
Executable 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
|
54
ipc/test/auxiliary/native/include/test_service.h
Executable file
54
ipc/test/auxiliary/native/include/test_service.h
Executable 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
|
||||
|
48
ipc/test/auxiliary/native/include/test_service_client.h
Executable file
48
ipc/test/auxiliary/native/include/test_service_client.h
Executable 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
|
31
ipc/test/auxiliary/native/include/test_service_command.h
Executable file
31
ipc/test/auxiliary/native/include/test_service_command.h
Executable 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
|
122
ipc/test/auxiliary/native/include/test_service_skeleton.h
Executable file
122
ipc/test/auxiliary/native/include/test_service_skeleton.h
Executable 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
|
391
ipc/test/auxiliary/native/src/assist_test_service.cpp
Executable file
391
ipc/test/auxiliary/native/src/assist_test_service.cpp
Executable 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
|
129
ipc/test/auxiliary/native/src/foo_service.cpp
Executable file
129
ipc/test/auxiliary/native/src/foo_service.cpp
Executable 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
|
337
ipc/test/auxiliary/native/src/ipc_test_helper.cpp
Executable file
337
ipc/test/auxiliary/native/src/ipc_test_helper.cpp
Executable 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
|
101
ipc/test/auxiliary/native/src/main_client.cpp
Executable file
101
ipc/test/auxiliary/native/src/main_client.cpp
Executable 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;
|
||||
}
|
31
ipc/test/auxiliary/native/src/main_server.cpp
Executable file
31
ipc/test/auxiliary/native/src/main_server.cpp
Executable 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
Loading…
Reference in New Issue
Block a user