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