blob: ab28e0a2e6a910661ab0b59790b4b180ea423cf5 [file] [log] [blame]
Alan Stokes3ef78d92021-09-08 11:51:06 +01001/*
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
Alan Stokes9ca14ca2021-10-20 14:25:57 +010020use crate::compilation_task::CompilationTask;
Victor Hsieh72c774c2021-11-18 15:52:28 -080021use crate::fd_server_helper::FdServerConfig;
Alan Stokesa2869d22021-09-22 09:06:41 +010022use crate::instance_manager::InstanceManager;
Alan Stokes8c840442021-11-26 15:54:30 +000023use crate::odrefresh_task::OdrefreshTask;
Alan Stokes9ca14ca2021-10-20 14:25:57 +010024use crate::util::to_binder_result;
25use android_system_composd::aidl::android::system::composd::{
26 ICompilationTask::{BnCompilationTask, ICompilationTask},
27 ICompilationTaskCallback::ICompilationTaskCallback,
28 IIsolatedCompilationService::{BnIsolatedCompilationService, IIsolatedCompilationService},
Alan Stokes3ef78d92021-09-08 11:51:06 +010029};
Alan Stokescb732dc2021-11-16 15:18:13 +000030use android_system_composd::binder::{
31 self, BinderFeatures, ExceptionCode, Interface, Status, Strong, ThreadState,
32};
Alan Stokes9ca14ca2021-10-20 14:25:57 +010033use anyhow::{Context, Result};
Victor Hsieh72c774c2021-11-18 15:52:28 -080034use rustutils::{system_properties, users::AID_ROOT, users::AID_SYSTEM};
Victor Hsieh6fb8b252021-12-03 16:30:04 -080035use std::fs::{File, OpenOptions};
Victor Hsieh72c774c2021-11-18 15:52:28 -080036use std::os::unix::fs::OpenOptionsExt;
37use std::os::unix::io::AsRawFd;
Victor Hsieh6fb8b252021-12-03 16:30:04 -080038use std::path::Path;
Alan Stokese5e1d8d2021-11-19 16:31:14 +000039use std::sync::Arc;
Alan Stokes3ef78d92021-09-08 11:51:06 +010040
Alan Stokesa2869d22021-09-22 09:06:41 +010041pub struct IsolatedCompilationService {
Alan Stokese5e1d8d2021-11-19 16:31:14 +000042 instance_manager: Arc<InstanceManager>,
Alan Stokesa2869d22021-09-22 09:06:41 +010043}
Alan Stokes3ef78d92021-09-08 11:51:06 +010044
Alan Stokese5e1d8d2021-11-19 16:31:14 +000045pub fn new_binder(
46 instance_manager: Arc<InstanceManager>,
47) -> Strong<dyn IIsolatedCompilationService> {
Alan Stokes69c610f2021-09-27 14:03:31 +010048 let service = IsolatedCompilationService { instance_manager };
Alan Stokes3ef78d92021-09-08 11:51:06 +010049 BnIsolatedCompilationService::new_binder(service, BinderFeatures::default())
50}
51
Alan Stokes3ef78d92021-09-08 11:51:06 +010052impl Interface for IsolatedCompilationService {}
53
54impl IIsolatedCompilationService for IsolatedCompilationService {
Alan Stokes6fc18372021-11-25 17:50:27 +000055 fn startStagedApexCompile(
56 &self,
57 callback: &Strong<dyn ICompilationTaskCallback>,
58 ) -> binder::Result<Strong<dyn ICompilationTask>> {
59 check_permissions()?;
60 to_binder_result(self.do_start_staged_apex_compile(callback))
61 }
62
Alan Stokes9ca14ca2021-10-20 14:25:57 +010063 fn startTestCompile(
64 &self,
65 callback: &Strong<dyn ICompilationTaskCallback>,
66 ) -> binder::Result<Strong<dyn ICompilationTask>> {
Alan Stokes6fc18372021-11-25 17:50:27 +000067 check_permissions()?;
Alan Stokes9ca14ca2021-10-20 14:25:57 +010068 to_binder_result(self.do_start_test_compile(callback))
Alan Stokesb2cc79e2021-09-14 14:08:46 +010069 }
Victor Hsieh72c774c2021-11-18 15:52:28 -080070
Alan Stokes8c840442021-11-26 15:54:30 +000071 fn startAsyncOdrefresh(
72 &self,
73 callback: &Strong<dyn ICompilationTaskCallback>,
74 ) -> binder::Result<Strong<dyn ICompilationTask>> {
75 check_permissions()?;
76 to_binder_result(self.do_start_async_odrefresh(callback))
77 }
78
Victor Hsieh72c774c2021-11-18 15:52:28 -080079 fn startTestOdrefresh(&self) -> binder::Result<i8> {
Alan Stokes6fc18372021-11-25 17:50:27 +000080 check_permissions()?;
Victor Hsieh72c774c2021-11-18 15:52:28 -080081 to_binder_result(self.do_odrefresh_for_test())
82 }
Alan Stokesb2cc79e2021-09-14 14:08:46 +010083}
84
Alan Stokesb2cc79e2021-09-14 14:08:46 +010085impl IsolatedCompilationService {
Alan Stokes6fc18372021-11-25 17:50:27 +000086 fn do_start_staged_apex_compile(
87 &self,
88 callback: &Strong<dyn ICompilationTaskCallback>,
89 ) -> Result<Strong<dyn ICompilationTask>> {
90 // TODO: Try to start the current instance with staged APEXes to see if it works?
91 let comp_os = self.instance_manager.start_pending_instance().context("Starting CompOS")?;
92
93 let task = CompilationTask::start_staged_apex_compile(comp_os, callback)?;
94
95 Ok(BnCompilationTask::new_binder(task, BinderFeatures::default()))
96 }
97
Alan Stokes9ca14ca2021-10-20 14:25:57 +010098 fn do_start_test_compile(
99 &self,
100 callback: &Strong<dyn ICompilationTaskCallback>,
101 ) -> Result<Strong<dyn ICompilationTask>> {
Alan Stokes388b88a2021-10-13 16:03:17 +0100102 let comp_os = self.instance_manager.start_test_instance().context("Starting CompOS")?;
Alan Stokesb2cc79e2021-09-14 14:08:46 +0100103
Alan Stokes9ca14ca2021-10-20 14:25:57 +0100104 let task = CompilationTask::start_test_compile(comp_os, callback)?;
Alan Stokesb2cc79e2021-09-14 14:08:46 +0100105
Alan Stokes9ca14ca2021-10-20 14:25:57 +0100106 Ok(BnCompilationTask::new_binder(task, BinderFeatures::default()))
Alan Stokes3ef78d92021-09-08 11:51:06 +0100107 }
Victor Hsieh72c774c2021-11-18 15:52:28 -0800108
Alan Stokes8c840442021-11-26 15:54:30 +0000109 fn do_start_async_odrefresh(
110 &self,
111 callback: &Strong<dyn ICompilationTaskCallback>,
112 ) -> Result<Strong<dyn ICompilationTask>> {
113 let output_dir_path =
114 composd_native::palette_create_odrefresh_staging_directory()?.to_path_buf();
115
116 let comp_os = self.instance_manager.start_test_instance().context("Starting CompOS")?;
117
118 let task = OdrefreshTask::start(comp_os, output_dir_path, callback)?;
119
120 Ok(BnCompilationTask::new_binder(task, BinderFeatures::default()))
121 }
122
Victor Hsieh72c774c2021-11-18 15:52:28 -0800123 fn do_odrefresh_for_test(&self) -> Result<i8> {
Victor Hsieh72c774c2021-11-18 15:52:28 -0800124 let compos = self
125 .instance_manager
126 .start_test_instance()
127 .context("Starting CompOS for odrefresh test")?;
Victor Hsieh72c774c2021-11-18 15:52:28 -0800128
Victor Hsieh6fb8b252021-12-03 16:30:04 -0800129 let output_dir = open_dir(composd_native::palette_create_odrefresh_staging_directory()?)?;
Victor Hsieh16804022021-12-01 14:09:13 -0800130 let system_dir = open_dir(Path::new("/system"))?;
Victor Hsieh72c774c2021-11-18 15:52:28 -0800131
132 // Spawn a fd_server to serve the FDs.
133 let fd_server_config = FdServerConfig {
134 ro_dir_fds: vec![system_dir.as_raw_fd()],
135 rw_dir_fds: vec![output_dir.as_raw_fd()],
136 ..Default::default()
137 };
138 let fd_server_raii = fd_server_config.into_fd_server()?;
139
140 let zygote_arch = system_properties::read("ro.zygote")?;
141 let result = compos.get_service().odrefresh(
142 system_dir.as_raw_fd(),
143 output_dir.as_raw_fd(),
144 &zygote_arch,
145 );
146 drop(fd_server_raii);
147 Ok(result?.exitCode)
148 }
149}
150
Alan Stokes6fc18372021-11-25 17:50:27 +0000151fn check_permissions() -> binder::Result<()> {
Victor Hsieh72c774c2021-11-18 15:52:28 -0800152 let calling_uid = ThreadState::get_calling_uid();
153 // This should only be called by system server, or root while testing
154 if calling_uid != AID_SYSTEM && calling_uid != AID_ROOT {
155 Err(Status::new_exception(ExceptionCode::SECURITY, None))
156 } else {
157 Ok(())
158 }
159}
160
Victor Hsieh16804022021-12-01 14:09:13 -0800161/// Returns an owned FD of the directory. It currently returns a `File` as a FD owner, but
Victor Hsieh72c774c2021-11-18 15:52:28 -0800162/// it's better to use `std::os::unix::io::OwnedFd` once/if it becomes standard.
Alan Stokes8c840442021-11-26 15:54:30 +0000163pub fn open_dir(path: &Path) -> Result<File> {
Victor Hsieh72c774c2021-11-18 15:52:28 -0800164 OpenOptions::new()
Victor Hsieh16804022021-12-01 14:09:13 -0800165 .custom_flags(libc::O_DIRECTORY)
166 .read(true) // O_DIRECTORY can only be opened with read
Victor Hsieh72c774c2021-11-18 15:52:28 -0800167 .open(path)
Alan Stokes6fc18372021-11-25 17:50:27 +0000168 .with_context(|| format!("Failed to open {:?} directory as path fd", path))
Alan Stokes3ef78d92021-09-08 11:51:06 +0100169}