这是用户在 2024-11-18 24:01 为 https://androidreverse.org/blog/2023/02/21/aosp-activitymanager-and-activitymanagerservice/ 保存的双语快照页面,由 沉浸式翻译 提供双语支持。了解如何保存?
Customize Consent Preferences
自定义同意首选项

We use cookies to help you navigate efficiently and perform certain functions. You will find detailed information about all cookies under each consent category below.... 
我们使用 cookie 来帮助您高效导航并执行某些功能。您将在下面找到有关每个同意类别下所有 cookie 的详细信息。

Always Active 始终处于活动状态

Necessary cookies are required to enable the basic features of this site, such as providing secure log-in or adjusting your consent preferences. These cookies do not store any personally identifiable data.
需要必要的 cookie 来启用本网站的基本功能,例如提供安全登录或调整您的同意偏好。这些 cookie 不存储任何个人身份数据。

No cookies to display.

Functional cookies help perform certain functionalities like sharing the content of the website on social media platforms, collecting feedback, and other third-party features.
功能性 cookie 有助于执行某些功能,例如在社交媒体平台上分享网站内容、收集反馈和其他第三方功能。

No cookies to display.

Analytical cookies are used to understand how visitors interact with the website. These cookies help provide information on metrics such as the number of visitors, bounce rate, traffic source, etc.
分析 Cookie 用于了解访问者如何与网站互动。这些 Cookie 有助于提供有关访客数量、跳出率、流量来源等指标的信息。

No cookies to display.

Performance cookies are used to understand and analyze the key performance indexes of the website which helps in delivering a better user experience for the visitors.
性能 cookie 用于了解和分析网站的关键性能指标,这有助于为访问者提供更好的用户体验。

No cookies to display.

Advertisement cookies are used to provide visitors with customized advertisements based on the pages you visited previously and to analyze the effectiveness of the ad campaigns.
广告 cookie 用于根据您之前访问的页面为访问者提供定制广告,并分析广告活动的有效性。

No cookies to display.

[AOSP] ActivityManager and ActivityManagerService
[AOSP]ActivityManager 和 ActivityManagerService

Lifecycle of ActivityManagerService
ActivityManagerService 的生命周期

Bildschirmfoto vom 2018-03-12 00-57-33
The Android Operating system consists of multiple Services like: AlarmManagerService, InputMethodManagerService, TrustManagerService, WindowManagerService, ServiceManager, PermissionController, SystemServer and also ActivityManagerService (see: https://android.googlesource.com/platform/frameworks/base/+/android-8.1.0_r18/services/core/java/com/android/server).
Android 操作系统由多个服务组成,例如:AlarmManagerService、InputMethodManagerService、TrustManagerService、WindowManagerService、ServiceManager、PermissionController、SystemServer 以及 ActivityManagerService(请参阅:https://android.googlesource.com/platform/frameworks/base/+/android-8.1.0_r18/services/core/java/com/android/server)。

 

Startup 启动

The lifecycle of ActivityManagerService begins with the following call in SystemServer.
ActivityManagerService 的生命周期从 SystemServer 中的以下调用开始。

startBootstrapServices(){
 [...] 
 traceBeginAndSlog("StartActivityManager");
 mActivityManagerService = mSystemServiceManager.startService( ActivityManagerService.Lifecycle.class).getService()
}

source: https://android.googlesource.com/platform/frameworks/base/+/android-8.1.0_r18/services/java/com/android/server/SystemServer.java : 510
来源: https://android.googlesource.com/platform/frameworks/base/+/android-8.1.0_r18/services/java/com/android/server/SystemServer.java : 510

Some of the core Services also where instantiated there and therefore belong to that process. By entering the following listed command you’ll see the system_server listed in the process table.
一些核心 Service 也在那里实例化,因此属于该进程。通过输入以下列出的命令,您将看到 process 表中列出了 system_server。

generic_x86:/ $ ps -A | grep system_server 
system 2151 2030 1559736 182860 SyS_epoll_wait 0 S system_serve

The SystemServiceManager is a component of SystemServer that handels  all system services running in SystemServer. See more about SystemServer in future posts.
SystemServiceManager 是 SystemServer 的一个组件,用于处理在 SystemServer 中运行的所有系统服务。在以后的文章中了解有关 SystemServer 的更多信息。

The SystemServer initializes ActivityManagerService with different values and connects it with other services like WindowManagerService. In general WindowManagerService and ActivityManagerService have a close relationship, because there won’t be any Activity without a Window. In android a Window can hold multiple activities and activities can hold multiple fragments.
SystemServer 使用不同的值初始化 ActivityManagerService,并将其与 WindowManagerService 等其他服务连接起来。通常,WindowManagerService 和 ActivityManagerService 具有密切的关系,因为没有 Window 就不会有任何 Activity。在 android 中,一个 Window 可以包含多个 Activity,而 Activity 可以包含多个 Fragment。

traceBeginAndSlog("SetWindowManagerService"); 
mActivityManagerService.setWindowManager(wm);

source: https://android.googlesource.com/platform/frameworks/base/+/android-8.1.0_r18/services/java/com/android/server/SystemServer.java : 845
来源: https://android.googlesource.com/platform/frameworks/base/+/android-8.1.0_r18/services/java/com/android/server/SystemServer.java : 845

After ActivityServiceManager and other system services are initialized, the SystemServer tells ActivityServiceManager to allow third party services or applications are allowed to run. The call systemReady(…) takes an callback as parameter, wich get’s called when ActivityManagerService is ready. SystemService starts now, alongside other matters, the system UI.
初始化 ActivityServiceManager 和其他系统服务后,SystemServer 会告知 ActivityServiceManager 允许第三方服务或应用程序运行。调用 systemReady(...) 将回调作为参数,当 ActivityManagerService 准备就绪时调用 get。SystemService 现在与其他事项一起启动系统 UI。

 // We now tell the activity manager it is okay to run third party
 // code. It will call back into us once it has gotten to the state
 // where third party code can really run (but before it has actually
 // started launching the initial applications), for us to complete our
 // initialization.
 mActivityManagerService.systemReady(() -> {
   Slog.i(TAG, "Making services ready");
   [...]
   startSystemUi(context, windowManagerF);
   [...]
 }, BOOT_TIMINGS_TRACE_LOG);

source: https://android.googlesource.com/platform/frameworks/base/+/android-8.1.0_r18/services/java/com/android/server/SystemServer.java : 1673
来源: https://android.googlesource.com/platform/frameworks/base/+/android-8.1.0_r18/services/java/com/android/server/SystemServer.java : 1673

By looking into the ActivityManagerService.systemReady(…) function, we recognize that systemReady(…) retrieves the devices serial number in order to provide it to new activities and starts the home activity. Home activity in that case means the activity that launches the launcher, an app that is inteded to show all apps to the user, in order to let him open an app. Except the user didn’t setup the system before by using welcome screen, the home activity doesn’t get system user permissions.
通过查看 ActivityManagerService.systemReady(...) 函数,我们发现 systemReady(...) 会检索设备序列号,以便将其提供给新 Activity 并启动 home activity。在这种情况下,Home activity 是指启动启动器的活动,该应用旨在向用户显示所有应用,以便用户打开应用。除了用户之前没有使用欢迎屏幕设置系统外,home activity 不会获得系统用户权限。

public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
    [...]
    sTheRealBuildSerial = IDeviceIdentifiersPolicyService.Stub.asInterface(ServiceManager.getService(Context.DEVICE_IDENTIFIERS_SERVICE)).getSerial();
    // Enable home activity for system user, so that the system can always boot. We don't   
    // do this when the system user is not setup since the setup wizard should be the one   
    // to handle home activity in this case.   
    [...]
    if (UserManager.isSplitSystemUser() && Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 0) != 0) {
        ComponentName cName = new ComponentName(mContext, SystemUserHomeActivity.class);
        try {
            AppGlobals.getPackageManager().setComponentEnabledSetting(cName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0, UserHandle.USER_SYSTEM);
        } catch (RemoteException e) {
            throw e.rethrowAsRuntimeException();
        }
    }
    startHomeActivityLocked(currentUserId, "systemReady");
    [...]
}

https://android.googlesource.com/platform/frameworks/base/+/android-8.1.0_r18/services/core/java/com/android/server/am/ActivityManagerService.java : 14148
https://android.googlesource.com/platform/frameworks/base/+/android-8.1.0_r18/services/core/java/com/android/server/am/ActivityManagerService.java : 14148

Shutdown 关闭

The ActivityManagerService is now started and ready for usage. It will run until the system will be shutdown. The function ActivityManagerService.shutDown(…) celebrates how the shutdown procedure of ActivityManagerService works.
ActivityManagerService 现已启动并可供使用。它将一直运行,直到系统关闭。函数 ActivityManagerService.shutDown(...) 庆祝 ActivityManagerService 的关闭过程的工作原理。

The first step is, to check if the calling user has got the required permissions, in that case the android.Manifest.permission.SHUTDOWN permission. By looking into checkCallingPermission, root user and system_server pid allways have the permission to call that function. If the check was successful the Activity stack get’s notified that we’re going to shutdown the system. After that all the other sub services will be shutdown too.
第一步是检查调用用户是否获得了所需的权限,在这种情况下是 android.Manifest.permission.SHUTDOWN 权限。通过查看 checkCallingPermission,root 用户和system_server pid 所有人都有权调用该函数。如果检查成功,则 Activity 堆栈会收到通知,我们将关闭系统。之后,所有其他子服务也将关闭。

@Override
public boolean shutdown(int timeout) {
    if (checkCallingPermission(android.Manifest.permission.SHUTDOWN) != PackageManager.PERMISSION_GRANTED) {
        throw new SecurityException("Requires permission " + android.Manifest.permission.SHUTDOWN);
    }
    boolean timedout = false;
    synchronized (this) {
        mShuttingDown = true;
        mStackSupervisor.prepareForShutdownLocked();
        updateEventDispatchingLocked();
        timedout = mStackSupervisor.shutdownLocked(timeout);
    }
    mAppOpsService.shutdown();
    if (mUsageStatsService != null) {
        mUsageStatsService.prepareShutdown();
    }
    mBatteryStatsService.shutdown();
    synchronized (this) {
        mProcessStats.shutdownLocked();
        notifyTaskPersisterLocked(null, true);
    }
    return timedout;
}

Communication

The ActivityManager

The ActivityManagerService can be reached by “client” processes by using the ActivityManger. This class represents the ActivityManagerService and provides an interface for communicate with that service. For transmit data from ActivityManger to ActivityManagerService, the Binder interface is used. The Binder interface will be explained in a future post. While looking into the ActivityManger you get a beatiful overview of all existing events of ActivityManagerService. But remember, not all functions you’ll see in ActivityManager are visible for App developers using Android SDK. Some of them are hidden api, so you’ll have to use Reflection to call them. An other position to get an overview over all events is the IActivityManager.java source file, generated by aidl (Android Interface Definition Language) by using IActivityManager.aidl. Please look at: https://android.googlesource.com/platform/frameworks/base/+/c80f952/core/java/android/app/IActivityManager.java

At the end of the file, you’ll see a lot of integers like:

START_ACTIVITY_TRANSACTION

the value of them define the event code, that must be send via the Binder interface, next to the event parameters. Let’s do an experiment here!

Send Activity finish

We’re going to send an FINISH_ACTIVITY_TRANSACTION event to ActivityManagerService and hope he finishes our activity, or at least gives us a positive return value. My code is usually writte in Kotlin because it’s the new Android way of writing code!

First, we define data Parcel and reply Parcel. A Parcel is an object that is able to be transmitted using Binder. By using writeInt(…), writeString(…) or something like that, the given value get’s serialized and stored into the Parcel.

While data is used to transfer data to our target Service, reply is used to receive the result. Then we’re using reflection in order to obtain the ActivityManagerService Binder interface from ServiceManager. ServiceManager holds all the representatives of Android’s system services. Then we get our Activity Binder token from our Activity instance by using Reflection. The mToken field holds the Binder token wich is used to identify our Activity in every Service. Now we initilize the Parcel’s and write the needed content into them.

The Parcel.writeInterfaceToken(…) is used by ActivityManagerService to consider that the sended event is targeted to him. The Service will check if the inserted string is equal to his package name.  Then we write the Activity’s Binder token and some values like result code and result intent. I suggest our Activity wasn’t started by using startActivityForResult(…) so we don’t have any results. Now we’re able to send our event via amBinder.transact(…) with the FINISH_ACTIVITY_TRANSACTION as event type.  By reading the first integer of our reply Parcel, we’re able to check if the transaction was successful. Take in mind that a negative value means our transaction failed.

fun finishActivity() {
    var reply: Parcel? = null
    var data: Parcel? = null
    val amBinder = Class.forName("android.os.ServiceManager").getMethod("getService", String::class.java).invoke(null, "activity") as IBinder
    val tokenField = Activity::class.java.getDeclaredField("mToken")
    tokenField.isAccessible = true
    val token = tokenField.get(getActivity()) as IBinder
    reply = Parcel.obtain()
    data = Parcel.obtain()
    data!!.writeInterfaceToken(ActivityManagerService.descriptor)
    data!!.writeStrongBinder(token)
    data!!.writeInt(0)
    data!!.writeInt(0)
    NativeInterface.onNativeLog("transact: " + data + " with token: " + token)
    amBinder.transact(ActivityManagerService.FINISH_ACTIVITY_TRANSACTION, data, reply, 0)
    var resValue: Int = reply!!.readInt()
    NativeInterface.onNativeLog("received: " + resValue)
    if (resValue < 0) {
        NativeInterface.onNativeLog("Transaction failed")
    } else {
        NativeInterface.onNativeLog("Transaction successful")
    }
}

After execute that code I got the following results on API 27 emulator:

03-11 23:51:00.683 12198-12225/com.saroteck.exploittester D/native: transact: android.os.Parcel@9a23f11 with token: android.os.BinderProxy@e0daee9
03-11 23:51:00.689 1616-2739/system_process W/ActivityManager: Force removing ActivityRecord{d3c1d31 u0 com.saroteck.exploittester/.MainActivity t57}: app died, no saved state
03-11 23:51:00.689 12246-12246/? I/cr_ChildProcessService: Destroying ChildProcessService pid=12246
03-11 23:51:00.702 1616-2739/system_process I/WindowManager: Failed to capture screenshot of Token{8638c16 ActivityRecord{d3c1d31 u0 com.saroteck.exploittester/.MainActivity t57 f}} appWin=Window{ff00d1f u0 Zeroday Kitchen} drawState=4
03-11 23:51:00.706 1616-2739/system_process W/ActivityManager: Crash of app com.saroteck.exploittester running instrumentation ComponentInfo{com.saroteck.exploittester.test/android.support.test.runner.AndroidJUnitRunner}
03-11 23:51:00.706 1616-2739/system_process I/ActivityManager: Force stopping com.saroteck.exploittester appid=10081 user=0: finished inst

You see, our app was finished imedately. The result value wasn’t parced because our activity was already removed befour our process was able to execute that line of code.

I guess you ask yourself, how to identify the content to write into our Parcel? To answer this question, take a look into the next ActivityManagerNative.java that defines the client side of aidl. The function finishActivity(…) shows us how to write the transaction to ActivityManagerService.

public boolean finishActivity(IBinder token, int resultCode, Intent resultData)
        throws RemoteException {
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IActivityManager.descriptor);
    data.writeStrongBinder(token);
    data.writeInt(resultCode);
    if (resultData != null) {
        data.writeInt(1);
        resultData.writeToParcel(data, 0);
    } else {
        data.writeInt(0);
    }
    mRemote.transact(FINISH_ACTIVITY_TRANSACTION, data, reply, 0);
    reply.readException();
    boolean res = reply.readInt() != 0;
    data.recycle();
    reply.recycle();
    return res;
}

source: https://android.googlesource.com/platform/frameworks/base/+/a45746e/core/java/android/app/ActivityManagerNative.java

Most recent events

Start Activity

Starting activity’s will be done by calling the startActivity(…) the Binder interface of ActivityManagerService provides different versions of it. Some are able to start an activity as different user (the user id is also an app identifier on android) or able to start multiple activities simultaneously.

Finish Activity

This event finishes the current activity identified by the given Binder token.

ACTIVITY_PAUSED_TRANSACTION

This event will be send to ActivityManagerService to set the Activtiy state to pause.

ACTIVITY_STOPPED_TRANSACTION

This event will be send to ActivityManagerService to set the Activtiy state to stopped.

HANG_TRANSACTION

This event will be send to inform ActivtiyManagerService that our application is hanging. The ActivityManagerService then, displays an dialog out of an other process in order to let the user decide to wait or to exit the application.

Conclusion

There are a lot of other Events take a look at ActivityManagerNative or IActivityManager.java.

The ActivityManagerService handels the lifecycle of all Activities running on the Operating system. It is one of the most important System Services of Android. If you wan’t a more deep diving article, feel free to comment!

4 Comments

  1. *downloads android exploit. Opens. Is eventually presented with privacy policy. Sees weblink.*
    🤔 *Click*….*quickly scans*….
    😯 *Reading more attentively*🕐…🤨🕜…🧐..🕝🕑………😐…🕝.😶….😶‍🌫️…..🤯*🧠level up!!* 💪 😎

Comments are closed.