blob: c49df0c5c902c671a8669c718e5a61d0a8da11c7 [file] [log] [blame]
Martijn Coenene6f6b8f2018-08-17 09:48:33 +02001/*
2 * Copyright (C) 2018 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
Andreas Gampe66b5dcd2018-10-17 19:20:00 -070017#include "apexservice.h"
18
Dario Freni8e88b682018-10-25 13:06:21 +010019#include <dirent.h>
Dario Freni6ed63322018-10-03 11:37:08 +010020#include <stdio.h>
Dario Freni8e88b682018-10-25 13:06:21 +010021#include <stdlib.h>
Dario Freni6ed63322018-10-03 11:37:08 +010022
Andreas Gampe66b5dcd2018-10-17 19:20:00 -070023#include <android-base/file.h>
24#include <android-base/logging.h>
Andreas Gampe8eb187a2018-10-19 21:18:03 -070025#include <android-base/properties.h>
Andreas Gampe66b5dcd2018-10-17 19:20:00 -070026#include <android-base/stringprintf.h>
Dario Freni8e88b682018-10-25 13:06:21 +010027#include <android-base/strings.h>
Andreas Gampe602ef782018-11-12 16:51:31 -080028#include <binder/IPCThreadState.h>
Andreas Gampe66b5dcd2018-10-17 19:20:00 -070029#include <binder/IResultReceiver.h>
Andreas Gampe602ef782018-11-12 16:51:31 -080030#include <binder/IServiceManager.h>
31#include <binder/ProcessState.h>
Andreas Gampe17739142019-01-09 16:00:26 -080032#include <binder/Status.h>
Andreas Gampe602ef782018-11-12 16:51:31 -080033#include <utils/String16.h>
Dario Freni6ed63322018-10-03 11:37:08 +010034
Andreas Gampeb99abdd2018-10-19 19:59:17 -070035#include "apexd.h"
Dario Frenid2437642019-01-11 14:35:23 +000036#include "apexd_session.h"
Andreas Gampec9a01e42018-10-22 12:50:19 -070037#include "status.h"
Jiyong Park9b800482018-12-03 22:16:40 +090038#include "string_log.h"
Dario Freni6ed63322018-10-03 11:37:08 +010039
Andreas Gampe602ef782018-11-12 16:51:31 -080040#include <android/apex/BnApexService.h>
41
Martijn Coenene6f6b8f2018-08-17 09:48:33 +020042namespace android {
43namespace apex {
Andreas Gampe602ef782018-11-12 16:51:31 -080044namespace binder {
45namespace {
Martijn Coenene6f6b8f2018-08-17 09:48:33 +020046
Andreas Gampec9a01e42018-10-22 12:50:19 -070047using BinderStatus = ::android::binder::Status;
48
Andreas Gampe602ef782018-11-12 16:51:31 -080049class ApexService : public BnApexService {
50 public:
51 using BinderStatus = ::android::binder::Status;
Martijn Coenen610909b2019-01-18 13:49:38 +010052 using SessionState = ::apex::proto::SessionState;
Andreas Gampe602ef782018-11-12 16:51:31 -080053
54 ApexService(){};
55
56 BinderStatus stagePackage(const std::string& packageTmpPath,
57 bool* aidl_return) override;
Andreas Gampea00c5452018-12-10 13:38:33 -080058 BinderStatus stagePackages(const std::vector<std::string>& paths,
59 bool* aidl_return) override;
Nikita Ioffe496a4a42019-03-05 16:32:51 +000060 BinderStatus unstagePackages(const std::vector<std::string>& paths) override;
Dario Freniab5b6c42019-01-15 11:53:57 +000061 BinderStatus submitStagedSession(int session_id,
62 const std::vector<int>& child_session_ids,
63 ApexInfoList* apex_info_list,
Dario Frenia6ad33e2019-01-09 14:35:43 +000064 bool* aidl_return) override;
Dario Frenif36c9622019-01-25 11:30:00 +000065 BinderStatus markStagedSessionReady(int session_id,
66 bool* aidl_return) override;
Nikita Ioffea0c0ccb2019-02-12 22:00:41 +000067 BinderStatus markStagedSessionSuccessful(int session_id) override;
Martijn Coenen4d206422019-01-31 15:58:55 +010068 BinderStatus getSessions(std::vector<ApexSessionInfo>* aidl_return) override;
Dario Frenid2437642019-01-11 14:35:23 +000069 BinderStatus getStagedSessionInfo(
70 int session_id, ApexSessionInfo* apex_session_info) override;
Andreas Gampe602ef782018-11-12 16:51:31 -080071 BinderStatus activatePackage(const std::string& packagePath) override;
72 BinderStatus deactivatePackage(const std::string& packagePath) override;
Dario Frenidded6c12018-11-19 16:02:26 +000073 BinderStatus getActivePackages(std::vector<ApexInfo>* aidl_return) override;
Narayan Kamath5ea57782019-01-03 18:17:05 +000074 BinderStatus getActivePackage(const std::string& packageName,
75 ApexInfo* aidl_return) override;
Gavin Corkery729905c2019-03-21 11:52:06 +000076 BinderStatus getAllPackages(std::vector<ApexInfo>* aidl_return) override;
Andreas Gampe17739142019-01-09 16:00:26 -080077 BinderStatus preinstallPackages(
78 const std::vector<std::string>& paths) override;
Andreas Gampef4c7e7c2019-01-14 12:33:34 -080079 BinderStatus postinstallPackages(
80 const std::vector<std::string>& paths) override;
Nikita Ioffe1c079c12019-02-07 17:41:27 +000081 BinderStatus abortActiveSession() override;
Andreas Gampe6e13ff82019-04-01 15:23:50 -070082 BinderStatus rollbackActiveSession() override;
83 BinderStatus resumeRollbackIfNeeded() override;
Andreas Gampe17739142019-01-09 16:00:26 -080084
Abhijeet Kaur54695d32019-01-15 13:07:20 +000085 status_t dump(int fd, const Vector<String16>& args) override;
Andreas Gampe602ef782018-11-12 16:51:31 -080086
87 // Override onTransact so we can handle shellCommand.
88 status_t onTransact(uint32_t _aidl_code, const Parcel& _aidl_data,
Nikita Ioffe6bea4e52019-02-10 22:46:05 +000089 Parcel* _aidl_reply, uint32_t _aidl_flags) override;
Andreas Gampe602ef782018-11-12 16:51:31 -080090
91 status_t shellCommand(int in, int out, int err, const Vector<String16>& args);
92};
Andreas Gampe8eb187a2018-10-19 21:18:03 -070093
Andreas Gamped6c3df82018-11-08 15:34:06 -080094BinderStatus CheckDebuggable(const std::string& name) {
Andreas Gampe8eb187a2018-10-19 21:18:03 -070095 if (!::android::base::GetBoolProperty("ro.debuggable", false)) {
Andreas Gamped6c3df82018-11-08 15:34:06 -080096 std::string tmp = name + " unavailable";
97 return BinderStatus::fromExceptionCode(BinderStatus::EX_SECURITY,
98 String8(tmp.c_str()));
Andreas Gampe8eb187a2018-10-19 21:18:03 -070099 }
100 return BinderStatus::ok();
101}
102
Dario Freni16cbb562018-11-07 12:09:15 +0000103BinderStatus ApexService::stagePackage(const std::string& packageTmpPath,
104 bool* aidl_return) {
Nikita Ioffe69309882019-02-13 01:31:15 +0000105 BinderStatus debugCheck = CheckDebuggable("stagePackage");
106 if (!debugCheck.isOk()) {
107 return debugCheck;
108 }
Andreas Gampea00c5452018-12-10 13:38:33 -0800109 std::vector<std::string> tmp;
110 tmp.push_back(packageTmpPath);
111 return stagePackages(tmp, aidl_return);
112}
113
114BinderStatus ApexService::stagePackages(const std::vector<std::string>& paths,
115 bool* aidl_return) {
Nikita Ioffe69309882019-02-13 01:31:15 +0000116 BinderStatus debugCheck = CheckDebuggable("stagePackages");
117 if (!debugCheck.isOk()) {
118 return debugCheck;
119 }
Andreas Gampea00c5452018-12-10 13:38:33 -0800120 LOG(DEBUG) << "stagePackages() received by ApexService, paths "
121 << android::base::Join(paths, ',');
Dario Freni6ed63322018-10-03 11:37:08 +0100122
Andreas Gampeb99abdd2018-10-19 19:59:17 -0700123 *aidl_return = false;
Andreas Gampea00c5452018-12-10 13:38:33 -0800124 Status res = ::android::apex::stagePackages(paths);
Dario Freni6ed63322018-10-03 11:37:08 +0100125
Andreas Gampeb99abdd2018-10-19 19:59:17 -0700126 if (res.Ok()) {
Andreas Gampec9a01e42018-10-22 12:50:19 -0700127 *aidl_return = true;
128 return BinderStatus::ok();
Dario Freni6ed63322018-10-03 11:37:08 +0100129 }
Dario Freni6ed63322018-10-03 11:37:08 +0100130
Andreas Gampeb99abdd2018-10-19 19:59:17 -0700131 // TODO: Get correct binder error status.
Andreas Gampea00c5452018-12-10 13:38:33 -0800132 LOG(ERROR) << "Failed to stage " << android::base::Join(paths, ',') << ": "
Dario Freni8e88b682018-10-25 13:06:21 +0100133 << res.ErrorMessage();
Andreas Gampec9a01e42018-10-22 12:50:19 -0700134 return BinderStatus::fromExceptionCode(BinderStatus::EX_ILLEGAL_ARGUMENT,
135 String8(res.ErrorMessage().c_str()));
Martijn Coenene6f6b8f2018-08-17 09:48:33 +0200136}
137
Nikita Ioffe496a4a42019-03-05 16:32:51 +0000138BinderStatus ApexService::unstagePackages(
139 const std::vector<std::string>& paths) {
140 Status res = ::android::apex::unstagePackages(paths);
141 if (res.Ok()) {
142 return BinderStatus::ok();
143 }
144
145 // TODO: Get correct binder error status.
146 LOG(ERROR) << "Failed to unstage " << android::base::Join(paths, ',') << ": "
147 << res.ErrorMessage();
148 return BinderStatus::fromExceptionCode(BinderStatus::EX_ILLEGAL_ARGUMENT,
149 String8(res.ErrorMessage().c_str()));
150}
151
Dario Freniab5b6c42019-01-15 11:53:57 +0000152BinderStatus ApexService::submitStagedSession(
153 int session_id, const std::vector<int>& child_session_ids,
154 ApexInfoList* apex_info_list, bool* aidl_return) {
Dario Freni56231b42019-01-04 11:58:17 +0000155 LOG(DEBUG) << "submitStagedSession() received by ApexService, session id "
156 << session_id;
157
158 StatusOr<std::vector<ApexFile>> packages =
Dario Freniab5b6c42019-01-15 11:53:57 +0000159 ::android::apex::submitStagedSession(session_id, child_session_ids);
Dario Freni56231b42019-01-04 11:58:17 +0000160 if (!packages.Ok()) {
Dario Frenia6ad33e2019-01-09 14:35:43 +0000161 *aidl_return = false;
Dario Freni56231b42019-01-04 11:58:17 +0000162 LOG(ERROR) << "Failed to submit session id " << session_id << ": "
163 << packages.ErrorMessage();
Dario Frenia6ad33e2019-01-09 14:35:43 +0000164 return BinderStatus::ok();
Dario Freni56231b42019-01-04 11:58:17 +0000165 }
166
167 for (const auto& package : *packages) {
168 ApexInfo out;
Abhijeet Kaur216e36c2019-01-04 10:15:01 +0000169 out.packageName = package.GetManifest().name();
Dario Freni56231b42019-01-04 11:58:17 +0000170 out.packagePath = package.GetPath();
Abhijeet Kaur216e36c2019-01-04 10:15:01 +0000171 out.versionCode = package.GetManifest().version();
Dario Frenia6ad33e2019-01-09 14:35:43 +0000172 apex_info_list->apexInfos.push_back(out);
Dario Freni56231b42019-01-04 11:58:17 +0000173 }
Dario Frenia6ad33e2019-01-09 14:35:43 +0000174 *aidl_return = true;
Dario Freni56231b42019-01-04 11:58:17 +0000175 return BinderStatus::ok();
176}
177
Dario Frenif36c9622019-01-25 11:30:00 +0000178BinderStatus ApexService::markStagedSessionReady(int session_id,
179 bool* aidl_return) {
180 LOG(DEBUG) << "markStagedSessionReady() received by ApexService, session id "
181 << session_id;
182 Status success = ::android::apex::markStagedSessionReady(session_id);
183 if (!success.Ok()) {
184 *aidl_return = false;
185 LOG(ERROR) << "Failed to mark session id " << session_id
186 << " as ready: " << success.ErrorMessage();
187 return BinderStatus::ok();
188 }
189 *aidl_return = true;
190 return BinderStatus::ok();
191}
192
Nikita Ioffea0c0ccb2019-02-12 22:00:41 +0000193BinderStatus ApexService::markStagedSessionSuccessful(int session_id) {
194 LOG(DEBUG)
195 << "markStagedSessionSuccessful() received by ApexService, session id "
196 << session_id;
197 Status ret = ::android::apex::markStagedSessionSuccessful(session_id);
198 if (!ret.Ok()) {
199 LOG(ERROR) << "Failed to mark session " << session_id
200 << " as SUCCESS: " << ret.ErrorMessage();
201 return BinderStatus::fromExceptionCode(BinderStatus::EX_ILLEGAL_ARGUMENT,
202 String8(ret.ErrorMessage().c_str()));
203 }
204 return BinderStatus::ok();
205}
206
Nikita Ioffe9ae986a2019-02-18 22:39:27 +0000207static void ClearSessionInfo(ApexSessionInfo* session_info) {
208 session_info->sessionId = -1;
Martijn Coenen4d206422019-01-31 15:58:55 +0100209 session_info->isUnknown = false;
210 session_info->isVerified = false;
211 session_info->isStaged = false;
212 session_info->isActivated = false;
Nikita Ioffe9ae986a2019-02-18 22:39:27 +0000213 session_info->isRollbackInProgress = false;
Martijn Coenen4d206422019-01-31 15:58:55 +0100214 session_info->isActivationFailed = false;
Nikita Ioffea0c0ccb2019-02-12 22:00:41 +0000215 session_info->isSuccess = false;
Nikita Ioffe9ae986a2019-02-18 22:39:27 +0000216 session_info->isRolledBack = false;
Nikita Ioffe6f87d542019-04-09 13:09:26 +0100217 session_info->isRollbackFailed = false;
Nikita Ioffe9ae986a2019-02-18 22:39:27 +0000218}
219
220void convertToApexSessionInfo(const ApexSession& session,
221 ApexSessionInfo* session_info) {
222 using SessionState = ::apex::proto::SessionState;
223
224 ClearSessionInfo(session_info);
225 session_info->sessionId = session.GetId();
Martijn Coenen4d206422019-01-31 15:58:55 +0100226
227 switch (session.GetState()) {
228 case SessionState::VERIFIED:
229 session_info->isVerified = true;
230 break;
231 case SessionState::STAGED:
232 session_info->isStaged = true;
233 break;
234 case SessionState::ACTIVATED:
235 session_info->isActivated = true;
236 break;
Martijn Coenen4d206422019-01-31 15:58:55 +0100237 case SessionState::ACTIVATION_FAILED:
238 session_info->isActivationFailed = true;
239 break;
Nikita Ioffea0c0ccb2019-02-12 22:00:41 +0000240 case SessionState::SUCCESS:
241 session_info->isSuccess = true;
242 break;
Nikita Ioffe9ae986a2019-02-18 22:39:27 +0000243 case SessionState::ROLLBACK_IN_PROGRESS:
244 session_info->isRollbackInProgress = true;
245 break;
246 case SessionState::ROLLED_BACK:
247 session_info->isRolledBack = true;
248 break;
Nikita Ioffe6f87d542019-04-09 13:09:26 +0100249 case SessionState::ROLLBACK_FAILED:
250 session_info->isRollbackFailed = true;
251 break;
Martijn Coenen4d206422019-01-31 15:58:55 +0100252 case SessionState::UNKNOWN:
253 default:
254 session_info->isUnknown = true;
255 break;
256 }
257}
258
Gavin Corkery729905c2019-03-21 11:52:06 +0000259static ApexInfo getApexInfo(const ApexFile& package) {
260 ApexInfo out;
261 out.packageName = package.GetManifest().name();
262 out.packagePath = package.GetPath();
263 out.versionCode = package.GetManifest().version();
Gavin Corkery43bd4b72019-04-30 10:40:12 +0100264 out.versionName = package.GetManifest().versionname();
Gavin Corkery729905c2019-03-21 11:52:06 +0000265 return out;
266}
267
268static std::string toString(const ApexInfo& package) {
269 std::string msg = StringLog()
270 << "Package: " << package.packageName
271 << " Version: " << package.versionCode
Gavin Corkery43bd4b72019-04-30 10:40:12 +0100272 << " VersionName: " << package.versionName
Gavin Corkery729905c2019-03-21 11:52:06 +0000273 << " Path: " << package.packagePath
274 << " IsActive: " << std::boolalpha << package.isActive
275 << " IsFactory: " << std::boolalpha << package.isFactory
276 << std::endl;
277 return msg;
278}
279
280static bool contains(const std::vector<ApexFile>& list,
281 const ApexFile& apexFile) {
282 return std::find_if(list.begin(), list.end(),
283 [&apexFile](const ApexFile& listFile) {
Nikita Ioffeff34b182019-09-06 12:51:58 +0100284 return apexFile.GetPath() == listFile.GetPath();
Gavin Corkery729905c2019-03-21 11:52:06 +0000285 }) != list.end();
286}
287
Martijn Coenen4d206422019-01-31 15:58:55 +0100288BinderStatus ApexService::getSessions(
289 std::vector<ApexSessionInfo>* aidl_return) {
290 auto sessions = ApexSession::GetSessions();
291 for (const auto& session : sessions) {
292 ApexSessionInfo sessionInfo;
293 convertToApexSessionInfo(session, &sessionInfo);
294 aidl_return->push_back(sessionInfo);
295 }
296
297 return BinderStatus::ok();
298}
299
Dario Frenid2437642019-01-11 14:35:23 +0000300BinderStatus ApexService::getStagedSessionInfo(
301 int session_id, ApexSessionInfo* apex_session_info) {
302 LOG(DEBUG) << "getStagedSessionInfo() received by ApexService, session id "
303 << session_id;
Martijn Coenen610909b2019-01-18 13:49:38 +0100304 auto session = ApexSession::GetSession(session_id);
305 if (!session.Ok()) {
Dario Frenid2437642019-01-11 14:35:23 +0000306 // Unknown session.
Nikita Ioffe9ae986a2019-02-18 22:39:27 +0000307 ClearSessionInfo(apex_session_info);
Martijn Coenen4d206422019-01-31 15:58:55 +0100308 apex_session_info->isUnknown = true;
Dario Frenid2437642019-01-11 14:35:23 +0000309 return BinderStatus::ok();
310 }
Martijn Coenen4d206422019-01-31 15:58:55 +0100311
312 convertToApexSessionInfo(*session, apex_session_info);
Dario Frenid2437642019-01-11 14:35:23 +0000313
314 return BinderStatus::ok();
315}
316
Dario Freniaf275042018-11-06 16:50:04 +0000317BinderStatus ApexService::activatePackage(const std::string& packagePath) {
Andreas Gamped6c3df82018-11-08 15:34:06 -0800318 BinderStatus debugCheck = CheckDebuggable("activatePackage");
Andreas Gampe8eb187a2018-10-19 21:18:03 -0700319 if (!debugCheck.isOk()) {
320 return debugCheck;
321 }
322
Dario Freniaf275042018-11-06 16:50:04 +0000323 LOG(DEBUG) << "activatePackage() received by ApexService, path "
324 << packagePath;
Andreas Gampe8eb187a2018-10-19 21:18:03 -0700325
Dario Freniaf275042018-11-06 16:50:04 +0000326 Status res = ::android::apex::activatePackage(packagePath);
Andreas Gampe8eb187a2018-10-19 21:18:03 -0700327
328 if (res.Ok()) {
329 return BinderStatus::ok();
330 }
331
332 // TODO: Get correct binder error status.
Dario Freniaf275042018-11-06 16:50:04 +0000333 LOG(ERROR) << "Failed to activate " << packagePath << ": "
334 << res.ErrorMessage();
Andreas Gampe8eb187a2018-10-19 21:18:03 -0700335 return BinderStatus::fromExceptionCode(BinderStatus::EX_ILLEGAL_ARGUMENT,
336 String8(res.ErrorMessage().c_str()));
337}
338
Andreas Gamped6c3df82018-11-08 15:34:06 -0800339BinderStatus ApexService::deactivatePackage(const std::string& packagePath) {
340 BinderStatus debugCheck = CheckDebuggable("deactivatePackage");
341 if (!debugCheck.isOk()) {
342 return debugCheck;
343 }
344
345 LOG(DEBUG) << "deactivatePackage() received by ApexService, path "
346 << packagePath;
347
348 Status res = ::android::apex::deactivatePackage(packagePath);
349
350 if (res.Ok()) {
351 return BinderStatus::ok();
352 }
353
354 // TODO: Get correct binder error status.
355 LOG(ERROR) << "Failed to deactivate " << packagePath << ": "
356 << res.ErrorMessage();
357 return BinderStatus::fromExceptionCode(BinderStatus::EX_ILLEGAL_ARGUMENT,
358 String8(res.ErrorMessage().c_str()));
359}
360
Dario Freni8e88b682018-10-25 13:06:21 +0100361BinderStatus ApexService::getActivePackages(
Dario Frenidded6c12018-11-19 16:02:26 +0000362 std::vector<ApexInfo>* aidl_return) {
Narayan Kamath5ea57782019-01-03 18:17:05 +0000363 auto packages = ::android::apex::getActivePackages();
364 for (const auto& package : packages) {
Gavin Corkery729905c2019-03-21 11:52:06 +0000365 ApexInfo apexInfo = getApexInfo(package);
366 apexInfo.isActive = true;
367 apexInfo.isFactory =
368 ::android::apex::isPathForBuiltinApexes(package.GetPath());
369 aidl_return->push_back(std::move(apexInfo));
Narayan Kamath5ea57782019-01-03 18:17:05 +0000370 }
371
372 return BinderStatus::ok();
373}
374
375BinderStatus ApexService::getActivePackage(const std::string& packageName,
376 ApexInfo* aidl_return) {
377 StatusOr<ApexFile> apex = ::android::apex::getActivePackage(packageName);
378 if (apex.Ok()) {
Abhijeet Kaur216e36c2019-01-04 10:15:01 +0000379 aidl_return->packageName = apex->GetManifest().name();
Narayan Kamath5ea57782019-01-03 18:17:05 +0000380 aidl_return->packagePath = apex->GetPath();
Abhijeet Kaur216e36c2019-01-04 10:15:01 +0000381 aidl_return->versionCode = apex->GetManifest().version();
Gavin Corkery43bd4b72019-04-30 10:40:12 +0100382 aidl_return->versionName = apex->GetManifest().versionname();
Gavin Corkery729905c2019-03-21 11:52:06 +0000383 aidl_return->isActive = true;
384 aidl_return->isFactory =
385 ::android::apex::isPathForBuiltinApexes(apex->GetPath());
Dario Freni8e88b682018-10-25 13:06:21 +0100386 }
Andreas Gampe0fa59af2018-11-16 11:12:11 -0800387
Dario Freni8e88b682018-10-25 13:06:21 +0100388 return BinderStatus::ok();
389}
390
Gavin Corkery729905c2019-03-21 11:52:06 +0000391BinderStatus ApexService::getAllPackages(std::vector<ApexInfo>* aidl_return) {
392 auto activePackages = ::android::apex::getActivePackages();
393 auto factoryPackages = ::android::apex::getFactoryPackages();
394 for (const ApexFile& factoryFile : factoryPackages) {
395 ApexInfo apexInfo = getApexInfo(factoryFile);
396 apexInfo.isFactory = true;
397 if (contains(activePackages, factoryFile)) {
398 apexInfo.isActive = true;
399 } else {
400 apexInfo.isActive = false;
401 }
402 aidl_return->push_back(std::move(apexInfo));
403 }
404
405 for (const ApexFile& activeFile : activePackages) {
406 if (!contains(factoryPackages, activeFile)) {
407 ApexInfo apexInfo = getApexInfo(activeFile);
408 apexInfo.isFactory = false;
409 apexInfo.isActive = true;
410 aidl_return->push_back(std::move(apexInfo));
411 }
412 }
413 return BinderStatus::ok();
414}
415
Andreas Gampe17739142019-01-09 16:00:26 -0800416BinderStatus ApexService::preinstallPackages(
417 const std::vector<std::string>& paths) {
418 BinderStatus debugCheck = CheckDebuggable("preinstallPackages");
419 if (!debugCheck.isOk()) {
420 return debugCheck;
421 }
422
423 Status res = ::android::apex::preinstallPackages(paths);
424 if (res.Ok()) {
425 return BinderStatus::ok();
426 }
427
428 // TODO: Get correct binder error status.
429 LOG(ERROR) << "Failed to preinstall packages "
430 << android::base::Join(paths, ',') << ": " << res.ErrorMessage();
431 return BinderStatus::fromExceptionCode(BinderStatus::EX_ILLEGAL_ARGUMENT,
432 String8(res.ErrorMessage().c_str()));
433}
434
Andreas Gampef4c7e7c2019-01-14 12:33:34 -0800435BinderStatus ApexService::postinstallPackages(
436 const std::vector<std::string>& paths) {
437 BinderStatus debugCheck = CheckDebuggable("postinstallPackages");
438 if (!debugCheck.isOk()) {
439 return debugCheck;
440 }
441
442 Status res = ::android::apex::postinstallPackages(paths);
443 if (res.Ok()) {
444 return BinderStatus::ok();
445 }
446
447 // TODO: Get correct binder error status.
448 LOG(ERROR) << "Failed to postinstall packages "
449 << android::base::Join(paths, ',') << ": " << res.ErrorMessage();
450 return BinderStatus::fromExceptionCode(BinderStatus::EX_ILLEGAL_ARGUMENT,
451 String8(res.ErrorMessage().c_str()));
452}
453
Nikita Ioffe1c079c12019-02-07 17:41:27 +0000454BinderStatus ApexService::abortActiveSession() {
Nikita Ioffe463d4e82019-02-10 18:46:20 +0000455 LOG(DEBUG) << "abortActiveSession() received by ApexService.";
456 Status res = ::android::apex::abortActiveSession();
457 if (!res.Ok()) {
458 return BinderStatus::fromExceptionCode(BinderStatus::EX_ILLEGAL_ARGUMENT,
459 String8(res.ErrorMessage().c_str()));
460 }
Nikita Ioffe1c079c12019-02-07 17:41:27 +0000461 return BinderStatus::ok();
462}
463
Andreas Gampe6e13ff82019-04-01 15:23:50 -0700464BinderStatus ApexService::rollbackActiveSession() {
465 BinderStatus debugCheck = CheckDebuggable("rollbackActiveSession");
466 if (!debugCheck.isOk()) {
467 return debugCheck;
468 }
469
470 LOG(DEBUG) << "rollbackActiveSession() received by ApexService.";
471 Status res = ::android::apex::rollbackActiveSession();
472 if (!res.Ok()) {
473 return BinderStatus::fromExceptionCode(BinderStatus::EX_ILLEGAL_ARGUMENT,
474 String8(res.ErrorMessage().c_str()));
475 }
476 return BinderStatus::ok();
477}
478
479BinderStatus ApexService::resumeRollbackIfNeeded() {
480 BinderStatus debugCheck = CheckDebuggable("resumeRollbackIfNeeded");
481 if (!debugCheck.isOk()) {
482 return debugCheck;
483 }
484
485 LOG(DEBUG) << "resumeRollbackIfNeeded() received by ApexService.";
486 Status res = ::android::apex::resumeRollbackIfNeeded();
487 if (!res.Ok()) {
488 return BinderStatus::fromExceptionCode(BinderStatus::EX_ILLEGAL_ARGUMENT,
489 String8(res.ErrorMessage().c_str()));
490 }
491 return BinderStatus::ok();
492}
493
Dario Freni8e88b682018-10-25 13:06:21 +0100494status_t ApexService::onTransact(uint32_t _aidl_code, const Parcel& _aidl_data,
495 Parcel* _aidl_reply, uint32_t _aidl_flags) {
Andreas Gampe66b5dcd2018-10-17 19:20:00 -0700496 switch (_aidl_code) {
497 case IBinder::SHELL_COMMAND_TRANSACTION: {
498 int in = _aidl_data.readFileDescriptor();
499 int out = _aidl_data.readFileDescriptor();
500 int err = _aidl_data.readFileDescriptor();
501 int argc = _aidl_data.readInt32();
502 Vector<String16> args;
503 for (int i = 0; i < argc && _aidl_data.dataAvail() > 0; i++) {
504 args.add(_aidl_data.readString16());
505 }
506 sp<IBinder> unusedCallback;
507 sp<IResultReceiver> resultReceiver;
508 status_t status;
509 if ((status = _aidl_data.readNullableStrongBinder(&unusedCallback)) != OK)
510 return status;
511 if ((status = _aidl_data.readNullableStrongBinder(&resultReceiver)) != OK)
512 return status;
513 status = shellCommand(in, out, err, args);
514 if (resultReceiver != nullptr) {
515 resultReceiver->send(status);
516 }
517 return OK;
518 }
519 }
Dario Freni8e88b682018-10-25 13:06:21 +0100520 return BnApexService::onTransact(_aidl_code, _aidl_data, _aidl_reply,
521 _aidl_flags);
Andreas Gampe66b5dcd2018-10-17 19:20:00 -0700522}
Abhijeet Kaur54695d32019-01-15 13:07:20 +0000523status_t ApexService::dump(int fd, const Vector<String16>& args) {
Abhijeet Kaur54695d32019-01-15 13:07:20 +0000524 std::vector<ApexInfo> list;
525 BinderStatus status = getActivePackages(&list);
Martijn Coenena418d312019-01-30 12:03:38 +0100526 dprintf(fd, "ACTIVE PACKAGES:\n");
527 if (!status.isOk()) {
528 std::string msg = StringLog() << "Failed to retrieve packages: "
529 << status.toString8().string() << std::endl;
530 dprintf(fd, "%s", msg.c_str());
531 return BAD_VALUE;
532 } else {
Abhijeet Kaur54695d32019-01-15 13:07:20 +0000533 for (const auto& item : list) {
Gavin Corkery729905c2019-03-21 11:52:06 +0000534 std::string msg = toString(item);
Abhijeet Kaur54695d32019-01-15 13:07:20 +0000535 dprintf(fd, "%s", msg.c_str());
536 }
Abhijeet Kaur54695d32019-01-15 13:07:20 +0000537 }
Martijn Coenena418d312019-01-30 12:03:38 +0100538
539 dprintf(fd, "SESSIONS:\n");
540 std::vector<ApexSession> sessions = ApexSession::GetSessions();
541
542 for (const auto& session : sessions) {
543 std::string child_ids_str = "";
544 auto child_ids = session.GetChildSessionIds();
545 if (child_ids.size() > 0) {
546 child_ids_str = "Child IDs:";
547 for (auto childSessionId : session.GetChildSessionIds()) {
548 child_ids_str += " " + std::to_string(childSessionId);
549 }
550 }
551 std::string msg =
552 StringLog() << "Session ID: " << session.GetId() << child_ids_str
553 << " State: " << SessionState_State_Name(session.GetState())
554 << std::endl;
555 dprintf(fd, "%s", msg.c_str());
556 }
557
558 return OK;
Abhijeet Kaur54695d32019-01-15 13:07:20 +0000559}
Andreas Gampe66b5dcd2018-10-17 19:20:00 -0700560
Dario Freni8e88b682018-10-25 13:06:21 +0100561status_t ApexService::shellCommand(int in, int out, int err,
562 const Vector<String16>& args) {
Andreas Gampe66b5dcd2018-10-17 19:20:00 -0700563 if (in == BAD_TYPE || out == BAD_TYPE || err == BAD_TYPE) {
564 return BAD_VALUE;
565 }
Andreas Gampee3864802018-12-19 14:12:59 -0800566 auto print_help = [](int fd, const char* prefix = nullptr) {
567 StringLog log;
568 if (prefix != nullptr) {
569 log << prefix << std::endl;
570 }
571 log << "ApexService:" << std::endl
572 << " help - display this help" << std::endl
573 << " stagePackage [packagePath] - stage package from the given path"
574 << std::endl
Dario Freni56231b42019-01-04 11:58:17 +0000575 << " stagePackages [packagePath1] ([packagePath2]...) - stage "
576 "multiple packages from the given path"
577 << std::endl
578 << " getActivePackage [packageName] - return info for active package "
579 "with given name, if present"
580 << std::endl
Gavin Corkery729905c2019-03-21 11:52:06 +0000581 << " getAllPackages - return the list of all packages" << std::endl
Andreas Gampee3864802018-12-19 14:12:59 -0800582 << " getActivePackages - return the list of active packages"
583 << std::endl
584 << " activatePackage [packagePath] - activate package from the "
585 "given path"
586 << std::endl
587 << " deactivatePackage [packagePath] - deactivate package from the "
588 "given path"
Dario Freni56231b42019-01-04 11:58:17 +0000589 << std::endl
Andreas Gampe1a48b1b2019-02-05 16:12:25 -0800590 << " preinstallPackages [packagePath1] ([packagePath2]...) - run "
591 "pre-install hooks of the given packages"
592 << std::endl
593 << " postinstallPackages [packagePath1] ([packagePath2]...) - run "
594 "post-install hooks of the given packages"
595 << std::endl
Dario Frenid2437642019-01-11 14:35:23 +0000596 << " getStagedSessionInfo [sessionId] - displays information about a "
597 "given session previously submitted"
Dario Freni56231b42019-01-04 11:58:17 +0000598 << " submitStagedSession [sessionId] - attempts to submit the "
599 "installer session with given id"
Andreas Gampee3864802018-12-19 14:12:59 -0800600 << std::endl;
601 dprintf(fd, "%s", log.operator std::string().c_str());
Andreas Gampe66b5dcd2018-10-17 19:20:00 -0700602 };
603
Andreas Gampee3864802018-12-19 14:12:59 -0800604 if (args.size() == 0) {
605 print_help(err, "No command given");
606 return BAD_VALUE;
607 }
608
609 const String16& cmd = args[0];
610
Andreas Gampe59ec1d92018-12-19 14:43:24 -0800611 if (cmd == String16("stagePackage") || cmd == String16("stagePackages")) {
612 if (args.size() < 2) {
613 print_help(err, "stagePackage(s) requires at least one packagePath");
614 return BAD_VALUE;
615 }
616 if (args.size() != 2 && cmd == String16("stagePackage")) {
Andreas Gampee3864802018-12-19 14:12:59 -0800617 print_help(err, "stagePackage requires one packagePath");
618 return BAD_VALUE;
619 }
Andreas Gampe59ec1d92018-12-19 14:43:24 -0800620 std::vector<std::string> pkgs;
621 pkgs.reserve(args.size() - 1);
622 for (size_t i = 1; i != args.size(); ++i) {
623 pkgs.emplace_back(String8(args[i]).string());
624 }
Andreas Gampe66b5dcd2018-10-17 19:20:00 -0700625 bool ret_value;
Andreas Gampe59ec1d92018-12-19 14:43:24 -0800626 BinderStatus status = stagePackages(pkgs, &ret_value);
Andreas Gampe66b5dcd2018-10-17 19:20:00 -0700627 if (status.isOk()) {
628 return OK;
629 }
Andreas Gampe59ec1d92018-12-19 14:43:24 -0800630 std::string msg = StringLog() << "Failed to stage package(s): "
631 << status.toString8().string() << std::endl;
Jiyong Park9b800482018-12-03 22:16:40 +0900632 dprintf(err, "%s", msg.c_str());
Dario Freni8e88b682018-10-25 13:06:21 +0100633 return BAD_VALUE;
634 }
Gavin Corkery729905c2019-03-21 11:52:06 +0000635 if (cmd == String16("getAllPackages")) {
636 if (args.size() != 1) {
637 print_help(err, "Unrecognized options");
638 return BAD_VALUE;
639 }
640 std::vector<ApexInfo> list;
641 BinderStatus status = getAllPackages(&list);
642 if (status.isOk()) {
643 for (const auto& item : list) {
644 std::string msg = toString(item);
645 dprintf(out, "%s", msg.c_str());
646 }
647 return OK;
648 }
649 std::string msg = StringLog() << "Failed to retrieve packages: "
650 << status.toString8().string() << std::endl;
651 dprintf(err, "%s", msg.c_str());
652 return BAD_VALUE;
653 }
Andreas Gampee3864802018-12-19 14:12:59 -0800654
655 if (cmd == String16("getActivePackages")) {
656 if (args.size() != 1) {
657 print_help(err, "Unrecognized options");
658 return BAD_VALUE;
659 }
Dario Frenidded6c12018-11-19 16:02:26 +0000660 std::vector<ApexInfo> list;
Andreas Gampee3864802018-12-19 14:12:59 -0800661 BinderStatus status = getActivePackages(&list);
Dario Freni8e88b682018-10-25 13:06:21 +0100662 if (status.isOk()) {
Chih-Hung Hsieh43bb0232018-12-12 14:30:01 -0800663 for (const auto& item : list) {
Gavin Corkery729905c2019-03-21 11:52:06 +0000664 std::string msg = toString(item);
Jiyong Park9b800482018-12-03 22:16:40 +0900665 dprintf(out, "%s", msg.c_str());
Dario Freni8e88b682018-10-25 13:06:21 +0100666 }
667 return OK;
668 }
Andreas Gampe17739142019-01-09 16:00:26 -0800669 std::string msg = StringLog() << "Failed to retrieve packages: "
670 << status.toString8().string() << std::endl;
Jiyong Park9b800482018-12-03 22:16:40 +0900671 dprintf(err, "%s", msg.c_str());
Andreas Gampe66b5dcd2018-10-17 19:20:00 -0700672 return BAD_VALUE;
673 }
Andreas Gampee3864802018-12-19 14:12:59 -0800674
Narayan Kamath5ea57782019-01-03 18:17:05 +0000675 if (cmd == String16("getActivePackage")) {
676 if (args.size() != 2) {
677 print_help(err, "Unrecognized options");
678 return BAD_VALUE;
679 }
680
681 ApexInfo package;
682 BinderStatus status = getActivePackage(String8(args[1]).string(), &package);
683 if (status.isOk()) {
Gavin Corkery729905c2019-03-21 11:52:06 +0000684 std::string msg = toString(package);
685 dprintf(out, "%s", msg.c_str());
Narayan Kamath5ea57782019-01-03 18:17:05 +0000686 return OK;
687 }
688
689 std::string msg = StringLog() << "Failed to fetch active package: "
690 << String8(args[1]).string()
691 << ", error: " << status.toString8().string()
692 << std::endl;
693 dprintf(err, "%s", msg.c_str());
694 return BAD_VALUE;
695 }
696
Andreas Gampee3864802018-12-19 14:12:59 -0800697 if (cmd == String16("activatePackage")) {
698 if (args.size() != 2) {
699 print_help(err, "activatePackage requires one packagePath");
700 return BAD_VALUE;
701 }
702 BinderStatus status = activatePackage(String8(args[1]).string());
Andreas Gampe8eb187a2018-10-19 21:18:03 -0700703 if (status.isOk()) {
704 return OK;
705 }
Andreas Gampe17739142019-01-09 16:00:26 -0800706 std::string msg = StringLog() << "Failed to activate package: "
707 << status.toString8().string() << std::endl;
Jiyong Park9b800482018-12-03 22:16:40 +0900708 dprintf(err, "%s", msg.c_str());
Andreas Gampe8eb187a2018-10-19 21:18:03 -0700709 return BAD_VALUE;
710 }
Andreas Gampee3864802018-12-19 14:12:59 -0800711
712 if (cmd == String16("deactivatePackage")) {
713 if (args.size() != 2) {
714 print_help(err, "deactivatePackage requires one packagePath");
715 return BAD_VALUE;
716 }
717 BinderStatus status = deactivatePackage(String8(args[1]).string());
Andreas Gampea4fe1132018-11-16 11:14:31 -0800718 if (status.isOk()) {
719 return OK;
720 }
Andreas Gampe17739142019-01-09 16:00:26 -0800721 std::string msg = StringLog() << "Failed to deactivate package: "
722 << status.toString8().string() << std::endl;
Jiyong Park9b800482018-12-03 22:16:40 +0900723 dprintf(err, "%s", msg.c_str());
Andreas Gampea4fe1132018-11-16 11:14:31 -0800724 return BAD_VALUE;
725 }
Andreas Gampee3864802018-12-19 14:12:59 -0800726
Dario Frenid2437642019-01-11 14:35:23 +0000727 if (cmd == String16("getStagedSessionInfo")) {
728 if (args.size() != 2) {
729 print_help(err, "getStagedSessionInfo requires one session id");
730 return BAD_VALUE;
731 }
732 int session_id = strtol(String8(args[1]).c_str(), nullptr, 10);
733 if (session_id < 0) {
734 std::string msg = StringLog()
735 << "Failed to parse session id. Must be an integer.";
736 dprintf(err, "%s", msg.c_str());
737 return BAD_VALUE;
738 }
739
740 ApexSessionInfo session_info;
741 BinderStatus status = getStagedSessionInfo(session_id, &session_info);
742 if (status.isOk()) {
743 std::string msg = StringLog()
744 << "session_info: "
745 << " isUnknown: " << session_info.isUnknown
746 << " isVerified: " << session_info.isVerified
747 << " isStaged: " << session_info.isStaged
748 << " isActivated: " << session_info.isActivated
Dario Frenid2437642019-01-11 14:35:23 +0000749 << " isActivationFailed: "
750 << session_info.isActivationFailed << std::endl;
751 dprintf(out, "%s", msg.c_str());
752 return OK;
753 }
754 std::string msg = StringLog() << "Failed to query session: "
755 << status.toString8().string() << std::endl;
756 dprintf(err, "%s", msg.c_str());
757 return BAD_VALUE;
758 }
759
Dario Freni56231b42019-01-04 11:58:17 +0000760 if (cmd == String16("submitStagedSession")) {
761 if (args.size() != 2) {
762 print_help(err, "submitStagedSession requires one session id");
763 return BAD_VALUE;
764 }
765 int session_id = strtol(String8(args[1]).c_str(), nullptr, 10);
766 if (session_id < 0) {
767 std::string msg = StringLog()
768 << "Failed to parse session id. Must be an integer.";
769 dprintf(err, "%s", msg.c_str());
770 return BAD_VALUE;
771 }
772
Dario Freniab5b6c42019-01-15 11:53:57 +0000773 ApexInfoList list;
774 std::vector<int> empty_child_session_ids;
Dario Frenia6ad33e2019-01-09 14:35:43 +0000775 bool ret_value;
Dario Freniab5b6c42019-01-15 11:53:57 +0000776
777 BinderStatus status = submitStagedSession(
778 session_id, empty_child_session_ids, &list, &ret_value);
Dario Freni56231b42019-01-04 11:58:17 +0000779 if (status.isOk()) {
Dario Frenia6ad33e2019-01-09 14:35:43 +0000780 if (ret_value) {
Dario Freniab5b6c42019-01-15 11:53:57 +0000781 for (const auto& item : list.apexInfos) {
Gavin Corkery729905c2019-03-21 11:52:06 +0000782 std::string msg = toString(item);
Dario Frenia6ad33e2019-01-09 14:35:43 +0000783 dprintf(out, "%s", msg.c_str());
784 }
785 } else {
786 std::string msg = StringLog() << "Verification failed." << std::endl;
Dario Freni56231b42019-01-04 11:58:17 +0000787 dprintf(out, "%s", msg.c_str());
788 }
789 return OK;
790 }
791 std::string msg = StringLog() << "Failed to submit session: "
792 << status.toString8().string() << std::endl;
793 dprintf(err, "%s", msg.c_str());
794 return BAD_VALUE;
795 }
796
Andreas Gampe1a48b1b2019-02-05 16:12:25 -0800797 if (cmd == String16("preinstallPackages") ||
798 cmd == String16("postinstallPackages")) {
799 if (args.size() < 2) {
800 print_help(err,
801 "preinstallPackages/postinstallPackages requires at least"
802 " one packagePath");
803 return BAD_VALUE;
804 }
805 std::vector<std::string> pkgs;
806 pkgs.reserve(args.size() - 1);
807 for (size_t i = 1; i != args.size(); ++i) {
808 pkgs.emplace_back(String8(args[i]).string());
809 }
810 BinderStatus status = cmd == String16("preinstallPackages")
811 ? preinstallPackages(pkgs)
812 : postinstallPackages(pkgs);
813 if (status.isOk()) {
814 return OK;
815 }
816 std::string msg = StringLog() << "Failed to pre/postinstall package(s): "
817 << status.toString8().string() << std::endl;
818 dprintf(err, "%s", msg.c_str());
819 return BAD_VALUE;
820 }
821
Andreas Gampee3864802018-12-19 14:12:59 -0800822 if (cmd == String16("help")) {
823 if (args.size() != 1) {
824 print_help(err, "Help has no options");
825 return BAD_VALUE;
826 }
Andreas Gampe66b5dcd2018-10-17 19:20:00 -0700827 print_help(out);
828 return OK;
829 }
Andreas Gampee3864802018-12-19 14:12:59 -0800830
Andreas Gampe66b5dcd2018-10-17 19:20:00 -0700831 print_help(err);
832 return BAD_VALUE;
833}
834
Andreas Gampe602ef782018-11-12 16:51:31 -0800835} // namespace
836
837static constexpr const char* kApexServiceName = "apexservice";
838
839using android::defaultServiceManager;
840using android::IPCThreadState;
841using android::ProcessState;
842using android::sp;
843using android::String16;
844
845void CreateAndRegisterService() {
846 sp<ProcessState> ps(ProcessState::self());
847
848 // Create binder service and register with servicemanager
849 sp<ApexService> apexService = new ApexService();
850 defaultServiceManager()->addService(String16(kApexServiceName), apexService);
851}
852
Zimuzo9cc0be42019-01-09 11:37:34 +0000853void StartThreadPool() {
Andreas Gampe602ef782018-11-12 16:51:31 -0800854 sp<ProcessState> ps(ProcessState::self());
855
856 // Start threadpool, wait for IPC
857 ps->startThreadPool();
Zimuzo9cc0be42019-01-09 11:37:34 +0000858}
859
860void JoinThreadPool() {
Andreas Gampe602ef782018-11-12 16:51:31 -0800861 IPCThreadState::self()->joinThreadPool(); // should not return
862}
863
864} // namespace binder
Andreas Gampeb99abdd2018-10-19 19:59:17 -0700865} // namespace apex
866} // namespace android