Android AMS ATMS

1.AMS/ATMS

在android10之前,android的四大组件统一由AMS进行管理;android10及之后,ATMS负责activity的相关管理,剩下的三大组件还是由AMS管理,不过在AMS中持有ATMS的引用。同时AMS也对进程、电池、内存、权限等进行管理。

注:AMS、ATMS服务都是在系统进程system server进程中。

 

2.Android系统启动

Android系统启动后Zygote进程第一个fork出SystemServer进程,ActivityManagerService是在SystemServer.java中启动的。

30a1e1f4883b4403a409283d1ea98d6c.png

在SystemServer中会按顺序依次启动各个服务。

SystemServer.java:

public static void main(String[] args) {

    new SystemServer().run();

}

private void run() {

    ...

    //1.初始化 System Context

    createSystemContext(); 

    //2.创建SystemServiceManager对象,主要用来管理SystemService的创建和启动等生命周期

    mSystemServiceManager = new SystemServiceManager(mSystemContext); 

   mSystemServiceManager.setStartInfo( mRuntimeRestart, mRuntimeStartElapsedTime, mRuntimeStartUptime);

    LocalServices.addService( SystemServiceManager.class, mSystemServiceManager);

    ...

    //3.启动服务

    startBootstrapServices(); //启动引导服务,在其中启动了ATM和AMS服务,通过AMS安装Installer、初始化Power,设置系统进程等

    startCoreServices(); //启动核心服务

    startOtherServices();  //启动其他服务

}

在SystemServer的run函数中,启动AMS之前,调用了createSystemContext函数,主要用来初始化System Context和SystemUi Context,并设置主题。

private void createSystemContext() {

    ActivityThread activityThread = ActivityThread.systemMain(); 

    ……

}

SystemServer初始化时ActivityThread.systemMain()创建的是系统进程(SystemServer进程)的主线程。

然后新建了SystemServiceManager对象,并将该对象保存到LocalServices中。然后通过三个方法启动各种服务。

AMS、ATM在startBootstrapServices函数里启动,WMS在startOtherServices函数里启动。

跟踪startBootstrapServices函数:

SystemServer.java:

private void startBootstrapServices() {

    .....

    //创建ATMS服务,并调用它的start方法

    ActivityTaskManagerService atm = mSystemServiceManager.startService(ActivityTaskManagerService.Lifecycle.class).getService();

    //创建AMS对象,并调用它的start方法(AMS中持有ATM的引用)

    mActivityManagerService = ActivityManagerService.Lifecycle.startService( mSystemServiceManager, atm);

    mActivityManagerService.setSystemServic eManager(mSystemServiceManager);

    mActivityManagerService.setInstaller( installer);

    mActivityManagerService.initPowerManagem ent();

    mActivityManagerService.setSystemProcess();

    watchdog.init(mSystemContext, mActivityManagerService);

}

在这里创建了ATMS对象和AMS对象,并启动服务。

 

3.ATMS的启动

startBootstrapServices方法中通过ActivityTaskManagerService atm = mSystemServiceManager.startService(ActivityTaskManagerService.Lifecycle.class).getService();创建并启动ATMS服务。

进入SystemServiceManager类的startService()中继续看:

SystemServiceManager.java:

public <T extends SystemService>T startService( Class<T> serviceClass) {

    final String name = serviceClass.getName();

    if (!SystemService.class.isAssignableFrom( serviceClass)) {

        throw new RuntimeException("Failed to create " + name + ": service must extend " + SystemService.class.getName());

    }

    //反射创建ATMS

    final T service;

    Constructor<T> constructor = serviceClass.getConstructor(Context.class);

    service = constructor.newInstance(mContext);

    //启动服务

    startService(service);

    return service;

}

通过反射调用了ATMS的构造方法,创建了ATMS服务,然后调用startService(service)启动服务。

SystemServiceManager.java:

private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();

public void startService(final SystemService service) {

    mServices.add(service); //注册服务

    service.onStart(); //启动服务,调用ATMS.LifeCycle的onStart方法

}

在startService(service) 中通过service.onStart()调用了ATMS.LifeCycle的onStart方法启动服务。

ActivityTaskManagerService.java:

public static final class Lifecycle extends SystemService {

    private final ActivityTaskManagerService mService;

    public Lifecycle(Context context) {

        super(context);

        mService = new ActivityTaskManagerService(context);

    }

    public void onStart() {

        publishBinderService( Context.ACTIVITY_TASK_SERVICE,  mService);

        mService.start();

    }

}

其中publishBinderService方法是将ActivityTaskManagerService加入到ServiceManager中。

SystemService.java:

protected final void publishBinderService(String name, IBinder service) {

    publishBinderService(name, service, false);

}

protected final void publishBinderService(String name, IBinder service, boolean allowIsolated) {

    publishBinderService(name, service, allowIsolated, DUMP_FLAG_PRIORITY_DEFAULT);

}

protected final void publishBinderService(String name, IBinder service, boolean allowIsolated, int dumpPriority) {

    ServiceManager.addService(name, service, allowIsolated, dumpPriority);

}

ServiceManager的addService()方法将ATMS与Context.ACTIVITY_TASK_SERVICE绑定,即将ATMS注册到ServiceManager统一管理,方便跨进程通信。这样其他进程中就可以通过如下方式获取ATMS:

IBinder b = ServiceManager.getService( Context.ACTIVITY_TASK_SERVICE);

IActivityTaskManager atm = IActivityTaskManager.Stub.asInterface(b);

 

4.AMS的启动

startBootstrapServices方法中通过mActivityManagerService = ActivityManagerService.Lifecycle.startService( mSystemServiceManager, atm);创建并启动AMS服务。

进入ActivityManagerService.Lifecycle类:

ActivityManagerService.java:

public static final class Lifecycle extends SystemService {

    private final ActivityManagerService mService;

    private static ActivityTaskManagerService sAtm; //AMS中持有ATMS的信用

    public Lifecycle(Context context) {

        super(context);

        mService = new ActivityManagerService( context, sAtm); //创建AMS对象,主要完成一些对象的构造及变量的初始化。三大组件的管理和调度、监控内存、电池、权限以及性能相关的对象或变量

    }

    public static ActivityManagerService startService(SystemServiceManager ssm, ActivityTaskManagerService atm) {

        sAtm = atm; //AMS中持有ATMS的信用

        return ssm.startService( ActivityManagerService.Lifecycle.class).getService(); //startService()最终返回的是mService,即创建的AMS对象

    }

    @Override

    public void onStart() {

        mService.start(); //调用AMS的start()方法

    }

    public ActivityManagerService getService() {

        return mService;

    }

}

这里的Lifecycle是AMS的内部类。在AMS.Lifecycle的startService中,首先调用了SystemServiceManager的startService方法启动服务。

SystemServiceManager.java:

public <T extends SystemService>T startService( Class<T> serviceClass) {

    final String name = serviceClass.getName();

    if (!SystemService.class.isAssignableFrom( serviceClass)) {

        throw new RuntimeException("Failed to create " + name + ": service must extend " + SystemService.class.getName());

    }

    //反射创建AMS

    final T service;

    Constructor<T> constructor = serviceClass.getConstructor(Context.class);

    service = constructor.newInstance(mContext);

    //启动服务

    startService(service);

    return service;

}

SystemServiceManager.java:

private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();

public void startService(final SystemService service) {

    mServices.add(service); //注册到ServiceManager列表中

    service.onStart(); //启动服务

}

在startService(service) 中反射创建AMS并调用service.onStart()启动了服务。启动服务后通过getService()最终返回mService,即创建的AMS对象。

 

5.总结AMS的启动

①系统启动后Zygote进程第一个fork出SystemServer进程;

②SystemServer->run()->createSystemContext():创建了系统的ActivityThread对象,运行环境mSystemContext、systemUiContext;

③SystemServer->run()->startBootstrapServices()->ActivityManagerService.Lifecycle.startService():AMS在引导服务启动方法中,通过构造函数new ActivityManagerService()进行了一些对象创建和初始化(除activity外3大组件的管理和调度对象创建;内存、电池、权限、性能、cpu等的监控等相关对象创建),start()启动服务(移除进程组、启动cpu线程、注册权限、电池等服务);

④SystemServer->run()->startBootstrapServices()->setSystemServiceManager()、setInstaller()、initPowerManagement()、setSystemProcess():AMS创建后进行了一系列相关的初始化和设置。

setSystemProcess():将framework-res.apk的信息加入到SystemServer进程的LoadedApk中,并创建了SystemServer进程的ProcessRecord,加入到mPidsSelfLocked,由AMS统一管理。

⑤SystemServer->run()->startOtherServices():AMS启动后的后续工作,主要调用systemReady()和运行调用时传入的goingCallback。

systemReady()/goingCallback:各种服务或进程等AMS启动完成后需进一步完成的工作及系统相关初始化。 桌面应用在systemReady()方法中启动,systemui在goingCallback中完成。当桌面应用启动完成后,发送开机广播ACTION_BOOT_COMPLETED。

 

6.如何启动一个未注册的activity

了解完Activity的启动流程后,思考一个问题:如何启动后一个没有在清单文件中注册过的Activity呢?这里就要通过HOOK技术来实现了。Android Hook技术底层原理其实就是java的反射和动态代理。接下来通过HOOK技术取启动一个未注册的Activity。

①未使用HOOK,直接启动一个未注册的Activity

public class MainActivity extends Activity {

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        findViewById(R.id.btn).setOnClickListener( new View.OnClickListener() {

            @Override

            public void onClick(View view) {

                Intent intent = new Intent();

                intent.setComponent(new ComponentName(" com.example.hmxxx"," com.example.hmxxx.UnregisteredActivity"));

                startActivity(intent);

            }

        });

    }

}

如果UnregisteredActivity没有在AndroidManifest.xml中注册,则startActivity是会报错的,从源码角度看一下原因:

Instrumentation.java:

 public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) {

    ...           

    try {

        intent.migrateExtraStreamToClipData(who);

        intent.prepareToLeaveProcess(who);

        // whoThread被传递过去,用于在ATMS中传递消息到ActivityThread  

        int result = ActivityTaskManager.getService().startActivity(whoThread, who.getOpPackageName(), who.getAttributionTag(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);

        checkStartActivityResult(result, intent);//对result进行检查,有异常机会报错

        } catch (RemoteException e) {

            throw new RuntimeException("Failure from system", e);

        }

        return null;

}

startActivity执行后,会对result进行检查,有异常机会报错。在启动一个未注册的activity时的报错就是这里产生的,换句话说就是result的结果有问题,然后checkStartActivityResult在检查Result,发现了问题并抛了出来,根据之前分析的activity启动流程,可以知道result是在ActivityStarter的executeRequest产生的:

private int executeRequest(Request request) {

     ....  

    int err = ActivityManager.START_SUCCESS;

    ....

  // 对启动的activity进行检查,要启动的activity未注册的秘密就是在这里被发现的,当发现要启动的acticvit未注册时,err就被赋予一个错误的值并返回回去

  return err;

}

所以在启动一个未注册的activity时会报错。那么如何启动有个未注册的activity呢?打哪很明显了 ,那就是绕过atms的检查。

2d16d75ac78846f6a8d794c3d0158fe4.png

思路如上图:在AndroidManifest里面声明一个代理activity,然后在启动真实Activity的地方,将Intent里面的Activity替换成代理activity。然后等atms检查完acitivity是否在AndroidManifest文件中注册后,替换成需要启动的activity,便实现了启动一个未注册过的Activity的效果。

接下来找HOOK点,找HOOK点尽量静态变量单例(方便反射调用),public(因为public的就是谷歌鼓励使用的)。

按照上面的思路,要在startActivity(intent);之后、在intent交给atms检查之前,把要启动的一个未注册的activity换成一个已经注册的代理activity。

新建一个进行hook的工具类:

public class HookUtil {

    private static final String TAG ="HookUtil" ;

    public static void hookAMS() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {

    Class <?> clazz = Class.forName( "android.app.ActivityTaskManager");

    Field singletonField = clazz.getDeclaredField( "IActivityTaskManagerSingleton");

    singletonField.setAccessible(true);

    Object singleton = singletonField.get(null);

    Class<?> singletonClass = Class.forName("android.util.Singleton");

    Field mInstanceField = singletonClass.getDeclaredField("mInstance");

    mInstanceField.setAccessible(true);

    Method getMethod = singletonClass.getMethod("get");

    Object mInstance = getMethod.invoke(singleton);

     Log.d(TAG, "invoke: hm test1");

    Class IActivityTaskManagerClass = Class.forName("android.app.IActivityTaskManager");

    Object InstanceProxy = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{IActivityTaskManagerClass}, new InvocationHandler() {

        @Override

        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

            if ("startActivity".equals( method.getName())) { // 方法名是startActivity时

                int index = -1;

                Log.d(TAG, "invoke: hm test");

                // 获取Itent参数在args 数组中的index值

                for (int i = 0; i < args.length; i++) {

                    if (args[i] instanceof Intent) {

                        index = i;

                        break;

                    }

                }

                // 生成代理proxyIntent

                Intent proxyIntent = new Intent();

                // 这个包名是宿主的

                proxyIntent.setClassName( "com.example.hmxxx","ProxyActivity");

                // 原始的Intent丢掉吗? 保留原始的Intent对象

                Intent intent = (Intent) args[index];

                proxyIntent.putExtra( "TARGET_INTENT",intent);

            }

            return method.invoke(mInstance,args);

        }

    });

    // 用代理的对象 替换系统的对象

    mInstanceField.set(singleton,InstanceProxy);

    }

}

MainActivity:

public class MainActivity extends Activity {

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        try {

            HookUtil.hookAMS(); // 注意这里

        } catch (ClassNotFoundException e) {

            e.printStackTrace();

        }

        findViewById(R.id.btn).setOnClickListener( new View.OnClickListener() {

            @Override

            public void onClick(View view) {

                Intent intent = new Intent();

                intent.setComponent(new ComponentName("com.example.hmxxx"," com.example.hmxxx.UnregisteredActivity"));

                startActivity(intent);

            }

        });

    }

}

以上的代码是在activity交给atms之前把未注册的activity替换成一个代理activity,最后还要想办法在返回来的时候,把代理activity替换成要启动的未注册的activity,思路就是在atms检测之后,这个activity的生命周期开始执行之前,把想要启动的activity替换回来。

try {

    Class<?> clazz = Class.forName( "android.app.ActivityThread");

    Field activityThreadField = clazz.getDeclaredField("sCurrentActivityThread");

    activityThreadField.setAccessible(true);

    Object activityThread = activityThreadField.get(null);

    Field mHField = clazz.getDeclaredField("mH");

    mHField.setAccessible(true);

    final Handler mH = (Handler) mHField.get(activityThread);

    Field mCallbackField = Handler.class.getDeclaredField("mCallback");

    mCallbackField.setAccessible(true);

    mCallbackField.set(mH, new Handler.Callback() {

        @Override

        public boolean handleMessage(Message msg) {

            switch (msg.what) {

                case 159:

                    // msg.obj = ClientTransaction

                    try {

                        // 获取 List<ClientTransactionItem> mActivityCallbacks 对象

                        Field mActivityCallbacksField = msg.obj.getClass().getDeclaredField("mActivityCallbacks");

                        mActivityCallbacksField.setAccess ible(true);

                        List mActivityCallbacks = (List) mActivityCallbacksField.get(msg.obj);

                        for (int i = 0; i < mActivityCallbacks.size(); i++) {

                            // 打印 mActivityCallbacks 的所有item

                            // 如果是 LaunchActivityItem,则获取该类中的 mIntent 值,即 proxyIntent

                            if (mActivityCallbacks.get( i).getClass().getName().equals("android.app.servertransaction.LaunchActivityItem")) {

                                Object launchActivityItem = mActivityCallbacks.get(i);

                                Field mIntentField = launchActivityItem.getClass().getDeclaredField("mIntent");

                                mIntentField.setAccessible( true);

                                Intent proxyIntent = (Intent) mIntentField.get(launchActivityItem);

                                // 获取启动插件的 Intent,并替换回来

                                Intent intent = proxyIntent.getParcelableExtra(TARGET_INTENT);

                                if (intent != null) {

                                    mIntentField.set( launchActivityItem, intent);

                                }

                            }

                        }

                    } catch (Exception e) {

                        e.printStackTrace();

                    }

                    break;

                }

                return false;

            }

        });

    } catch (Exception e) {

        e.printStackTrace();

    }

 

                   

 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值