1 // Copyright (C) 2020 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "package_manager_remote.h"
16
17 #include <android-base/logging.h>
18 #include <android-base/properties.h>
19
20 #include <chrono>
21 #include <thread>
22
23 namespace iorap::binder {
24
25 const constexpr int64_t kTimeoutMs = 60 * 1000; // 1 min
26 const constexpr int64_t kIntervalMs = 1000; // 1 sec
27
Create()28 std::shared_ptr<PackageManagerRemote> PackageManagerRemote::Create() {
29 std::shared_ptr<PackageManagerRemote> package_manager =
30 std::make_shared<PackageManagerRemote>();
31 if (package_manager->ReconnectWithTimeout(kTimeoutMs)) {
32 return package_manager;
33 }
34 return nullptr;
35 }
36
GetPackageService()37 android::sp<IPackageManager> PackageManagerRemote::GetPackageService() {
38 android::sp<android::IBinder> binder = android::defaultServiceManager()->getService(
39 android::String16{"package_native"});
40 if (binder == nullptr) {
41 LOG(ERROR) << "Cannot get package manager service!";
42 return nullptr;
43 }
44
45 return android::interface_cast<IPackageManager>(binder);
46 }
47
GetPackageVersion(const std::string & package_name)48 std::optional<int64_t> PackageManagerRemote::GetPackageVersion(
49 const std::string& package_name) {
50 int64_t version_code;
51 android::binder::Status status = InvokeRemote(
52 [this, &version_code, &package_name]() {
53 return package_service_->getVersionCodeForPackage(
54 android::String16(package_name.c_str()), /*out*/&version_code);
55 });
56 if (status.isOk()) {
57 return version_code;
58 } else {
59 LOG(WARNING) << "Failed to get version: "
60 << status.toString8().c_str()
61 << " for " << package_name
62 << ". Retry to connect package manager service.";
63 return std::nullopt;
64 }
65 }
66
GetPackageVersionMap()67 std::optional<VersionMap> PackageManagerRemote::GetPackageVersionMap() {
68 VersionMap package_version_map;
69 std::optional<std::vector<std::string>> packages = GetAllPackages();
70 if (!packages) {
71 LOG(DEBUG) << "Failed to get all packages. The package manager may be down.";
72 return std::nullopt;
73 }
74 LOG(DEBUG) << "PackageManagerRemote::GetPackageVersionMap: "
75 << packages->size()
76 << " packages are found.";
77
78 for (const std::string& package : *packages) {
79 std::optional<int64_t> version = GetPackageVersion(package);
80 if (!version) {
81 LOG(DEBUG) << "Cannot get version for " << package
82 << "Package manager may be down";
83 return std::nullopt;
84 }
85 package_version_map[package] = *version;
86 }
87
88 return package_version_map;
89 }
90
GetAllPackages()91 std::optional<std::vector<std::string>> PackageManagerRemote::GetAllPackages() {
92 std::vector<std::string> packages;
93 android::binder::Status status = InvokeRemote(
94 [this, &packages]() {
95 return package_service_->getAllPackages(/*out*/&packages);
96 });
97
98 if (status.isOk()) {
99 return packages;
100 }
101
102 LOG(ERROR) << "Failed to get all packages: " << status.toString8().c_str();
103 return std::nullopt;
104
105 }
106
ReconnectWithTimeout(int64_t timeout_ms)107 bool PackageManagerRemote::ReconnectWithTimeout(int64_t timeout_ms) {
108 int64_t count = 0;
109 package_service_ = nullptr;
110 std::chrono::duration interval = std::chrono::milliseconds(1000);
111 std::chrono::duration timeout = std::chrono::milliseconds(timeout_ms);
112
113 while (package_service_ == nullptr) {
114 LOG(WARNING) << "Reconnect to package manager service: " << ++count << " times";
115 package_service_ = GetPackageService();
116 std::this_thread::sleep_for(interval);
117 if (count * interval >= timeout) {
118 LOG(ERROR) << "Fail to create version map in "
119 << timeout.count()
120 << " milliseconds."
121 << " Reason: Failed to connect to package manager service."
122 << " Is system_server down?";
123 return false;
124 }
125 }
126
127 return true;
128 }
129
130 template <typename T>
InvokeRemote(T && lambda)131 android::binder::Status PackageManagerRemote::InvokeRemote(T&& lambda) {
132 android::binder::Status status =
133 static_cast<android::binder::Status>(lambda());
134 if (status.isOk()) {
135 return status;
136 }
137
138 if (!ReconnectWithTimeout(kTimeoutMs)) {
139 return status;
140 }
141
142 return lambda();
143 }
144
RegisterPackageChangeObserver(android::sp<PackageChangeObserver> observer)145 void PackageManagerRemote::RegisterPackageChangeObserver(
146 android::sp<PackageChangeObserver> observer) {
147 LOG(DEBUG) << "Register package change observer.";
148 android::binder::Status status = InvokeRemote(
149 [this, &observer]() {
150 return package_service_->registerPackageChangeObserver(observer);
151 });
152
153 if (!status.isOk()) {
154 LOG(ERROR) << "Cannot register package change observer. Is system_server down?";
155 exit(1);
156 }
157 }
158
UnregisterPackageChangeObserver(android::sp<PackageChangeObserver> observer)159 void PackageManagerRemote::UnregisterPackageChangeObserver(
160 android::sp<PackageChangeObserver> observer) {
161 LOG(DEBUG) << "Unregister package change observer.";
162 android::binder::Status status = InvokeRemote(
163 [this, &observer]() {
164 return package_service_->unregisterPackageChangeObserver(observer);
165 });
166
167 if (!status.isOk()) {
168 LOG(WARNING) << "Cannot unregister package change observer.";
169 }
170 }
171
RegisterPackageManagerDeathRecipient(android::sp<PackageManagerDeathRecipient> death_recipient)172 void PackageManagerRemote::RegisterPackageManagerDeathRecipient(
173 android::sp<PackageManagerDeathRecipient> death_recipient) {
174 LOG(DEBUG) << "Register package manager death recipient.";
175 android::status_t status =
176 android::IInterface::asBinder(package_service_.get())->linkToDeath(death_recipient);
177
178 if (status == android::OK) {
179 return;
180 }
181
182 if (!ReconnectWithTimeout(kTimeoutMs) ||
183 android::OK != android::IInterface::asBinder(
184 package_service_.get())->linkToDeath(death_recipient)) {
185 LOG(ERROR) << "Failed to register package manager death recipient. Is system_server down?";
186 exit(1);
187 }
188 }
189
binderDied(const android::wp<android::IBinder> &)190 void PackageManagerDeathRecipient::binderDied(const android::wp<android::IBinder>& /* who */) {
191 LOG(DEBUG) << "PackageManagerDeathRecipient::binderDied try to re-register";
192 package_manager_->RegisterPackageChangeObserver(observer_);
193 package_manager_->
194 RegisterPackageManagerDeathRecipient(this);
195 }
196 } // namespace iorap::package_manager
197