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 <android-base/file.h>
20 #include <android-base/logging.h>
21 #include <android-base/properties.h>
22 #include <android-base/result.h>
23 #include <android-base/stringprintf.h>
24 #include <android-base/strings.h>
25 #include <android/apex/BnApexService.h>
26 #include <binder/IPCThreadState.h>
27 #include <binder/IResultReceiver.h>
28 #include <binder/IServiceManager.h>
29 #include <binder/LazyServiceRegistrar.h>
30 #include <binder/ProcessState.h>
31 #include <binder/Status.h>
32 #include <dirent.h>
33 #include <private/android_filesystem_config.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <utils/String16.h>
37
38 #include "apex_constants.h"
39 #include "apex_file.h"
40 #include "apex_file_repository.h"
41 #include "apexd.h"
42 #include "apexd_metrics.h"
43 #include "apexd_session.h"
44 #include "string_log.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(msg.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(msg.c_str()));
72 }
73 return BinderStatus::ok();
74 }
75
CheckCallerSystemKsOrRoot(const std::string & name)76 BinderStatus CheckCallerSystemKsOrRoot(const std::string& name) {
77 uid_t uid = IPCThreadState::self()->getCallingUid();
78 if (uid != AID_ROOT && uid != AID_SYSTEM && uid != AID_KEYSTORE) {
79 std::string msg =
80 "Only root, keystore, and system_server are allowed to call " + name;
81 return BinderStatus::fromExceptionCode(BinderStatus::EX_SECURITY,
82 String8(msg.c_str()));
83 }
84 return BinderStatus::ok();
85 }
86
87 class ApexService : public BnApexService {
88 public:
89 using BinderStatus = ::android::binder::Status;
90 using SessionState = ::apex::proto::SessionState;
91
ApexService()92 ApexService(){};
93
94 BinderStatus stagePackages(const std::vector<std::string>& paths) override;
95 BinderStatus unstagePackages(const std::vector<std::string>& paths) override;
96 BinderStatus submitStagedSession(const ApexSessionParams& params,
97 ApexInfoList* apex_info_list) override;
98 BinderStatus markStagedSessionReady(int session_id) override;
99 BinderStatus markStagedSessionSuccessful(int session_id) override;
100 BinderStatus getSessions(std::vector<ApexSessionInfo>* aidl_return) override;
101 BinderStatus getStagedSessionInfo(
102 int session_id, ApexSessionInfo* apex_session_info) override;
103 BinderStatus getStagedApexInfos(const ApexSessionParams& params,
104 std::vector<ApexInfo>* aidl_return) override;
105 BinderStatus getActivePackages(std::vector<ApexInfo>* aidl_return) override;
106 BinderStatus getAllPackages(std::vector<ApexInfo>* aidl_return) override;
107 BinderStatus abortStagedSession(int session_id) override;
108 BinderStatus revertActiveSessions() override;
109 BinderStatus resumeRevertIfNeeded() override;
110 BinderStatus snapshotCeData(int user_id, int rollback_id,
111 const std::string& apex_name) override;
112 BinderStatus restoreCeData(int user_id, int rollback_id,
113 const std::string& apex_name) override;
114 BinderStatus destroyDeSnapshots(int rollback_id) override;
115 BinderStatus destroyCeSnapshots(int user_id, int rollback_id) override;
116 BinderStatus destroyCeSnapshotsNotSpecified(
117 int user_id, const std::vector<int>& retain_rollback_ids) override;
118 BinderStatus recollectPreinstalledData() override;
119 BinderStatus markBootCompleted() override;
120 BinderStatus calculateSizeForCompressedApex(
121 const CompressedApexInfoList& compressed_apex_info_list,
122 int64_t* required_size) override;
123 BinderStatus reserveSpaceForCompressedApex(
124 const CompressedApexInfoList& compressed_apex_info_list) override;
125 BinderStatus installAndActivatePackage(const std::string& package_path,
126 bool force,
127 ApexInfo* aidl_return) override;
128
129 status_t dump(int fd, const Vector<String16>& args) override;
130
131 // Override onTransact so we can handle shellCommand.
132 status_t onTransact(uint32_t _aidl_code, const Parcel& _aidl_data,
133 Parcel* _aidl_reply, uint32_t _aidl_flags) override;
134
135 status_t shellCommand(int in, int out, int err, const Vector<String16>& args);
136 };
137
CheckDebuggable(const std::string & name)138 BinderStatus CheckDebuggable(const std::string& name) {
139 if (!::android::base::GetBoolProperty("ro.debuggable", false)) {
140 std::string tmp = name + " unavailable on non-debuggable builds";
141 return BinderStatus::fromExceptionCode(BinderStatus::EX_SECURITY,
142 String8(tmp.c_str()));
143 }
144 return BinderStatus::ok();
145 }
146
stagePackages(const std::vector<std::string> & paths)147 BinderStatus ApexService::stagePackages(const std::vector<std::string>& paths) {
148 LOG(INFO) << "stagePackages() received by ApexService, paths "
149 << android::base::Join(paths, ',');
150
151 BinderStatus debug_check = CheckDebuggable("stagePackages");
152 if (!debug_check.isOk()) {
153 return debug_check;
154 }
155 if (auto is_root = CheckCallerIsRoot("stagePackages"); !is_root.isOk()) {
156 return is_root;
157 }
158 Result<void> res = ::android::apex::StagePackages(paths);
159
160 if (res.ok()) {
161 return BinderStatus::ok();
162 }
163
164 LOG(ERROR) << "Failed to stage " << android::base::Join(paths, ',') << ": "
165 << res.error();
166 return BinderStatus::fromExceptionCode(
167 BinderStatus::EX_SERVICE_SPECIFIC,
168 String8(res.error().message().c_str()));
169 }
170
unstagePackages(const std::vector<std::string> & paths)171 BinderStatus ApexService::unstagePackages(
172 const std::vector<std::string>& paths) {
173 LOG(INFO) << "unstagePackages() received by ApexService, paths "
174 << android::base::Join(paths, ',');
175
176 if (auto check = CheckCallerSystemOrRoot("unstagePackages"); !check.isOk()) {
177 return check;
178 }
179
180 Result<void> res = ::android::apex::UnstagePackages(paths);
181 if (res.ok()) {
182 return BinderStatus::ok();
183 }
184
185 LOG(ERROR) << "Failed to unstage " << android::base::Join(paths, ',') << ": "
186 << res.error();
187 return BinderStatus::fromExceptionCode(
188 BinderStatus::EX_SERVICE_SPECIFIC,
189 String8(res.error().message().c_str()));
190 }
191
submitStagedSession(const ApexSessionParams & params,ApexInfoList * apex_info_list)192 BinderStatus ApexService::submitStagedSession(const ApexSessionParams& params,
193 ApexInfoList* apex_info_list) {
194 LOG(INFO) << "submitStagedSession() received by ApexService, session id "
195 << params.sessionId << " child sessions: ["
196 << android::base::Join(params.childSessionIds, ',') << "]";
197
198 auto check = CheckCallerSystemOrRoot("submitStagedSession");
199 if (!check.isOk()) {
200 return check;
201 }
202
203 Result<std::vector<ApexFile>> packages = ::android::apex::SubmitStagedSession(
204 params.sessionId, params.childSessionIds, params.hasRollbackEnabled,
205 params.isRollback, params.rollbackId);
206 if (!packages.ok()) {
207 LOG(ERROR) << "Failed to submit session id " << params.sessionId << ": "
208 << packages.error();
209 return BinderStatus::fromExceptionCode(
210 BinderStatus::EX_SERVICE_SPECIFIC,
211 String8(packages.error().message().c_str()));
212 }
213
214 for (const auto& package : *packages) {
215 ApexInfo out;
216 out.moduleName = package.GetManifest().name();
217 out.modulePath = package.GetPath();
218 out.versionCode = package.GetManifest().version();
219 apex_info_list->apexInfos.push_back(out);
220 }
221 return BinderStatus::ok();
222 }
223
markStagedSessionReady(int session_id)224 BinderStatus ApexService::markStagedSessionReady(int session_id) {
225 LOG(INFO) << "markStagedSessionReady() received by ApexService, session id "
226 << session_id;
227
228 auto check = CheckCallerSystemOrRoot("markStagedSessionReady");
229 if (!check.isOk()) {
230 return check;
231 }
232
233 Result<void> success = ::android::apex::MarkStagedSessionReady(session_id);
234 if (!success.ok()) {
235 LOG(ERROR) << "Failed to mark session id " << session_id
236 << " as ready: " << success.error();
237 return BinderStatus::fromExceptionCode(
238 BinderStatus::EX_SERVICE_SPECIFIC,
239 String8(success.error().message().c_str()));
240 }
241 return BinderStatus::ok();
242 }
243
markStagedSessionSuccessful(int session_id)244 BinderStatus ApexService::markStagedSessionSuccessful(int session_id) {
245 LOG(INFO)
246 << "markStagedSessionSuccessful() received by ApexService, session id "
247 << session_id;
248
249 auto check = CheckCallerSystemOrRoot("markStagedSessionSuccessful");
250 if (!check.isOk()) {
251 return check;
252 }
253
254 Result<void> ret = ::android::apex::MarkStagedSessionSuccessful(session_id);
255 if (!ret.ok()) {
256 LOG(ERROR) << "Failed to mark session " << session_id
257 << " as SUCCESS: " << ret.error();
258 return BinderStatus::fromExceptionCode(
259 BinderStatus::EX_ILLEGAL_ARGUMENT,
260 String8(ret.error().message().c_str()));
261 }
262 return BinderStatus::ok();
263 }
264
markBootCompleted()265 BinderStatus ApexService::markBootCompleted() {
266 LOG(INFO) << "markBootCompleted() received by ApexService";
267
268 auto check = CheckCallerSystemOrRoot("markBootCompleted");
269 if (!check.isOk()) {
270 return check;
271 }
272
273 ::android::apex::OnBootCompleted();
274 return BinderStatus::ok();
275 }
276
calculateSizeForCompressedApex(const CompressedApexInfoList & compressed_apex_info_list,int64_t * required_size)277 BinderStatus ApexService::calculateSizeForCompressedApex(
278 const CompressedApexInfoList& compressed_apex_info_list,
279 int64_t* required_size) {
280 std::vector<std::tuple<std::string, int64_t, int64_t>> compressed_apexes;
281 compressed_apexes.reserve(compressed_apex_info_list.apexInfos.size());
282 for (const auto& apex_info : compressed_apex_info_list.apexInfos) {
283 compressed_apexes.emplace_back(apex_info.moduleName, apex_info.versionCode,
284 apex_info.decompressedSize);
285 }
286 *required_size =
287 ::android::apex::CalculateSizeForCompressedApex(compressed_apexes);
288 return BinderStatus::ok();
289 }
290
reserveSpaceForCompressedApex(const CompressedApexInfoList & compressed_apex_info_list)291 BinderStatus ApexService::reserveSpaceForCompressedApex(
292 const CompressedApexInfoList& compressed_apex_info_list) {
293 int64_t required_size;
294 if (auto res = calculateSizeForCompressedApex(compressed_apex_info_list,
295 &required_size);
296 !res.isOk()) {
297 return res;
298 }
299 if (auto res = ReserveSpaceForCompressedApex(required_size, kOtaReservedDir);
300 !res.ok()) {
301 return BinderStatus::fromExceptionCode(
302 BinderStatus::EX_SERVICE_SPECIFIC,
303 String8(res.error().message().c_str()));
304 }
305 return BinderStatus::ok();
306 }
307
ClearSessionInfo(ApexSessionInfo * session_info)308 static void ClearSessionInfo(ApexSessionInfo* session_info) {
309 session_info->sessionId = -1;
310 session_info->isUnknown = false;
311 session_info->isVerified = false;
312 session_info->isStaged = false;
313 session_info->isActivated = false;
314 session_info->isRevertInProgress = false;
315 session_info->isActivationFailed = false;
316 session_info->isSuccess = false;
317 session_info->isReverted = false;
318 session_info->isRevertFailed = false;
319 }
320
ConvertToApexSessionInfo(const ApexSession & session,ApexSessionInfo * session_info)321 void ConvertToApexSessionInfo(const ApexSession& session,
322 ApexSessionInfo* session_info) {
323 using SessionState = ::apex::proto::SessionState;
324
325 ClearSessionInfo(session_info);
326 session_info->sessionId = session.GetId();
327 session_info->crashingNativeProcess = session.GetCrashingNativeProcess();
328 session_info->errorMessage = session.GetErrorMessage();
329
330 switch (session.GetState()) {
331 case SessionState::VERIFIED:
332 session_info->isVerified = true;
333 break;
334 case SessionState::STAGED:
335 session_info->isStaged = true;
336 break;
337 case SessionState::ACTIVATED:
338 session_info->isActivated = true;
339 break;
340 case SessionState::ACTIVATION_FAILED:
341 session_info->isActivationFailed = true;
342 break;
343 case SessionState::SUCCESS:
344 session_info->isSuccess = true;
345 break;
346 case SessionState::REVERT_IN_PROGRESS:
347 session_info->isRevertInProgress = true;
348 break;
349 case SessionState::REVERTED:
350 session_info->isReverted = true;
351 break;
352 case SessionState::REVERT_FAILED:
353 session_info->isRevertFailed = true;
354 break;
355 case SessionState::UNKNOWN:
356 default:
357 session_info->isUnknown = true;
358 break;
359 }
360 }
361
Cast(ApexPartition in)362 static ::android::apex::ApexInfo::Partition Cast(ApexPartition in) {
363 switch (in) {
364 case ApexPartition::System:
365 return ::android::apex::ApexInfo::Partition::SYSTEM;
366 case ApexPartition::SystemExt:
367 return ::android::apex::ApexInfo::Partition::SYSTEM_EXT;
368 case ApexPartition::Product:
369 return ::android::apex::ApexInfo::Partition::PRODUCT;
370 case ApexPartition::Vendor:
371 return ::android::apex::ApexInfo::Partition::VENDOR;
372 case ApexPartition::Odm:
373 return ::android::apex::ApexInfo::Partition::ODM;
374 }
375 }
376
GetApexInfo(const ApexFile & package)377 static ApexInfo GetApexInfo(const ApexFile& package) {
378 auto& instance = ApexFileRepository::GetInstance();
379 ApexInfo out;
380 out.moduleName = package.GetManifest().name();
381 out.modulePath = package.GetPath();
382 out.versionCode = package.GetManifest().version();
383 out.versionName = package.GetManifest().versionname();
384 out.isFactory = instance.IsPreInstalledApex(package);
385 out.isActive = false;
386 Result<std::string> preinstalled_path =
387 instance.GetPreinstalledPath(package.GetManifest().name());
388 if (preinstalled_path.ok()) {
389 out.preinstalledModulePath = *preinstalled_path;
390 }
391 out.activeApexChanged = ::android::apex::IsActiveApexChanged(package);
392 out.partition = Cast(OR_FATAL(instance.GetPartition(package)));
393 return out;
394 }
395
ToString(const ApexInfo & package)396 static std::string ToString(const ApexInfo& package) {
397 std::string msg =
398 StringLog() << "Module: " << package.moduleName
399 << " Version: " << package.versionCode
400 << " VersionName: " << package.versionName
401 << " Path: " << package.modulePath
402 << " IsActive: " << std::boolalpha << package.isActive
403 << " IsFactory: " << std::boolalpha << package.isFactory
404 << " Partition: " << toString(package.partition) << std::endl;
405 return msg;
406 }
407
getSessions(std::vector<ApexSessionInfo> * aidl_return)408 BinderStatus ApexService::getSessions(
409 std::vector<ApexSessionInfo>* aidl_return) {
410 LOG(INFO) << "getSessions() received by ApexService";
411
412 auto check = CheckCallerSystemOrRoot("getSessions");
413 if (!check.isOk()) {
414 return check;
415 }
416
417 auto sessions = GetSessionManager()->GetSessions();
418 for (const auto& session : sessions) {
419 ApexSessionInfo session_info;
420 ConvertToApexSessionInfo(session, &session_info);
421 aidl_return->push_back(session_info);
422 }
423
424 return BinderStatus::ok();
425 }
426
getStagedSessionInfo(int session_id,ApexSessionInfo * apex_session_info)427 BinderStatus ApexService::getStagedSessionInfo(
428 int session_id, ApexSessionInfo* apex_session_info) {
429 LOG(INFO) << "getStagedSessionInfo() received by ApexService, session id "
430 << session_id;
431
432 auto check = CheckCallerSystemOrRoot("getStagedSessionInfo");
433 if (!check.isOk()) {
434 return check;
435 }
436
437 auto session = GetSessionManager()->GetSession(session_id);
438 if (!session.ok()) {
439 // Unknown session.
440 ClearSessionInfo(apex_session_info);
441 apex_session_info->isUnknown = true;
442 return BinderStatus::ok();
443 }
444
445 ConvertToApexSessionInfo(*session, apex_session_info);
446
447 return BinderStatus::ok();
448 }
449
getStagedApexInfos(const ApexSessionParams & params,std::vector<ApexInfo> * aidl_return)450 BinderStatus ApexService::getStagedApexInfos(
451 const ApexSessionParams& params, std::vector<ApexInfo>* aidl_return) {
452 LOG(INFO) << "getStagedApexInfos() received by ApexService, session id "
453 << params.sessionId << " child sessions: ["
454 << android::base::Join(params.childSessionIds, ',') << "]";
455
456 auto check = CheckCallerSystemOrRoot("getStagedApexInfos");
457 if (!check.isOk()) {
458 return check;
459 }
460
461 Result<std::vector<ApexFile>> files = ::android::apex::GetStagedApexFiles(
462 params.sessionId, params.childSessionIds);
463 if (!files.ok()) {
464 LOG(ERROR) << "Failed to getStagedApexInfo session id " << params.sessionId
465 << ": " << files.error();
466 return BinderStatus::fromExceptionCode(
467 BinderStatus::EX_SERVICE_SPECIFIC,
468 String8(files.error().message().c_str()));
469 }
470
471 // Retrieve classpath information
472 auto class_path = ::android::apex::MountAndDeriveClassPath(*files);
473 if (!class_path.ok()) {
474 LOG(ERROR) << "Failed to getStagedApexInfo session id " << params.sessionId
475 << ": " << class_path.error();
476 return BinderStatus::fromExceptionCode(
477 BinderStatus::EX_SERVICE_SPECIFIC,
478 String8(class_path.error().message().c_str()));
479 }
480
481 for (const auto& apex_file : *files) {
482 ApexInfo apex_info = GetApexInfo(apex_file);
483 auto package_name = apex_info.moduleName;
484 apex_info.hasClassPathJars = class_path->HasClassPathJars(package_name);
485 aidl_return->push_back(std::move(apex_info));
486 }
487
488 return BinderStatus::ok();
489 }
490
getActivePackages(std::vector<ApexInfo> * aidl_return)491 BinderStatus ApexService::getActivePackages(
492 std::vector<ApexInfo>* aidl_return) {
493 LOG(INFO) << "getActivePackages received by ApexService";
494
495 auto check = CheckCallerSystemKsOrRoot("getActivePackages");
496 if (!check.isOk()) {
497 return check;
498 }
499
500 auto packages = ::android::apex::GetActivePackages();
501 for (const auto& package : packages) {
502 ApexInfo apex_info = GetApexInfo(package);
503 apex_info.isActive = true;
504 aidl_return->push_back(std::move(apex_info));
505 }
506
507 return BinderStatus::ok();
508 }
509
getAllPackages(std::vector<ApexInfo> * aidl_return)510 BinderStatus ApexService::getAllPackages(std::vector<ApexInfo>* aidl_return) {
511 LOG(INFO) << "getAllPackages received by ApexService";
512
513 auto check = CheckCallerSystemOrRoot("getAllPackages");
514 if (!check.isOk()) {
515 return check;
516 }
517
518 const auto& active = ::android::apex::GetActivePackages();
519 const auto& factory = ::android::apex::GetFactoryPackages();
520 for (const ApexFile& pkg : active) {
521 ApexInfo apex_info = GetApexInfo(pkg);
522 apex_info.isActive = true;
523 aidl_return->push_back(std::move(apex_info));
524 }
525 for (const ApexFile& pkg : factory) {
526 const auto& same_path = [&pkg](const auto& o) {
527 return o.GetPath() == pkg.GetPath();
528 };
529 if (std::find_if(active.begin(), active.end(), same_path) == active.end()) {
530 aidl_return->push_back(GetApexInfo(pkg));
531 }
532 }
533 return BinderStatus::ok();
534 }
535
installAndActivatePackage(const std::string & package_path,bool force,ApexInfo * aidl_return)536 BinderStatus ApexService::installAndActivatePackage(
537 const std::string& package_path, bool force, ApexInfo* aidl_return) {
538 LOG(INFO) << "installAndActivatePackage() received by ApexService, path: "
539 << package_path << " force : " << force;
540
541 auto check = CheckCallerSystemOrRoot("installAndActivatePackage");
542 if (!check.isOk()) {
543 return check;
544 }
545
546 if (force) {
547 auto debug_check = CheckDebuggable("Forced non-staged APEX update");
548 if (!debug_check.isOk()) {
549 return debug_check;
550 }
551 }
552
553 auto res = InstallPackage(package_path, force);
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
recollectPreinstalledData()721 BinderStatus ApexService::recollectPreinstalledData() {
722 LOG(INFO) << "recollectPreinstalledData() received by ApexService";
723
724 if (auto debug = CheckDebuggable("recollectPreinstalledData");
725 !debug.isOk()) {
726 return debug;
727 }
728 if (auto root = CheckCallerIsRoot("recollectPreinstalledData");
729 !root.isOk()) {
730 return root;
731 }
732
733 ApexFileRepository& instance = ApexFileRepository::GetInstance();
734 if (auto res = instance.AddPreInstalledApex(kBuiltinApexPackageDirs);
735 !res.ok()) {
736 return BinderStatus::fromExceptionCode(
737 BinderStatus::EX_SERVICE_SPECIFIC,
738 String8(res.error().message().c_str()));
739 }
740 return BinderStatus::ok();
741 }
742
onTransact(uint32_t _aidl_code,const Parcel & _aidl_data,Parcel * _aidl_reply,uint32_t _aidl_flags)743 status_t ApexService::onTransact(uint32_t _aidl_code, const Parcel& _aidl_data,
744 Parcel* _aidl_reply, uint32_t _aidl_flags) {
745 switch (_aidl_code) {
746 case IBinder::SHELL_COMMAND_TRANSACTION: {
747 int in = _aidl_data.readFileDescriptor();
748 int out = _aidl_data.readFileDescriptor();
749 int err = _aidl_data.readFileDescriptor();
750 int argc = _aidl_data.readInt32();
751 Vector<String16> args;
752 for (int i = 0; i < argc && _aidl_data.dataAvail() > 0; i++) {
753 args.add(_aidl_data.readString16());
754 }
755 sp<IBinder> unused_callback;
756 sp<IResultReceiver> result_receiver;
757 status_t status;
758 if ((status = _aidl_data.readNullableStrongBinder(&unused_callback)) !=
759 OK)
760 return status;
761 if ((status = _aidl_data.readNullableStrongBinder(&result_receiver)) !=
762 OK)
763 return status;
764 status = shellCommand(in, out, err, args);
765 if (result_receiver != nullptr) {
766 result_receiver->send(status);
767 }
768 return OK;
769 }
770 }
771 return BnApexService::onTransact(_aidl_code, _aidl_data, _aidl_reply,
772 _aidl_flags);
773 }
dump(int fd,const Vector<String16> &)774 status_t ApexService::dump(int fd, const Vector<String16>& /*args*/) {
775 std::vector<ApexInfo> list;
776 BinderStatus status = getActivePackages(&list);
777 dprintf(fd, "ACTIVE PACKAGES:\n");
778 if (!status.isOk()) {
779 std::string msg = StringLog() << "Failed to retrieve packages: "
780 << status.toString8().c_str() << std::endl;
781 dprintf(fd, "%s", msg.c_str());
782 return BAD_VALUE;
783 } else {
784 for (const auto& item : list) {
785 std::string msg = ToString(item);
786 dprintf(fd, "%s", msg.c_str());
787 }
788 }
789
790 dprintf(fd, "SESSIONS:\n");
791 std::vector<ApexSession> sessions = GetSessionManager()->GetSessions();
792
793 for (const auto& session : sessions) {
794 std::string child_ids_str = "";
795 auto child_ids = session.GetChildSessionIds();
796 if (child_ids.size() > 0) {
797 child_ids_str = "Child IDs:";
798 for (auto childSessionId : session.GetChildSessionIds()) {
799 child_ids_str += " " + std::to_string(childSessionId);
800 }
801 }
802 std::string revert_reason = "";
803 const auto& crashing_native_process = session.GetCrashingNativeProcess();
804 if (!crashing_native_process.empty()) {
805 revert_reason = " Revert Reason: " + crashing_native_process;
806 }
807 std::string error_message_dump = "";
808 const auto& error_message = session.GetErrorMessage();
809 if (!error_message.empty()) {
810 error_message_dump = " Error Message: " + error_message;
811 }
812 std::string msg =
813 StringLog() << "Session ID: " << session.GetId() << child_ids_str
814 << " State: " << SessionState_State_Name(session.GetState())
815 << revert_reason << error_message_dump << std::endl;
816 dprintf(fd, "%s", msg.c_str());
817 }
818
819 return OK;
820 }
821
shellCommand(int in,int out,int err,const Vector<String16> & args)822 status_t ApexService::shellCommand(int in, int out, int err,
823 const Vector<String16>& args) {
824 if (in == BAD_TYPE || out == BAD_TYPE || err == BAD_TYPE) {
825 return BAD_VALUE;
826 }
827 auto print_help = [](int fd, const char* prefix = nullptr) {
828 StringLog log;
829 if (prefix != nullptr) {
830 log << prefix << std::endl;
831 }
832 log << "ApexService:" << std::endl
833 << " help - display this help" << std::endl
834 << " getAllPackages - return the list of all packages" << std::endl
835 << " getActivePackages - return the list of active packages"
836 << std::endl
837 << " getStagedSessionInfo [sessionId] - displays information about a "
838 "given session previously submitted"
839 << std::endl;
840 dprintf(fd, "%s", log.operator std::string().c_str());
841 };
842
843 if (args.size() == 0) {
844 print_help(err, "No command given");
845 return BAD_VALUE;
846 }
847
848 const String16& cmd = args[0];
849
850 if (cmd == String16("getAllPackages")) {
851 if (args.size() != 1) {
852 print_help(err, "Unrecognized options");
853 return BAD_VALUE;
854 }
855 std::vector<ApexInfo> list;
856 BinderStatus status = getAllPackages(&list);
857 if (status.isOk()) {
858 for (const auto& item : list) {
859 std::string msg = ToString(item);
860 dprintf(out, "%s", msg.c_str());
861 }
862 return OK;
863 }
864 std::string msg = StringLog() << "Failed to retrieve packages: "
865 << status.toString8().c_str() << std::endl;
866 dprintf(err, "%s", msg.c_str());
867 return BAD_VALUE;
868 }
869
870 if (cmd == String16("getActivePackages")) {
871 if (args.size() != 1) {
872 print_help(err, "Unrecognized options");
873 return BAD_VALUE;
874 }
875 std::vector<ApexInfo> list;
876 BinderStatus status = getActivePackages(&list);
877 if (status.isOk()) {
878 for (const auto& item : list) {
879 std::string msg = ToString(item);
880 dprintf(out, "%s", msg.c_str());
881 }
882 return OK;
883 }
884 std::string msg = StringLog() << "Failed to retrieve packages: "
885 << status.toString8().c_str() << std::endl;
886 dprintf(err, "%s", msg.c_str());
887 return BAD_VALUE;
888 }
889
890 if (cmd == String16("getStagedSessionInfo")) {
891 if (args.size() != 2) {
892 print_help(err, "getStagedSessionInfo requires one session id");
893 return BAD_VALUE;
894 }
895 int session_id = strtol(String8(args[1]).c_str(), nullptr, 10);
896 if (session_id < 0) {
897 std::string msg = StringLog()
898 << "Failed to parse session id. Must be an integer.";
899 dprintf(err, "%s", msg.c_str());
900 return BAD_VALUE;
901 }
902
903 ApexSessionInfo session_info;
904 BinderStatus status = getStagedSessionInfo(session_id, &session_info);
905 if (status.isOk()) {
906 std::string revert_reason = "";
907 std::string crashing_native_process = session_info.crashingNativeProcess;
908 if (!crashing_native_process.empty()) {
909 revert_reason = " revertReason: " + crashing_native_process;
910 }
911 std::string msg = StringLog()
912 << "session_info: "
913 << " isUnknown: " << session_info.isUnknown
914 << " isVerified: " << session_info.isVerified
915 << " isStaged: " << session_info.isStaged
916 << " isActivated: " << session_info.isActivated
917 << " isActivationFailed: "
918 << session_info.isActivationFailed << revert_reason
919 << std::endl;
920 dprintf(out, "%s", msg.c_str());
921 return OK;
922 }
923 std::string msg = StringLog() << "Failed to query session: "
924 << status.toString8().c_str() << std::endl;
925 dprintf(err, "%s", msg.c_str());
926 return BAD_VALUE;
927 }
928
929 if (cmd == String16("help")) {
930 if (args.size() != 1) {
931 print_help(err, "Help has no options");
932 return BAD_VALUE;
933 }
934 print_help(out);
935 return OK;
936 }
937
938 print_help(err);
939 return BAD_VALUE;
940 }
941
942 } // namespace
943
944 static constexpr const char* kApexServiceName = "apexservice";
945
946 using android::IPCThreadState;
947 using android::ProcessState;
948 using android::sp;
949 using android::binder::LazyServiceRegistrar;
950
CreateAndRegisterService()951 void CreateAndRegisterService() {
952 sp<ProcessState> ps(ProcessState::self());
953
954 // Create binder service and register with LazyServiceRegistrar
955 sp<ApexService> apex_service = sp<ApexService>::make();
956 auto lazy_registrar = LazyServiceRegistrar::getInstance();
957 lazy_registrar.forcePersist(true);
958 lazy_registrar.registerService(apex_service, kApexServiceName);
959 }
960
AllowServiceShutdown()961 void AllowServiceShutdown() {
962 auto lazy_registrar = LazyServiceRegistrar::getInstance();
963 lazy_registrar.forcePersist(false);
964 }
965
StartThreadPool()966 void StartThreadPool() {
967 sp<ProcessState> ps(ProcessState::self());
968
969 // Start threadpool, wait for IPC
970 ps->startThreadPool();
971 }
972
JoinThreadPool()973 void JoinThreadPool() {
974 IPCThreadState::self()->joinThreadPool(); // should not return
975 }
976
977 } // namespace binder
978 } // namespace apex
979 } // namespace android
980