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