| // Copyright (C) 2025 The Android Open Source Project | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| //! Rust interface to the dropbox service. | |
| use anyhow::Result; | |
| use binder::{wait_for_interface, Strong}; | |
| use dropboxmanager_aidl::aidl::com::android::internal::os::IDropBoxManagerService::IDropBoxManagerService; | |
| const INTERFACE_NAME: &str = "dropbox"; | |
| /// Interface to the DropBox system service. | |
| pub struct DropBoxManager { | |
| binder: Strong<dyn IDropBoxManagerService>, | |
| } | |
| impl DropBoxManager { | |
| /// Acquires the underlying binder interface. | |
| pub fn new() -> Result<Self> { | |
| Ok(Self { binder: wait_for_interface(INTERFACE_NAME)? }) | |
| } | |
| /// Creates a dropbox entry with the supplied tag. The supplied text is passed as bytes to create the file contents. | |
| pub fn add_text(&self, tag: &str, text: &str) -> Result<()> { | |
| self.binder.addData(tag, text.as_bytes(), 2 /* DropBoxManager.java IS_TEXT */)?; | |
| Ok(()) | |
| } | |
| } | |
| #[cfg(test)] | |
| mod tests { | |
| use super::*; | |
| use std::fs; | |
| use std::path::PathBuf; | |
| const DROPBOX_PATH: &str = "/data/system/dropbox"; | |
| const TAG: &str = "foo"; | |
| const CONTENT: &str = "bar\nbaz\n"; | |
| #[test] | |
| fn add_text() { | |
| let _ = find_dropbox_files(true).unwrap(); | |
| let manager = DropBoxManager::new().unwrap(); | |
| manager.add_text(TAG, CONTENT).unwrap(); | |
| let path_buf = find_dropbox_files(false).unwrap().unwrap(); | |
| let content = fs::read_to_string(path_buf.as_path()).unwrap(); | |
| assert_eq!(content, CONTENT); | |
| } | |
| fn find_dropbox_files(delete_them: bool) -> Result<Option<PathBuf>> { | |
| let mut found = None; | |
| for entry in fs::read_dir(DROPBOX_PATH)? { | |
| let entry = entry?; | |
| let path_buf = entry.path(); | |
| if !path_buf.is_file() { | |
| continue; | |
| } | |
| let Some(filename) = path_buf.file_name() else { | |
| continue; | |
| }; | |
| let filename = filename.to_string_lossy(); | |
| if !filename.starts_with(TAG) { | |
| continue; | |
| } | |
| found = Some(path_buf.clone()); | |
| if delete_them { | |
| fs::remove_file(&path_buf)?; | |
| } else { | |
| break; | |
| } | |
| } | |
| Ok(found) | |
| } | |
| } |