为了账号安全,请及时绑定邮箱和手机立即绑定

Android应用程序安装过程解析(源码角度)(上篇)

标签:
Java Android

Android应用程序安装过程解析

1.程序安装的4大步骤
(1) 拷贝apk文件到指定目录

在Android系统中,apk安装文件是会被保存起来的,默认情况下,用户安装的apk首先会被拷贝到 /data/app 目录下。

/data/app目录是用户有权限访问的目录,在安装apk的时候会自动选择该目录存放用户安装的文件,而系统出厂的apk文件则被放到了 /system 分区下,包括 /system/app,/system/vendor/app,以及 /system/priv-app 等等,该分区只有Root权限的用户才能访问,这也就是为什么在没有Root手机之前,我们无法删除系统出厂的app的原因了。

(2) 解压apk,拷贝文件,创建应用的数据目录

为了加快app的启动速度,apk在安装的时候,会首先将app的可执行文件(dex)拷贝到 /data/dalvik-cache 目录,缓存起来。

然后,在/data/data/目录下创建应用程序的数据目录(以应用的包名命名),存放应用的相关数据,如数据库、xml文件、cache、二进制的so动态库等等。

(3) 解析apk的AndroidManifinest.xml文件

Android系统中,也有一个类似注册表的东西,用来记录当前所有安装的应用的基本信息,每次系统安装或者卸载了任何apk文件,都会更新这个文件。这个文件位于如下目录:

/data/system/packages.xml

系统在安装apk的过程中,会解析apk的AndroidManifinest.xml文件,提取出这个apk的重要信息写入到packages.xml文件中,这些信息包括:权限、应用包名、APK的安装位置、版本、userID等等。

由此,我们就知道了为啥一些应用市场和软件管理类的app能够很清楚地知道当前手机所安装的所有的app,以及这些app的详细信息了。

另外一件事就是Linux的用户Id和用户组Id,以便他可以获得合适的运行权限。

以上这些都是由PackageServiceManager完成的,下面我们会重点介绍PackageServiceManager。

(4) 显示快捷方式

这些应用程序只是相当于在PackageManagerService服务注册好了,如果我们想要在Android桌面上看到这些应用程序,还需要有一个Home应用程序,负责从PackageManagerService服务中把这些安装好的应用程序取出来,并以友好的方式在桌面上展现出来,例如以快捷图标的形式。在Android系统中,负责把系统中已经安装的应用程序在桌面中展现出来的Home应用程序就是Launcher了

2.PackageManagerService的启动过程

Android系统在启动的过程中,会启动一个应用程序管理服务PackageManagerService,这个服务负责扫描系统中特定的目录,找到里面的应用程序文件,即以Apk为后缀的文件,然后对这些文件进解析,得到应用程序的相关信息。应用程序管理服务PackageManagerService安装应用程序的过程,其实就是解析析应用程序配置文件AndroidManifest.xml的过程,并从里面得到得到应用程序的相关信息,例如得到应用程序的组件Activity、Service、Broadcast Receiver和Content Provider等信息,有了这些信息后,通过ActivityManagerService这个服务,我们就可以在系统中正常地使用这些应用程序了。应用程序管理服务PackageManagerService是系统启动的时候由SystemServer组件启动的,启后它就会执行应用程序安装的过程,因此,本文将从SystemServer启动PackageManagerService服务的过程开始分析系统中的应用程序安装的过程。

下面我们具体分析每一个步骤。
Step 1. SystemServer.main

这个函数定义在frameworks/base/services/Java/com/android/server/SystemServer.java文件中:


public class SystemServer  
{  
    ......  

    native public static void init1(String[] args);  

    ......  

    public static void main(String[] args) {  
        ......  

        init1(args);  

        ......  
    }  

    ......  
}  

SystemServer组件是由Zygote进程负责启动的,启动的时候就会调用它的main函数,这个函数主要调用了JNI方法init1来做一些系统初始化的工作。

Step 2. SystemServer.init1

这个函数是一个JNI方法,实现在 frameworks/base/services/jni/com_android_server_SystemServer.cpp文件中:


namespace android {  

extern "C" int system_init();  

static void android_server_SystemServer_init1(JNIEnv* env, jobject clazz)  
{  
    system_init();  
}  

/* 
 * JNI registration. 
 */  
static JNINativeMethod gMethods[] = {  
    /* name, signature, funcPtr */  
    { "init1", "([Ljava/lang/String;)V", (void*) android_server_SystemServer_init1 },  
};  

int register_android_server_SystemServer(JNIEnv* env)  
{  
    return jniRegisterNativeMethods(env, "com/android/server/SystemServer",  
            gMethods, NELEM(gMethods));  
}  

}; // namespace android  

这个函数很简单,只是调用了system_init函数来进一步执行操作。

Step 3. libsystem_server.system_init

函数system_init实现在libsystem_server库中,源代码位于frameworks/base/cmds/system_server/library/system_init.cpp文件中:


extern "C" status_t system_init()  
{  
    LOGI("Entered system_init()");  

    sp<ProcessState> proc(ProcessState::self());  

    sp<IServiceManager> sm = defaultServiceManager();  
    LOGI("ServiceManager: %p\n", sm.get());  

    sp<GrimReaper> grim = new GrimReaper();  
    sm->asBinder()->linkToDeath(grim, grim.get(), 0);  

    char propBuf[PROPERTY_VALUE_MAX];  
    property_get("system_init.startsurfaceflinger", propBuf, "1");  
    if (strcmp(propBuf, "1") == 0) {  
        // Start the SurfaceFlinger  
        SurfaceFlinger::instantiate();  
    }  

    // Start the sensor service  
    SensorService::instantiate();  

    // On the simulator, audioflinger et al don't get started the  
    // same way as on the device, and we need to start them here  
    if (!proc->supportsProcesses()) {  

        // Start the AudioFlinger  
        AudioFlinger::instantiate();  

        // Start the media playback service  
        MediaPlayerService::instantiate();  

        // Start the camera service  
        CameraService::instantiate();  

        // Start the audio policy service  
        AudioPolicyService::instantiate();  
    }  

    // And now start the Android runtime.  We have to do this bit  
    // of nastiness because the Android runtime initialization requires  
    // some of the core system services to already be started.  
    // All other servers should just start the Android runtime at  
    // the beginning of their processes's main(), before calling  
    // the init function.  
    LOGI("System server: starting Android runtime.\n");  

    AndroidRuntime* runtime = AndroidRuntime::getRuntime();  

    LOGI("System server: starting Android services.\n");  
    runtime->callStatic("com/android/server/SystemServer", "init2");  

    // If running in our own process, just go into the thread  
    // pool.  Otherwise, call the initialization finished  
    // func to let this process continue its initilization.  
    if (proc->supportsProcesses()) {  
        LOGI("System server: entering thread pool.\n");  
        ProcessState::self()->startThreadPool();  
        IPCThreadState::self()->joinThreadPool();  
        LOGI("System server: exiting thread pool.\n");  
    }  

    return NO_ERROR;  
}  

这个函数首先会初始化SurfaceFlinger、SensorService、AudioFlinger、MediaPlayerService、CameraService和AudioPolicyService这几个服务,然后就通过系统全局唯一的AndroidRuntime实例变量runtime的callStatic来调用SystemServer的init2函数了。关于这个AndroidRuntime实例变量runtime的相关资料,可能参考前面一篇文章Android应用程序进程启动过程的源代码分析一文。

Step 4. AndroidRuntime.callStatic

这个函数定义在frameworks/base/core/jni/AndroidRuntime.cpp文件中:


/* 
* Call a static Java Programming Language function that takes no arguments and returns void. 
*/  
status_t AndroidRuntime::callStatic(const char* className, const char* methodName)  
{  
    JNIEnv* env;  
    jclass clazz;  
    jmethodID methodId;  

    env = getJNIEnv();  
    if (env == NULL)  
        return UNKNOWN_ERROR;  

    clazz = findClass(env, className);  
    if (clazz == NULL) {  
        LOGE("ERROR: could not find class '%s'\n", className);  
        return UNKNOWN_ERROR;  
    }  
    methodId = env->GetStaticMethodID(clazz, methodName, "()V");  
    if (methodId == NULL) {  
        LOGE("ERROR: could not find method %s.%s\n", className, methodName);  
        return UNKNOWN_ERROR;  
    }  

    env->CallStaticVoidMethod(clazz, methodId);  

    return NO_ERROR;  
}

这个函数调用由参数className指定的java类的静态成员函数,这个静态成员函数是由参数methodName指定的。上面传进来的参数className的值为"com/android/server/SystemServer",而参数methodName的值为"init2",因此,接下来就会调用SystemServer类的init2函数了。

Step 5. SystemServer.init2

这个函数定义在frameworks/base/services/java/com/android/server/SystemServer.java文件中:


public class SystemServer  
{  
    ......  

    public static final void init2() {  
        Slog.i(TAG, "Entered the Android system server!");  
        Thread thr = new ServerThread();  
        thr.setName("android.server.ServerThread");  
        thr.start();  
    }  
}  

这个函数创建了一个ServerThread线程,PackageManagerService服务就是这个线程中启动的了。这里调用了ServerThread实例thr的start函数之后,下面就会执行这个实例的run函数了。

Step 6. ServerThread.run

这个函数定义在frameworks/base/services/java/com/android/server/SystemServer.java文件中:


class ServerThread extends Thread {  
    ......  

    @Override  
    public void run() {  
        ......  

        IPackageManager pm = null;  

        ......  

        // Critical services...  
        try {  
            ......  

            Slog.i(TAG, "Package Manager");  
            pm = PackageManagerService.main(context,  
                        factoryTest != SystemServer.FACTORY_TEST_OFF);  

            ......  
        } catch (RuntimeException e) {  
            Slog.e("System", "Failure starting core service", e);  
        }  

        ......  
    }  

    ......  
}  

这个函数除了启动PackageManagerService服务之外,还启动了其它很多的服务,例如在前面学习Activity和Service的几篇文章中经常看到的ActivityManagerService服务,有兴趣的读者可以自己研究一下。

Step 7. PackageManagerService.main

这个函数定义在frameworks/base/services/java/com/android/server/PackageManagerService.java文件中:


class PackageManagerService extends IPackageManager.Stub {  
    ......  

    public static final IPackageManager main(Context context, boolean factoryTest) {  
        PackageManagerService m = new PackageManagerService(context, factoryTest);  
        ServiceManager.addService("package", m);  
        return m;  
    }  

    ......  
}  

接着看下一篇

方法最后我们可以看到再次调用安装接口完成安装。

对于mSetting的介绍还不完善,后续会继续补充

本文是读过下面的几篇博客和Android系统源代码情景分析之后写成的,感谢各位作者。

参考:

http://ticktick.blog.51cto.com/823160/1669525
http://blog.csdn.net/hdhd588/article/details/6739281
http://blog.csdn.net/luoshengyang/article/details/6766010
《Android系统源代码情景分析》

点击查看更多内容
9人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
移动开发工程师
手记
粉丝
424
获赞与收藏
5663

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消