Android 开机过程PMS分析
12-13 12:25:05.595 3253 3253 SystemServer !@Boot: Start PackageManagerService pm/PackageManagerService.java
public PackageManagerService(Context context, Installer installer, boolean factoryTest, boolean onlyCore)
PMS的构造函数中
① mSettings 初始化,发现 packages.list 找不到 报出以上的log
mSettings = new Settings(context);
//因为data分区 被Security的加密feature卸载,所以data下面的文件全都找不到
12-13 12:25:05.625 3253 3253 SELinuxMMAC Error opening /data/system/seapp_hash. Assuming first boot.
12-13 12:25:05.640 3253 3253 FileUtils Failed to chmod(/data/system/packages.list): android.system.ErrnoException: chmod failed: ENOENT (No such file or directory) ② SystemConfig systemConfig = SystemConfig.getInstance();
mGlobalGids = systemConfig.getGlobalGids();
mSystemPermissions = systemConfig.getSystemPermissions();
mAvailableFeatures = systemConfig.getAvailableFeatures();
packages.xml在data目录下,所以也找不到 12-13 12:25:05.650 3253 3253 SystemConfig No directory /system/etc/sysconfig, skipping
12-13 12:25:05.940 3253 3253 SystemConfig Got execption parsing permissions.
org.xmlpull.v1.XmlPullParserException: No start tag found
at com.android.server.SystemConfig.readPermissionsFromXml(SystemConfig.java:193)
at com.android.server.SystemConfig.readPermissions(SystemConfig.java:164)
at com.android.server.SystemConfig.<init>(SystemConfig.java:126)
at com.android.server.SystemConfig.getInstance(SystemConfig.java:87)
at com.android.server.pm.PackageManagerService.<init>(PackageManagerService.java:1937)
at com.android.server.pm.PackageManagerService.main(PackageManagerService.java:1825)
at com.android.server.SystemServer.startBootstrapServices(SystemServer.java:514)
at com.android.server.SystemServer.run(SystemServer.java:412)
at com.android.server.SystemServer.main(SystemServer.java:313)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1389)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1184)
12-13 12:25:06.060 3253 3253 Revision File not found at: /data/security/sepolicy
12-13 12:25:06.060 3253 3253 Revision File not found at: /data/security/spota/sepolicy_version
12-13 12:25:06.065 3253 3253 xxxxxxsetupresourcelist entered setup resource list in selinuxmmac
12-13 12:25:06.065 3253 3253 SELinuxMMAC Read and parse file: /system/etc/security/mac_permissions.xml
12-13 12:25:06.665 3253 3253 SELinuxMMAC Read and parse file: /data/security/good/mac_permissions.xml
12-13 12:25:06.665 3253 3253 SELinuxMMAC File not found exception: /data/security/good/mac_permissions.xml
12-13 12:25:06.665 3253 3253 SELinuxMMAC Read and parse file: /data/security/mycontainer/mac_permissions.xml
12-13 12:25:06.665 3253 3253 SELinuxMMAC File not found exception: /data/security/mycontainer/mac_permissions.xml
12-13 12:25:06.665 3253 3253 SELinuxMMAC Read and parse file: /data/security/whitelist/mac_permissions.xml
12-13 12:25:06.665 3253 3253 SELinuxMMAC File not found exception: /data/security/whitelist/mac_permissions.xml mInstaller = installer;
mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
// Process.THREAD_PRIORITY_BACKGROUND) 设置线程优先级为后台,这样当多个线程并发后很多无关紧要的线程分配的CPU时间将会减少,有利于主线程的处理
mHandlerThread.start();
mHandler = new PackageHandler(mHandlerThread.getLooper()); 用一个后台线程来处理安装请求
Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT); File dataDir = Environment.getDataDirectory();
mAppDataDir = new File(dataDir, "data");
mAppInstallDir = new File(dataDir, "app");
mAppLib32InstallDir = new File(dataDir, "app-lib");
mAsecInternalPath = new File(dataDir, "app-asec").getPath();
mUserAppDataDir = new File(dataDir, "user");
mDrmAppPrivateInstallDir = new File(dataDir, "app-private"); ArrayMap<String, SystemConfig.PermissionEntry> permConfig = systemConfig.getPermissions(); //权限管理配置相关
ArrayMap<String, String> libConfig = systemConfig.getSharedLibraries(); //共享库配置 相关 ③ mFoundPolicyFile = SELinuxMMAC.readInstallPolicy(); //scan SELinux install policy耗时
mRestoredSettings = mSettings.readLPw(this, sUserManager.getUsers(false), mSdkVersion, mOnlyCore); //pm/Settings.java
readLPw的时候发现data目录下的 packages.xml 找不到了,重建一个,同时return false
mRestoredSettings =false, 则被认为是第一次烧机,或者重置。 所以:First Boot Or Factory Reset : I9502ZNUHNL2 12-13 12:25:06.670 3253 3253 PackageManager Time to scan SELinux install policy: 0.612 seconds
12-13 12:25:06.670 3253 3253 PackageManager No settings file; creating initial state
12-13 12:25:06.675 3253 3253 PackageManager First Boot Or Factory Reset : I9502ZNUHNL2 String customResolverActivity = Resources.getSystem().getString( R.string.config_customResolverActivity);
if (TextUtils.isEmpty(customResolverActivity)) {
customResolverActivity = null;
} else {
mCustomResolverComponentName = ComponentName.unflattenFromString(customResolverActivity);
}
使用客户化的 customResolverActivity 来替代系统原有的,如果没有客户化的,就调用系统原有的 "/data/system/.aasa/managedpackages.xml";
AASA_readXml();
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START, startTime); //系统扫描开始,打出扫描开始时间 final int scanFlags = SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING; //设定扫描的flag
final HashSet<String> alreadyDexOpted = new HashSet<String>(); //保存 DexOpted已经解析过的 zygote 启动的时候,如果必要的话,会运行dexopt。所以要将 boot class path 中的所有东西 都添加上
final String bootClassPath = System.getenv("BOOTCLASSPATH"); //Libcore.os.getenv(name);
final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH");
在bootClassPath和systemServerClassPath 下的 默认 加入alreadyDexOpted。 ④ boolean didDexOptLibraryOrTool = false; //初始化,没有运行过dexopt的库或工具
final List<String> allInstructionSets = getAllInstructionSets(); //取得所有指令集
final String[] dexCodeInstructionSets = getDexCodeInstructionSets(allInstructionSets.toArray(new String[allInstructionSets.size()])); //所有指令集中,dexCode相关的指令集
if (mSharedLibraries.size() > 0) {...} //确保所有的external libraries 有dexopt运行过。
找到这个lib以后,将它加入alreadyDexOpted,并且调用 mInstaller.dexopt或mInstaller.patchoat 解析成可用的东西。 didDexOptLibraryOrTool = true;
// NOTE: For now, we're compiling these system "shared libraries"
// (and framework jars) into all available architectures. It's possible
// to compile them only when we come across an app that uses them (there's
// already logic for that in scanPackageLI) but that adds some complexity.
对象: "shared libraries" (and framework jars) 12-13 12:25:07.795 3253 3253 PackageManager Library not found: /system/framework/javax.btobex.jar
12-13 12:25:08.755 3253 3253 PackageManager Library not found: /system/framework/imsmanager-internal.jar File frameworkDir = new File(Environment.getRootDirectory(), "framework"); // 对system/framework目录下的东西进行处理
framework-res.apk, twframework-res.apk, 不解析,因为不包含任何代码
core-libart.jar , boot class path路径下的,art使用的东西,已经处理过了,不处理了
String[] frameworkFiles = frameworkDir.list(); //在java中实现了许多命令,需要dexopt来解析
只处理 .apk 和 .jar 类型的文件, 如果有需要解析的 也会把 didDexOptLibraryOrTool设为true. ⑤ if (didDexOptLibraryOrTool || "1".equals(SystemProperties.get("sys.prune_dex_cache", "unknown"))) {...}
//If we dexopted a library or tool, then something on the system has changed.
这部分本应该在boot classpath中做,但是由于 DexFile.isDexOptNeeded 对所有的boot classpath文件返回为false,所以我们要在这里做。
这部分是耗时最长的 12-13 12:25:12.480 3253 3253 PackageManager System has been changed!! : I9502ZNUHNL2 ⑥ File vendorOverlayDir = new File(VENDOR_OVERLAY_DIR);
final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
vendorOverlayDir = "/vendor/overlay"
frameworkDir = "/system/framework"
privilegedAppDir = "/system/priv-app"
carrierAppDir = "/carrier/itson/app"
systemAppDir = "/system/app"
vendorAppDir = "/vendor/app"
oemAppDir =
containerAppDir = "/system/container"
扫描以上目录中存在的 packages, 然后交给scanDirLI()处理, scanDirLI() 具体做了哪些操作待定
12-13 12:25:12.505 3253 3253 PackageManager not yet prefetched, retry parse package:
12-13 12:25:21.315 3253 3253 PackageManager Permission android.permission.sec.MDM_ENTERPRISE_VPN_SOLUTION from package android ignored: no group null
......
12-13 12:25:24.200 3253 3253 PackageManager not yet prefetched, retry parse package:
12-13 12:25:24.205 3253 3253 PackageManager Failed to parse /system/priv-app/LogsProvider: Not a coreApp: /system/priv-app/LogsProvider
......
12-13 12:25:48.435 3253 3253 PackageManager not yet prefetched, retry parse package:
12-13 12:25:48.435 3253 3253 PackageManager Failed to parse /system/container/resources: Missing base APK in /system/container/resources Line 3774: 12-13 12:25:12.480 3566 3566 dex2oat dex2oat took 35.592ms (threads: 4)
Line 3970: 12-13 12:25:48.490 3573 3573 dex2oat dex2oat took 23.313ms (threads: 4) //这个时间段没有跑dex2oat, 所以需要仔细分析. scanDirLI(vendorOverlayDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_TRUSTED_OVERLAY, 0);
scanDirLI(frameworkDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR | PackageParser.PARSE_IS_PRIVILEGED, scanFlags | SCAN_NO_DEX, 0);
scanDirLI(privilegedAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR | PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);
scanDirLI(carrierAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR | PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0); //CSC控制
scanDirLI(systemAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
scanDirLI(vendorAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
scanDirLI(oemAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
scanDirLI(containerAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0); if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
mInstaller.moveFiles(); 修减 packages.xml 中保存的不再存在的 system packages。// Prune any system packages that no longer exist.
mOnlyCore = onlyCore; // 参数传入的。
if (!mOnlyCore) {
Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
while (psit.hasNext()) {
PackageSetting ps = psit.next();
!ApplicationInfo.FLAG_SYSTEM: 不是系统apk,略
if (mSettings.isDisabledSystemPackageLPr(ps.name)){
removePackageLI(ps, true);
expectingBetter.put(ps.name, ps.codePath);
如果有 FLAG_SYSTEM, 并且在 disabled packages list 中,那么这个apk一定是通过OTA添加的。
将它从当前扫描中移除,然后先前user-installed的应用就会被扫描到。
加入到 expectingBetter 中。
}
if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
psit.remove();
removeDataDirsLI(ps.name);
//added to remove package setting's deleted package information
int ret = mSettings.removePackageLPw(ps);
如果有 FLAG_SYSTEM, 并且 不是disabled的系统apk, 从mSettings中移除.
} else {
final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {
possiblyDeletedUpdatedSystemApps.add(ps.name);
}
mSettings中已经标识的 disabled 的系统apk, 放到 possiblyDeletedUpdatedSystemApps 中。
} //look for any incomplete package installations. 查找所有安装 不完全 的package
cleanupInstallFailedPackage(deletePkgsList.get(i)); //清除掉安装失败的 package
deleteTempPackageFiles(); //删除临时文件
mSettings.pruneSharedUsersLPw(); //移除掉所有 和 shared userIDs 无关的 packages if (!mOnlyCore) {
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START, SystemClock.uptimeMillis()); //开始扫描data目录
scanDirLI(mAppInstallDir, 0, scanFlags, 0); //扫描app安装目录 data/app
scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK, scanFlags, 0); //特权apk安装目录 data/app-private Remove disable package settings for any updated system apps that were removed via an OTA. If they're not a previously-updated app, remove them completely.
Otherwise, just revoke their system-level permissions. for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
mSettings.removeDisabledSystemPackageLPw(deletedAppName); //mSettings中移除 disable掉的 系统apk
if (deletedPkg == null) { //被更新的系统apk已经不再存在。
removeDataDirsLI(deletedAppName); // 擦出它的数据目录,
PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
int ret = mSettings.removePackageLPw(deletedPs); // 移除掉mSetting中的该apk的信息
} else { //被更新的系统apk已经不再出现,移除它的系统特权
deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
}// end if-else
}// end for
}// end if (!mOnlyCore) /**
* Make sure all system apps that we expected to appear on
* the userdata partition actually showed up. If they never
* appeared, crawl back and revive the system version.
*/确保所有的我们期望显示的apk都被显示出来了。如果它们从来没有显示过,将他们回复到系统版本
for (int i = 0; i < expectingBetter.size(); i++) {
final String packageName = expectingBetter.keyAt(i);
if (!mPackages.containsKey(packageName)) {
privilegedAppDir, systemAppDir, vendorAppDir, oemAppDir,
mSettings.enableSystemPackageLPw(packageName);
scanPackageLI(scanFile, reparseFlags, scanFlags, 0, null);
}
} //end for ⑥ // Now that we know all of the shared libraries, update all clients to have the correct library paths.
updateAllSharedLibrariesLPw(); //我们知道了所有的共享库路径,更新所有的客户 使用正确的library paths.
12-13 12:25:48.440 3253 3253 PackageManager Package com.android.server.telecom desires unavailable shared library commonimsinterface; ignoring!
12-13 12:25:48.440 3253 3253 PackageManager Package com.android.settings desires unavailable shared library com.google.android.maps; ignoring!
12-13 12:25:48.440 3253 3253 PackageManager Package com.android.settings desires unavailable shared library TmoWfcUtils; ignoring!
12-13 12:25:48.440 3253 3253 PackageManager Package com.android.settings desires unavailable shared library commonimsinterface; ignoring!
12-13 12:25:48.440 3253 3253 PackageManager Package com.android.systemui desires unavailable shared library TmoWfcUtils; ignoring!
12-13 12:25:48.440 3253 3253 PackageManager Package com.android.phone desires unavailable shared library commonimsinterface; ignoring!
12-13 12:25:48.440 3253 3253 PackageManager Package com.android.phone desires unavailable shared library TmoWfcUtils; ignoring!
12-13 12:25:48.440 3253 3253 PackageManager Package com.android.incallui desires unavailable shared library commonimsinterface; ignoring!
12-13 12:25:48.440 3253 3253 PackageManager Package com.android.incallui desires unavailable shared library com.sec.imslibrary; ignoring!
12-13 12:25:48.440 3253 3253 PackageManager Package com.android.incallui desires unavailable shared library TmoWfcUtils; ignoring!
12-13 12:25:48.445 3253 3253 PackageManager updateAllSharedLibrariesLPw failed: Package android requires unavailable shared library com.ipsec.client; failing! ⑦ for (SharedUserSetting setting : mSettings.getAllSharedUsersLPw()) {
// NOTE: We ignore potential failures here during a system scan (like the rest of the commands above) because there's precious little we can do about it. A settings error is reported, though.
//我们忽视了 系统扫描(像其余的命令以上)的潜在故障 因为没有多少我们可以做的事。尽管报出了设置错误。
adjustCpuAbisForSharedUserLPw(setting.packages, null /* scanned package */, false /* force dexopt */, false /* defer dexopt */);
}
12-13 12:25:48.445 3253 3253 PackageManager ps : PackageSetting{1b14ab05 com.samsung.inputmethod/1000} instructionSet : arm
12-13 12:25:48.445 3253 3253 PackageManager ps : PackageSetting{2419cbb7 android/1000} instructionSet : arm 12-13 12:25:48.445 3253 3253 PackageManager Adjusting ABI for : com.sec.knox.switcher to armeabi-v7a
12-13 12:25:48.445 3253 3253 PackageManager Running dexopt on: /system/container/KnoxSwitcher/KnoxSwitcher.apk pkg=com.sec.knox.switcher isa=arm vmSafeMode=false interpret_only=false
12-13 12:25:48.500 3253 3253 PackageManager do mInstaller.dexopt : 0
12-13 12:25:48.500 3253 3253 PackageManager Time to dexopt: 0.056 seconds
12-13 12:25:48.500 3253 3253 PackageManager remove mDeferredDexOpt : Package{15cbec8c com.sec.knox.switcher}
12-13 12:25:48.500 3253 3253 PackageManager Skipping remove dex(arm) for : com.sec.knox.switcher
......
12-13 12:25:48.815 3253 3253 PackageManager Adjusting ABI for : com.android.settings to armeabi-v7a
12-13 12:25:48.815 3253 3253 PackageManager Running dexopt on: /system/priv-app/SecSettings/SecSettings.apk pkg=com.android.settings isa=arm vmSafeMode=false interpret_only=false
12-13 12:25:50.345 3253 3253 PackageManager do mInstaller.dexopt : 0
12-13 12:25:50.345 3253 3253 PackageManager Time to dexopt: 1.533 seconds
12-13 12:25:50.345 3253 3253 PackageManager remove mDeferredDexOpt : Package{2b0db67f com.android.settings}
12-13 12:25:50.345 3253 3253 PackageManager Skipping remove dex(arm) for : com.android.settings mSettings.getAllSharedUsersLPw() ⑧ mPackageUsage.readLP(); //我们知道了所有的package,读取并更新它们的 上次使用时间
readLP() 调用了convertUsageHistory();
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END, SystemClock.uptimeMillis()); //PMS扫描结束。
Slog.i(TAG, "Time to scan packages: " + ((SystemClock.uptimeMillis()-startTime)/1000f) + " seconds"); //扫描PMS一共耗时 12-13 12:25:50.350 3253 3253 PackageManager Error reading history stats: java.io.FileNotFoundException: /data/system/usage-history.xml: open failed: ENOENT (No such file or directory)
12-13 12:25:50.350 3253 3253 PackageManager Time to scan packages: 43.669 seconds // If the platform SDK has changed since the last time we booted,
// we need to re-grant app permission to catch any new ones that
// appear. This is really a hack, and means that apps can in some
// cases get permissions that the user didn't initially explicitly
// allow... it would be nice to have some better way to handle
// this situation.
如果 自上次启动以来,平台SDK版本有了变化, 那么我们需要对app重新授权。 这意味着,app可能会获取到刚开始安装时
用户没有授予的权限... 应该找一个更好的方法来处理这种情况
Slog.i(TAG, "Platform changed from " + mSettings.mInternalSdkPlatform + " to " + mSdkVersion + "; regranting permissions for internal storage");
mSettings.mInternalSdkPlatform = mSdkVersion;
updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL
| (regrantPermissions
? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
: 0)); updatePermissionsLPw() -> grantPermissionsLPw() 12-13 12:25:50.390 3253 3253 PackageManager Unknown permission com.sec.factory.permission.ALLOWFTCLIENTCPOBIND in package com.sec.phone
12-13 12:25:50.390 3253 3253 PackageManager Unknown permission com.samsungtest.SlateTest.SLATE_DM_CMD in package com.sec.phone
12-13 12:25:50.390 3253 3253 PackageManager Unknown permission com.samsung.InputEventApp.permission.UTS_DM_CMD in package com.sec.phone
12-13 12:25:50.390 3253 3253 PackageManager Unknown permission com.sec.android.app.InputEventApp.permission.KEYSTRING in package com.sec.phone // If this is the first boot, and it is a normal boot, then we need to initialize the default preferred apps.
如果这个第一次正常的启动,我们需要初始化 默认app
if (!mRestoredSettings && !onlyCore) {
mSettings.readDefaultPreferredAppsLPw(this, 0);
} // If this is first boot after an OTA, and a normal boot, then we need to clear code cache directories.
如果这个OTA以后的第一次正常启动,我们需要清除代码缓存目录
if (!Build.FINGERPRINT.equals(mSettings.mFingerprint) && !onlyCore) {
Slog.i(TAG, "Build fingerprint changed; clearing code caches");
for (String pkgName : mSettings.mPackages.keySet()) {
deleteCodeCacheDirsLI(pkgName);
}
mSettings.mFingerprint = Build.FINGERPRINT;
} mSettings.updateInternalDatabaseVersion(); //更新内置的数据库版本 // can downgrade to reader
mSettings.writeLPr(); // 可降级 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY, SystemClock.uptimeMillis()); //PMS准备好了
// synchronized (mPackages)
// synchronized (mInstallLock) // Now after opening every single application zip, make sure they are all flushed.
// Not really needed, but keeps things nice and tidy.
现在打开每一个app的zip包以后,确保他们都已经被缓存好了。
不是真正的需要,但是 要保持一切已经被准备好了
Runtime.getRuntime().gc(); 12-13 12:25:50.555 3253 3253 SystemServer !@Boot: End PackageManagerService
12-13 12:25:50.555 3253 3253 SystemServer User Service
12-13 12:25:50.570 3253 3253 SystemServiceManager Starting com.android.server.lights.LightsService
Android 开机过程PMS分析的更多相关文章
- Android开机过程
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha Android开机过程 BootLoder引导,然后加载Linux内核. 0号进程ini ...
- android开机过程简单描述
1 开机引导bootloader,相当于电脑开机启动bios 2 引导过后可以进入三种模式:fastboot, recovery, linux kernel.前两种跟版本升级相关,正常开机进入linu ...
- Android 开机动画源码分析
Android系统在启动SystemServer进程时,通过两个阶段来启动系统所有服务,在第一阶段启动本地服务,如SurfaceFlinger,SensorService等,在第二阶段则启动一系列的J ...
- OpenGL—Android 开机动画源码分析二
引自http://blog.csdn.net/luoshengyang/article/details/7691321/ BootAnimation类的成员函数的实现比较长,我们分段来阅读: 第三个开 ...
- OpenGL—Android 开机动画源码分析一
.1 Android开机动画实现方式目前实现Android开机动画的方式主要是逐帧动画和OpenGL动画. ?逐帧动画 逐帧动画是一种常见的动画形式(Frame By Frame),其原理是在“连续的 ...
- [Android systrace系列] 抓取开机过程systrace
------------------------------------------------------------------------- 这篇文章的小目标:了解抓取开机过程systrace的 ...
- android开机启动过程
Android系统开机主要经历三个阶段: bootloader启动 Linux启动 Android启动 启动文件: 对于机器从通电到加载Linux系统一般需要三个文件:bootloader(引导文件) ...
- Android系统默认Home应用程序(Launcher)的启动过程源代码分析
在前面一篇文章中,我们分析了Android系统在启动时安装应用程序的过程,这些应用程序安装好之后,还需要有一个 Home应用程序来负责把它们在桌面上展示出来,在Android系统中,这个默认的Home ...
- Android应用程序安装过程源代码分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6766010 Android系统在启动的过程中, ...
随机推荐
- 360浏览器拦截弹窗,window.open方式打不开新页面
window.open虽然在很多时候被广大中小站长用于弹窗广告的展示,所以广受争议,但是在业务需求中还是有很多场景需要用到此功能.然而,大多数浏览器对此都有一定的安全策略进行阻止,为此本文将针对以下浏 ...
- github pages简易指南
在我之前的博客用Octopress在Github pages上写博客(博客园上,github pages上)中介绍了怎么在Github Pages上写博客,今天发现了一个很不错的github page ...
- mac下教你如何开源项目托管GitHub
自从google code关闭了下载服务了之后,GitHub作为了目前最好用的免费开源项目托管站点,众多开源项目都托管在github,其中不乏著名的播放器MPC-HC. 这里教大家如何把代码库上传到G ...
- iOS开发总结-UITableView 自定义cell和动态计算cell的高度
UITableView cell自定义头文件:shopCell.h#import <UIKit/UIKit.h>@interface shopCell : UITableViewCell@ ...
- PHPExcel的读取excel的操作
首先导入类库: require_once 'PHPExcel.php'; require_once 'PHPExcel\IOFactory.php'; require_once 'PHPExcel\R ...
- android82 文件下载框架xUtils
package com.itheima.xutils; import java.io.File; import com.lidroid.xutils.HttpUtils; import com.lid ...
- Java基础知识强化之IO流笔记30:字节流4种方式复制mp4并测试效率
1. 需求:把e:\\哥有老婆.mp4 复制到当前项目目录下的copy.mp4中 字节流四种方式复制文件: • 基本字节流一次读写一个字节 • 基本字节流一次读写一个字节数组 • 高效字节流一次读写一 ...
- windows向ubuntu过渡之常用软件安装
好久没有写博客了,介于最近上操作系统实验课,好多同学装上了ubuntu,网上的教程比较杂乱,下面我就总结分享一些安装完ubuntu要安装的常用软件,会持续更新... 1.搜狗拼音安装 (1)在安装输入 ...
- HDU-1020(水题)
Encoding Problem Description Given a string containing only 'A' - 'Z', we could encode it using the ...
- JS 判断 Radio 单选按钮是否为选中状态 并弹出 值信息
今天项目中所解决的问题:JS 判断 Radio 单选按钮是否为选中状态 并弹出 值信息,一开始总是获取不到 radio 的值,后来发现逻辑存在些问题,特此共享该代码留笔记 和 分享给遇到 这类问题的 ...