OverviewFollowing the last requirement of starting an Activity in the background, I followed some methods in Actual Combat | Android Background Start Activity Practice Road to handle it. Although there are still some problems on the Android Q version, the ability to start in the background is basically complete. Later, I unlocked the source code of Xiaomi ROM and found out how they implemented the permission of background start and how to bypass this permission. I found that the result was unexpectedly simple... (I will write a separate article on this part later if I have the opportunity).
This article was written after the investigation of background startup. If the Activity page we want to start in the background is in a third-party SDK, and the action (startActivity) to start the page also occurs in the third-party SDK, then their direct startActivity method does not have the ability to start in the background. For some reasons, we cannot ask the SDK to modify the method of starting the Activity, so we need to find a way to enable it to have the ability to start in the background without modifying the third-party SDK's call to startActivity code. The first reaction is to intercept the request for startActivity. Referring to the Android system_server process and the Android-Activity startup process, we know that AMS is a thread in the system_server process. It is responsible for the specific work of starting the Activity. After its work is completed, it will call back the life cycle method of the Activity instance in the APP process through Binder. When the APP process calls startActivity, the Binder proxy of AMS will be obtained by Instrumentation, and then the relevant methods of AMS will be called across processes through it. The place where we can do Hook interception is this Binder proxy object! Next, we will look at the implementation method of this process and how we intercept it in various Android versions. We will mainly look at the source code of Android P. Although the processes of other versions are different, the Hook method is similar. Android PThe way to obtain the AMS agent in AOSP from Android 8 to Android 9 is the same. After calling context.startActivity, the APP process will come to the relevant method in Instrumentation and call the following code:
Here, we use Binder to call the relevant methods in AMS across processes. Let’s take a look at the implementation of ActivityManager.getService():
You can see that IActivityManagerSingleton is an instance of the Singleton type. Obviously, this Singleton is a lazy loaded singleton template class:
So we can know that what IActivityManagerSingleton.get() returns is the instance in the create method. Here is the create method code omitted in the above 1:
Students who are familiar with Binder can see at a glance that am here is a Binder proxy object. If there is a ServiceManager.getService method, there must be a ServiceManager.addService method. One is to query the Binder service from the ServiceManager, and the other is to register the service in the ServiceManager. The registration time is when the system starts the system_server process. Please refer to the AMS startup process, which will not be described in depth here. So the ActivityManager.getService() method actually returns a Binder proxy object of AMS, which is used to call AMS related methods across processes. Therefore, we can use the JDK dynamic proxy method to create an am proxy Proxy object through the Proxy.newProxyInstance method, and replace the am object returned by the ActivityManager.getService() method with our Proxy object through reflection. Then, when the App process calls the ActivityManager.getService().XXX method, it will be intercepted by our Proxy and then processed. JDK dynamic proxy is also one of the commonly used design patterns in Java. Students who are not familiar with it can refer to the use of JDK dynamic proxy. This process can be divided into three steps:
We can see that the am object is actually the mInstance property in Singleton (whose instance is IActivityManagerSingleton), so the third step is just to set the mInstance property to our Proxy object through reflection. The following AmsHooker is an abstract class with different implementations on different Android platforms. It is mainly used to obtain am objects of different Android platforms and replace am objects through reflection:
The implementation on the Android P platform is as follows, see the comments for details:
Next, create the proxy class (the code has been deleted):
In the above, a proxy object Proxy is created with the AMSProxy instance as a parameter, and the am object is replaced by the Proxy object through the hookAms method. In this way, when the process calls the relevant method through ActivityManager.getService(), the above invoke method will be called, and interception can be done here:
When there is code in this process that tries to call related methods (such as startActivity, etc.) through am, it will be intercepted by the invoke method, and then we will choose whether to intercept it through the interception condition (canIntercept) we set. It is recommended that after completing the interception business needs each time, the original am object should be restored through the hookAms method to prevent continuous interception of system requests in this process. It is emphasized here that this process is always the current process. Obviously, the method of replacing the am object through reflection will only work for this process. Android QOn Android Q, the call in the above Instrumentation becomes as follows:
This becomes ActivityTaskManager.getService():
You can see that on Android Q, the class has changed from ActivityManager to ActivityTaskManager series, so our AmsQHooker is implemented as follows:
The other steps are the same as Android P. Android NOn Android 7.1 and below, the Instrumentation call is different:
This becomes ActivityManagerNative.getDefault():
You can see that although the class name and method have changed, the Singleton class is still used, so you only need to inherit AmsHooker and rewrite the relevant methods:
The others also reuse the logic on Android P. Summarize Through the above method, it is possible to intercept the related methods called by the Binder proxy of AMS in this process, which can be used to implement some unconventional functions. Although the recent requirements are relatively unconventional (liumang), putting aside the requirements, it is still interesting for developers to investigate these technologies..ha~ Blogging is an interesting, rewarding, and difficult thing. You need to try to sort out the context and logic of the article and know how to write it in a clearer and easier to understand way. It's been a long time since I updated. I've been too busy recently and haven't had time to do these things. When I thought about the possibility that my articles might be liked, I instantly became motivated. So I wrote one in my busy schedule. The content is not very deep, so just treat it as your usual development notes. |
<<: There is a new way to play during the Spring Festival: WeChat can send "video red envelopes"
>>: WeChat 8.0 released: Yellow face emojis can move and you can throw bombs to friends
How much does it cost to be an agent of Hengshui ...
Job Responsibilities: CP: Different from the CP p...
Recently, according to foreign media reports, aff...
During the Spring Festival, there are family reun...
[[150517]] On September 24, on the morning of Sep...
The current Lexus LS has been launched for more t...
Our lives have become increasingly dependent on t...
In the ending of "In the Name of Family"...
As the saying goes, "An old person in the fa...
"Why are humans right-handed?" is a que...
[Original article from 51CTO.com] Cloud computing...
Currently, many universities adhere to the concep...
Can you avoid high blood lipids by sticking to a ...
On November 12, WeChat Windows version was update...
The train is suspended in mid-air and shuttles fr...