Lifecycle of ActivityManagerService
ActivityManagerService 的生命周期
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!
Cool
*downloads android exploit. Opens. Is eventually presented with privacy policy. Sees weblink.*
🤔 *Click*….*quickly scans*….
😯 *Reading more attentively*🕐…🤨🕜…🧐..🕝🕑………😐…🕝.😶….😶🌫️…..🤯*🧠level up!!* 💪 😎
Very useful and informative!!!
Greetings! Very useful advice in this particular article! Its the little changes that will make the biggest changes. Thanks for sharing!