PackageManagerService也是有ServerThread启动的,运行在system_process进程。
我们先来看下PackageManagerService是怎么启动的:
PackageManagerService的启动需要四个参数,context上下文环境信息由ActivityManagerService获
取,installer是一个安装器,是对install程序的一个封装,在new一个Installer之后会调用ping命令测试是否能连接的上
install的服务端。
再来看一下PackageManagerService的初始化流程:
相关代码:
-
public PackageManagerService(Context context, Installer installer,
-
boolean factoryTest, boolean onlyCore) {
-
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
-
SystemClock.uptimeMillis());
-
-
if (mSdkVersion <= 0) {
-
Slog.w(TAG, "**** ro.build.version.sdk not set!");
-
}
-
-
mContext = context;
-
mFactoryTest = factoryTest;
-
mOnlyCore = onlyCore;
-
mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
-
mMetrics = new DisplayMetrics();
-
mSettings = new Settings(context);
-
mSettings.addSharedUserLPw("android.uid.system",
-
Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
-
mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID, ApplicationInfo.FLAG_SYSTEM);
-
mSettings.addSharedUserLPw("android.uid.log", LOG_UID, ApplicationInfo.FLAG_SYSTEM);
-
mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID, ApplicationInfo.FLAG_SYSTEM);
-
mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID, ApplicationInfo.FLAG_SYSTEM);
-
-
String separateProcesses = SystemProperties.get("debug.separate_processes");
-
if (separateProcesses != null && separateProcesses.length() > 0) {
-
if ("*".equals(separateProcesses)) {
-
mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
-
mSeparateProcesses = null;
-
Slog.w(TAG, "Running with debug.separate_processes: * (ALL)");
-
} else {
-
mDefParseFlags = 0;
-
mSeparateProcesses = separateProcesses.split(",");
-
Slog.w(TAG, "Running with debug.separate_processes: "
-
+ separateProcesses);
-
}
-
} else {
-
mDefParseFlags = 0;
-
mSeparateProcesses = null;
-
}
-
-
mInstaller = installer;
-
-
WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
-
Display d = wm.getDefaultDisplay();
-
d.getMetrics(mMetrics);
-
-
synchronized (mInstallLock) {
-
-
synchronized (mPackages) {
-
mHandlerThread.start();
-
mHandler = new PackageHandler(mHandlerThread.getLooper());
-
-
File dataDir = Environment.getDataDirectory();
-
mAppDataDir = new File(dataDir, "data");
-
mAppInstallDir = new File(dataDir, "app");
-
mAppLibInstallDir = new File(dataDir, "app-lib");
-
mAsecInternalPath = new File(dataDir, "app-asec").getPath();
-
mUserAppDataDir = new File(dataDir, "user");
-
mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
-
-
sUserManager = new UserManagerService(context, this,
-
mInstallLock, mPackages);
-
-
readPermissions();
-
-
mRestoredSettings = mSettings.readLPw(sUserManager.getUsers(false));
-
long startTime = SystemClock.uptimeMillis();
-
-
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
-
startTime);
-
-
-
-
int scanMode = SCAN_MONITOR | SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING;
-
if (mNoDexOpt) {
-
Slog.w(TAG, "Running ENG build: no pre-dexopt!");
-
scanMode |= SCAN_NO_DEX;
-
}
-
-
final HashSet libFiles = new HashSet();
-
-
mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
-
mDalvikCacheDir = new File(dataDir, "dalvik-cache");
-
-
boolean didDexOpt = false;
-
-
-
-
-
-
String bootClassPath = System.getProperty("java.boot.class.path");
-
if (bootClassPath != null) {
-
String[] paths = splitString(bootClassPath, ':');
-
for (int i=0; i
-
try {
-
if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
-
libFiles.add(paths[i]);
-
mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
-
didDexOpt = true;
-
}
-
} catch (FileNotFoundException e) {
-
Slog.w(TAG, "Boot class path not found: " + paths[i]);
-
} catch (IOException e) {
-
Slog.w(TAG, "Cannot dexopt " + paths[i] + "; is it an APK or JAR? "
-
+ e.getMessage());
-
}
-
}
-
} else {
-
Slog.w(TAG, "No BOOTCLASSPATH found!");
-
}
-
-
-
-
-
if (mSharedLibraries.size() > 0) {
-
Iterator libs = mSharedLibraries.values().iterator();
-
while (libs.hasNext()) {
-
String lib = libs.next();
-
try {
-
if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
-
libFiles.add(lib);
-
mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
-
didDexOpt = true;
-
}
-
} catch (FileNotFoundException e) {
-
Slog.w(TAG, "Library not found: " + lib);
-
} catch (IOException e) {
-
Slog.w(TAG, "Cannot dexopt " + lib + "; is it an APK or JAR? "
-
+ e.getMessage());
-
}
-
}
-
}
-
-
-
-
libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
-
-
-
-
-
-
-
String[] frameworkFiles = mFrameworkDir.list();
-
if (frameworkFiles != null) {
-
for (int i=0; i
-
File libPath = new File(mFrameworkDir, frameworkFiles[i]);
-
String path = libPath.getPath();
-
-
if (libFiles.contains(path)) {
-
continue;
-
}
-
-
if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
-
continue;
-
}
-
try {
-
if (dalvik.system.DexFile.isDexOptNeeded(path)) {
-
mInstaller.dexopt(path, Process.SYSTEM_UID, true);
-
didDexOpt = true;
-
}
-
} catch (FileNotFoundException e) {
-
Slog.w(TAG, "Jar not found: " + path);
-
} catch (IOException e) {
-
Slog.w(TAG, "Exception reading jar: " + path, e);
-
}
-
}
-
}
-
-
if (didDexOpt) {
-
-
-
-
-
-
String[] files = mDalvikCacheDir.list();
-
if (files != null) {
-
for (int i=0; i
-
String fn = files[i];
-
if (fn.startsWith("data@app@")
-
|| fn.startsWith("data@app-private@")) {
-
Slog.i(TAG, "Pruning dalvik file: " + fn);
-
(new File(mDalvikCacheDir, fn)).delete();
-
}
-
}
-
}
-
}
-
-
-
mFrameworkInstallObserver = new AppDirObserver(
-
mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
-
mFrameworkInstallObserver.startWatching();
-
scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM
-
| PackageParser.PARSE_IS_SYSTEM_DIR,
-
scanMode | SCAN_NO_DEX, 0);
-
-
-
mSystemAppDir = new File(Environment.getRootDirectory(), "app");
-
mSystemInstallObserver = new AppDirObserver(
-
mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
-
mSystemInstallObserver.startWatching();
-
scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM
-
| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
-
-
-
mVendorAppDir = new File("/vendor/app");
-
mVendorInstallObserver = new AppDirObserver(
-
mVendorAppDir.getPath(), OBSERVER_EVENTS, true);
-
mVendorInstallObserver.startWatching();
-
scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM
-
| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
-
-
if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
-
mInstaller.moveFiles();
-
-
-
final List possiblyDeletedUpdatedSystemApps = new ArrayList();
-
if (!mOnlyCore) {
-
Iterator psit = mSettings.mPackages.values().iterator();
-
while (psit.hasNext()) {
-
PackageSetting ps = psit.next();
-
-
-
-
-
-
if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
-
continue;
-
}
-
-
-
-
-
final PackageParser.Package scannedPkg = mPackages.get(ps.name);
-
if (scannedPkg != null) {
-
-
-
-
-
-
-
//如果系统app刚被扫描并且在disabled列表,则它肯定是通过ota添加的,从当前扫描的package中移除它,所以以前用户安装的可以被扫描到
-
if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
-
Slog.i(TAG, "Expecting better updatd system app for " + ps.name
-
+ "; removing system app");
-
removePackageLI(ps, true);
-
}
-
-
continue;
-
}
-
-
if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
-
psit.remove();
-
String msg = "System package " + ps.name
-
+ " no longer exists; wiping its data";
-
reportSettingsProblem(Log.WARN, msg);
-
removeDataDirsLI(ps.name);
-
} else {
-
final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
-
if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {
-
possiblyDeletedUpdatedSystemApps.add(ps.name);
-
}
-
}
-
}
-
}
-
-
-
ArrayList deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
-
-
for(int i = 0; i < deletePkgsList.size(); i++) {
-
-
cleanupInstallFailedPackage(deletePkgsList.get(i));
-
}
-
-
deleteTempPackageFiles();
-
-
if (!mOnlyCore) {
-
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
-
SystemClock.uptimeMillis());
-
mAppInstallObserver = new AppDirObserver(
-
mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
-
mAppInstallObserver.startWatching();
-
scanDirLI(mAppInstallDir, 0, scanMode, 0);
-
-
mDrmAppInstallObserver = new AppDirObserver(
-
mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
-
mDrmAppInstallObserver.startWatching();
-
scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
-
scanMode, 0);
-
-
-
-
-
-
-
-
for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
-
PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
-
mSettings.removeDisabledSystemPackageLPw(deletedAppName);
-
-
String msg;
-
if (deletedPkg == null) {
-
msg = "Updated system package " + deletedAppName
-
+ " no longer exists; wiping its data";
-
removeDataDirsLI(deletedAppName);
-
} else {
-
msg = "Updated system app + " + deletedAppName
-
+ " no longer present; removing system privileges for "
-
+ deletedAppName;
-
-
deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
-
-
PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
-
deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
-
}
-
reportSettingsProblem(Log.WARN, msg);
-
}
-
} else {
-
mAppInstallObserver = null;
-
mDrmAppInstallObserver = null;
-
}
-
-
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
-
SystemClock.uptimeMillis());
-
Slog.i(TAG, "Time to scan packages: "
-
+ ((SystemClock.uptimeMillis()-startTime)/1000f)
-
+ " seconds");
-
-
-
-
-
-
-
-
final boolean regrantPermissions = mSettings.mInternalSdkPlatform
-
!= mSdkVersion;
-
if (regrantPermissions) 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));
-
-
-
mSettings.writeLPr();
-
-
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
-
SystemClock.uptimeMillis());
-
-
-
-
-
Runtime.getRuntime().gc();
-
-
mRequiredVerifierPackage = getRequiredVerifierLPr();
-
}
-
}
-
}
PackageManagerService的初始化工作都是在它的构造函数中完成的,主要完成一下任务:
1、 添加一些用户id,如system、phone等;
2、 建立并启动PackageHandler消息循环,用于处理apk安装请求如adbinstall
packageinstaller安装apk时就会发送消息;
3、
解析/system/etc/permission下的xml文件,主要是platform.xml,建立permission和gid之间的关系,可以
指定一个权限与几个组对应,当一个apk被授予这个权限时它也同时属于这几个组,readPermission(parser,
perm);给一些底层用户分配一些权限,如shell授予各种permission,把一个权限赋予一个uid,当apk使用这个uid运行时,就具备
了这个权限系统增加的一些应用需要link的扩展的jar库,系统每增加一个硬件,都要添加相应的featrue,将解析结果放入
mAvailableFeatures;
4、
检查/data/system/packages.xml是否存在,里面记录了系统的ppermission,以及每个apk的
name,codePath,flags,ts,version,userid等,这些信息主要是通过apk安装的时候解析
AndroidManifest.xml获取到的,解析完apk后将更新信息写入这个文件并保存到flash,下次开机直接从里面读取相关信息添加到内存
相关列表中,当有apk安装,升级,删除时会更新这个文件;
5、 检查BootClassPath,mSharedLibraries及/system/framework下的jar是否需要dexopt,需要则通过dexopt进行优化,这里面主要是调用mInstaller.dexopt进行相应的优化;
6、 建立 java 层的 installer 与 c 层的 installd 的 socket 联接,使得在上层的 install,remove,dexopt等功能最终由installd在底层实现;
7、
启动AppDirObserver线程往中监测/system/framework,/system/app,/data/app/data/app-
private目录的事件,主要监听add和remove事件,对于目录监听底层通过innotify机制实现,inotify是一种文件系统的变化通知
机制如文件增加、删除等事件可以立刻让用户态得知,它为用户态监视文件系统的变化提供了强大的支持,当有add
event时调用scanPackageLI(File,int,int)处理,当有remove
event时调用removePackageLI处理;
8、 调用scanDirLI启动apk解析,解析目录包括:/system/framework、/system/app、/vendor/app、/data/app、/data/app-private;
9、 移除临时文件;
10、 赋予package相应请求的权限;
11、 将解析出的Package的相关信息保存到相关全局变量,还有文件。
下面来分析前面每一步大概都做了些什么:
一、添加用户:
添加用户调用的是Settings的addSharedUserLPw
-
SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags) {
-
SharedUserSetting s = mSharedUsers.get(name);
-
if (s != null) {
-
if (s.userId == uid) {
-
return s;
-
}
-
PackageManagerService.reportSettingsProblem(Log.ERROR,
-
"Adding duplicate shared user, keeping first: " + name);
-
return null;
-
}
-
s = new SharedUserSetting(name, pkgFlags);
-
s.userId = uid;
-
if (addUserIdLPw(uid, s, name)) {
-
mSharedUsers.put(name, s);
-
return s;
-
}
-
return null;
首先检查mSharedUsers中是否有这个用户,没有的话则新建一个SharedUserSetting,调用addUserIdLPw保存到mUserIds或mOtherUserIds,并添加到mSharedUsers。
-
private boolean addUserIdLPw(int uid, Object obj, Object name) {
-
if (uid > Process.LAST_APPLICATION_UID) {
-
return false;
-
}
-
-
if (uid >= Process.FIRST_APPLICATION_UID) {
-
int N = mUserIds.size();
-
final int index = uid - Process.FIRST_APPLICATION_UID;
-
while (index >= N) {
-
mUserIds.add(null);
-
N++;
-
}
-
if (mUserIds.get(index) != null) {
-
PackageManagerService.reportSettingsProblem(Log.ERROR,
-
"Adding duplicate user id: " + uid
-
+ " name=" + name);
-
return false;
-
}
-
mUserIds.set(index, obj);
-
} else {
-
if (mOtherUserIds.get(uid) != null) {
-
PackageManagerService.reportSettingsProblem(Log.ERROR,
-
"Adding duplicate shared id: " + uid
-
+ " name=" + name);
-
return false;
-
}
-
mOtherUserIds.put(uid, obj);
-
}
-
return true;
-
}
二、建立并启动PackageHandler消息循环
PackageHandler用来处理安装apk等过程中的各种消息,后面降到apk安装的时候会涉及到。
这个比较简单,主要就新建一个PackageHandler,用来处理消息。
三、解析/system/etc/permission下的xml文件
主要是读取并解析/etc/permissions的xml文件,如我的平板上面:
看一下读取的流程:
相关代码:
-
void readPermissions() {
-
-
File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
-
if (!libraryDir.exists() || !libraryDir.isDirectory()) {
-
Slog.w(TAG, "No directory " + libraryDir + ", skipping");
-
return;
-
}
-
if (!libraryDir.canRead()) {
-
Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
-
return;
-
}
-
-
-
for (File f : libraryDir.listFiles()) {
-
-
if (f.getPath().endsWith("etc/permissions/platform.xml")) {
-
continue;
-
}
-
-
if (!f.getPath().endsWith(".xml")) {
-
Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
-
continue;
-
}
-
if (!f.canRead()) {
-
Slog.w(TAG, "Permissions library file " + f + " cannot be read");
-
continue;
-
}
-
-
readPermissionsFromXml(f);
-
}
-
-
-
final File permFile = new File(Environment.getRootDirectory(),
-
"etc/permissions/platform.xml");
-
readPermissionsFromXml(permFile);
-
}
readPermissions先读取除platform.xml的其他文件,并调用readPermissionsFromXml进行解析,继续看一下readPermissionsFromXml
-
private void readPermissionsFromXml(File permFile) {
-
FileReader permReader = null;
-
try {
-
permReader = new FileReader(permFile);
-
} catch (FileNotFoundException e) {
-
Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
-
return;
-
}
-
-
try {
-
XmlPullParser parser = Xml.newPullParser();
-
parser.setInput(permReader);
-
-
XmlUtils.beginDocument(parser, "permissions");
-
-
while (true) {
-
XmlUtils.nextElement(parser);
-
if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
-
break;
-
}
-
-
String name = parser.getName();
-
if ("group".equals(name)) {
-
String gidStr = parser.getAttributeValue(null, "gid");
-
if (gidStr != null) {
-
int gid = Integer.parseInt(gidStr);
-
mGlobalGids = appendInt(mGlobalGids, gid);
-
} else {
-
Slog.w(TAG, " without gid at "
-
+ parser.getPositionDescription());
-
}
-
-
XmlUtils.skipCurrentTag(parser);
-
continue;
-
} else if ("permission".equals(name)) {
-
String perm = parser.getAttributeValue(null, "name");
-
if (perm == null) {
-
Slog.w(TAG, " without name at "
-
+ parser.getPositionDescription());
-
XmlUtils.skipCurrentTag(parser);
-
continue;
-
}
-
perm = perm.intern();
-
readPermission(parser, perm);
-
-
} else if ("assign-permission".equals(name)) {
-
String perm = parser.getAttributeValue(null, "name");
-
if (perm == null) {
-
Slog.w(TAG, " without name at "
-
+ parser.getPositionDescription());
-
XmlUtils.skipCurrentTag(parser);
-
continue;
-
}
-
String uidStr = parser.getAttributeValue(null, "uid");
-
if (uidStr == null) {
-
Slog.w(TAG, " without uid at "
-
+ parser.getPositionDescription());
-
XmlUtils.skipCurrentTag(parser);
-
continue;
-
}
-
int uid = Process.getUidForName(uidStr);
-
if (uid < 0) {
-
Slog.w(TAG, " with unknown uid \""
-
+ uidStr + "\" at "
-
+ parser.getPositionDescription());
-
XmlUtils.skipCurrentTag(parser);
-
continue;
-
}
-
perm = perm.intern();
-
HashSet perms = mSystemPermissions.get(uid);
-
if (perms == null) {
-
perms = new HashSet();
-
mSystemPermissions.put(uid, perms);
-
}
-
perms.add(perm);
-
XmlUtils.skipCurrentTag(parser);
-
-
} else if ("library".equals(name)) {
-
String lname = parser.getAttributeValue(null, "name");
-
String lfile = parser.getAttributeValue(null, "file");
-
if (lname == null) {
-
Slog.w(TAG, " without name at "
-
+ parser.getPositionDescription());
-
} else if (lfile == null) {
-
Slog.w(TAG, " without file at "
-
+ parser.getPositionDescription());
-
} else {
-
-
mSharedLibraries.put(lname, lfile);
-
}
-
XmlUtils.skipCurrentTag(parser);
-
continue;
-
-
} else if ("feature".equals(name)) {
-
String fname = parser.getAttributeValue(null, "name");
-
if (fname == null) {
-
Slog.w(TAG, " without name at "
-
+ parser.getPositionDescription());
-
} else {
-
-
FeatureInfo fi = new FeatureInfo();
-
fi.name = fname;
-
mAvailableFeatures.put(fname, fi);
-
}
-
XmlUtils.skipCurrentTag(parser);
-
continue;
-
-
} else {
-
XmlUtils.skipCurrentTag(parser);
-
continue;
-
}
-
-
}
-
permReader.close();
-
} catch (XmlPullParserException e) {
-
Slog.w(TAG, "Got execption parsing permissions.", e);
-
} catch (IOException e) {
-
Slog.w(TAG, "Got execption parsing permissions.", e);
-
}
-
}
readPermissionsFromXml主要是:
1、读取permission name添加到mSettings.mPermissions
2、读取gid添加到mSettings.mPermissions
readPermissionsFromXml:
permission
a、读取permission name添加到mSettings.mPermissions
b、读取gid添加到mSettings.mPermissions
assign-permission
a、设置相应uid所具有的权限,保存到mSystemPermissions
library
a、.jar包保存到mSharedLibraries
feature
a、 硬件相关信息保存到mAvailableFeatures
我们来看一下platform.xml:
-
xml version="1.0" encoding="utf-8"?>
-
-
-
-
-
-
<permission name="android.permission.READ_NETWORK_USAGE_HISTORY">
-
<group gid="net_bw_stats" />
-
permission>
-
-
-
<permission name="android.permission.MODIFY_NETWORK_ACCOUNTING">
-
<group gid="net_bw_acct" />
-
permission>
-
-
-
-
-
-
-
<assign-permission name="android.permission.WRITE_EXTERNAL_STORAGE" uid="shell" />
-
<assign-permission name="android.permission.SEND_SMS" uid="shell" />
-
<assign-permission name="android.permission.CALL_PHONE" uid="shell" />
-
<assign-permission name="android.permission.READ_CONTACTS" uid="shell" />
-
<assign-permission name="android.permission.WRITE_CONTACTS" uid="shell" />
-
<assign-permission name="android.permission.READ_CALENDAR" uid="shell" />
-
<assign-permission name="android.permission.WRITE_CALENDAR" uid="shell" />
-
<assign-permission name="android.permission.READ_USER_DICTIONARY" uid="shell" />
-
<assign-permission name="android.permission.WRITE_USER_DICTIONARY" uid="shell" />
-
<assign-permission name="android.permission.ACCESS_FINE_LOCATION" uid="shell" />
-
<assign-permission name="android.permission.ACCESS_COARSE_LOCATION" uid="shell" />
-
<assign-permission name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" uid="shell" />
-
<assign-permission name="android.permission.ACCESS_NETWORK_STATE" uid="shell" />
-
<assign-permission name="android.permission.ACCESS_WIFI_STATE" uid="shell" />
-
<assign-permission name="android.permission.BLUETOOTH" uid="shell" />
-
-
<assign-permission name="android.permission.GET_TASKS" uid="shell" />
-
<assign-permission name="android.permission.CHANGE_CONFIGURATION" uid="shell" />
-
<assign-permission name="android.permission.REORDER_TASKS" uid="shell" />
-
<assign-permission name="android.permission.SET_ANIMATION_SCALE" uid="shell" />
-
<assign-permission name="android.permission.SET_PREFERRED_APPLICATIONS" uid="shell" />
-
<assign-permission name="android.permission.WRITE_SETTINGS" uid="shell" />
-
<assign-permission name="android.permission.WRITE_SECURE_SETTINGS" uid="shell" />
-
<assign-permission name="android.permission.BROADCAST_STICKY" uid="shell" />
-
-
<assign-permission name="android.permission.SET_DEBUG_APP" uid="shell" />
-
<assign-permission name="android.permission.SET_PROCESS_LIMIT" uid="shell" />
-
<assign-permission name="android.permission.SET_ALWAYS_FINISH" uid="shell" />
-
<assign-permission name="android.permission.DUMP" uid="shell" />
-
<assign-permission name="android.permission.SIGNAL_PERSISTENT_PROCESSES" uid="shell" />
-
<assign-permission name="android.permission.KILL_BACKGROUND_PROCESSES" uid="shell" />
-
-
<assign-permission name="android.permission.FORCE_BACK" uid="shell" />
-
<assign-permission name="android.permission.BATTERY_STATS" uid="shell" />
-
<assign-permission name="android.permission.INTERNAL_SYSTEM_WINDOW" uid="shell" />
-
<assign-permission name="android.permission.INJECT_EVENTS" uid="shell" />
-
<assign-permission name="android.permission.RETRIEVE_WINDOW_CONTENT" uid="shell" />
-
<assign-permission name="android.permission.SET_ACTIVITY_WATCHER" uid="shell" />
-
<assign-permission name="android.permission.READ_INPUT_STATE" uid="shell" />
-
<assign-permission name="android.permission.SET_ORIENTATION" uid="shell" />
-
<assign-permission name="android.permission.INSTALL_PACKAGES" uid="shell" />
-
<assign-permission name="android.permission.CLEAR_APP_USER_DATA" uid="shell" />
-
<assign-permission name="android.permission.DELETE_CACHE_FILES" uid="shell" />
-
<assign-permission name="android.permission.DELETE_PACKAGES" uid="shell" />
-
<assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="shell" />
-
<assign-permission name="android.permission.READ_FRAME_BUFFER" uid="shell" />
-
<assign-permission name="android.permission.DEVICE_POWER" uid="shell" />
-
<assign-permission name="android.permission.INSTALL_LOCATION_PROVIDER" uid="shell" />
-
<assign-permission name="android.permission.BACKUP" uid="shell" />
-
<assign-permission name="android.permission.FORCE_STOP_PACKAGES" uid="shell" />
-
<assign-permission name="android.permission.STOP_APP_SWITCHES" uid="shell" />
-
<assign-permission name="android.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY" uid="shell" />
-
<assign-permission name="android.permission.GRANT_REVOKE_PERMISSIONS" uid="shell" />
-
<assign-permission name="android.permission.SET_KEYBOARD_LAYOUT" uid="shell" />
-
<assign-permission name="android.permission.GET_DETAILED_TASKS" uid="shell" />
-
<assign-permission name="android.permission.SET_SCREEN_COMPATIBILITY" uid="shell" />
-
<assign-permission name="android.permission.READ_EXTERNAL_STORAGE" uid="shell" />
-
<assign-permission name="android.permission.WRITE_EXTERNAL_STORAGE" uid="shell" />
-
<assign-permission name="android.permission.INTERACT_ACROSS_USERS" uid="shell" />
-
<assign-permission name="android.permission.INTERACT_ACROSS_USERS_FULL" uid="shell" />
-
<assign-permission name="android.permission.MANAGE_USERS" uid="shell" />
-
<assign-permission name="android.permission.BLUETOOTH_STACK" uid="shell" />
-
-
<assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="media" />
-
<assign-permission name="android.permission.ACCESS_DRM" uid="media" />
-
<assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="media" />
-
<assign-permission name="android.permission.WAKE_LOCK" uid="media" />
-
-
<assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="graphics" />
-
-
阅读(2292) | 评论(0) | 转发(0) |