Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c465946b authored by Ryuichiro Chiba's avatar Ryuichiro Chiba
Browse files

Implement the functionality for managing the native process

This CL implements the functionality for managing native application
process to NativeActivityThread.
Basically this functionality is a reimplementation of ActivityThread.

Bug: 402614577
Test: Run the test app
Flag: build.RELEASE_NATIVE_FRAMEWORK_PROTOTYPE

Change-Id: I18febe9981f18d9e94dc095828b164383fdb267a
parent fe6783b8
Loading
Loading
Loading
Loading
+23 −1
Original line number Diff line number Diff line
@@ -265,7 +265,12 @@ filegroup {
        "android/util/AndroidException.java",
        "android/view/DisplayAdjustments.java",
        "android/view/ViewDebug.java",
    ] + select(release_flag("RELEASE_NATIVE_FRAMEWORK_PROTOTYPE"), {
        true: [
            "android/app/INativeApplicationThread.aidl",
        ],
        default: [],
    }),
    visibility: ["//frameworks/base/test-mock"],
}

@@ -843,3 +848,20 @@ aidl_interface {
        },
    },
}

aidl_interface {
    name: "native_application_thread_aidl",
    srcs: [
        "android/app/INativeApplicationThread.aidl",
    ],
    unstable: true,
    backend: {
        java: {
            // java code is generated through framework-core-sources.
            enabled: false,
        },
        rust: {
            enabled: true,
        },
    },
}
+53 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

package android.app;

import java.util.List;
import java.util.Map;

/**
 * System private API for communicating with the application.  This is given to
 * the activity manager by an application  when it starts up, for the activity
 * manager to tell the application about things it needs to do.
 *
 * {@hide}
 */
oneway interface INativeApplicationThread {
    @UnsupportedAppUsage
    void scheduleCreateService(IBinder serviceToken,
            in List<String> libraryPaths, in String permittedLibsDir,
            in String libraryName, in String baseSymbolName, int processState);

    @UnsupportedAppUsage
    void scheduleDestroyService(IBinder serviceToken);

    @UnsupportedAppUsage
    void scheduleBindService(IBinder serviceToken, IBinder bindToken,
            int intentHash,
            in @nullable @utf8InCpp String action,
            in @nullable @utf8InCpp String data,
            boolean rebind, int processState, long bindSeq);

    @UnsupportedAppUsage
    void scheduleUnbindService(IBinder serviceToken, IBinder bindToken, int intentHash);

    @UnsupportedAppUsage
    void scheduleTrimMemory(int level);

    @UnsupportedAppUsage
    void bindApplication();
}
+16 −0
Original line number Diff line number Diff line
@@ -41,6 +41,20 @@ rust_bindgen {
    ],
}

rust_bindgen {
    name: "libnative_service_bindgen",
    crate_name: "native_service_bindgen",
    wrapper_src: "src/bindings/native_service.h",
    source_stem: "native_service_bindings",
    header_libs: [
        "libandroid_headers_private",
    ],
    shared_libs: [
        "libandroid",
        "libbinder_ndk",
    ],
}

rust_library {
    name: "libnative_activity_thread",
    crate_name: "native_activity_thread",
@@ -57,5 +71,7 @@ rust_library {
        "liblibc",
        "liblog_rust",
        "liblooper_bindgen",
        "libnative_service_bindgen",
        "native_application_thread_aidl-rust",
    ],
}
+2 −0
Original line number Diff line number Diff line
#include <native_service.h>
#include <native_service_private.h>
+40 −2
Original line number Diff line number Diff line
@@ -15,11 +15,23 @@

//! The crate providing the functionality to manage the native application process.

use activitymanager_structured_aidl::aidl::android::app::IActivityManagerStructured::IActivityManagerStructured;
use anyhow::{Context, Result};
use binder::{BinderFeatures, ProcessState, Strong};
use log::{info, LevelFilter};
use native_application_thread_aidl::aidl::android::app::INativeApplicationThread::BnNativeApplicationThread;

mod library_loader;
mod native_activity_thread;
mod native_application_thread;
mod task;

use crate::native_activity_thread::NativeActivityThread;
use crate::native_application_thread::NativeApplicationThread;
use crate::task::{run_thread_loop, Handler};

static ACTIVITY_MANAGER_SERVICE_NAME: &str = "activity_structured";

/// Start NativeActivityThread to manage the process.
pub fn run_native_activity_thread(start_seq: i64) -> ! {
    logger::init(
@@ -29,7 +41,33 @@ pub fn run_native_activity_thread(start_seq: i64) -> ! {
    );
    info!("Hello from the native activity thread! start_seq={start_seq}");

    // TODO(b/402614577): Implement the ActivityThread logic.
    // This must be done before creating any Binder client or server.
    ProcessState::start_thread_pool();

    let activity_manager = get_activity_manager_proxy().unwrap();

    // Prepare the handler of INativeApplicationThread requests from the ActivityManager
    let handler = Handler::new_on_current_thread(NativeActivityThread::new(
        activity_manager.clone(),
        start_seq,
    ))
    .unwrap();

    let sender = handler.get_sender().unwrap();
    let binder_node = BnNativeApplicationThread::new_binder(
        NativeApplicationThread::new(sender),
        BinderFeatures::default(),
    );

    // Notify the ActivityManager that this process is ready to be used for application.
    activity_manager.attachNativeApplication(&binder_node.as_binder(), start_seq).unwrap();

    // Start the main thread loop.
    run_thread_loop().unwrap();

    panic!("Shouldn't come here!");
}

    panic!("Something wrong happened!");
fn get_activity_manager_proxy() -> Result<Strong<dyn IActivityManagerStructured>> {
    binder::check_interface(ACTIVITY_MANAGER_SERVICE_NAME).context("Failed to find ActivityManager")
}
Loading