• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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