aconfig: follow Java conventions for Java file paths

Update codegen_java to write the generated Java file(s) to
"java/package/File.java" instead of just "File.java".

Also generalize codegen_java::GeneratedFile to commands::OutputFile in
preparation for the upcoming C++ and Rust codegen.

Also change Java package name to 'com.android.internal.aconfig'.

Bug: 279485059
Test: atest aconfig.test
Change-Id: I13978697e35010fe6be8637aa495d4b852dbed7e
diff --git a/tools/aconfig/src/main.rs b/tools/aconfig/src/main.rs
index 4abcb90..513e313 100644
--- a/tools/aconfig/src/main.rs
+++ b/tools/aconfig/src/main.rs
@@ -16,11 +16,12 @@
 
 //! `aconfig` is a build time tool to manage build time configurations, such as feature flags.
 
-use anyhow::Result;
+use anyhow::{anyhow, ensure, Result};
 use clap::{builder::ArgAction, builder::EnumValueParser, Arg, ArgMatches, Command};
 use std::fs;
 use std::io;
 use std::io::Write;
+use std::path::{Path, PathBuf};
 
 mod aconfig;
 mod cache;
@@ -29,7 +30,7 @@
 mod protos;
 
 use crate::cache::Cache;
-use commands::{Input, Source};
+use commands::{Input, OutputFile, Source};
 
 fn cli() -> Command {
     Command::new("aconfig")
@@ -68,6 +69,22 @@
     Ok(opened_files)
 }
 
+fn write_output_file_realtive_to_dir(root: &Path, output_file: &OutputFile) -> Result<()> {
+    ensure!(
+        root.is_dir(),
+        "output directory {} does not exist or is not a directory",
+        root.display()
+    );
+    let path = root.join(output_file.path.clone());
+    let parent = path
+        .parent()
+        .ok_or(anyhow!("unable to locate parent of output file {}", path.display()))?;
+    fs::create_dir_all(parent)?;
+    let mut file = fs::File::create(path)?;
+    file.write_all(&output_file.contents)?;
+    Ok(())
+}
+
 fn main() -> Result<()> {
     let matches = cli().get_matches();
     match matches.subcommand() {
@@ -84,12 +101,9 @@
             let path = sub_matches.get_one::<String>("cache").unwrap();
             let file = fs::File::open(path)?;
             let cache = Cache::read_from_reader(file)?;
-            let out = sub_matches.get_one::<String>("out").unwrap();
+            let dir = PathBuf::from(sub_matches.get_one::<String>("out").unwrap());
             let generated_file = commands::generate_code(&cache).unwrap();
-            fs::write(
-                format!("{}/{}", out, generated_file.file_name),
-                generated_file.file_content,
-            )?;
+            write_output_file_realtive_to_dir(&dir, &generated_file)?;
         }
         Some(("dump", sub_matches)) => {
             let path = sub_matches.get_one::<String>("cache").unwrap();