• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "ADynamicInstrumentationManager"
18 #include <android-base/properties.h>
19 #include <android/dynamic_instrumentation_manager.h>
20 #include <android/os/instrumentation/BnOffsetCallback.h>
21 #include <android/os/instrumentation/ExecutableMethodFileOffsets.h>
22 #include <android/os/instrumentation/IDynamicInstrumentationManager.h>
23 #include <android/os/instrumentation/MethodDescriptor.h>
24 #include <android/os/instrumentation/TargetProcess.h>
25 #include <binder/Binder.h>
26 #include <binder/IServiceManager.h>
27 #include <utils/Log.h>
28 #include <utils/StrongPointer.h>
29 
30 #include <future>
31 #include <mutex>
32 #include <optional>
33 #include <string>
34 #include <vector>
35 
36 namespace android::dynamicinstrumentationmanager {
37 
38 using android::os::instrumentation::BnOffsetCallback;
39 using android::os::instrumentation::ExecutableMethodFileOffsets;
40 
41 // Global instance of IDynamicInstrumentationManager, service is obtained only on first use.
42 static std::mutex mLock;
43 static sp<os::instrumentation::IDynamicInstrumentationManager> mService;
44 
getService()45 sp<os::instrumentation::IDynamicInstrumentationManager> getService() {
46     std::lock_guard<std::mutex> scoped_lock(mLock);
47     if (mService == nullptr || !IInterface::asBinder(mService)->isBinderAlive()) {
48         sp<IBinder> binder =
49                 defaultServiceManager()->waitForService(String16("dynamic_instrumentation"));
50         mService = interface_cast<os::instrumentation::IDynamicInstrumentationManager>(binder);
51     }
52     return mService;
53 }
54 
55 } // namespace android::dynamicinstrumentationmanager
56 
57 using namespace android;
58 using namespace dynamicinstrumentationmanager;
59 
60 struct ADynamicInstrumentationManager_TargetProcess {
61     uid_t uid;
62     uid_t pid;
63     std::string processName;
64 
ADynamicInstrumentationManager_TargetProcessADynamicInstrumentationManager_TargetProcess65     ADynamicInstrumentationManager_TargetProcess(uid_t uid, pid_t pid, const char* processName)
66           : uid(uid), pid(pid), processName(processName) {}
67 };
68 
ADynamicInstrumentationManager_TargetProcess_create(uid_t uid,pid_t pid,const char * processName)69 ADynamicInstrumentationManager_TargetProcess* ADynamicInstrumentationManager_TargetProcess_create(
70         uid_t uid, pid_t pid, const char* processName) {
71     return new ADynamicInstrumentationManager_TargetProcess(uid, pid, processName);
72 }
73 
ADynamicInstrumentationManager_TargetProcess_destroy(const ADynamicInstrumentationManager_TargetProcess * instance)74 void ADynamicInstrumentationManager_TargetProcess_destroy(
75         const ADynamicInstrumentationManager_TargetProcess* instance) {
76     if (instance == nullptr) return;
77     delete instance;
78 }
79 
80 struct ADynamicInstrumentationManager_MethodDescriptor {
81     std::string fqcn;
82     std::string methodName;
83     std::vector<std::string> fqParameters;
84 
ADynamicInstrumentationManager_MethodDescriptorADynamicInstrumentationManager_MethodDescriptor85     ADynamicInstrumentationManager_MethodDescriptor(const char* fqcn, const char* methodName,
86                                                     const char* fullyQualifiedParameters[],
87                                                     size_t numParameters)
88           : fqcn(fqcn), methodName(methodName) {
89         std::vector<std::string> fqParameters;
90         fqParameters.reserve(numParameters);
91         std::copy_n(fullyQualifiedParameters, numParameters, std::back_inserter(fqParameters));
92         this->fqParameters = std::move(fqParameters);
93     }
94 };
95 
96 ADynamicInstrumentationManager_MethodDescriptor*
ADynamicInstrumentationManager_MethodDescriptor_create(const char * fullyQualifiedClassName,const char * methodName,const char * fullyQualifiedParameters[],size_t numParameters)97 ADynamicInstrumentationManager_MethodDescriptor_create(const char* fullyQualifiedClassName,
98                                                        const char* methodName,
99                                                        const char* fullyQualifiedParameters[],
100                                                        size_t numParameters) {
101     return new ADynamicInstrumentationManager_MethodDescriptor(fullyQualifiedClassName, methodName,
102                                                                fullyQualifiedParameters,
103                                                                numParameters);
104 }
105 
ADynamicInstrumentationManager_MethodDescriptor_destroy(const ADynamicInstrumentationManager_MethodDescriptor * instance)106 void ADynamicInstrumentationManager_MethodDescriptor_destroy(
107         const ADynamicInstrumentationManager_MethodDescriptor* instance) {
108     if (instance == nullptr) return;
109     delete instance;
110 }
111 
112 struct ADynamicInstrumentationManager_ExecutableMethodFileOffsets {
113     std::string containerPath;
114     uint64_t containerOffset;
115     uint64_t methodOffset;
116 };
117 
118 ADynamicInstrumentationManager_ExecutableMethodFileOffsets*
ADynamicInstrumentationManager_ExecutableMethodFileOffsets_create()119 ADynamicInstrumentationManager_ExecutableMethodFileOffsets_create() {
120     return new ADynamicInstrumentationManager_ExecutableMethodFileOffsets();
121 }
122 
ADynamicInstrumentationManager_ExecutableMethodFileOffsets_getContainerPath(const ADynamicInstrumentationManager_ExecutableMethodFileOffsets * instance)123 const char* ADynamicInstrumentationManager_ExecutableMethodFileOffsets_getContainerPath(
124         const ADynamicInstrumentationManager_ExecutableMethodFileOffsets* instance) {
125     return instance->containerPath.c_str();
126 }
127 
ADynamicInstrumentationManager_ExecutableMethodFileOffsets_getContainerOffset(const ADynamicInstrumentationManager_ExecutableMethodFileOffsets * instance)128 uint64_t ADynamicInstrumentationManager_ExecutableMethodFileOffsets_getContainerOffset(
129         const ADynamicInstrumentationManager_ExecutableMethodFileOffsets* instance) {
130     return instance->containerOffset;
131 }
132 
ADynamicInstrumentationManager_ExecutableMethodFileOffsets_getMethodOffset(const ADynamicInstrumentationManager_ExecutableMethodFileOffsets * instance)133 uint64_t ADynamicInstrumentationManager_ExecutableMethodFileOffsets_getMethodOffset(
134         const ADynamicInstrumentationManager_ExecutableMethodFileOffsets* instance) {
135     return instance->methodOffset;
136 }
137 
ADynamicInstrumentationManager_ExecutableMethodFileOffsets_destroy(const ADynamicInstrumentationManager_ExecutableMethodFileOffsets * instance)138 void ADynamicInstrumentationManager_ExecutableMethodFileOffsets_destroy(
139         const ADynamicInstrumentationManager_ExecutableMethodFileOffsets* instance) {
140     if (instance == nullptr) return;
141     delete instance;
142 }
143 
144 class ResultCallback : public BnOffsetCallback {
145 public:
onResult(const::std::optional<ExecutableMethodFileOffsets> & offsets)146     ::android::binder::Status onResult(
147             const ::std::optional<ExecutableMethodFileOffsets>& offsets) override {
148         promise_.set_value(offsets);
149         return android::binder::Status::ok();
150     }
151 
waitForResult()152     std::optional<ExecutableMethodFileOffsets> waitForResult() {
153         std::future<std::optional<ExecutableMethodFileOffsets>> futureResult =
154                 promise_.get_future();
155         auto futureStatus = futureResult.wait_for(
156                 std::chrono::seconds(1 * android::base::HwTimeoutMultiplier()));
157         if (futureStatus == std::future_status::ready) {
158             return futureResult.get();
159         } else {
160             return std::nullopt;
161         }
162     }
163 
164 private:
165     std::promise<std::optional<ExecutableMethodFileOffsets>> promise_;
166 };
167 
ADynamicInstrumentationManager_getExecutableMethodFileOffsets(const ADynamicInstrumentationManager_TargetProcess * targetProcess,const ADynamicInstrumentationManager_MethodDescriptor * methodDescriptor,const ADynamicInstrumentationManager_ExecutableMethodFileOffsets ** out)168 int32_t ADynamicInstrumentationManager_getExecutableMethodFileOffsets(
169         const ADynamicInstrumentationManager_TargetProcess* targetProcess,
170         const ADynamicInstrumentationManager_MethodDescriptor* methodDescriptor,
171         const ADynamicInstrumentationManager_ExecutableMethodFileOffsets** out) {
172     android::os::instrumentation::TargetProcess targetProcessParcel;
173     targetProcessParcel.uid = targetProcess->uid;
174     targetProcessParcel.pid = targetProcess->pid;
175     targetProcessParcel.processName = targetProcess->processName;
176 
177     android::os::instrumentation::MethodDescriptor methodDescriptorParcel;
178     methodDescriptorParcel.fullyQualifiedClassName = methodDescriptor->fqcn;
179     methodDescriptorParcel.methodName = methodDescriptor->methodName;
180     methodDescriptorParcel.fullyQualifiedParameters = methodDescriptor->fqParameters;
181 
182     sp<os::instrumentation::IDynamicInstrumentationManager> service = getService();
183     if (service == nullptr) {
184         return INVALID_OPERATION;
185     }
186 
187     android::sp<ResultCallback> resultCallback = android::sp<ResultCallback>::make();
188     binder_status_t result =
189             service->getExecutableMethodFileOffsets(targetProcessParcel, methodDescriptorParcel,
190                                                     resultCallback)
191                     .exceptionCode();
192     if (result != OK) {
193         return result;
194     }
195     std::optional<ExecutableMethodFileOffsets> offsets = resultCallback->waitForResult();
196     if (offsets != std::nullopt) {
197         auto* value = new ADynamicInstrumentationManager_ExecutableMethodFileOffsets();
198         value->containerPath = offsets->containerPath;
199         value->containerOffset = offsets->containerOffset;
200         value->methodOffset = offsets->methodOffset;
201         *out = value;
202     } else {
203         *out = nullptr;
204     }
205 
206     return result;
207 }
208