hook activity 兼容android 10 Q 未完待续

本文中你都能了解到什么

  1. android 9 关于如何启动一个activity的源码分析,本文源码分析的系统版本是android9.0.0.r8
  2. 在android10 和Q以下的机型上如何hook startActivity函数并且实现我们想要的功能,例如本例中是启动了一个activity2 ,但是经过我们hook之后实际上启动的是activity3.

源码分析简陋,想要代码的同学请直达github

推荐两个在线查看源码的地方

  1. [http://androidxref.com/] 该网站是本人在android9及以前查看源码的常用的一个网站
  2. [https://cs.android.com/] 这个网站是新出来的一个网站,个人感觉从体验上要比第一个好很多,但是有时候总是无法访问,很是恼火

先上android 10hook代码

不想去github下载的同学可以直接将下面的类拷贝过去,部分代码是借鉴而来,如有同学知道出处请指出

package com.lhc.hook.myapplication;

import android.os.IBinder;
import android.util.Log;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ServiceHook implements InvocationHandler {
    private static final String TAG = "ServiceHook";

    private IBinder mBase;
    private Class<?> mStub;
    private Class<?> mInterface;
    private InvocationHandler mInvocationHandler;

    public ServiceHook(IBinder mBase, String iInterfaceName, boolean isStub, InvocationHandler InvocationHandler) {
        this.mBase = mBase;
        this.mInvocationHandler = InvocationHandler;

        try {
            this.mInterface = Class.forName(iInterfaceName);
            this.mStub = Class.forName(String.format("%s%s", iInterfaceName, isStub ? "$Stub" : ""));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if ("queryLocalInterface".equals(method.getName())) {
            return Proxy.newProxyInstance(proxy.getClass().getClassLoader(), new Class[] { mInterface },
                    new HookHandler(mBase, mStub, mInvocationHandler));
        }

        Log.e(TAG, "ERROR!!!!! method:name = " + method.getName());
        return method.invoke(mBase, args);
    }

    private static class HookHandler implements InvocationHandler {
        private Object mBase;
        private InvocationHandler mInvocationHandler;
 
        public HookHandler(IBinder base, Class<?> stubClass,
                           InvocationHandler InvocationHandler) {
            mInvocationHandler = InvocationHandler;

            try {
                Method asInterface = stubClass.getDeclaredMethod("asInterface", IBinder.class);
                this.mBase = asInterface.invoke(null, base);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if (mInvocationHandler != null) {
                return mInvocationHandler.invoke(mBase, method, args);
            }
            return method.invoke(mBase, args);
        }
    }
}
package com.lhc.hook.myapplication;

import android.os.IBinder;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;

public class ServiceManager {

    private static Method sGetServiceMethod;
    private static Map<String, IBinder> sCacheService;
    private static Class c_ServiceManager;

    static {
        try {
            c_ServiceManager = Class.forName("android.os.ServiceManager");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static IBinder getService(String serviceName) {
        if (c_ServiceManager == null) {
            return null;
        }

        if (sGetServiceMethod == null) {
            try {
                sGetServiceMethod = c_ServiceManager.getDeclaredMethod("getService", String.class);
                sGetServiceMethod.setAccessible(true);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        }

        if (sGetServiceMethod != null) {
            try {
                return (IBinder) sGetServiceMethod.invoke(null, serviceName);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return null;
    }

    public static void setService(String serviceName, IBinder service) {
        if (c_ServiceManager == null) {
            return;
        }

        if (sCacheService == null) {
            try {
                Field sCache = c_ServiceManager.getDeclaredField("sCache");
                sCache.setAccessible(true);
                sCacheService = (Map<String, IBinder>) sCache.get(null);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        sCacheService.remove(serviceName);
        sCacheService.put(serviceName, service);
    }
}
package com.lhc.hook.myapplication;

import android.content.Context;
import android.content.Intent;
import android.os.IBinder;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 *
 *
 */

public class ActivityTaskHook {

    private static final String TAG = ActivityTaskHook.class.getSimpleName();
    private Context context;


    public ActivityTaskHook(Context context) {
        this.context = context;
    }

    public void hookService() {
        IBinder clipboardService = ServiceManager.getService("activity_task");
        String IClipboard = "android.app.IActivityTaskManager";
        try {
        	//这里是android Q hook 
            if (clipboardService != null) {
                IBinder hookClipboardService =
                        (IBinder) Proxy.newProxyInstance(IBinder.class.getClassLoader(),
                                new Class[]{IBinder.class},
                                new ServiceHook(clipboardService, IClipboard, true, new ActivityTaskHookHandler()));
                ServiceManager.setService("activity_task", hookClipboardService);
            } else {
            	//如果android Q hook失败了就使用非android Q的hook, 其实市面上androidQ的手机没有其他的版本多可以先尝试hook这里,但是这个demo主要是为了hook android Q
                HookAMS hookAMS = new HookAMS(context);
                hookAMS.hookAms();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public class ActivityTaskHookHandler implements InvocationHandler {

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if ("startActivity".contains(method.getName())) {
              	 //这些代码完全可以删除 ,看客官的业务需求了
                Intent intent = null;
                int intentIndex = 0;
                for (int i = 0; i < args.length; i++) {
                    Object arg = args[i];
                    if (arg instanceof Intent) {
                        intent = (Intent) args[i];
                        intentIndex = i;
                        break;
                    }
                }
               
                //我们在startactivity中启动的是Main2Activity,这里替换成Main3Activity
                if (intent != null) {
                    Intent main3Intent = new Intent(context, Main3Activity.class);
                    args[intentIndex] = main3Intent;
                }
            }
            return method.invoke(proxy, args);
        }
    }

}
package com.lhc.hook.myapplication;

import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.util.Log;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 *
 *
 *
 **/
public class HookAMS {

    private Context context;
    private final String TAG = "HookAMS";

    public HookAMS(Context context) {
        this.context = context;
    }

    public void hookAms() {
        try {

            Field defaultFiled = null;
            Object iActivityManagerObject = null;
            Field mInstance = null;
            if (Build.VERSION.SDK_INT > 28) {
                Class<?> clazz = Class.forName("android.app.ActivityTaskManager");
                defaultFiled = clazz.getDeclaredField("IActivityTaskManagerSingleton");
                defaultFiled.setAccessible(true);
                Object defaultValue = defaultFiled.get(null);

                if (defaultValue == null) {
                    Log.i("testabc", "efaultValue==null");
                }
                //反射SingleTon
                Class<?> SingletonClass = Class.forName("android.util.Singleton");
                mInstance = SingletonClass.getDeclaredField("mInstance");
                mInstance.setAccessible(true);
                iActivityManagerObject = mInstance.get(defaultValue);
                if (iActivityManagerObject != null) {
                    Log.e("testabc", "IActivityTaskManagerSingleton 2 ");
                    //开始动态代理,用代理对象替换掉真实的ActivityManager,瞒天过海
                    Class<?> IActivityManagerIntercept = Class.forName("android.app.IActivityTaskManager");
                    AmsInvocationHandler handler = new AmsInvocationHandler(iActivityManagerObject);
                    Object proxy = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[]{IActivityManagerIntercept}, handler);
                    //现在替换掉这个对象
                    mInstance.set(defaultValue, proxy);
                    Log.e("testabc", "IActivityTaskManagerSingleton 3 ");
                } else {
                    Log.e("testabc", "IActivityTaskManagerSingleton: is null ");
                }

            } else if (Build.VERSION.SDK_INT > 25 || (Build.VERSION.SDK_INT == 25 && Build.VERSION.PREVIEW_SDK_INT > 0)) {
                Class<?> clazz = Class.forName("android.app.ActivityManager");
                defaultFiled = clazz.getDeclaredField("IActivityManagerSingleton");
                defaultFiled.setAccessible(true);
                Object defaultValue = defaultFiled.get(null);
                //反射SingleTon
                Class<?> SingletonClass = Class.forName("android.util.Singleton");
                mInstance = SingletonClass.getDeclaredField("mInstance");
                mInstance.setAccessible(true);
                iActivityManagerObject = mInstance.get(defaultValue);
                //开始动态代理,用代理对象替换掉真实的ActivityManager,瞒天过海
                Class<?> IActivityManagerIntercept = Class.forName("android.app.IActivityManager");
                AmsInvocationHandler handler = new AmsInvocationHandler(iActivityManagerObject);
                Object proxy = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[]{IActivityManagerIntercept}, handler);
                //现在替换掉这个对象
                mInstance.set(defaultValue, proxy);
            } else {
                Class<?> ActivityManagerNativeClss = Class.forName("android.app.ActivityManagerNative");
                defaultFiled = ActivityManagerNativeClss.getDeclaredField("gDefault");
                Log.e("HookUtil", "singleton:123");
                defaultFiled.setAccessible(true);
                Object defaultValue = defaultFiled.get(null);
                //反射SingleTon
                Class<?> SingletonClass = Class.forName("android.util.Singleton");
                Log.e("HookUtil", "singleton:456");
                mInstance = SingletonClass.getDeclaredField("mInstance");
                mInstance.setAccessible(true);
                //到这里已经拿到ActivityManager对象
                iActivityManagerObject = mInstance.get(defaultValue);
                //开始动态代理,用代理对象替换掉真实的ActivityManager,瞒天过海
                Class<?> IActivityManagerIntercept = Class.forName("android.app.IActivityManager");

                AmsInvocationHandler handler = new AmsInvocationHandler(iActivityManagerObject);
                Object proxy = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[]{IActivityManagerIntercept}, handler);

                //现在替换掉这个对象
                mInstance.set(defaultValue, proxy);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private class AmsInvocationHandler implements InvocationHandler {
        private Object iActivityManagerObject;

        private AmsInvocationHandler(Object iActivityManagerObject) {
            this.iActivityManagerObject = iActivityManagerObject;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//            Log.i("HookUtil", method.getName());
            //我要在这里搞点事情
            Log.e(TAG, "invoke: 129 ");
            if ("startActivity".contains(method.getName())) {
                Intent intent = null;
                int index = 0;
                for (int i = 0; i < args.length; i++) {
                    Object arg = args[i];
                    if (arg instanceof Intent) {
                        intent = (Intent) args[i];
                        index = i;
                        break;
                    }
                }


            }
            return method.invoke(iActivityManagerObject, args);
        }
    }


}
package com.lhc.hook.myapplication;

import android.app.Application;
import android.content.Context;

/**
 * Created by Administrator on 星期四.
 * 
 */
public class App extends Application {
    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        Reflection.unseal(this);

        //开始hook
        ActivityTaskHook taskHook = new ActivityTaskHook(this);
        taskHook.hookService();

    }
}

当然由于现在很多地方禁止hook,你还要添加这样一段代码才能hook,否则会闪退的

package com.lhc.hook.myapplication;

import android.content.Context;
import android.os.Build;
import android.util.Log;

import java.lang.reflect.Method;

import static android.os.Build.VERSION.SDK_INT;

/**
 *
 */

public class Reflection {
    private static final String TAG = "Reflection";

    private static Object sVmRuntime;
    private static Method setHiddenApiExemptions;

    static {
        if (SDK_INT >= Build.VERSION_CODES.P) {
            try {
                Method forName = Class.class.getDeclaredMethod("forName", String.class);
                Method getDeclaredMethod = Class.class.getDeclaredMethod("getDeclaredMethod", String.class, Class[].class);

                Class<?> vmRuntimeClass = (Class<?>) forName.invoke(null, "dalvik.system.VMRuntime");
                Method getRuntime = (Method) getDeclaredMethod.invoke(vmRuntimeClass, "getRuntime", null);
                setHiddenApiExemptions = (Method) getDeclaredMethod.invoke(vmRuntimeClass, "setHiddenApiExemptions", new Class[]{String[].class});
                sVmRuntime = getRuntime.invoke(null);
            } catch (Throwable e) {
                Log.e(TAG, "reflect bootstrap failed:", e);
            }
        }
    }




    private static final int ERROR_EXEMPT_FAILED = -21;


    public static int unseal(Context context) {
        if (SDK_INT < 28) {
            // Below Android P, ignore
            return 0;
        }

        // try exempt API first.
        if (exemptAll()) {
            return 0;
        } else {
            return ERROR_EXEMPT_FAILED;
        }
    }


    /**
     * make specific methods exempted from hidden API check.
     *
     * @param methods the method signature prefix, such as "Ldalvik/system", "Landroid" or even "L"
     * @return true if success
     */
    public static boolean exempt(String... methods) {
        if (sVmRuntime == null || setHiddenApiExemptions == null) {
            return false;
        }

        try {
            setHiddenApiExemptions.invoke(sVmRuntime, new Object[]{methods});
            return true;
        } catch (Throwable e) {
            return false;
        }
    }

    /**
     * Make all hidden API exempted.
     *
     * @return true if success.
     */
    public static boolean exemptAll() {
        return exempt(new String[]{"L"});
    }
}

准备工作准备完毕,接下来就开始我们今天的正题了吧

activity是如何被启动的

  1. 一个程序是如何做到长期在后台运行的,我们最开始学习java的时候知道一个java程序都是从main函数开始的,那么android的main程序在哪儿呢,下面我们就先看看android的main函数,android
	public static void main(String[] args) {
        Looper.prepareMainLooper();
        //Looper一直在循环,如果循环结束了也就是程序结束了
        ActivityThread thread = new ActivityThread();
        thread.attach(false, startSeq);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        // End of event ActivityThreadMain.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        Looper.loop();
        
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

上面的代码是节选自frameworks/base/core/java/android/app/ActivityThread.java的一段代码,从上面的代码我们可以看到在main函数中系统创建了一个Looper,并且这个函数是一直在做死循环的,这就是为什么我们的android程序不会一闪而退的原因了,因为在android中main是一直循环运行的

开始分析我们的重头戏startactivity

我们一点点的分析,既然已经写好了hook startactivity的源码,那么我们就从源码开始吧,首先看我们源码中的这样一段代码,如下图所示
来自我们的源码中
首先我们点击startActivity方法,发现我们进入了Activity类中,最终所有的startActivity都会调用到 Activity的startActivityForResult(@RequiresPermission Intent intent, int requestCode,@Nullable Bundle options)方法中去,我们接下来看一下startActivityForResult方法都做了什么

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {
        	//真正启动activity的地方
            options = transferSpringboardActivityOptions(options);
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
            	//返回启动activity的返回结果的地方
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            if (requestCode >= 0) {
                mStartedActivity = true;
            }

            cancelInputsAndStartExitTransition(options);
            // TODO Consider clearing/flushing other event sources and events for child windows.
        } else {
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                // Note we want to go through this method for compatibility with
                // existing applications that may have overridden it.
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }

经过我们的分析发现其实Activity最终还是通过Instrumentation类来实现对activity的启动的,那么接下来就让我们看一下Instrumentation中都做了什么

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        Uri referrer = target != null ? target.onProvideReferrer() : null;
        if (referrer != null) {
            intent.putExtra(Intent.EXTRA_REFERRER, referrer);
        }
        if (mActivityMonitors != null) {
        	//检查是否存在要启动的activity
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    ActivityResult result = null;
                    if (am.ignoreMatchingSpecificIntents()) {
                        result = am.onStartActivity(intent);
                    }
                    if (result != null) {
                        am.mHits++;
                        return result;
                    } else if (am.match(who, null, intent)) {
                        am.mHits++;
                        if (am.isBlocking()) {
                            return requestCode >= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        //启动一个activity
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

从上面的代码我们可以看到在启动一个activity的地方有这么一句话

ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);

这句就是启动activity的地方了,首先ActivityManager.getService()是什么呢,我们进去看看,我们会发现有这样的一个类IActivityManagerSingleton,而这个类其实就是关键所在了,在IActivityManagerSingleton的创建中ServiceManager.getService(Context.ACTIVITY_SERVICE)实际上是获取到了一个ActivityManager的远程引用,然后在通过IActivityManager.Stub.asInterface(b);最终执行ActivityManagerService的startActivity方法 .
下面我们看ActivityManagerService的startActivity的代码

 @Override
    public int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
        return mActivityTaskManager.startActivity(caller, callingPackage, intent, resolvedType,
                resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions);
    }

从上面的代码我们可以看到实际上是执行了ActivityTaskManagerService的startActivity方法,这个startactivity只有一个方法就是startActivityAsUs我们来看看这个方法


    int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
            boolean validateIncomingUser) {
        enforceNotIsolatedCaller("startActivityAsUser");

        userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
                Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

        // TODO: Switch to user app stacks here.
        return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(bOptions)
                .setMayWait(userId)
                .execute();

    }

看到这个方法的时候我其实是一脸懵逼的,之前的版本好像不是这样的啊,就让我们看看这个方法到底做了什么

  return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(bOptions)
                .setMayWait(userId)
                .execute();

简单分析发现其实这个方法就是设置一些必要的信息,那么我们直接看最后一句execute();到底执行了什么

 int execute() {
        try {
            // TODO(b/64750076): Look into passing request directly to these methods to allow
            // for transactional diffs and preprocessing.
            if (mRequest.mayWait) {
                return startActivityMayWait(mRequest.caller, mRequest.callingUid,
                        mRequest.callingPackage, mRequest.realCallingPid, mRequest.realCallingUid,
                        mRequest.intent, mRequest.resolvedType,
                        mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                        mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
                        mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
                        mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
                        mRequest.inTask, mRequest.reason,
                        mRequest.allowPendingRemoteAnimationRegistryLookup,
                        mRequest.originatingPendingIntent, mRequest.allowBackgroundActivityStart);
            } else {
                return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
                        mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
                        mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                        mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
                        mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
                        mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
                        mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
                        mRequest.outActivity, mRequest.inTask, mRequest.reason,
                        mRequest.allowPendingRemoteAnimationRegistryLookup,
                        mRequest.originatingPendingIntent, mRequest.allowBackgroundActivityStart);
            }
        } finally {
            onExecutionComplete();
        }
    }

我们发现这个地方就是我们要找的ActivityStarte的startActivityMayWait()方法了

private int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, int requestRealCallingPid, int requestRealCallingUid,
            Intent intent, String resolvedType, IVoiceInteractionSession voiceSession,
            IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, WaitResult outResult,
            Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
            int userId, TaskRecord inTask, String reason,
            boolean allowPendingRemoteAnimationRegistryLookup,
            PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) {
        //省略intent等相关参数的解析过程
        synchronized (mService.mGlobalLock) {
             .
             .
             .
             //我们直接看最关键的地方
            final ActivityRecord[] outRecord = new ActivityRecord[1];
            int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
                    voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
                    ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
                    allowPendingRemoteAnimationRegistryLookup, originatingPendingIntent,
                    allowBackgroundActivityStart);

            if (outResult != null) {
                outResult.result = res;

                final ActivityRecord r = outRecord[0];

                switch(res) {
                    case START_SUCCESS: {
                        mSupervisor.mWaitingActivityLaunched.add(outResult);
                        do {
                            try {
                                mService.mGlobalLock.wait();
                            } catch (InterruptedException e) {
                            }
                        } while (outResult.result != START_TASK_TO_FRONT
                                && !outResult.timeout && outResult.who == null);
                        if (outResult.result == START_TASK_TO_FRONT) {
                            res = START_TASK_TO_FRONT;
                        }
                        break;
                    }
                    case START_DELIVERED_TO_TOP: {
                        outResult.timeout = false;
                        outResult.who = r.mActivityComponent;
                        outResult.totalTime = 0;
                        break;
                    }
                    case START_TASK_TO_FRONT: {
                        outResult.launchState =
                                r.attachedToProcess() ? LAUNCH_STATE_HOT : LAUNCH_STATE_COLD;
                        // ActivityRecord may represent a different activity, but it should not be
                        // in the resumed state.
                        if (r.nowVisible && r.isState(RESUMED)) {
                            outResult.timeout = false;
                            outResult.who = r.mActivityComponent;
                            outResult.totalTime = 0;
                        } else {
                            final long startTimeMs = SystemClock.uptimeMillis();
                            mSupervisor.waitActivityVisible(
                                    r.mActivityComponent, outResult, startTimeMs);
                            // Note: the timeout variable is not currently not ever set.
                            do {
                                try {
                                    mService.mGlobalLock.wait();
                                } catch (InterruptedException e) {
                                }
                            } while (!outResult.timeout && outResult.who == null);
                        }
                        break;
                    }
                }
            }

            return res;
        }
    }

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值