Android应用启动过程

来源:互联网 发布:域名加空间 编辑:程序博客网 时间:2024/05/21 07:55

1.Launcher启动桌面图标
Launcher.java在packages/apps/Launcher2/src/com/android/launcher2/Launcher.java
点击桌面图标时首先触发onClick(View v)函数:

public void onClick(View v) {        // 防止恶意点击        if (v.getWindowToken() == null) {            return;        }        if (!mWorkspace.isFinishedSwitchingState()) {            return;        }        Object tag = v.getTag();        if (tag instanceof ShortcutInfo) {            // 通过图标获取intent            final Intent intent = ((ShortcutInfo) tag).intent;            int[] pos = new int[2];            v.getLocationOnScreen(pos);            intent.setSourceBounds(new Rect(pos[0], pos[1],                    pos[0] + v.getWidth(), pos[1] + v.getHeight()));            //启动意图            boolean success = startActivitySafely(v, intent, tag);            if (success && v instanceof BubbleTextView) {                mWaitingForResume = (BubbleTextView) v;                mWaitingForResume.setStayPressed(true);            }         //如果快捷方式是文件夹之类的图标        } else if (tag instanceof FolderInfo) {            if (v instanceof FolderIcon) {                FolderIcon fi = (FolderIcon) v;                handleFolderClick(fi);            }        } else if (v == mAllAppsButton) {            if (isAllAppsVisible()) {                showWorkspace(true);            } else {                onClickAllAppsButton(v);            }        }    }

之后执行startActivitySafely方法,该方法调用success = startActivity(v, intent, tag);方法:

 boolean startActivity(View v, Intent intent, Object tag) {        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);        try {            //使用动画            boolean useLaunchAnimation = (v != null) &&                    !intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);        //获取luncher_app_service服务            LauncherApps launcherApps = (LauncherApps)                    this.getSystemService(Context.LAUNCHER_APPS_SERVICE);            if (useLaunchAnimation) {                ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(v, 0, 0,                        v.getMeasuredWidth(), v.getMeasuredHeight());                if (user == null || user.equals(android.os.Process.myUserHandle())) {                    // ①可以启动一些其它Activity                    startActivity(intent, opts.toBundle());                } else {                //②启动应用的MainActivity                    launcherApps.startMainActivity(intent.getComponent(), user,                            intent.getSourceBounds(),                            opts.toBundle());                }            } else {                if (user == null || user.equals(android.os.Process.myUserHandle())) {                    startActivity(intent);                } else {                    launcherApps.startMainActivity(intent.getComponent(), user,                            intent.getSourceBounds(), null);                }            }            return true;        } catch (SecurityException e) {            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();            Log.e(TAG, "Launcher does not have the permission to launch " + intent +                    ". Make sure to create a MAIN intent-filter for the corresponding activity " +                    "or use the exported attribute for this activity. "                    + "tag="+ tag + " intent=" + intent, e);        }        return false;    }

其中①中即转到Activity.java中的startActivity方法中:

    public void startActivity(Intent intent, @Nullable Bundle options) {        if (options != null) {            startActivityForResult(intent, -1, options);        } else {            // Note we want to go through this call for compatibility with            // applications that may have overridden the method.            startActivityForResult(intent, -1);        }    }

②则启动LauncherApps中的startMainActivity方法如下:

public void startMainActivity(ComponentName component, UserHandle user, Rect sourceBounds,            Bundle opts) {        if (DEBUG) {            Log.i(TAG, "StartMainActivity " + component + " " + user.getIdentifier());        }        try {            mService.startActivityAsUser(component, sourceBounds, opts, user);        } catch (RemoteException re) {            // Oops!        }    }

由于LauncherApps.java—-ILauncherApps—-LauncherAppsService三者使用aidl的形式通信,所以此处的startMainActivity()方法其实是调用的LauncherAppsService中的startActivityAsUser()方法.LauncherAppsService.java位于frameworks/base/services/core/java/com/android/server/pm/LauncherAppsService.java.下面分析LauncherAppsService中的startActivityAsUser函数:

public void startActivityAsUser(ComponentName component, Rect sourceBounds,                Bundle opts, UserHandle user) throws RemoteException {            ensureInUserProfiles(user, "Cannot start activity for unrelated profile " + user);            if (!isUserEnabled(user)) {                throw new IllegalStateException("Cannot start activity for disabled profile "  + user);            }            //初始化launchIntent            Intent launchIntent = new Intent(Intent.ACTION_MAIN);            launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);            launchIntent.setSourceBounds(sourceBounds);            launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);            launchIntent.setPackage(component.getPackageName());            long ident = Binder.clearCallingIdentity();            try {            //获取PackageManagerService的实例对象.                IPackageManager pm = AppGlobals.getPackageManager();                //获取Activity信息                ActivityInfo info = pm.getActivityInfo(component, 0, user.getIdentifier());                if (!info.exported) {                    throw new SecurityException("Cannot launch non-exported components "                            + component);                }                // Check that the component actually has Intent.CATEGORY_LAUCNCHER                // as calling startActivityAsUser ignores the category and just                // resolves based on the component if present.                List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(launchIntent,                        0 /* flags */, user.getIdentifier());                final int size = apps.size();                for (int i = 0; i < size; ++i) {                    ActivityInfo activityInfo = apps.get(i).activityInfo;                    if (activityInfo.packageName.equals(component.getPackageName()) &&                            activityInfo.name.equals(component.getClassName())) {                        // Found an activity with category launcher that matches                        // this component so ok to launch.                        launchIntent.setComponent(component);                        mContext.startActivityAsUser(launchIntent, opts, user);                        return;                    }                }                throw new SecurityException("Attempt to launch activity without "                        + " category Intent.CATEGORY_LAUNCHER " + component);            } finally {                Binder.restoreCallingIdentity(ident);            }        }

PackageManagerService中的getActivityInfo方法如下:

public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {    //此处的userId为Luncher中传进来的user获得的getIdentifier();        if (!sUserManager.exists(userId)) return null;        //该函数判断是否为该应用的用户启动该应用,详见下面分析        enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get activity info");        ......    }

首先判断是否存在该用户,如果不存在,怎返回null,否则继续执行enforceCrossUserPermission()函数,该函数还在PackageManagerService.java中:

void enforceCrossUserPermission(int callingUid, int userId, boolean requireFullPermission,                                    boolean checkShell, String message) {        //先判断合法性        if (userId < 0) {            throw new IllegalArgumentException("Invalid userId " + userId);        }        //此处传进的参数为false        if (checkShell) {            enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, userId);        }        //如果是应用自身的用户启动则返回.        if (userId == UserHandle.getUserId(callingUid)) return;        //若是非系统用户而且UID不等于0,则需要如下检测        if (callingUid != Process.SYSTEM_UID && callingUid != 0) {        //此处传入的是false            if (requireFullPermission) {                mContext.enforceCallingOrSelfPermission(                        android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);            } else {                try {                    mContext.enforceCallingOrSelfPermission(                            android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);                } catch (SecurityException se) {                    mContext.enforceCallingOrSelfPermission(                            android.Manifest.permission.INTERACT_ACROSS_USERS, message);                }            }        }    }

此处执行的enforceCallingOrSelfPermission()函数在实现Context类的ContextImpl.java中,如下所示:

    public void enforceCallingOrSelfPermission(            String permission, String message) {        enforce(permission,                checkCallingOrSelfPermission(permission),                true,                Binder.getCallingUid(),                message);    }

其中checkCallingOrSelfPermission()函数 (在ContextImpl.java中)如下:

    public int checkCallingOrSelfPermission(String permission) {        if (permission == null) {            throw new IllegalArgumentException("permission is null");        }    //检查"android.permission.INTERACT_ACROSS_USERS_FULL"权限        return checkPermission(permission, Binder.getCallingPid(),                Binder.getCallingUid());    }

而此处的checkPermission函数 (在ContextImpl.java中):

    public int checkPermission(String permission, int pid, int uid) {        if (permission == null) {            throw new IllegalArgumentException("permission is null");        }        try {            return ActivityManagerNative.getDefault().checkPermission(                    permission, pid, uid);        } catch (RemoteException e) {        //如果发生通信意外就要拒绝该权限.            return PackageManager.PERMISSION_DENIED;        }    }

此处的ActivityManagerNative.getDefault().checkPermission调用的是ActivityManagerService.java中的checkPermission()方法.如下:

    public int checkPermission(String permission, int pid, int uid) {        if (permission == null) {            return PackageManager.PERMISSION_DENIED;        }        return checkComponentPermission(permission, pid, UserHandle.getAppId(uid), -1, true);    }

checkComponentPermission()方法(在ActivityManagerService.java中)如下:

    int checkComponentPermission(String permission, int pid, int uid,            int owningUid, boolean exported) {        // We might be performing an operation on behalf of an indirect binder        // invocation, e.g. via {@link #openContentUri}.  Check and adjust the        // client identity accordingly before proceeding.        Identity tlsIdentity = sCallerIdentity.get();        if (tlsIdentity != null) {            Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"                    + tlsIdentity.pid + "," + tlsIdentity.uid + "}");            uid = tlsIdentity.uid;            pid = tlsIdentity.pid;        }        if (pid == MY_PID) {            return PackageManager.PERMISSION_GRANTED;        }        return ActivityManager.checkComponentPermission(permission, uid,                owningUid, exported);    }

这个地方,uid和pid都换了一遍,而且如果pid等于Process.myPid()就授予权限,但是,为什么在这才用这种方法判断呢?是不是从这开始进程才开始启动.(暂时没弄懂),下面继续说ActivityManager.checkComponentPermission()方法:

    public static int checkComponentPermission(String permission, int uid,            int owningUid, boolean exported) {        // 如果是root或者system用户,则授予.        if (uid == 0 || uid == Process.SYSTEM_UID) {            return PackageManager.PERMISSION_GRANTED;        }        // 被隔离的进程不能具有任何权限.        if (UserHandle.isIsolated(uid)) {            return PackageManager.PERMISSION_DENIED;        }        // If there is a uid that owns whatever is being accessed, it has        // blanket access to it regardless of the permissions it requires.        if (owningUid >= 0 && UserHandle.isSameApp(uid, owningUid)) {            return PackageManager.PERMISSION_GRANTED;        }        // If the target is not exported, then nobody else can get to it.        if (!exported) {            /*            RuntimeException here = new RuntimeException("here");            here.fillInStackTrace();            Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid,                    here);            */            return PackageManager.PERMISSION_DENIED;        }        if (permission == null) {            return PackageManager.PERMISSION_GRANTED;        }        try {            return AppGlobals.getPackageManager()                    .checkUidPermission(permission, uid);        } catch (RemoteException e) {            // Should never happen, but if it does... deny!            Slog.e(TAG, "PackageManager is dead?!?", e);        }        return PackageManager.PERMISSION_DENIED;    }

最终AppGlobals.getPackageManager().checkUidPermission(permission, uid)执行的是PackageManagerService中的checkPermission()方法.
最后回到ContextImpl类中的enforceCallingOrSelfPermission方法.执行enfore函数,如下:

    private void enforce(            String permission, int resultOfCheck,            boolean selfToo, int uid, String message) {         //如果PackageManagerService中的checkPermission函数返回的不是PackageManager.PERMISSION_GRANTED,则抛出安全异常.        if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {            throw new SecurityException(                    (message != null ? (message + ": ") : "") +                            (selfToo                                    ? "Neither user " + uid + " nor current process has "                                    : "uid " + uid + " does not have ") +                            permission +                            ".");        }    }

2.执行完 enforceCrossUserPermission()函数之后,执行如下代码:

      synchronized (mPackages) {            PackageParser.Activity a = mActivities.mActivities.get(component);            if (DEBUG_PACKAGE_INFO) Log.v(TAG, "getActivityInfo " + component + ": " + a);            if (a != null && mSettings.isEnabledLPr(a.info, flags, userId)) {                PackageSetting ps = mSettings.mPackages.get(component.getPackageName());                if (ps == null) return null;                //返回生成Activity信息                return PackageParser.generateActivityInfo(a, flags, ps.readUserState(userId),                        userId);            }            if (mResolveComponentName.equals(component)) {                return PackageParser.generateActivityInfo(mResolveActivity, flags,                        new PackageUserState(), userId);            }        }        return null;

返回应用中特定Activity的信息, 如元数据,uid,共享库文件,dataDir等.符合AndroidManifest.xml文件.
继续执行LauncherAppsService中的startActivityAsUser()方法.

      //查找此用户可以启动该intent的所有activity.      List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(launchIntent,                        0 /* flags */, user.getIdentifier());      final int size = apps.size();      for (int i = 0; i < size; ++i) {           ActivityInfo activityInfo = apps.get(i).activityInfo;           if (activityInfo.packageName.equals(component.getPackageName()) &&                            activityInfo.name.equals(component.getClassName())) {                // Found an activity with category launcher that matches                // this component so ok to launch.                launchIntent.setComponent(component);                //启动intent,此处调用的是ContextImpl类中的startActivityAsUser方法.                mContext.startActivityAsUser(launchIntent, opts, user);                return;            }     }

3.两种其中activity的方式最终都是调用了ActivityManagerNative.getDefault().startActivityAsUser()方法.也就是
ActivityManagerService.java中的startActivityAsUser()方法.
然后通过以下方法,启动activity:

1./home/wdy/Android-5.0/android/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.javafinal int startActivityMayWait(IApplicationThread caller, int callingUid,            String callingPackage, Intent intent, String resolvedType,            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,            IBinder resultTo, String resultWho, int requestCode, int startFlags,            ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,            Bundle options, int userId, IActivityContainer iContainer, TaskRecord inTask) {        // Refuse possible leaked file descriptors        if (intent != null && intent.hasFileDescriptors()) 2./home/wdy/Android-5.0/android/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.javafinal int startActivityLocked(IApplicationThread caller,            Intent intent, String resolvedType, ActivityInfo aInfo,            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,            IBinder resultTo, String resultWho, int requestCode,            int callingPid, int callingUid, String callingPackage,            int realCallingPid, int realCallingUid, int startFlags, Bundle options,            boolean componentSpecified, ActivityRecord[] outActivity, ActivityContainer container,            TaskRecord inTask) 3./home/wdy/Android-5.0/android/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.javafinal int startActivityUncheckedLocked(ActivityRecord r, ActivityRecord sourceRecord,            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,            boolean doResume, Bundle options, TaskRecord inTask) {4./home/wdy/Android-5.0/android/frameworks/base/services/core/java/com/android/server/am/ActivityStack.javafinal void startActivityLocked(ActivityRecord r, boolean newTask,            boolean doResume, boolean keepCurTransition, Bundle options) {  
0 0
原创粉丝点击