這篇blog主要是介紹Android是怎樣將system_server這個系統(tǒng)進程配置成android的application的運行環(huán)境的。
其中會涉及到framework-res.apk , SettingsProvider.apk
注: 該篇代碼是基本 Android M 6.0.1
這篇文章最早發(fā)表于我的個人主頁github乓旗,現(xiàn)在只是將它移到簡書上。
轉載請標注來處: http://www.reibang.com/p/4378ebb1847f
一颁督、framework-res.apk
framework-res.apk是android framework相關的資源文件apk, 里面保存了framework使用到的layout渣触、圖片、string等資源蟋字, 同時也會聲明一些系統(tǒng)級的Activity.
代碼地址: frameworks/base/core/res
1.1 Android.mk
LOCAL_PACKAGE_NAME := framework-res
LOCAL_CERTIFICATE := platform
LOCAL_EXPORT_PACKAGE_RESOURCES := true
LOCAL_EXPORT_PACKAGE_RESOURCES 為true, 表示允許framework-res.apk里的資源可以被其它app使用.
1.2 AndroidManifest.mk
- 配置成system sharedUserId
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android"
coreApp="true"
android:sharedUserId="android.uid.system"
<!--system權限-->
android:sharedUserLabel="@string/android_system_label"
>
從AndroidManifest里可以看出framework-res.apk的package name為 “android”, 且要運行在system進程中.
- 定義protected-broadcast
<protected-broadcast android:name="android.intent.action.SCREEN_OFF" />
<protected-broadcast android:name="android.intent.action.SCREEN_ON" />
pretected-broadcast廣播只能由系統(tǒng)級應用發(fā)出, 它是由PackageManagerService解析.
在Android系統(tǒng)運作起來之后稿蹲,如果某個不具有系統(tǒng)權限的APP試圖發(fā)送系統(tǒng)中的“保護性廣播”,那么AMS的broadcastIntentLocked()會攔截鹊奖,AMS會拋出異常
java.lang.SecurityException: Permission Denial: not allowed to send broadcast
android.intent.action.SCREEN_OFF from pid=3225, uid=10068
- 定義permission與permission-group
<!-- Allows an application to send SMS messages.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.SEND_SMS"
android:permissionGroup="android.permission-group.SMS"
android:label="@string/permlab_sendSms"
android:description="@string/permdesc_sendSms"
android:permissionFlags="costsMoney"
android:protectionLevel="dangerous" />
<!-- Allows an application to receive SMS messages.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.RECEIVE_SMS"
android:permissionGroup="android.permission-group.SMS"
android:label="@string/permlab_receiveSms"
android:description="@string/permdesc_receiveSms"
android:protectionLevel="dangerous"/>
permission-element用來作為安全權限限制訪問一些特殊的模塊或者features或者其它應用程序苛聘。
若APP要使用,必須要聲明
<use-permission />
- 定義主application
<application android:process="system"
android:persistent="true" //persistent進程
android:hasCode="false" //沒有application的code,
android:label="@string/android_system_label"
android:allowClearUserData="false"
android:backupAgent="com.android.server.backup.SystemBackupAgent"
android:killAfterRestore="false"
android:icon="@drawable/ic_launcher_android"
android:supportsRtl="true">
<!--定義一些activity-->
<activity android:name="com.android.internal.app.ChooserActivity"
android:theme="@style/Theme.DeviceDefault.Resolver"
android:finishOnCloseSystemDialogs="true"
android:excludeFromRecents="true"
android:documentLaunchMode="never"
android:relinquishTaskIdentity="true"
默認所有的components都運行在system進程, 當然前提是有相同的shared User ID, 和相同的簽名(Android.mk里定義了platform)
二忠聚、SettingsProvider.apk
SettingsProvider.apk 是一個ContentProvider, 主要用來提供系統(tǒng)的Settings的值设哗,它是運行
在system進程中的,因為system進程里面有很多service, 這些service都可能需要訪問到SettingsProvider里的值两蟀。
因此將SettingsProvider.apk跑在system進程中可以避免不必要的跨進程間消耗.
參見鄧凡平的android 系統(tǒng)2
2.1 Android.mk
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-subdir-java-files) \
src/com/android/providers/settings/EventLogTags.logtags
LOCAL_JAVA_LIBRARIES := telephony-common ims-common
LOCAL_PACKAGE_NAME := SettingsProvider
LOCAL_CERTIFICATE := platform //platform簽名
LOCAL_PRIVILEGED_MODULE := true //privileged的apk
從上面可以看出, SettingsProvider.apk也是platform簽名
2.2 AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.providers.settings"
coreApp="true"
android:sharedUserId="android.uid.system"> <!-- system權限 -->
<application android:allowClearUserData="false"
android:label="@string/app_label"
android:process="system"
<!--該application下的所有Component運行在 system進程中-->
android:backupAgent="SettingsBackupAgent"
android:killAfterRestore="false"
android:icon="@mipmap/ic_launcher_settings">
<!-- todo add: android:neverEncrypt="true" -->
<provider android:name="SettingsProvider"
android:authorities="settings"
android:multiprocess="false"
android:exported="true"
<!--其它application可通過 URL訪問該Provider-->
android:singleUser="true"
android:initOrder="100" />
</application>
</manifest>
從AndroidManifest.xml中定義來看网梢,SettingsProvider.apk里所有的組件默認也是運行在system進程,且SettingsProvider.apk這個進程是system權限赂毯。
三战虏、配置 SystemServer為Android application的環(huán)境
接下來這節(jié)主要來介紹如何將SystemServer配置成android應用程序的運行環(huán)境
整個簡化的流程如下所示:
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
…
// Initialize the system context.
createSystemContext();
//初始化系統(tǒng)上下文
// Set up the Application instance for the system process and get started.
mActivityManagerService.setSystemProcess();
//通過AMS,將當前進程設置成android的應用程序的環(huán)境党涕,安裝framework-res.apk,生成進程相關的ProcessRecord
//安裝系統(tǒng)Providers
mActivityManagerService.installSystemProviders();
}
3.1 createSystemContext
每個android 應用程序在進行初始化的時候首先都會生成一個全局的Applicaton實例(不管App代碼有沒有去實現(xiàn)這樣一個application).
而createSystemContext創(chuàng)建的系統(tǒng)上下文就是去生成這樣一個Application實例烦感。
private void createSystemContext() {
ActivityThread activityThread = ActivityThread.systemMain();
//創(chuàng)建與線程相關的AcivityThread, 并且創(chuàng)建系統(tǒng)context
mSystemContext = activityThread.getSystemContext();
…
}
public static ActivityThread systemMain() {
…
ActivityThread thread = new ActivityThread();
//將當前system_server運行的主線程關聯(lián)一個AcivityThread.
thread.attach(true);
return thread;
}
// attach 系統(tǒng)進程
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
…
} else {
// Don't set application object here -- if the system crashes,
// we can't display an alert, we just want to die die die.
android.ddm.DdmHandleAppName.setAppName("system_process",
UserHandle.myUserId());
//將Systemserver進程在DDM里設置名稱為 system_process,這樣就可以在DDMS里看到
// system server進程了
try {
mInstrumentation = new Instrumentation();
//生成一個Instrumentation遣鼓,這是一個工具類
ContextImpl context = ContextImpl.createAppContext(
this, getSystemContext().mPackageInfo);
//這個context完全沒用啸盏,只是臨時使用LoadedApk, “android/system”
mInitialApplication = context.mPackageInfo.makeApplication(true, null);
//生成應用程序對應的全局的Application
mInitialApplication.onCreate();
//進入Application的生命周期 onCreate()
} catch (Exception e) {
…
}
}
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
Application app = null;
String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
//強制初始化"android.app.Application"
}
try {
java.lang.ClassLoader cl = getClassLoader();
if (!mPackageName.equals("android")) {
initializeJavaContextClassLoader();
}
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
//這個創(chuàng)建出來的Context是真正的Systemserver的Application里對應的那個Context
//原來的application實例僅是一個殼
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
//生成Application, Application是繼承于ContextWrapper重贺,類似于proxy模式骑祟,
// ContextImpl與Application通過mOuterContext, mBase互相引用
} catch (Exception e) {
…
}
mActivityThread.mAllApplications.add(app);
//將當前生成的Application加入到mAllApplications里,
//可以看出气笙,一個線程是可以跑多個apk的次企,(一個apk對應一個Application)
mApplication = app; //用mApplication表示最初始化的Application
return app;
}
3.2 setSystemProcess
createSystemContext 僅僅是將應用程序的環(huán)境準備好,如ActivityThread, Application潜圃, context等等缸棵。
里面還沒有一些真正意義上的程序、資源谭期,僅僅是一個進程空殼堵第。
AMS setSystemProcess()
//安裝framework-res.apk, 生成systemserver對應的ProcessRecord, 并與ActivityThread進行綁定
public void setSystemProcess() {
ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
"android", STOCK_PM_FLAGS);
//注意,這里的mContext是 mSystemContext, 即系統(tǒng)級的上下文隧出, 查找package name為 “android”
//的ApplicationInfo踏志,從以上可知package name為 “android”的 apk是 framework-res.apk,
//即framework的資源文件apk, ApplicationInfo是通過解析framework-res.apk里的AndroidManifest.xml獲得的
mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());
//開始為ActivityThread 安裝 system application相關信息,將framework-res.apk對應的
//ApplicationInfo安裝到LoadedApk中的mApplicationInfo
//為systemserver 主進程開辟一個ProcessRecord來維護進程的相關信息
synchronized (this) {
//從framework-res.apk里可以知道info.processName為 “system”進程,即framework-res.apk是要跑在system進程中的胀瞪。
ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
app.persistent = true;
app.pid = MY_PID; //為ProcessRecord賦值當前進程ID针余,即system_server進程ID
app.maxAdj = ProcessList.SYSTEM_ADJ; //這個值跟OOM killer有關,值越小,越不容易被kill來釋放內存
app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
//將ProcessRecord與ActivityThread進行關聯(lián)
synchronized (mPidsSelfLocked) {
mPidsSelfLocked.put(app.pid, app);
//將ProcessRecord放到mPidSelfLocked里統(tǒng)一管理
}
updateLruProcessLocked(app, false, null);
updateOomAdjLocked(); //更新oom adj, 沒看
}
}
//生成 ProcessRecord對象
final ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess,
boolean isolated, int isolatedUid) {
String proc = customProcess != null ? customProcess : info.processName;
final ProcessRecord r = new ProcessRecord(stats, info, proc, uid);
if (!mBooted && !mBooting
&& userId == UserHandle.USER_OWNER
&& (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
r.persistent = true; //persistent
}
addProcessNameLocked(r);
return r;
}
3.3 installSystemProviders
為系統(tǒng)安裝settings provider
AMS installSystemProviders() //安裝系統(tǒng)級的Providers
public final void installSystemProviders() {
List<ProviderInfo> providers;
synchronized (this) {
ProcessRecord app = mProcessNames.get("system", Process.SYSTEM_UID);
//這里是查找system進程的ProcessRecord圆雁,即 3.2節(jié) 生成的
providers = generateApplicationProvidersLocked(app);
//根據app.processName “system” 來查看Providers, 在這里是SettingsProvider
if (providers != null) {
for (int i=providers.size()-1; i>=0; i--) {
ProviderInfo pi = (ProviderInfo)providers.get(i);
if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
Slog.w(TAG, "Not installing system proc provider " + pi.name
+ ": not system .apk");
//這里只安裝系統(tǒng)級的Providers
providers.remove(i);
}
}
}
}
if (providers != null) {
mSystemThread.installSystemProviders(providers);
}
mCoreSettingsObserver = new CoreSettingsObserver(this);
//mUsageStatsService.monitorPackages();
}
//往ActivityThread里安裝SystemProviders, mInitialApplication即是systemserver進程的Application, 前面有講
mSystemThread.installSystemProviders(providers);
installContentProviders(mInitialApplication, providers);
private void installContentProviders(
Context context, List<ProviderInfo> providers) {
final ArrayList<IActivityManager.ContentProviderHolder> results =
new ArrayList<IActivityManager.ContentProviderHolder>();
for (ProviderInfo cpi : providers) {
if (DEBUG_PROVIDER) {
StringBuilder buf = new StringBuilder(128);
buf.append("Pub ");
buf.append(cpi.authority);
buf.append(": ");
buf.append(cpi.name);
Log.i(TAG, buf.toString());
}
//具體安裝到 ActivityThread里的mProviderMap
IActivityManager.ContentProviderHolder cph = installProvider(context, null,
cpi, false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
if (cph != null) {
cph.noReleaseNeeded = true;
results.add(cph);
}
}
try {
ActivityManagerNative.getDefault().publishContentProviders(
getApplicationThread(), results);
} catch (RemoteException ex) {
}
}