Introduce derive_classpath service.

Initial version simply copies existing /etc/classpath to
/data/system/environ/classpath for init to export.

The topic also sets appropriate sepolicy rules for the service.

See go/updatable-classpath for more details.

Bug: 180105615
Test: manual + boot test
Change-Id: I6e3c64e7a68ae8803f77c30f0698551fd79a350b
diff --git a/Android.bp b/Android.bp
index e6302aa..87a811e 100644
--- a/Android.bp
+++ b/Android.bp
@@ -20,7 +20,10 @@
 apex {
     name: "com.android.sdkext",
     defaults: [ "com.android.sdkext-defaults" ],
-    binaries: [ "derive_sdk" ],
+    binaries: [
+        "derive_classpath",
+        "derive_sdk",
+    ],
     java_libs: [ "framework-sdkextensions" ],
     prebuilts: [
         "cur_sdkinfo",
@@ -35,6 +38,7 @@
     updatable: true,
     min_sdk_version: "30",
     prebuilts: [
+        "derive_classpath.rc",
         "derive_sdk.rc",
     ],
     key: "com.android.sdkext.key",
diff --git a/derive_classpath/.clang-format b/derive_classpath/.clang-format
new file mode 120000
index 0000000..86b1593
--- /dev/null
+++ b/derive_classpath/.clang-format
@@ -0,0 +1 @@
+../../../../build/soong/scripts/system-clang-format-2
\ No newline at end of file
diff --git a/derive_classpath/Android.bp b/derive_classpath/Android.bp
new file mode 100644
index 0000000..2bcc715
--- /dev/null
+++ b/derive_classpath/Android.bp
@@ -0,0 +1,63 @@
+// Copyright (C) 2019 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.
+
+cc_defaults {
+    name: "derive_classpath-defaults",
+    min_sdk_version: "30",
+    shared_libs: ["liblog"],
+    // static c++/libbase for smaller size
+    stl: "c++_static",
+    static_libs: [
+        "libbase",
+        "libmodules-utils-build",
+        "libprotobuf-cpp-lite",
+    ],
+}
+
+cc_library {
+    name: "libderive_classpath",
+    srcs: ["derive_classpath.cpp"],
+    defaults: ["derive_classpath-defaults"],
+    apex_available: ["com.android.sdkext"],
+}
+
+cc_defaults {
+    name: "derive_classpath_binary-defaults",
+    defaults: ["derive_classpath-defaults"],
+    srcs: ["main.cpp"],
+    static_libs: ["libderive_classpath"],
+}
+
+cc_binary {
+    name: "derive_classpath",
+    defaults: ["derive_classpath_binary-defaults"],
+    apex_available: ["com.android.sdkext"],
+}
+
+// Work around testing using a 64-bit test suite on 32-bit test device by
+// using a prefer32 version of derive_sdk in testing.
+cc_binary {
+    name: "derive_classpath_prefer32",
+    defaults: ["derive_classpath_binary-defaults"],
+    compile_multilib: "prefer32",
+    stem: "derive_classpath",
+    apex_available: ["test_com.android.sdkext"],
+    installable: false,
+}
+
+prebuilt_etc {
+    name: "derive_classpath.rc",
+    src: "derive_classpath.rc",
+    installable: false,
+}
diff --git a/derive_classpath/derive_classpath.cpp b/derive_classpath/derive_classpath.cpp
new file mode 100644
index 0000000..b20dfe0
--- /dev/null
+++ b/derive_classpath/derive_classpath.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#include "derive_classpath.h"
+#include <android-base/file.h>
+#include <android-base/logging.h>
+
+namespace android {
+namespace derive_classpath {
+
+static const std::string kBaseClasspathExportsFilepath = "/system/etc/classpath";
+static const std::string kGeneratedClasspathExportsFilepath = "/data/system/environ/classpath";
+
+bool GenerateClasspathExports() {
+  std::string contents;
+  if (!android::base::ReadFileToString(kBaseClasspathExportsFilepath, &contents)) {
+    PLOG(ERROR) << "Failed to read " << kBaseClasspathExportsFilepath;
+    return false;
+  }
+
+  if (!android::base::WriteStringToFile(contents, kGeneratedClasspathExportsFilepath)) {
+    PLOG(ERROR) << "Failed to write " << kGeneratedClasspathExportsFilepath;
+  }
+
+  return true;
+}
+
+}  // namespace derive_classpath
+}  // namespace android
diff --git a/derive_classpath/derive_classpath.h b/derive_classpath/derive_classpath.h
new file mode 100644
index 0000000..ea75c37
--- /dev/null
+++ b/derive_classpath/derive_classpath.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#pragma once
+
+#include <string>
+
+namespace android {
+namespace derive_classpath {
+
+bool GenerateClasspathExports();
+
+}  // namespace derive_classpath
+}  // namespace android
diff --git a/derive_classpath/derive_classpath.rc b/derive_classpath/derive_classpath.rc
new file mode 100644
index 0000000..262b89e
--- /dev/null
+++ b/derive_classpath/derive_classpath.rc
@@ -0,0 +1,5 @@
+service derive_classpath /apex/com.android.sdkext/bin/derive_classpath
+    user system
+    group system
+    oneshot
+    disabled
diff --git a/derive_classpath/main.cpp b/derive_classpath/main.cpp
new file mode 100644
index 0000000..71e11e7
--- /dev/null
+++ b/derive_classpath/main.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#include <cstdlib>
+
+#include "derive_classpath.h"
+
+int main(int, char**) {
+  if (!android::derive_classpath::GenerateClasspathExports()) {
+    return EXIT_FAILURE;
+  }
+  return EXIT_SUCCESS;
+}
diff --git a/testing/Android.bp b/testing/Android.bp
index 6abdd5a..46c40e1 100644
--- a/testing/Android.bp
+++ b/testing/Android.bp
@@ -29,7 +29,10 @@
     installable: false, // Should never be installed on the systemimage
     multilib: {
         prefer32: {
-            binaries: ["derive_sdk_prefer32"],
+            binaries: [
+                "derive_classpath_prefer32",
+                "derive_sdk_prefer32",
+            ],
         },
     },
     // The automated test infra ends up building this apex for 64+32-bit and