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