Android系统原理性问题分析 - Android Java框架层的结构

声明

  • 在Android系统中经常会遇到一些系统原理性的问题,在此专栏中集中来讨论下。
  • Android系统,为了能够更好的理解Android的Java世界的运行规律,此篇分析Android Java框架的结构。
  • 此篇参考一些博客和书籍,代码基于Android 7.1.1,不方便逐一列出,仅供学习、知识分享。

1 Java框架层结构

Android系统Java 框架层库的实体内容主要有 3个,如下所示:

  • Java 框架库:framework.jar
  • Java 服务库:services.jar
  • 资源包:framework-res.apk

在目标系统中,Java框架层的几个库都位于framework目录中。Java 框架层的主体结构如图所示:
Android系统原理性问题分析 - Android Java框架层的结构_第1张图片
  Java 框架库是系统的核心,其中定义并实现了 Android 中大多数的Java 类,也提供作为标准接口的框架层API。
Java 服务库包含了一些比较复杂的服务,为框架层提供一部分功能的实现。服务库也具有 Java 框架层中一个主要的程序入口。进入此入口运行后,服务库将形成Java 框架层的一个在后台长期运行的程序。
  资源包是一个 apk 文件,其中没有 Java 代码,基本是由纯资源组成的包。资源包是 Java框架层唯一的包含资源和工程描述文件的包,框架层所有的资源和组件定义均包含在资源包中。
  与 Android 本地层次中各部分分离的实现不同,Java 框架层实现的合性比较强,3个库之间具有相互依赖的关系。随着 Android 系统的演进,以上3 个库主体的结构没有变化。

2 Android Java 层的API

2.1 Java 框架层API的含义

  Java 层API的含义是一个基于Android 系统下 Java 应用层的标准接口。按照Android系统的标准,原则上第4 层的应用程序通过 Java 层的 API 调用第3 层的 Java 架。Android 设备提供 API,第三方应用程序基于 API 的开发标准化的 API作为二者之间的协议,可以让系统具有兼容性。
提示:在Android 的 SDK 环境中开发 Java 应用,一般只能调用框架层 API。而在源代码环境中开发 Java 应用,可以调用框架层非 API部分的其他接口。

  框架层API的来源主要有以下的方面。

  • Java 核心库 core.jar 中对外的部分(主要为java.,javax. 和 org.*的各个包)。
  • Java 框架库 framework.jar 中对外的部分(为 android.*的各个包)。

  框架层API 还包括与资源相关的内容 (android.R 包),是根据资源文件自动生成,并没有 Java 源代码与之对应。用预测 core-unit.jar 包当中也有部分框架层API (junit.*包)。
  Java 框架层具有很多类,每个类中具有自己域(字段,属性)和方法,所谓框架层 API,只是这些类中标准化的部分。不标准的部分不属于框架层 API,但依然可以被位于 Android系统APP层的应用程序所调用,这样有可能带来兼容性问题。

Android 版本升级中的API兼容性如图所示:
Android系统原理性问题分析 - Android Java框架层的结构_第2张图片
标准化的 API保证了兼容性,主要体现在两个方面:

  1. 第一方面,基于前一个版本 API 开发的第三方应用程序包,标准化的 API 可以在后面版本的 Android 设备上运行。由于下一版本的 API 包含了上一个版本的 API,因此提供标准化 API 的Android 设备的功能会逐渐增加,而不会减少。因此,基于上一个版本 API 开发出的第三方应用程序包所调用的功能,在下面的版本中依然具有,它是可以运行的。
  2. 第二方面,基于某个级别源代码开发具体的 Android 设备,标准化的 API 应当可以运行对于此 API 级别的所有应用程序包。具体的 Android 设备在开发过程中可以更改 API,原则是只能增加而不能减少。这样其对应标准 API 级别的设备功能就依然还具有,基于某个API(及其之前)开发的第三方应用程序包,在其上面预计依然是可以运行的。

  在源代码的 prebuilt/sdk//目录中,有一个名称为 android.jar 的包。在编译的时候,也可以根据 Java 代码的情况生成这个包。android.jar 是一个表示 Java 标准API的“桩”,用于在 SDK 环境的开发。android.jar 并不是一个提供实际功能的库,它的存在只是为了在 SDK 环境中开发应用程序包的时候,可以找到标准 API 定义的各个内容。

2.2 API 的描述文件

  API 的描述文件是对Java层的标准API的描述。它们是位于frameworks/base/api/目录中的各个文件。
  其中,current.xml 文件表示当前的API,可以根据当前的代码改动情况自动生成,在Android某个版本的源代码包中,current.xml 应该和当前的 API 级别的 xml 文件是一样的,在改动代码后重新生成的current.xml 文件将可能不一样。
在Android 全系统编译的时候,如果源代码和 current.xml 描述的API不一致,编译过程将报错,可以使用如下的命令更新current.xml文件:

make update-api

执行后,将根据当前的代码情况更新 current.xml 文件本身。

  API 描述文件使用 XML 语法的各种标签来描述 Java 语言中的各个元素,主要使用的标签如下所示:

<api>api>: 包含所有内容的标签,位于文件的根部。
<package>package>: Java 包,将包含其中的各个内容。
<class>class>: Java 类。
<interface>interface>: Java 接口。
<implements>implements>: 当前类或接口所实现的接口。
<constructor><constructor>: 类的构造函数
<method>method>: 方法
<parameter>parameter>: 方法中的参数
<field> field>: 域(字段,属性)。
<exception>exception>: 异常。

  以上的标签在描述 API 的 xml 文件中具有层次包含关系,各个标签具有不同的 xml 属性描述其中不同的内容。

2.3 @hide 和 @Deprecated

  对于 Android Java 框架层的代码,android.*子包所有公共类、属性和方法等,将被视为框架层 API。对于不希望作为 API 使用的内容,可以在源代码的注释中使用@hide 描述,将其隐藏。
@hide 描述可以隐藏方法、域,也可以是整个类。

  在Android 的框架层 API 中,有一些 API 属于不赞成使用的(也称之为过时的)。它们般是在比较旧的 API级别上公开的接口,但是到了新的API 级别上,已经被其他接口所代替。由于要保证向后兼容性,因此这种接口是不能被去掉的,只能被标示为不赞成使用( deprecated)。处理不赞成使用的内容的方法是在代码中加入@Deprecated。
  在Android 系统中,“不赞成使用”的 API依然是 API的一部分,在用的时候和正常的 API类似(编译的过程中可能报出 warning)。所谓“不赞成使用”的意思只是 Android 官方不再推荐使用此类接口,而建议使用更健全的其他接口替代。在兼容性和内容更新两个方面具有矛盾的时候,不赞成使用的 API 的定义实际上是种折中的解决方式。

3 Java 框架库 framework.jar

  Java 框架库(framework.jar)是 Java 框架层的主体,提供了Android 的 Java 框架层中大多数 API 类和内部类的实现。

3.1 框架库的组成和作用

  Java 框架库提供了 Java 框架层大部分的 Java 类的实现。Java 框架库的代码为frameworks/base/中的若于个子目录中,生成 Java 的包:framework.jar,放置到目标系统的/system/framework目录中。

Java 框架库的主要分布在 frameworks/base/的以下几个子目录中:

dockdroid@zj-x86:base$ tree -L 1
.
├── Android.mk
├── api
├── CleanSpec.mk
├── cmds
├── compiled-classes-phone
├── core								//Android 核心包
├── data
├── docs
├── drm
├── graphics							//图形处理包
├── include
├── keystore
├── libs
├── location							//定位相关内容
├── media								//多媒体和音频相关内容
├── MODULE_LICENSE_APACHE2
├── native
├── nfc-extras
├── NOTICE
├── obex
├── opengl								//Android OpenGL 3D 实现
├── packages
├── preloaded-classes
├── proto
├── rs
├── samples
├── sax
├── services
├── telecomm
├── telephony							//电话部分相关内容
├── test-runner
├── tests
├── tools
└── wifi								//无线局域网相关内容

  在以上的目录中都包含了一个 Java 子目录,也就是 Java 框架层的代码。其中,core是主要的目录,实现了 Android 系统所定义的大部分 Java 类。其他的部分通常是和硬件有些关系的,每个部分单独使用一个目录。
  框架库 framework,jar 内容众多,但它的确只是一个“库”,而不是一个运行时的概念只有在其中的各个 Java 类被调用的时候,该库中才有可能得到运行。

3.2 框架库的 API

框架中的类分为对外的 API 和内部类,其中的内容放在不同的目录中

<path>/java/android/: android.* 包中的内容,其中包括 API
<path>/java/com/: com.* 包中的内容,其中都是内部类。

  表示框架库的一个模块,例如:core、graphics 或 media 等。也就是说,在模块的 java 路径中,只有 android 目录才有可能提供对外的 API,com 目录当中都是内部使用的包。当然,android 目录中的内容也不都是 API,在代码中使用@hide 可以隐藏内容。除此之外,还可以隐藏各个目录中的package.html。
  各个目录中的 package.html 文件为对这个部分的描述。在这个文件中可以使用标记,将整个目录的内容“隐藏”。
  例如:core/java/android/hardware 中的 package.html文件,如下所示:

<HTML>
<BODY>
<p>Provides support for hardware features, such as the camera and other sensors. Be aware that
not all Android-powered devices support all hardware features, so you should declare hardware
that your application requires using the <a
href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code
<uses-feature>}a> manifest element.p>
BODY>
HTML>

  以上的 package.html 文件只包含了一些描述性的内容,在编译 API 和生成文档的同时将生成相应的信息。
  core/java/android/中的ddm、pim、server 等目录中的内容,虽然是Android 的子包,但是这几个子包的内容整体隐藏,不作为 API。整体隐藏的方法就是在它们的 package.html 文件中增加隐藏信息。例如,pim目录中的 package.html 文件如下所示:

<html>
<body>
    {@hide}
body>
html>

3.3 框架库的编译结构

  由于框架库的内容比较多,其编译的包含关系也是比较复杂的。frameworks/base/目录中的Android.mk 文件负责 framework.jar 包的编译。其主要的片段如下所示:

ifneq ($(ANDROID_BUILD_EMBEDDED),true)

include $(CLEAR_VARS)
# FRAMEWORKS_BASE_SUBDIRS comes from build/core/pathmap.mk
LOCAL_SRC_FILES := $(call find-other-java-files,$(FRAMEWORKS_BASE_SUBDIRS))

# EventLogTags files.
LOCAL_SRC_FILES += \
       core/java/android/app/admin/SecurityLogTags.logtags \
       core/java/android/content/EventLogTags.logtags \
       core/java/android/speech/tts/EventLogTags.logtags \
       core/java/android/webkit/EventLogTags.logtags \
       core/java/com/android/internal/logging/EventLogTags.logtags \

LOCAL_SRC_FILES += \
    core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl \
    core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl \

......

LOCAL_MODULE := framework

LOCAL_DX_FLAGS := --core-library --multi-dex
LOCAL_JACK_FLAGS := --multi-dex native

LOCAL_RMTYPEDEFS := true

ifeq ($(EMMA_INSTRUMENT_FRAMEWORK),true)
LOCAL_EMMA_INSTRUMENT := true
endif

include $(BUILD_JAVA_LIBRARY)

  这里使用宏FRAMEWORKS BASE_SUBDIRS所指定的各个Java 源代码的路径这个宏由 build/core/目录的 pathmap.mk 文件定义。

3.4 属性机制

Android 的属性机制在 Java 框架层也有对应的接口,可以进行属性的r/w。
与属性相关的内容在以下目录中:frameworks/base/core/java/android/os/。
与属性相关的是android.os 包中的 SystemProperties 类,其基本内容如下所示:

public class SystemProperties
{
    public static final int PROP_NAME_MAX = 31;
    public static final int PROP_VALUE_MAX = 91;

    private static final ArrayList<Runnable> sChangeCallbacks = new ArrayList<Runnable>();

    private static native String native_get(String key);
    private static native String native_get(String key, String def);
    private static native int native_get_int(String key, int def);
    private static native long native_get_long(String key, long def);
    private static native boolean native_get_boolean(String key, boolean def);
    private static native void native_set(String key, String def);
    private static native void native_add_change_callback();

    /**
     * Get the value for the given key.
     * @return an empty string if the key isn't found
     * @throws IllegalArgumentException if the key exceeds 32 characters
     */
    public static String get(String key) {
        if (key.length() > PROP_NAME_MAX) {
            throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX);
        }
        return native_get(key);
    }

    /**
     * Get the value for the given key.
     * @return if the key isn't found, return def if it isn't null, or an empty string otherwise
     * @throws IllegalArgumentException if the key exceeds 32 characters
     */
    public static String get(String key, String def) {
        if (key.length() > PROP_NAME_MAX) {
            throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX);
        }
        return native_get(key, def);
    }
......
}

  由于使用了@hide标记,SystemProperties 是一个内部的类,其中只包含一些静态的方法,因此 Java 中的属性操作其实就是一个不需要上下文的方法集合。Java 中的属性机制实际上依赖于本地的 libcutils 库中的属性r/w操作来完成 SystemProperties 是对它的一个简单的封装。

3.5 套接字机制

Android 套接字具有一定的特殊性,在 Java 层也具有相应的套接字处理方法。Android 套接字相关的内容在以下目录中:frameworks/base/core/java/android/net/。
套接字的内容涉及 android.net 包中的几个类,其中 LocalSocketAddress、LocalSocket 和 LocalServerSocket 几个类是 API 的一部分,而 LocalSocketImpl 则是内部实现类 LocalSocketAddress 表示套接字的地址,构造函数如下所示:

    /**
     * Creates an instance with a given name.
     *
     * @param name non-null name
     * @param namespace namespace the name should be created in.
     */
    public LocalSocketAddress(String name, Namespace namespace) {
        this.name = name;
        this.namespace = namespace;
    }

    /**
     * Creates an instance with a given name in the {@link Namespace#ABSTRACT}
     * namespace
     *
     * @param name non-null name
     */
    public LocalSocketAddress(String name) {
        this(name,Namespace.ABSTRACT);
    }

LocalSocketAddressNamespace 是一个表示套接字的类型的枚举值,其定义内容如下所示:

    public enum Namespace {
        /** A socket in the Linux abstract namespace */
        ABSTRACT(0),
        /**
         * A socket in the Android reserved namespace in /dev/socket.
         * Only the init process may create a socket here.
         */
        RESERVED(1),
        /**
         * A socket named with a normal filesystem path.
         */
        FILESYSTEM(2);

        /** The id matches with a #define in include/cutils/sockets.h */
        private int id;
        Namespace (int id) {
            this.id = id;
        }

        /**
         * @return int constant shared with native code
         */
        /*package*/ int getId() {
            return id;
        }
    }

以上几个数值和底层的相对应。其中,Android 系统使用的通信特别手段是保留套接字RESERVED,也是由init.rc 在 /dev/socket 目录中建立的。
LocalSocket 类是套接字操作所使用的主要类。通常建立 LocalSocket 的实例后,需要连接到某个地址,表示与那个地址的套接字进行通信。LocalSocket 中包括了控制方法和数据方法。
LocalSocket 的控制方法如下所示:

    /**
     * Connects this socket to an endpoint. May only be called on an instance
     * that has not yet been connected.
     *
     * @param endpoint endpoint address
     * @throws IOException if socket is in invalid state or the address does
     * not exist.
     */
    public void connect(LocalSocketAddress endpoint) throws IOException {
        synchronized (this) {
            if (isConnected) {
                throw new IOException("already connected");
            }

            implCreateIfNeeded();
            impl.connect(endpoint, 0);
            isConnected = true;
            isBound = true;
        }
    }

    /**
     * Binds this socket to an endpoint name. May only be called on an instance
     * that has not yet been bound.
     *
     * @param bindpoint endpoint address
     * @throws IOException
     */
    public void bind(LocalSocketAddress bindpoint) throws IOException {
        implCreateIfNeeded();

        synchronized (this) {
            if (isBound) {
                throw new IOException("already bound");
            }

            localAddress = bindpoint;
            impl.bind(localAddress);
            isBound = true;
        }
    }
    /**
     * Closes the socket.
     *
     * @throws IOException
     */
    @Override
    public void close() throws IOException {
        implCreateIfNeeded();
        impl.close();
    }

建立一个 LocalSocket 之后,就可以调用 connect() 连接到使用 LocalSocketAddress 表示的某个地址,bind() 方法则只有当地址没有被绑定的时候才需要使用。LocalSocket 的数据方法如下所示:

    /**
     * Retrieves the input stream for this instance.
     *
     * @return input stream
     * @throws IOException if socket has been closed or cannot be created.
     */
    public InputStream getInputStream() throws IOException {
        implCreateIfNeeded();
        return impl.getInputStream();
    }

    /**
     * Retrieves the output stream for this instance.
     *
     * @return output stream
     * @throws IOException if socket has been closed or cannot be created.
     */
    public OutputStream getOutputStream() throws IOException {
        implCreateIfNeeded();
        return impl.getOutputStream();
    }

获得输入、输出流之后,相当于得到了套接字的数据访问句柄,可以进一步通过 InputStream 和 OutputStream 抽象类中的方法对套接字进行R/W 。LocalServerSocket 用于建立一个服务性质的 Socket,其内容如下所示:

    public LocalServerSocket(String name)
    public LocalServerSocket(FileDescriptor fd)
    public LocalSocket accept()
    public void close()
    public FileDescriptor getFileDescriptor()
    public LocalSocketAddress getLocalSocketAddress()

LocalServerSocket 实际上只用于使用抽象套接字,Android 系统保留的套接字不使用 LocalServerSocket。建立后通过 accept() 可以获得一个 LocalSocket 的实例,根据它可以进行后续的操作。
LocalSocket 和 LocalServerSocket 都是基于关键性的内部类为 LocalSocketImpl 实现的,LocalSocketImpl 类的结构如下所示:

class LocalSocketImpl {
    /**
     * An input stream for local sockets. Needed because we may
     * need to read ancillary data.
     */
    class SocketInputStream extends InputStream {...}

    /**
     * An output stream for local sockets. Needed because we may
     * need to read ancillary data.
     */
    class SocketOutputStream extends OutputStream {}

	public void create(int sockType)
	public void close()
	protected void connect(LocalSocketAddress address, int timeout)
	public void bind(LocalSocketAddress endpoint)
	protected void listen(int backlog)
	protected void accept(LocalSocketImpl s)
}

LocalSocketImpl 中的几个方法为 protected 类型,只能被本包中的 LocalSocket 和 LocalServerSocket 所调用。LocalSocket 主要使用其中 bind()、connect() 等几个方法。
LocalServerSocket 使用其中的 bind()、listen()和 accept() 方法。LocalSocketImp 的实现最终需要依赖于本地部分。对于抽象套接字(基于网络协议)部分,直接调用了 Linux 底层的套接字建立接口;Android 保留套接字的部分,则是基于libcutils 中的内容来实现的。

4 Java服务库 services.jar

Java 服务库(services.jar)提供了 Java 框架层中公共的后台运行部分。

4.1 服务库的组成和作用

  Android 中 Java 框架层的服务部分的目录为:frameworks/base/services/core/java/,其中的Android.mk 文件负责这个包的编译,其中内容生成Java 包:services.jar,将被放置到目标
系统的路径:/system/framework。
  服务库当中只包含实现了com.android.server 一个Java 包,这是一个内部类,不提供对外的API。 com.android.server 中具有众多的 Java 类。SystemServer 是其中的入口部分,服务库中还有执行某个部分具体功能的服务。
  服务库的核心内容为系统服务器(SystemServer),它提供了 Android 框架层的主要入口。进入这个入口之后,将形成一个长时间运行的后台循环。这也是 Android 系统的 Java 层运行时主要的公共部分。
  服务库中的各个子模块提供了不同方面的功能,这部分内容的名字通常为 Service。它们被 SystemServer主入口启动,随后进行自己的运行。主要的一些 Service 如下所示:

  • 活动管理服务(am/ActivityManagerService)
  • 包管理服务(pm/PackageManagerService)
  • 窗口管理器服务(wm/WindowManagerService)
  • 电源管理服务(power/PowerManagerService)
  • 输入法(Ipnut/MethodManagerService)
  • 通知服务(notification/NotificationManagerService)
  • 墙纸管理器服务(wallpaper/WallpaperManagerService)
  • 警报器服务(AlarmManagerService)
  • 光系统服务(lights/LightsService)
  • 振动器服务(VibratorService)
  • 电池服务(BatteryService)
  • 定位服务(location/LocationManagerService)

  Java 服务库 (services.jar) 和 Java 框架库 (framework.jar) 在功能上是互相依存的。服务库本身需要使用框架库中定义的各个基础类,而框架库中的部分功能又是依赖于服务库中的“服务”来实现的。

4.2 服务管理器 SystemServer

  代码位置:frameworks/base/services/java/com/android/server/SystemServer.java,SystemServer的启动过程可参考:cm-14.1 Android系统启动过程分析(6)-SystemServer进程启动过程

4.3 主要服务的功能

Java 服务库中的服务为框架层提供了功能的实现。一个通常的使用方式是,在框架库中定义接口,在服务库中实现这个接口,框架库通过接口调用服务库。这些服务是 Java 框架层的“公用部分”,它们通常有类似的运行行为:

  • 它们自已在后台运行一个循环
  • 又提供接口让外部可以对其进行调用

服务库中很多类实现了 aidl 定义的接口中所描述的功能,然后由 Java 框架库根据这些 aidl 接口对其进行调用。服务库中的很多类继承了某个 aidl 文件中定义的 XXX.Stub 类,如下所示:

public class VibratorService extends IVibratorService.Stub {...}
public class LocationManagerService extends ILocationManager.Stub {...}

有些类也直接继承了 Binder,如下所示:

public class DiskStatsService extends Binder {...}

上面两种继承方式,都是通过 Java 层的 Binder 进程间通信机制,向其他 Java 程序提供接口。随着 Android 系统的发展,服务库中的内容有所增加。这里各个组件实现的基本模式是通过实现 aidl 向框架库提供接口的实现,但是少数所谓“服务”也不是用这种方式实现的。

4.3.1 活动管理服务(am/ActivityManagerService)

4.3.2 窗口管理器服务(wm/WindowManagerService)

4.3.3 包管理服务(pm/PackageManagerService)

4.3.4 电源管理服务(power/PowerManagerService)

4.3.5 输入法(Ipnut/MethodManagerService)

4.3.6 通知服务(notification/NotificationManagerService)

4.3.7 墙纸管理器服务(wallpaper/WallpaperManagerService)

4.3.8 外设相关的几个服务

4.4 启动结束时的处理

  Android 系统 Java 部分的启动过程本身是由服务库来负责的。服务库中的一个部分提供了启动完成时间点执行的操作。
  frameworks/base/core/java/com/android/server/BootReceiver.java 文件在Java 框架层定义了一个 BroadcastReceiver 的组件。它处理了名称为 android.intent.action.BOOT_COMPLETED 的动作,其中的 onReceive() 方法将在 Android 系统启动之后执行。
  BootReceiver 中默认进行启动信息的处理,例如,在系统第一次启动完成后,保存一些信息到数据库中。如果需要系统启动完成后,处理一些全局性的工作,可以通过在 BootReceiver.java 文件增加调用内容来完成。

5 资源包 framework-res.apk

  资源包 (framework-res.apk) 包含了 Java 框架层的所有资源,也包括在 API 中声明的资源和内部资源。

5.1 资源包的组成和作用

  Android 资源包的目录为:frameworks/base/core/res/,其中的 Android.mk 文件负责这个包的编译。生成Android 的应用程序包:framework-res.apk,将被放置到目标系统的路径:/system/framework 。
  资源包 framework-res.apk 是 Android 的Java 框架层的唯一 apk 文件,其他均为 Jar 包。因此框架层中的资源文件、资产文件和 AndroidManifest.xml 文件都包含在这个资源包中,并且这个资源包中不包含 Java 代码。除此之外,资源包其他部分的结构和应用程序层的一个应用程序工程基本相同。

  资源包主要包括 res 资源目录、assets 资产目录和 AndroidManifest.xml 文件,没有源代码目录。
其中 res 中的内容为资源文件,各个子目录的含义如下所示:

anim 动画文件
color 颜色定义
drawable-<修饰符> 图片等可绘制内容,修饰符通常是不同屏幕的支持
layout-<修饰符> 布局文件,修饰符为不同的方向
values-<修饰符> 数值定义文件,修饰符通常是不同语言的支持
xml-<修饰符> XML格式的文件
raw-<修饰符> 原始文件,修饰符通常是不同语言的支持

  其中的各个资源文件将会自动生成相应描述资源 id 的 Java 源代码文件,也就是out/target/common/R/android 目录中R.java文件,片段如下所示:

package android;

public final class R {
    public static final class anim {
        public static final int accelerate_decelerate_interpolator=0x010a0004;
        /**  Acceleration curve matching Flash's quadratic ease out function.
         */
        public static final int accelerate_interpolator=0x010a0005;
        public static final int anticipate_interpolator=0x010a0007;
        public static final int anticipate_overshoot_interpolator=0x010a0009;
        public static final int bounce_interpolator=0x010a000a;
        public static final int cycle_interpolator=0x010a000c;
......
}

  R类中的 R.anim、R.array 等类,其中的内容是表示资源的一些整数值。这个 R.java 文件将作为源代码被编入Java 框架库 framework.jar 中。
  res/values-<修饰符>/目录中的各个文件为不同数值定义,各个文件的功能如下所示:

ids.xml 定义android.R.id 类中的各个数值,为一些固定的 id
strings.xml 定义android.R.string 类中的各个数值,为各个字符串
arrays.xml 定义android.R.array 类中的各个数值,为各个数组
attrs.xml 定义android.R.attrs 类中的各个数值,为各个属性
styles.xml 和 themes.xml 定义android.R.style 类中的各个数值,为样式和主题
colors.xml 定义android.R.color 类中的各个数值,也作为可绘制内容使用
dimens.xml 定义android.R.dimen 类中的各个数值,为尺寸值

  各文件定义均包含在和标签中。注意:这些文件的名称只是命名上的习惯,并非强制使用的名称。实际起到作用的是文件中各个标签定义内容的使用,在所有 xml文件中的意义都是一样的。

5.2 作为API的资源id

  资源包的部分资源是公共资源。它们的 id 也是 Android 标准 API的一部分通常使用android.R.*类中的整数值来表示。
资源包的 res/values/ 目录中的 public.xml 文件用于定义公共资源的 id。截取其中一段如下所示:

  <public type="drawable" name="sym_action_chat" id="0x0108008e" />
  <public type="drawable" name="sym_action_email" id="0x0108008f" />
  <public type="drawable" name="sym_call_incoming" id="0x01080090" />

  以上的内容由类型drawable 表示了android.R.drawable 类,其中的名称为 sym_action_email 和 sym_call_incoming 的值,它们的本质是整数值。
  在 public.xml中定义的各个资源,为系统公共的资源,具有固定的 id。它们等同于 Java 层的API,在系统编译的时候也会根据 public.xml 更新 current.xml 文件。

5.3 资源包 AndroidManifest.xml 文件

  资源包的 AndroidManifest.xml 文件定义了框架层的包名(package=“android”)和运行用户(android:sharedUserId=“android.uid.system”),并声明了许可和内部组件。
  资源包没有 Java 源代码目录 (src),却有 AndroidManifest.xml 文件,其中除了全局的声明,还有系统预定义的许可以及框架层的应用程序组件 (Activity、Service 等) 的声明。例如,前面提到的服务库中的 BootReceiver 广播接收器,在这个AndroidManifest.xml文件中就有如下的定义:

        <receiver android:name="com.android.server.BootReceiver"
                android:systemUserOnly="true">
            <intent-filter android:priority="1000">
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            intent-filter>
        receiver>

  组件对应的代码通常在 Java 框架库和Java 服务库中。
  Java 框架库 firamework.jar 和服务 services.jar 包括一些内部的活动、服务、广播接收器等。但是这两个包都是以 jar 文件形式构建的,不能包含 AndroidManifest.xml 和资源文件,因此相应的内容包含在资源包 framework-res.apk 当中。

5 策略库

策略库(android.policyjar)负责实现 Java框架层中一些细节的行为。
待补充

你可能感兴趣的:(#,Android系统中的原理分析,android,framework)