1 /*
2 * Copyright (C) 2021 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 //! Implementation of IIsolatedCompilationService, called from system server when compilation is
18 //! desired.
19
20 use crate::instance_manager::InstanceManager;
21 use crate::odrefresh_task::OdrefreshTask;
22 use android_system_composd::aidl::android::system::composd::{
23 ICompilationTask::{BnCompilationTask, ICompilationTask},
24 ICompilationTaskCallback::ICompilationTaskCallback,
25 IIsolatedCompilationService::{
26 ApexSource::ApexSource, BnIsolatedCompilationService, IIsolatedCompilationService,
27 },
28 };
29 use anyhow::{Context, Result};
30 use binder::{self, BinderFeatures, ExceptionCode, Interface, Status, Strong, ThreadState};
31 use compos_aidl_interface::aidl::com::android::compos::ICompOsService::CompilationMode::CompilationMode;
32 use compos_common::binder::to_binder_result;
33 use compos_common::odrefresh::{PENDING_ARTIFACTS_SUBDIR, TEST_ARTIFACTS_SUBDIR};
34 use rustutils::{users::AID_ROOT, users::AID_SYSTEM};
35 use std::sync::Arc;
36
37 pub struct IsolatedCompilationService {
38 instance_manager: Arc<InstanceManager>,
39 }
40
new_binder( instance_manager: Arc<InstanceManager>, ) -> Strong<dyn IIsolatedCompilationService>41 pub fn new_binder(
42 instance_manager: Arc<InstanceManager>,
43 ) -> Strong<dyn IIsolatedCompilationService> {
44 let service = IsolatedCompilationService { instance_manager };
45 BnIsolatedCompilationService::new_binder(service, BinderFeatures::default())
46 }
47
48 impl Interface for IsolatedCompilationService {}
49
50 impl IIsolatedCompilationService for IsolatedCompilationService {
startStagedApexCompile( &self, callback: &Strong<dyn ICompilationTaskCallback>, ) -> binder::Result<Strong<dyn ICompilationTask>>51 fn startStagedApexCompile(
52 &self,
53 callback: &Strong<dyn ICompilationTaskCallback>,
54 ) -> binder::Result<Strong<dyn ICompilationTask>> {
55 check_permissions()?;
56 to_binder_result(self.do_start_staged_apex_compile(callback))
57 }
58
startTestCompile( &self, apex_source: ApexSource, callback: &Strong<dyn ICompilationTaskCallback>, ) -> binder::Result<Strong<dyn ICompilationTask>>59 fn startTestCompile(
60 &self,
61 apex_source: ApexSource,
62 callback: &Strong<dyn ICompilationTaskCallback>,
63 ) -> binder::Result<Strong<dyn ICompilationTask>> {
64 check_permissions()?;
65 let prefer_staged = match apex_source {
66 ApexSource::NoStaged => false,
67 ApexSource::PreferStaged => true,
68 _ => unreachable!("Invalid ApexSource {:?}", apex_source),
69 };
70 to_binder_result(self.do_start_test_compile(prefer_staged, callback))
71 }
72 }
73
74 impl IsolatedCompilationService {
do_start_staged_apex_compile( &self, callback: &Strong<dyn ICompilationTaskCallback>, ) -> Result<Strong<dyn ICompilationTask>>75 fn do_start_staged_apex_compile(
76 &self,
77 callback: &Strong<dyn ICompilationTaskCallback>,
78 ) -> Result<Strong<dyn ICompilationTask>> {
79 let comp_os = self.instance_manager.start_current_instance().context("Starting CompOS")?;
80
81 let target_dir_name = PENDING_ARTIFACTS_SUBDIR.to_owned();
82 let task = OdrefreshTask::start(
83 comp_os,
84 CompilationMode::NORMAL_COMPILE,
85 target_dir_name,
86 callback,
87 )?;
88
89 Ok(BnCompilationTask::new_binder(task, BinderFeatures::default()))
90 }
91
do_start_test_compile( &self, prefer_staged: bool, callback: &Strong<dyn ICompilationTaskCallback>, ) -> Result<Strong<dyn ICompilationTask>>92 fn do_start_test_compile(
93 &self,
94 prefer_staged: bool,
95 callback: &Strong<dyn ICompilationTaskCallback>,
96 ) -> Result<Strong<dyn ICompilationTask>> {
97 let comp_os =
98 self.instance_manager.start_test_instance(prefer_staged).context("Starting CompOS")?;
99
100 let target_dir_name = TEST_ARTIFACTS_SUBDIR.to_owned();
101 let task = OdrefreshTask::start(
102 comp_os,
103 CompilationMode::TEST_COMPILE,
104 target_dir_name,
105 callback,
106 )?;
107
108 Ok(BnCompilationTask::new_binder(task, BinderFeatures::default()))
109 }
110 }
111
check_permissions() -> binder::Result<()>112 fn check_permissions() -> binder::Result<()> {
113 let calling_uid = ThreadState::get_calling_uid();
114 // This should only be called by system server, or root while testing
115 if calling_uid != AID_SYSTEM && calling_uid != AID_ROOT {
116 Err(Status::new_exception(ExceptionCode::SECURITY, None))
117 } else {
118 Ok(())
119 }
120 }
121