1 /*
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
17 #include "apexservice.h"
18
19 #include <dirent.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22
23 #include <android-base/file.h>
24 #include <android-base/logging.h>
25 #include <android-base/properties.h>
26 #include <android-base/result.h>
27 #include <android-base/stringprintf.h>
28 #include <android-base/strings.h>
29 #include <binder/IPCThreadState.h>
30 #include <binder/IResultReceiver.h>
31 #include <binder/IServiceManager.h>
32 #include <binder/LazyServiceRegistrar.h>
33 #include <binder/ProcessState.h>
34 #include <binder/Status.h>
35 #include <private/android_filesystem_config.h>
36 #include <utils/String16.h>
37
38 #include "apex_file.h"
39 #include "apex_file_repository.h"
40 #include "apexd.h"
41 #include "apexd_session.h"
42 #include "string_log.h"
43
44 #include <android/apex/BnApexService.h>
45
46 using android::base::Join;
47 using android::base::Result;
48
49 namespace android {
50 namespace apex {
51 namespace binder {
52 namespace {
53
54 using BinderStatus = ::android::binder::Status;
55
CheckCallerIsRoot(const std::string & name)56 BinderStatus CheckCallerIsRoot(const std::string& name) {
57 uid_t uid = IPCThreadState::self()->getCallingUid();
58 if (uid != AID_ROOT) {
59 std::string msg = "Only root is allowed to call " + name;
60 return BinderStatus::fromExceptionCode(BinderStatus::EX_SECURITY,
61 String8(name.c_str()));
62 }
63 return BinderStatus::ok();
64 }
65
CheckCallerSystemOrRoot(const std::string & name)66 BinderStatus CheckCallerSystemOrRoot(const std::string& name) {
67 uid_t uid = IPCThreadState::self()->getCallingUid();
68 if (uid != AID_ROOT && uid != AID_SYSTEM) {
69 std::string msg = "Only root and system_server are allowed to call " + name;
70 return BinderStatus::fromExceptionCode(BinderStatus::EX_SECURITY,
71 String8(name.c_str()));
72 }
73 return BinderStatus::ok();
74 }
75
76 class ApexService : public BnApexService {
77 public:
78 using BinderStatus = ::android::binder::Status;
79 using SessionState = ::apex::proto::SessionState;
80
ApexService()81 ApexService(){};
82
83 BinderStatus stagePackages(const std::vector<std::string>& paths) override;
84 BinderStatus unstagePackages(const std::vector<std::string>& paths) override;
85 BinderStatus submitStagedSession(const ApexSessionParams& params,
86 ApexInfoList* apex_info_list) override;
87 BinderStatus markStagedSessionReady(int session_id) override;
88 BinderStatus markStagedSessionSuccessful(int session_id) override;
89 BinderStatus getSessions(std::vector<ApexSessionInfo>* aidl_return) override;
90 BinderStatus getStagedSessionInfo(
91 int session_id, ApexSessionInfo* apex_session_info) override;
92 BinderStatus getStagedApexInfos(const ApexSessionParams& params,
93 std::vector<ApexInfo>* aidl_return) override;
94 BinderStatus getActivePackages(std::vector<ApexInfo>* aidl_return) override;
95 BinderStatus getActivePackage(const std::string& package_name,
96 ApexInfo* aidl_return) override;
97 BinderStatus getAllPackages(std::vector<ApexInfo>* aidl_return) override;
98 BinderStatus abortStagedSession(int session_id) override;
99 BinderStatus revertActiveSessions() override;
100 BinderStatus resumeRevertIfNeeded() override;
101 BinderStatus snapshotCeData(int user_id, int rollback_id,
102 const std::string& apex_name) override;
103 BinderStatus restoreCeData(int user_id, int rollback_id,
104 const std::string& apex_name) override;
105 BinderStatus destroyDeSnapshots(int rollback_id) override;
106 BinderStatus destroyCeSnapshots(int user_id, int rollback_id) override;
107 BinderStatus destroyCeSnapshotsNotSpecified(
108 int user_id, const std::vector<int>& retain_rollback_ids) override;
109 BinderStatus remountPackages() override;
110 BinderStatus recollectPreinstalledData(
111 const std::vector<std::string>& paths) override;
112 BinderStatus recollectDataApex(const std::string& path,
113 const std::string& decompression_dir) override;
114 BinderStatus markBootCompleted() override;
115 BinderStatus calculateSizeForCompressedApex(
116 const CompressedApexInfoList& compressed_apex_info_list,
117 int64_t* required_size) override;
118 BinderStatus reserveSpaceForCompressedApex(
119 const CompressedApexInfoList& compressed_apex_info_list) override;
120 BinderStatus installAndActivatePackage(const std::string& package_path,
121 ApexInfo* aidl_return) override;
122
123 status_t dump(int fd, const Vector<String16>& args) override;
124
125 // Override onTransact so we can handle shellCommand.
126 status_t onTransact(uint32_t _aidl_code, const Parcel& _aidl_data,
127 Parcel* _aidl_reply, uint32_t _aidl_flags) override;
128
129 status_t shellCommand(int in, int out, int err, const Vector<String16>& args);
130 };
131
CheckDebuggable(const std::string & name)132 BinderStatus CheckDebuggable(const std::string& name) {
133 if (!::android::base::GetBoolProperty("ro.debuggable", false)) {
134 std::string tmp = name + " unavailable";
135 return BinderStatus::fromExceptionCode(BinderStatus::EX_SECURITY,
136 String8(tmp.c_str()));
137 }
138 return BinderStatus::ok();
139 }
140
stagePackages(const std::vector<std::string> & paths)141 BinderStatus ApexService::stagePackages(const std::vector<std::string>& paths) {
142 LOG(INFO) << "stagePackages() received by ApexService, paths "
143 << android::base::Join(paths, ',');
144
145 BinderStatus debug_check = CheckDebuggable("stagePackages");
146 if (!debug_check.isOk()) {
147 return debug_check;
148 }
149 if (auto is_root = CheckCallerIsRoot("stagePackages"); !is_root.isOk()) {
150 return is_root;
151 }
152 Result<void> res = ::android::apex::StagePackages(paths);
153
154 if (res.ok()) {
155 return BinderStatus::ok();
156 }
157
158 LOG(ERROR) << "Failed to stage " << android::base::Join(paths, ',') << ": "
159 << res.error();
160 return BinderStatus::fromExceptionCode(
161 BinderStatus::EX_SERVICE_SPECIFIC,
162 String8(res.error().message().c_str()));
163 }
164
unstagePackages(const std::vector<std::string> & paths)165 BinderStatus ApexService::unstagePackages(
166 const std::vector<std::string>& paths) {
167 LOG(INFO) << "unstagePackages() received by ApexService, paths "
168 << android::base::Join(paths, ',');
169
170 if (auto check = CheckCallerSystemOrRoot("unstagePackages"); !check.isOk()) {
171 return check;
172 }
173
174 Result<void> res = ::android::apex::UnstagePackages(paths);
175 if (res.ok()) {
176 return BinderStatus::ok();
177 }
178
179 LOG(ERROR) << "Failed to unstage " << android::base::Join(paths, ',') << ": "
180 << res.error();
181 return BinderStatus::fromExceptionCode(
182 BinderStatus::EX_SERVICE_SPECIFIC,
183 String8(res.error().message().c_str()));
184 }
185
submitStagedSession(const ApexSessionParams & params,ApexInfoList * apex_info_list)186 BinderStatus ApexService::submitStagedSession(const ApexSessionParams& params,
187 ApexInfoList* apex_info_list) {
188 LOG(INFO) << "submitStagedSession() received by ApexService, session id "
189 << params.sessionId << " child sessions: ["
190 << android::base::Join(params.childSessionIds, ',') << "]";
191
192 auto check = CheckCallerSystemOrRoot("submitStagedSession");
193 if (!check.isOk()) {
194 return check;
195 }
196
197 Result<std::vector<ApexFile>> packages = ::android::apex::SubmitStagedSession(
198 params.sessionId, params.childSessionIds, params.hasRollbackEnabled,
199 params.isRollback, params.rollbackId);
200 if (!packages.ok()) {
201 LOG(ERROR) << "Failed to submit session id " << params.sessionId << ": "
202 << packages.error();
203 return BinderStatus::fromExceptionCode(
204 BinderStatus::EX_SERVICE_SPECIFIC,
205 String8(packages.error().message().c_str()));
206 }
207
208 for (const auto& package : *packages) {
209 ApexInfo out;
210 out.moduleName = package.GetManifest().name();
211 out.modulePath = package.GetPath();
212 out.versionCode = package.GetManifest().version();
213 apex_info_list->apexInfos.push_back(out);
214 }
215 return BinderStatus::ok();
216 }
217
markStagedSessionReady(int session_id)218 BinderStatus ApexService::markStagedSessionReady(int session_id) {
219 LOG(INFO) << "markStagedSessionReady() received by ApexService, session id "
220 << session_id;
221
222 auto check = CheckCallerSystemOrRoot("markStagedSessionReady");
223 if (!check.isOk()) {
224 return check;
225 }
226
227 Result<void> success = ::android::apex::MarkStagedSessionReady(session_id);
228 if (!success.ok()) {
229 LOG(ERROR) << "Failed to mark session id " << session_id
230 << " as ready: " << success.error();
231 return BinderStatus::fromExceptionCode(
232 BinderStatus::EX_SERVICE_SPECIFIC,
233 String8(success.error().message().c_str()));
234 }
235 return BinderStatus::ok();
236 }
237
markStagedSessionSuccessful(int session_id)238 BinderStatus ApexService::markStagedSessionSuccessful(int session_id) {
239 LOG(INFO)
240 << "markStagedSessionSuccessful() received by ApexService, session id "
241 << session_id;
242
243 auto check = CheckCallerSystemOrRoot("markStagedSessionSuccessful");
244 if (!check.isOk()) {
245 return check;
246 }
247
248 Result<void> ret = ::android::apex::MarkStagedSessionSuccessful(session_id);
249 if (!ret.ok()) {
250 LOG(ERROR) << "Failed to mark session " << session_id
251 << " as SUCCESS: " << ret.error();
252 return BinderStatus::fromExceptionCode(
253 BinderStatus::EX_ILLEGAL_ARGUMENT,
254 String8(ret.error().message().c_str()));
255 }
256 return BinderStatus::ok();
257 }
258
markBootCompleted()259 BinderStatus ApexService::markBootCompleted() {
260 LOG(INFO) << "markBootCompleted() received by ApexService";
261
262 auto check = CheckCallerSystemOrRoot("markBootCompleted");
263 if (!check.isOk()) {
264 return check;
265 }
266
267 ::android::apex::OnBootCompleted();
268 return BinderStatus::ok();
269 }
270
calculateSizeForCompressedApex(const CompressedApexInfoList & compressed_apex_info_list,int64_t * required_size)271 BinderStatus ApexService::calculateSizeForCompressedApex(
272 const CompressedApexInfoList& compressed_apex_info_list,
273 int64_t* required_size) {
274 std::vector<std::tuple<std::string, int64_t, int64_t>> compressed_apexes;
275 compressed_apexes.reserve(compressed_apex_info_list.apexInfos.size());
276 for (const auto& apex_info : compressed_apex_info_list.apexInfos) {
277 compressed_apexes.emplace_back(apex_info.moduleName, apex_info.versionCode,
278 apex_info.decompressedSize);
279 }
280 const auto& instance = ApexFileRepository::GetInstance();
281 *required_size = ::android::apex::CalculateSizeForCompressedApex(
282 compressed_apexes, instance);
283 return BinderStatus::ok();
284 }
285
reserveSpaceForCompressedApex(const CompressedApexInfoList & compressed_apex_info_list)286 BinderStatus ApexService::reserveSpaceForCompressedApex(
287 const CompressedApexInfoList& compressed_apex_info_list) {
288 int64_t required_size;
289 if (auto res = calculateSizeForCompressedApex(compressed_apex_info_list,
290 &required_size);
291 !res.isOk()) {
292 return res;
293 }
294 if (auto res = ReserveSpaceForCompressedApex(required_size, kOtaReservedDir);
295 !res.ok()) {
296 return BinderStatus::fromExceptionCode(
297 BinderStatus::EX_SERVICE_SPECIFIC,
298 String8(res.error().message().c_str()));
299 }
300 return BinderStatus::ok();
301 }
302
ClearSessionInfo(ApexSessionInfo * session_info)303 static void ClearSessionInfo(ApexSessionInfo* session_info) {
304 session_info->sessionId = -1;
305 session_info->isUnknown = false;
306 session_info->isVerified = false;
307 session_info->isStaged = false;
308 session_info->isActivated = false;
309 session_info->isRevertInProgress = false;
310 session_info->isActivationFailed = false;
311 session_info->isSuccess = false;
312 session_info->isReverted = false;
313 session_info->isRevertFailed = false;
314 }
315
ConvertToApexSessionInfo(const ApexSession & session,ApexSessionInfo * session_info)316 void ConvertToApexSessionInfo(const ApexSession& session,
317 ApexSessionInfo* session_info) {
318 using SessionState = ::apex::proto::SessionState;
319
320 ClearSessionInfo(session_info);
321 session_info->sessionId = session.GetId();
322 session_info->crashingNativeProcess = session.GetCrashingNativeProcess();
323 session_info->errorMessage = session.GetErrorMessage();
324
325 switch (session.GetState()) {
326 case SessionState::VERIFIED:
327 session_info->isVerified = true;
328 break;
329 case SessionState::STAGED:
330 session_info->isStaged = true;
331 break;
332 case SessionState::ACTIVATED:
333 session_info->isActivated = true;
334 break;
335 case SessionState::ACTIVATION_FAILED:
336 session_info->isActivationFailed = true;
337 break;
338 case SessionState::SUCCESS:
339 session_info->isSuccess = true;
340 break;
341 case SessionState::REVERT_IN_PROGRESS:
342 session_info->isRevertInProgress = true;
343 break;
344 case SessionState::REVERTED:
345 session_info->isReverted = true;
346 break;
347 case SessionState::REVERT_FAILED:
348 session_info->isRevertFailed = true;
349 break;
350 case SessionState::UNKNOWN:
351 default:
352 session_info->isUnknown = true;
353 break;
354 }
355 }
356
GetApexInfo(const ApexFile & package)357 static ApexInfo GetApexInfo(const ApexFile& package) {
358 auto& instance = ApexFileRepository::GetInstance();
359 ApexInfo out;
360 out.moduleName = package.GetManifest().name();
361 out.modulePath = package.GetPath();
362 out.versionCode = package.GetManifest().version();
363 out.versionName = package.GetManifest().versionname();
364 out.isFactory = instance.IsPreInstalledApex(package);
365 out.isActive = false;
366 Result<std::string> preinstalled_path =
367 instance.GetPreinstalledPath(package.GetManifest().name());
368 if (preinstalled_path.ok()) {
369 // We replace the preinstalled paths for block devices to /system/apex
370 // because PackageManager will not resolve them if they aren't in one of
371 // the SYSTEM_PARTITIONS defined in PackagePartitions.java.
372 // b/195363518 for more context.
373 const std::string block_path = "/dev/block/";
374 const std::string sys_apex_path =
375 std::string(kApexPackageSystemDir) + "/" +
376 preinstalled_path->substr(block_path.length());
377 out.preinstalledModulePath = preinstalled_path->starts_with(block_path)
378 ? sys_apex_path
379 : *preinstalled_path;
380 }
381 out.activeApexChanged = ::android::apex::IsActiveApexChanged(package);
382 return out;
383 }
384
ToString(const ApexInfo & package)385 static std::string ToString(const ApexInfo& package) {
386 std::string msg = StringLog()
387 << "Module: " << package.moduleName
388 << " Version: " << package.versionCode
389 << " VersionName: " << package.versionName
390 << " Path: " << package.modulePath
391 << " IsActive: " << std::boolalpha << package.isActive
392 << " IsFactory: " << std::boolalpha << package.isFactory
393 << std::endl;
394 return msg;
395 }
396
getSessions(std::vector<ApexSessionInfo> * aidl_return)397 BinderStatus ApexService::getSessions(
398 std::vector<ApexSessionInfo>* aidl_return) {
399 LOG(INFO) << "getSessions() received by ApexService";
400
401 auto check = CheckCallerSystemOrRoot("getSessions");
402 if (!check.isOk()) {
403 return check;
404 }
405
406 auto sessions = ApexSession::GetSessions();
407 for (const auto& session : sessions) {
408 ApexSessionInfo session_info;
409 ConvertToApexSessionInfo(session, &session_info);
410 aidl_return->push_back(session_info);
411 }
412
413 return BinderStatus::ok();
414 }
415
getStagedSessionInfo(int session_id,ApexSessionInfo * apex_session_info)416 BinderStatus ApexService::getStagedSessionInfo(
417 int session_id, ApexSessionInfo* apex_session_info) {
418 LOG(INFO) << "getStagedSessionInfo() received by ApexService, session id "
419 << session_id;
420
421 auto check = CheckCallerSystemOrRoot("getStagedSessionInfo");
422 if (!check.isOk()) {
423 return check;
424 }
425
426 auto session = ApexSession::GetSession(session_id);
427 if (!session.ok()) {
428 // Unknown session.
429 ClearSessionInfo(apex_session_info);
430 apex_session_info->isUnknown = true;
431 return BinderStatus::ok();
432 }
433
434 ConvertToApexSessionInfo(*session, apex_session_info);
435
436 return BinderStatus::ok();
437 }
438
getStagedApexInfos(const ApexSessionParams & params,std::vector<ApexInfo> * aidl_return)439 BinderStatus ApexService::getStagedApexInfos(
440 const ApexSessionParams& params, std::vector<ApexInfo>* aidl_return) {
441 LOG(INFO) << "getStagedApexInfos() received by ApexService, session id "
442 << params.sessionId << " child sessions: ["
443 << android::base::Join(params.childSessionIds, ',') << "]";
444
445 auto check = CheckCallerSystemOrRoot("getStagedApexInfos");
446 if (!check.isOk()) {
447 return check;
448 }
449
450 Result<std::vector<ApexFile>> files = ::android::apex::GetStagedApexFiles(
451 params.sessionId, params.childSessionIds);
452 if (!files.ok()) {
453 LOG(ERROR) << "Failed to getStagedApexInfo session id " << params.sessionId
454 << ": " << files.error();
455 return BinderStatus::fromExceptionCode(
456 BinderStatus::EX_SERVICE_SPECIFIC,
457 String8(files.error().message().c_str()));
458 }
459
460 // Retrieve classpath information
461 auto class_path = ::android::apex::MountAndDeriveClassPath(*files);
462 if (!class_path.ok()) {
463 LOG(ERROR) << "Failed to getStagedApexInfo session id " << params.sessionId
464 << ": " << class_path.error();
465 return BinderStatus::fromExceptionCode(
466 BinderStatus::EX_SERVICE_SPECIFIC,
467 String8(class_path.error().message().c_str()));
468 }
469
470 for (const auto& apex_file : *files) {
471 ApexInfo apex_info = GetApexInfo(apex_file);
472 auto package_name = apex_info.moduleName;
473 apex_info.hasClassPathJars = class_path->HasClassPathJars(package_name);
474 aidl_return->push_back(std::move(apex_info));
475 }
476
477 return BinderStatus::ok();
478 }
479
getActivePackages(std::vector<ApexInfo> * aidl_return)480 BinderStatus ApexService::getActivePackages(
481 std::vector<ApexInfo>* aidl_return) {
482 LOG(INFO) << "getActivePackages received by ApexService";
483
484 auto check = CheckCallerSystemOrRoot("getActivePackages");
485 if (!check.isOk()) {
486 return check;
487 }
488
489 auto packages = ::android::apex::GetActivePackages();
490 for (const auto& package : packages) {
491 ApexInfo apex_info = GetApexInfo(package);
492 apex_info.isActive = true;
493 aidl_return->push_back(std::move(apex_info));
494 }
495
496 return BinderStatus::ok();
497 }
498
getActivePackage(const std::string & package_name,ApexInfo * aidl_return)499 BinderStatus ApexService::getActivePackage(const std::string& package_name,
500 ApexInfo* aidl_return) {
501 LOG(INFO) << "getActivePackage received by ApexService package_name : "
502 << package_name;
503
504 auto check = CheckCallerSystemOrRoot("getActivePackage");
505 if (!check.isOk()) {
506 return check;
507 }
508
509 Result<ApexFile> apex = ::android::apex::GetActivePackage(package_name);
510 if (apex.ok()) {
511 *aidl_return = GetApexInfo(*apex);
512 aidl_return->isActive = true;
513 }
514 return BinderStatus::ok();
515 }
516
getAllPackages(std::vector<ApexInfo> * aidl_return)517 BinderStatus ApexService::getAllPackages(std::vector<ApexInfo>* aidl_return) {
518 LOG(INFO) << "getAllPackages received by ApexService";
519
520 auto check = CheckCallerSystemOrRoot("getAllPackages");
521 if (!check.isOk()) {
522 return check;
523 }
524
525 const auto& active = ::android::apex::GetActivePackages();
526 const auto& factory = ::android::apex::GetFactoryPackages();
527 for (const ApexFile& pkg : active) {
528 ApexInfo apex_info = GetApexInfo(pkg);
529 apex_info.isActive = true;
530 aidl_return->push_back(std::move(apex_info));
531 }
532 for (const ApexFile& pkg : factory) {
533 const auto& same_path = [&pkg](const auto& o) {
534 return o.GetPath() == pkg.GetPath();
535 };
536 if (std::find_if(active.begin(), active.end(), same_path) == active.end()) {
537 aidl_return->push_back(GetApexInfo(pkg));
538 }
539 }
540 return BinderStatus::ok();
541 }
542
installAndActivatePackage(const std::string & package_path,ApexInfo * aidl_return)543 BinderStatus ApexService::installAndActivatePackage(
544 const std::string& package_path, ApexInfo* aidl_return) {
545 LOG(INFO) << "installAndActivatePackage() received by ApexService, path: "
546 << package_path;
547
548 auto check = CheckCallerSystemOrRoot("installAndActivatePackage");
549 if (!check.isOk()) {
550 return check;
551 }
552
553 auto res = InstallPackage(package_path);
554 if (!res.ok()) {
555 LOG(ERROR) << "Failed to install package " << package_path << " : "
556 << res.error();
557 return BinderStatus::fromExceptionCode(
558 BinderStatus::EX_SERVICE_SPECIFIC,
559 String8(res.error().message().c_str()));
560 }
561 *aidl_return = GetApexInfo(*res);
562 aidl_return->isActive = true;
563 return BinderStatus::ok();
564 }
565
abortStagedSession(int session_id)566 BinderStatus ApexService::abortStagedSession(int session_id) {
567 LOG(INFO) << "abortStagedSession() received by ApexService session : "
568 << session_id;
569
570 auto check = CheckCallerSystemOrRoot("abortStagedSession");
571 if (!check.isOk()) {
572 return check;
573 }
574
575 Result<void> res = ::android::apex::AbortStagedSession(session_id);
576 if (!res.ok()) {
577 return BinderStatus::fromExceptionCode(
578 BinderStatus::EX_ILLEGAL_ARGUMENT,
579 String8(res.error().message().c_str()));
580 }
581 return BinderStatus::ok();
582 }
583
revertActiveSessions()584 BinderStatus ApexService::revertActiveSessions() {
585 LOG(INFO) << "revertActiveSessions() received by ApexService.";
586
587 auto check = CheckCallerSystemOrRoot("revertActiveSessions");
588 if (!check.isOk()) {
589 return check;
590 }
591
592 Result<void> res = ::android::apex::RevertActiveSessions("", "");
593 if (!res.ok()) {
594 return BinderStatus::fromExceptionCode(
595 BinderStatus::EX_ILLEGAL_ARGUMENT,
596 String8(res.error().message().c_str()));
597 }
598 return BinderStatus::ok();
599 }
600
resumeRevertIfNeeded()601 BinderStatus ApexService::resumeRevertIfNeeded() {
602 LOG(INFO) << "resumeRevertIfNeeded() received by ApexService.";
603
604 BinderStatus debug_check = CheckDebuggable("resumeRevertIfNeeded");
605 if (!debug_check.isOk()) {
606 return debug_check;
607 }
608
609 auto root_check = CheckCallerIsRoot("resumeRevertIfNeeded");
610 if (!root_check.isOk()) {
611 return root_check;
612 }
613
614 Result<void> res = ::android::apex::ResumeRevertIfNeeded();
615 if (!res.ok()) {
616 return BinderStatus::fromExceptionCode(
617 BinderStatus::EX_ILLEGAL_ARGUMENT,
618 String8(res.error().message().c_str()));
619 }
620 return BinderStatus::ok();
621 }
622
snapshotCeData(int user_id,int rollback_id,const std::string & apex_name)623 BinderStatus ApexService::snapshotCeData(int user_id, int rollback_id,
624 const std::string& apex_name) {
625 LOG(INFO) << "snapshotCeData() received by ApexService user_id : " << user_id
626 << " rollback_id : " << rollback_id << " apex_name : " << apex_name;
627
628 auto check = CheckCallerSystemOrRoot("snapshotCeData");
629 if (!check.isOk()) {
630 return check;
631 }
632
633 Result<void> res =
634 ::android::apex::SnapshotCeData(user_id, rollback_id, apex_name);
635 if (!res.ok()) {
636 return BinderStatus::fromExceptionCode(
637 BinderStatus::EX_SERVICE_SPECIFIC,
638 String8(res.error().message().c_str()));
639 }
640 return BinderStatus::ok();
641 }
642
restoreCeData(int user_id,int rollback_id,const std::string & apex_name)643 BinderStatus ApexService::restoreCeData(int user_id, int rollback_id,
644 const std::string& apex_name) {
645 LOG(INFO) << "restoreCeData() received by ApexService user_id : " << user_id
646 << " rollback_id : " << rollback_id << " apex_name : " << apex_name;
647
648 auto check = CheckCallerSystemOrRoot("restoreCeData");
649 if (!check.isOk()) {
650 return check;
651 }
652
653 Result<void> res =
654 ::android::apex::RestoreCeData(user_id, rollback_id, apex_name);
655 if (!res.ok()) {
656 return BinderStatus::fromExceptionCode(
657 BinderStatus::EX_SERVICE_SPECIFIC,
658 String8(res.error().message().c_str()));
659 }
660 return BinderStatus::ok();
661 }
662
destroyDeSnapshots(int rollback_id)663 BinderStatus ApexService::destroyDeSnapshots(int rollback_id) {
664 LOG(INFO) << "destroyDeSnapshots() received by ApexService rollback_id : "
665 << rollback_id;
666
667 auto check = CheckCallerSystemOrRoot("destroyDeSnapshots");
668 if (!check.isOk()) {
669 return check;
670 }
671
672 Result<void> res = ::android::apex::DestroyDeSnapshots(rollback_id);
673 if (!res.ok()) {
674 return BinderStatus::fromExceptionCode(
675 BinderStatus::EX_SERVICE_SPECIFIC,
676 String8(res.error().message().c_str()));
677 }
678 return BinderStatus::ok();
679 }
680
destroyCeSnapshots(int user_id,int rollback_id)681 BinderStatus ApexService::destroyCeSnapshots(int user_id, int rollback_id) {
682 LOG(INFO) << "destroyCeSnapshots() received by ApexService user_id : "
683 << user_id << " rollback_id : " << rollback_id;
684
685 auto check = CheckCallerSystemOrRoot("destroyCeSnapshots");
686 if (!check.isOk()) {
687 return check;
688 }
689
690 Result<void> res = ::android::apex::DestroyCeSnapshots(user_id, rollback_id);
691 if (!res.ok()) {
692 return BinderStatus::fromExceptionCode(
693 BinderStatus::EX_SERVICE_SPECIFIC,
694 String8(res.error().message().c_str()));
695 }
696 return BinderStatus::ok();
697 }
698
destroyCeSnapshotsNotSpecified(int user_id,const std::vector<int> & retain_rollback_ids)699 BinderStatus ApexService::destroyCeSnapshotsNotSpecified(
700 int user_id, const std::vector<int>& retain_rollback_ids) {
701 LOG(INFO)
702 << "destroyCeSnapshotsNotSpecified() received by ApexService user_id : "
703 << user_id << " retain_rollback_ids : [" << Join(retain_rollback_ids, ',')
704 << "]";
705
706 auto check = CheckCallerSystemOrRoot("destroyCeSnapshotsNotSpecified");
707 if (!check.isOk()) {
708 return check;
709 }
710
711 Result<void> res = ::android::apex::DestroyCeSnapshotsNotSpecified(
712 user_id, retain_rollback_ids);
713 if (!res.ok()) {
714 return BinderStatus::fromExceptionCode(
715 BinderStatus::EX_SERVICE_SPECIFIC,
716 String8(res.error().message().c_str()));
717 }
718 return BinderStatus::ok();
719 }
720
remountPackages()721 BinderStatus ApexService::remountPackages() {
722 LOG(INFO) << "remountPackages() received by ApexService";
723
724 if (auto debug = CheckDebuggable("remountPackages"); !debug.isOk()) {
725 return debug;
726 }
727 if (auto root = CheckCallerIsRoot("remountPackages"); !root.isOk()) {
728 return root;
729 }
730 if (auto res = ::android::apex::RemountPackages(); !res.ok()) {
731 return BinderStatus::fromExceptionCode(
732 BinderStatus::EX_SERVICE_SPECIFIC,
733 String8(res.error().message().c_str()));
734 }
735 return BinderStatus::ok();
736 }
737
recollectPreinstalledData(const std::vector<std::string> & paths)738 BinderStatus ApexService::recollectPreinstalledData(
739 const std::vector<std::string>& paths) {
740 LOG(INFO) << "recollectPreinstalledData() received by ApexService, paths: "
741 << Join(paths, ',');
742
743 if (auto debug = CheckDebuggable("recollectPreinstalledData");
744 !debug.isOk()) {
745 return debug;
746 }
747 if (auto root = CheckCallerIsRoot("recollectPreinstalledData");
748 !root.isOk()) {
749 return root;
750 }
751 ApexFileRepository& instance = ApexFileRepository::GetInstance();
752 if (auto res = instance.AddPreInstalledApex(paths); !res.ok()) {
753 return BinderStatus::fromExceptionCode(
754 BinderStatus::EX_SERVICE_SPECIFIC,
755 String8(res.error().message().c_str()));
756 }
757 return BinderStatus::ok();
758 }
759
recollectDataApex(const std::string & path,const std::string & decompression_dir)760 BinderStatus ApexService::recollectDataApex(
761 const std::string& path, const std::string& decompression_dir) {
762 LOG(INFO) << "recollectDataApex() received by ApexService, paths " << path
763 << " and " << decompression_dir;
764
765 if (auto debug = CheckDebuggable("recollectDataApex"); !debug.isOk()) {
766 return debug;
767 }
768 if (auto root = CheckCallerIsRoot("recollectDataApex"); !root.isOk()) {
769 return root;
770 }
771 ApexFileRepository& instance = ApexFileRepository::GetInstance();
772 if (auto res = instance.AddDataApex(path); !res.ok()) {
773 return BinderStatus::fromExceptionCode(
774 BinderStatus::EX_SERVICE_SPECIFIC,
775 String8(res.error().message().c_str()));
776 }
777 return BinderStatus::ok();
778 }
779
onTransact(uint32_t _aidl_code,const Parcel & _aidl_data,Parcel * _aidl_reply,uint32_t _aidl_flags)780 status_t ApexService::onTransact(uint32_t _aidl_code, const Parcel& _aidl_data,
781 Parcel* _aidl_reply, uint32_t _aidl_flags) {
782 switch (_aidl_code) {
783 case IBinder::SHELL_COMMAND_TRANSACTION: {
784 int in = _aidl_data.readFileDescriptor();
785 int out = _aidl_data.readFileDescriptor();
786 int err = _aidl_data.readFileDescriptor();
787 int argc = _aidl_data.readInt32();
788 Vector<String16> args;
789 for (int i = 0; i < argc && _aidl_data.dataAvail() > 0; i++) {
790 args.add(_aidl_data.readString16());
791 }
792 sp<IBinder> unused_callback;
793 sp<IResultReceiver> result_receiver;
794 status_t status;
795 if ((status = _aidl_data.readNullableStrongBinder(&unused_callback)) !=
796 OK)
797 return status;
798 if ((status = _aidl_data.readNullableStrongBinder(&result_receiver)) !=
799 OK)
800 return status;
801 status = shellCommand(in, out, err, args);
802 if (result_receiver != nullptr) {
803 result_receiver->send(status);
804 }
805 return OK;
806 }
807 }
808 return BnApexService::onTransact(_aidl_code, _aidl_data, _aidl_reply,
809 _aidl_flags);
810 }
dump(int fd,const Vector<String16> &)811 status_t ApexService::dump(int fd, const Vector<String16>& /*args*/) {
812 std::vector<ApexInfo> list;
813 BinderStatus status = getActivePackages(&list);
814 dprintf(fd, "ACTIVE PACKAGES:\n");
815 if (!status.isOk()) {
816 std::string msg = StringLog() << "Failed to retrieve packages: "
817 << status.toString8().string() << std::endl;
818 dprintf(fd, "%s", msg.c_str());
819 return BAD_VALUE;
820 } else {
821 for (const auto& item : list) {
822 std::string msg = ToString(item);
823 dprintf(fd, "%s", msg.c_str());
824 }
825 }
826
827 dprintf(fd, "SESSIONS:\n");
828 std::vector<ApexSession> sessions = ApexSession::GetSessions();
829
830 for (const auto& session : sessions) {
831 std::string child_ids_str = "";
832 auto child_ids = session.GetChildSessionIds();
833 if (child_ids.size() > 0) {
834 child_ids_str = "Child IDs:";
835 for (auto childSessionId : session.GetChildSessionIds()) {
836 child_ids_str += " " + std::to_string(childSessionId);
837 }
838 }
839 std::string revert_reason = "";
840 const auto& crashing_native_process = session.GetCrashingNativeProcess();
841 if (!crashing_native_process.empty()) {
842 revert_reason = " Revert Reason: " + crashing_native_process;
843 }
844 std::string error_message_dump = "";
845 const auto& error_message = session.GetErrorMessage();
846 if (!error_message.empty()) {
847 error_message_dump = " Error Message: " + error_message;
848 }
849 std::string msg =
850 StringLog() << "Session ID: " << session.GetId() << child_ids_str
851 << " State: " << SessionState_State_Name(session.GetState())
852 << revert_reason << error_message_dump << std::endl;
853 dprintf(fd, "%s", msg.c_str());
854 }
855
856 return OK;
857 }
858
shellCommand(int in,int out,int err,const Vector<String16> & args)859 status_t ApexService::shellCommand(int in, int out, int err,
860 const Vector<String16>& args) {
861 if (in == BAD_TYPE || out == BAD_TYPE || err == BAD_TYPE) {
862 return BAD_VALUE;
863 }
864 auto print_help = [](int fd, const char* prefix = nullptr) {
865 StringLog log;
866 if (prefix != nullptr) {
867 log << prefix << std::endl;
868 }
869 log << "ApexService:" << std::endl
870 << " help - display this help" << std::endl
871 << " stagePackages [package_path1] ([package_path2]...) - stage "
872 "multiple packages from the given path"
873 << std::endl
874 << " getActivePackage [package_name] - return info for active package "
875 "with given name, if present"
876 << std::endl
877 << " getAllPackages - return the list of all packages" << std::endl
878 << " getActivePackages - return the list of active packages"
879 << std::endl
880 << " activatePackage [package_path] - activate package from the "
881 "given path"
882 << std::endl
883 << " deactivatePackage [package_path] - deactivate package from the "
884 "given path"
885 << std::endl
886 << " getStagedSessionInfo [sessionId] - displays information about a "
887 "given session previously submitted"
888 << std::endl
889 << " submitStagedSession [sessionId] - attempts to submit the "
890 "installer session with given id"
891 << std::endl
892 << " remountPackages - Force apexd to remount active packages. This "
893 "call can be used to speed up development workflow of an APEX "
894 "package. Example of usage:\n"
895 " 1. adb shell stop\n"
896 " 2. adb sync\n"
897 " 3. adb shell cmd -w apexservice remountPackages\n"
898 " 4. adb shell start\n"
899 "\n"
900 "Note: APEX package will be successfully remounted only if there "
901 "are no alive processes holding a reference to it"
902 << std::endl;
903 dprintf(fd, "%s", log.operator std::string().c_str());
904 };
905
906 if (args.size() == 0) {
907 print_help(err, "No command given");
908 return BAD_VALUE;
909 }
910
911 const String16& cmd = args[0];
912
913 if (cmd == String16("stagePackages")) {
914 if (args.size() < 2) {
915 print_help(err, "stagePackages requires at least one package_path");
916 return BAD_VALUE;
917 }
918 std::vector<std::string> pkgs;
919 pkgs.reserve(args.size() - 1);
920 for (size_t i = 1; i != args.size(); ++i) {
921 pkgs.emplace_back(String8(args[i]).string());
922 }
923 BinderStatus status = stagePackages(pkgs);
924 if (status.isOk()) {
925 return OK;
926 }
927 std::string msg = StringLog() << "Failed to stage package(s): "
928 << status.toString8().string() << std::endl;
929 dprintf(err, "%s", msg.c_str());
930 return BAD_VALUE;
931 }
932 if (cmd == String16("getAllPackages")) {
933 if (args.size() != 1) {
934 print_help(err, "Unrecognized options");
935 return BAD_VALUE;
936 }
937 std::vector<ApexInfo> list;
938 BinderStatus status = getAllPackages(&list);
939 if (status.isOk()) {
940 for (const auto& item : list) {
941 std::string msg = ToString(item);
942 dprintf(out, "%s", msg.c_str());
943 }
944 return OK;
945 }
946 std::string msg = StringLog() << "Failed to retrieve packages: "
947 << status.toString8().string() << std::endl;
948 dprintf(err, "%s", msg.c_str());
949 return BAD_VALUE;
950 }
951
952 if (cmd == String16("getActivePackages")) {
953 if (args.size() != 1) {
954 print_help(err, "Unrecognized options");
955 return BAD_VALUE;
956 }
957 std::vector<ApexInfo> list;
958 BinderStatus status = getActivePackages(&list);
959 if (status.isOk()) {
960 for (const auto& item : list) {
961 std::string msg = ToString(item);
962 dprintf(out, "%s", msg.c_str());
963 }
964 return OK;
965 }
966 std::string msg = StringLog() << "Failed to retrieve packages: "
967 << status.toString8().string() << std::endl;
968 dprintf(err, "%s", msg.c_str());
969 return BAD_VALUE;
970 }
971
972 if (cmd == String16("getActivePackage")) {
973 if (args.size() != 2) {
974 print_help(err, "Unrecognized options");
975 return BAD_VALUE;
976 }
977
978 ApexInfo package;
979 BinderStatus status = getActivePackage(String8(args[1]).string(), &package);
980 if (status.isOk()) {
981 std::string msg = ToString(package);
982 dprintf(out, "%s", msg.c_str());
983 return OK;
984 }
985
986 std::string msg = StringLog() << "Failed to fetch active package: "
987 << String8(args[1]).string()
988 << ", error: " << status.toString8().string()
989 << std::endl;
990 dprintf(err, "%s", msg.c_str());
991 return BAD_VALUE;
992 }
993
994 if (cmd == String16("activatePackage")) {
995 if (args.size() != 2) {
996 print_help(err, "activatePackage requires one package_path");
997 return BAD_VALUE;
998 }
999 std::string path = String8(args[1]).string();
1000 auto status = ::android::apex::ActivatePackage(path);
1001 if (status.ok()) {
1002 return OK;
1003 }
1004 std::string msg = StringLog() << "Failed to activate package: "
1005 << status.error().message() << std::endl;
1006 dprintf(err, "%s", msg.c_str());
1007 return BAD_VALUE;
1008 }
1009
1010 if (cmd == String16("deactivatePackage")) {
1011 if (args.size() != 2) {
1012 print_help(err, "deactivatePackage requires one package_path");
1013 return BAD_VALUE;
1014 }
1015 std::string path = String8(args[1]).string();
1016 auto status = ::android::apex::DeactivatePackage(path);
1017 if (status.ok()) {
1018 return OK;
1019 }
1020 std::string msg = StringLog() << "Failed to deactivate package: "
1021 << status.error().message() << std::endl;
1022 dprintf(err, "%s", msg.c_str());
1023 return BAD_VALUE;
1024 }
1025
1026 if (cmd == String16("getStagedSessionInfo")) {
1027 if (args.size() != 2) {
1028 print_help(err, "getStagedSessionInfo requires one session id");
1029 return BAD_VALUE;
1030 }
1031 int session_id = strtol(String8(args[1]).c_str(), nullptr, 10);
1032 if (session_id < 0) {
1033 std::string msg = StringLog()
1034 << "Failed to parse session id. Must be an integer.";
1035 dprintf(err, "%s", msg.c_str());
1036 return BAD_VALUE;
1037 }
1038
1039 ApexSessionInfo session_info;
1040 BinderStatus status = getStagedSessionInfo(session_id, &session_info);
1041 if (status.isOk()) {
1042 std::string revert_reason = "";
1043 std::string crashing_native_process = session_info.crashingNativeProcess;
1044 if (!crashing_native_process.empty()) {
1045 revert_reason = " revertReason: " + crashing_native_process;
1046 }
1047 std::string msg = StringLog()
1048 << "session_info: "
1049 << " isUnknown: " << session_info.isUnknown
1050 << " isVerified: " << session_info.isVerified
1051 << " isStaged: " << session_info.isStaged
1052 << " isActivated: " << session_info.isActivated
1053 << " isActivationFailed: "
1054 << session_info.isActivationFailed << revert_reason
1055 << std::endl;
1056 dprintf(out, "%s", msg.c_str());
1057 return OK;
1058 }
1059 std::string msg = StringLog() << "Failed to query session: "
1060 << status.toString8().string() << std::endl;
1061 dprintf(err, "%s", msg.c_str());
1062 return BAD_VALUE;
1063 }
1064
1065 if (cmd == String16("submitStagedSession")) {
1066 if (args.size() != 2) {
1067 print_help(err, "submitStagedSession requires one session id");
1068 return BAD_VALUE;
1069 }
1070 int session_id = strtol(String8(args[1]).c_str(), nullptr, 10);
1071 if (session_id < 0) {
1072 std::string msg = StringLog()
1073 << "Failed to parse session id. Must be an integer.";
1074 dprintf(err, "%s", msg.c_str());
1075 return BAD_VALUE;
1076 }
1077
1078 ApexInfoList list;
1079 std::vector<int> empty_child_session_ids;
1080 ApexSessionParams params;
1081 params.sessionId = session_id;
1082 params.childSessionIds = empty_child_session_ids;
1083 BinderStatus status = submitStagedSession(params, &list);
1084 if (status.isOk()) {
1085 for (const auto& item : list.apexInfos) {
1086 std::string msg = ToString(item);
1087 dprintf(out, "%s", msg.c_str());
1088 }
1089 return OK;
1090 }
1091 std::string msg = StringLog() << "Failed to submit session: "
1092 << status.toString8().string() << std::endl;
1093 dprintf(err, "%s", msg.c_str());
1094 return BAD_VALUE;
1095 }
1096
1097 if (cmd == String16("remountPackages")) {
1098 BinderStatus status = remountPackages();
1099 if (status.isOk()) {
1100 return OK;
1101 }
1102 std::string msg = StringLog() << "remountPackages failed: "
1103 << status.toString8().string() << std::endl;
1104 dprintf(err, "%s", msg.c_str());
1105 return BAD_VALUE;
1106 }
1107
1108 if (cmd == String16("help")) {
1109 if (args.size() != 1) {
1110 print_help(err, "Help has no options");
1111 return BAD_VALUE;
1112 }
1113 print_help(out);
1114 return OK;
1115 }
1116
1117 print_help(err);
1118 return BAD_VALUE;
1119 }
1120
1121 } // namespace
1122
1123 static constexpr const char* kApexServiceName = "apexservice";
1124
1125 using android::IPCThreadState;
1126 using android::ProcessState;
1127 using android::sp;
1128 using android::binder::LazyServiceRegistrar;
1129
CreateAndRegisterService()1130 void CreateAndRegisterService() {
1131 sp<ProcessState> ps(ProcessState::self());
1132
1133 // Create binder service and register with LazyServiceRegistrar
1134 sp<ApexService> apex_service = sp<ApexService>::make();
1135 auto lazy_registrar = LazyServiceRegistrar::getInstance();
1136 lazy_registrar.forcePersist(true);
1137 lazy_registrar.registerService(apex_service, kApexServiceName);
1138 }
1139
AllowServiceShutdown()1140 void AllowServiceShutdown() {
1141 auto lazy_registrar = LazyServiceRegistrar::getInstance();
1142 lazy_registrar.forcePersist(false);
1143 }
1144
StartThreadPool()1145 void StartThreadPool() {
1146 sp<ProcessState> ps(ProcessState::self());
1147
1148 // Start threadpool, wait for IPC
1149 ps->startThreadPool();
1150 }
1151
JoinThreadPool()1152 void JoinThreadPool() {
1153 IPCThreadState::self()->joinThreadPool(); // should not return
1154 }
1155
1156 } // namespace binder
1157 } // namespace apex
1158 } // namespace android
1159