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