CustomLocale.apk所需要的权限"android.permission.CHANGE_CONFIGURATION"自Android 4.2,4.2.2起系统定义为android:protectionLevel="signature|system|development",这就需要在已root的android设置上运行命令:

adb shell pm grant application_package android.permission.CHANGE_CONFIGURATION

下面具体说说pm grant的调用路径。

Pm.java

public void run(String[] args) {
boolean validCommand = false;
if (args.length < 1) {
showUsage();
return;
}
...
if ("grant".equals(op)) {
runGrantRevokePermission(true);
return;
}
... private void runGrantRevokePermission(boolean grant) {
String pkg = nextArg();
if (pkg == null) {
System.err.println("Error: no package specified");
showUsage();
return;
}
String perm = nextArg();
if (perm == null) {
System.err.println("Error: no permission specified");
showUsage();
return;
}
try {
if (grant) {
mPm.grantPermission(pkg, perm);
} else {
mPm.revokePermission(pkg, perm);
}
} catch (RemoteException e) {
System.err.println(e.toString());
System.err.println(PM_NOT_RUNNING_ERR);
} catch (IllegalArgumentException e) {
System.err.println("Bad argument: " + e.toString());
showUsage();
} catch (SecurityException e) {
System.err.println("Operation not allowed: " + e.toString());
}
}

PackageManagerService.java

public class PackageManagerService extends IPackageManager.Stub {
...
public void grantPermission(String packageName, String permissionName) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.GRANT_REVOKE_PERMISSIONS, null);
synchronized (mPackages) {
final PackageParser.Package pkg = mPackages.get(packageName);
if (pkg == null) {
throw new IllegalArgumentException("Unknown package: " + packageName);
}
final BasePermission bp = mSettings.mPermissions.get(permissionName);
if (bp == null) {
throw new IllegalArgumentException("Unknown permission: " + permissionName);
} checkGrantRevokePermissions(pkg, bp); final PackageSetting ps = (PackageSetting) pkg.mExtras;
if (ps == null) {
return;
}
final GrantedPermissions gp = (ps.sharedUser != null) ? ps.sharedUser : ps;
if (gp.grantedPermissions.add(permissionName)) {
if (ps.haveGids) {
gp.gids = appendInts(gp.gids, bp.gids);
}
mSettings.writeLPr();
}
}
}
...

Settings.java

final class Settings {
...
private final File mSettingsFilename;
...
Settings(Context context, File dataDir) {
mContext = context;
mSystemDir = new File(dataDir, "system");
mSystemDir.mkdirs();
FileUtils.setPermissions(mSystemDir.toString(),
FileUtils.S_IRWXU|FileUtils.S_IRWXG
|FileUtils.S_IROTH|FileUtils.S_IXOTH,
-1, -1);
mSettingsFilename = new File(mSystemDir, "packages.xml");
mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
mPackageListFilename = new File(mSystemDir, "packages.list");
FileUtils.setPermissions(mPackageListFilename, 0660, SYSTEM_UID, PACKAGE_INFO_GID); // Deprecated: Needed for migration
mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
}
...
void writeLPr() {
//Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024); // Keep the old settings around until we know the new ones have
// been successfully written.
if (mSettingsFilename.exists()) {
// Presence of backup settings file indicates that we failed
// to persist settings earlier. So preserve the older
// backup for future reference since the current settings
// might have been corrupted.
if (!mBackupSettingsFilename.exists()) {
if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {
Log.wtf(PackageManagerService.TAG, "Unable to backup package manager settings, "
+ " current changes will be lost at reboot");
return;
}
} else {
mSettingsFilename.delete();
Slog.w(PackageManagerService.TAG, "Preserving older settings backup");
}
} mPastSignatures.clear(); try {
FileOutputStream fstr = new FileOutputStream(mSettingsFilename);
BufferedOutputStream str = new BufferedOutputStream(fstr); //XmlSerializer serializer = XmlUtils.serializerInstance();
XmlSerializer serializer = new FastXmlSerializer();
serializer.setOutput(str, "utf-8");
serializer.startDocument(null, true);
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); serializer.startTag(null, "packages"); serializer.startTag(null, "last-platform-version");
serializer.attribute(null, "internal", Integer.toString(mInternalSdkPlatform));
serializer.attribute(null, "external", Integer.toString(mExternalSdkPlatform));
serializer.endTag(null, "last-platform-version"); if (mVerifierDeviceIdentity != null) {
serializer.startTag(null, "verifier");
serializer.attribute(null, "device", mVerifierDeviceIdentity.toString());
serializer.endTag(null, "verifier");
} if (mReadExternalStorageEnforced != null) {
serializer.startTag(null, TAG_READ_EXTERNAL_STORAGE);
serializer.attribute(
null, ATTR_ENFORCEMENT, mReadExternalStorageEnforced ? "" : "");
serializer.endTag(null, TAG_READ_EXTERNAL_STORAGE);
} serializer.startTag(null, "permission-trees");
for (BasePermission bp : mPermissionTrees.values()) {
writePermissionLPr(serializer, bp);
}
serializer.endTag(null, "permission-trees"); serializer.startTag(null, "permissions");
for (BasePermission bp : mPermissions.values()) {
writePermissionLPr(serializer, bp);
}
serializer.endTag(null, "permissions"); for (final PackageSetting pkg : mPackages.values()) {
writePackageLPr(serializer, pkg);
} for (final PackageSetting pkg : mDisabledSysPackages.values()) {
writeDisabledSysPackageLPr(serializer, pkg);
} for (final SharedUserSetting usr : mSharedUsers.values()) {
serializer.startTag(null, "shared-user");
serializer.attribute(null, ATTR_NAME, usr.name);
serializer.attribute(null, "userId",
Integer.toString(usr.userId));
usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
serializer.startTag(null, "perms");
for (String name : usr.grantedPermissions) {
serializer.startTag(null, TAG_ITEM);
serializer.attribute(null, ATTR_NAME, name);
serializer.endTag(null, TAG_ITEM);
}
serializer.endTag(null, "perms");
serializer.endTag(null, "shared-user");
} if (mPackagesToBeCleaned.size() > 0) {
for (PackageCleanItem item : mPackagesToBeCleaned) {
final String userStr = Integer.toString(item.userId);
serializer.startTag(null, "cleaning-package");
serializer.attribute(null, ATTR_NAME, item.packageName);
serializer.attribute(null, ATTR_CODE, item.andCode ? "true" : "false");
serializer.attribute(null, ATTR_USER, userStr);
serializer.endTag(null, "cleaning-package");
}
} if (mRenamedPackages.size() > 0) {
for (Map.Entry<String, String> e : mRenamedPackages.entrySet()) {
serializer.startTag(null, "renamed-package");
serializer.attribute(null, "new", e.getKey());
serializer.attribute(null, "old", e.getValue());
serializer.endTag(null, "renamed-package");
}
} mKeySetManager.writeKeySetManagerLPr(serializer); serializer.endTag(null, "packages"); serializer.endDocument(); str.flush();
FileUtils.sync(fstr);
str.close(); // New settings successfully written, old ones are no longer
// needed.
mBackupSettingsFilename.delete();
FileUtils.setPermissions(mSettingsFilename.toString(),
FileUtils.S_IRUSR|FileUtils.S_IWUSR
|FileUtils.S_IRGRP|FileUtils.S_IWGRP,
-1, -1); // Write package list file now, use a JournaledFile.
File tempFile = new File(mPackageListFilename.getAbsolutePath() + ".tmp");
JournaledFile journal = new JournaledFile(mPackageListFilename, tempFile); final File writeTarget = journal.chooseForWrite();
fstr = new FileOutputStream(writeTarget);
str = new BufferedOutputStream(fstr);
try {
FileUtils.setPermissions(fstr.getFD(), 0660, SYSTEM_UID, PACKAGE_INFO_GID); StringBuilder sb = new StringBuilder();
for (final PackageSetting pkg : mPackages.values()) {
if (pkg.pkg == null || pkg.pkg.applicationInfo == null) {
Slog.w(TAG, "Skipping " + pkg + " due to missing metadata");
continue;
} final ApplicationInfo ai = pkg.pkg.applicationInfo;
final String dataPath = ai.dataDir;
final boolean isDebug = (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
final int[] gids = pkg.getGids(); // Avoid any application that has a space in its path.
if (dataPath.indexOf("") >= 0)
continue; // we store on each line the following information for now:
//
// pkgName - package name
// userId - application-specific user id
// debugFlag - 0 or 1 if the package is debuggable.
// dataPath - path to package's data path
// seinfo - seinfo label for the app (assigned at install time)
// gids - supplementary gids this app launches with
//
// NOTE: We prefer not to expose all ApplicationInfo flags for now.
//
// DO NOT MODIFY THIS FORMAT UNLESS YOU CAN ALSO MODIFY ITS USERS
// FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES:
// system/core/run-as/run-as.c
// system/core/sdcard/sdcard.c
//
sb.setLength(0);
sb.append(ai.packageName);
sb.append("");
sb.append((int)ai.uid);
sb.append(isDebug ? " 1 " : " 0 ");
sb.append(dataPath);
sb.append("");
sb.append(ai.seinfo);
sb.append("");
if (gids != null && gids.length > 0) {
sb.append(gids[0]);
for (int i = 1; i < gids.length; i++) {
sb.append(",");
sb.append(gids[i]);
}
} else {
sb.append("none");
}
sb.append("\n");
str.write(sb.toString().getBytes());
}
str.flush();
FileUtils.sync(fstr);
str.close();
journal.commit();
} catch (Exception e) {
Log.wtf(TAG, "Failed to write packages.list", e);
IoUtils.closeQuietly(str);
journal.rollback();
} writeAllUsersPackageRestrictionsLPr();
return; } catch(XmlPullParserException e) {
Log.wtf(PackageManagerService.TAG, "Unable to write package manager settings, "
+ "current changes will be lost at reboot", e);
} catch(java.io.IOException e) {
Log.wtf(PackageManagerService.TAG, "Unable to write package manager settings, "
+ "current changes will be lost at reboot", e);
}
// Clean up partially written files
if (mSettingsFilename.exists()) {
if (!mSettingsFilename.delete()) {
Log.wtf(PackageManagerService.TAG, "Failed to clean up mangled file: "
+ mSettingsFilename);
}
}
//Debug.stopMethodTracing();
}
...

pm grant 命令的更多相关文章

  1. 如何使用mysql的grant命令(详解)

    grant命令的基本格式 grant 权限 on 数据库对象 to 用户 实例一:在任意ip地址登陆的common_user用户可以对testdb数据库里的数据进行查询操作.插入操作.更新操作.删除操 ...

  2. MySQL grant命令使用

    MySQL 赋予用户权限命令的简单格式可概括为: grant 权限 on 数据库对象 to 用户 一.grant 普通数据用户,查询.插入.更新.删除 数据库中所有表数据的权利. grant sele ...

  3. php 通过 create user 和grant 命令无法创建数据库用户和授权的解决办法

    php 通过 create user 和grant 命令无法创建数据库用户和授权的解决办法 解决办法, 通过 insert 命令的方式进行创建. 创建数据库用户: $sql= "insert ...

  4. adb shell am broadcast 手动发送广播及adb shell am/pm其他命令

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/zi_zhe/article/details/72229201 在命令行可用adb shell am ...

  5. (转)MySQL的Grant命令

    [MySQL] - MySQL的Grant命令 来源:http://yingxiong.javaeye.com/blog/451208 本文实例,运行于 MySQL 5.0 及以上版本. MySQL ...

  6. win10安装mysql过程&&链接过程&&备份和导入数据&&grant命令

    win10安装mysql过程&&链接过程&&备份和导入数据&&grant命令   一 .安装 一开始在mysql官网(https://www.mysql ...

  7. MySQL的Grant命令[转]

    本文实例,运行于 MySQL 5.0 及以上版本. MySQL 赋予用户权限命令的简单格式可概括为: grant 权限 on 数据库对象 to 用户 一.grant 普通数据用户,查询.插入.更新.删 ...

  8. [MySQL] - MySQL的Grant命令

    本文实例,运行于 MySQL 5.0 及以上版本. MySQL 赋予用户权限命令的简单格式可概括为: grant 权限 on 数据库对象 to 用户 一.grant 普通数据用户,查询.插入.更新.删 ...

  9. MySQL的Grant命令

    来源:http://yingxiong.javaeye.com/blog/451208   本文实例,运行于 MySQL 5.0 及以上版本. MySQL 赋予用户权限命令的简单格式可概括为: gra ...

随机推荐

  1. .NET设计模式(9):桥接模式(Bridge Pattern)

      .NET设计模式(9):桥接模式(Bridge Pattern)   桥接模式(Bridge Pattern) --.NET设计模式系列之九 年月 实现代码如下:..所谓抽象和实现沿着各自维度的变 ...

  2. 线性布局LinearLayout和相对布局RelativeLayout 之间的比较

    LinearLayout和RelativeLayout之间: 共有属性:java代码中通过btn1关联次控件android:id="@+id/btn1" 控件宽度android:l ...

  3. SQL Server 中WITH (NOLOCK)

    with(nolock)的功能: 1: 指定允许脏读.不发布共享锁来阻止其他事务修改当前事务读取的数据,其他事务设置的排他锁不会阻碍当前事务读取锁定数据.允许脏读可能产生较多的并发操作,但其代价是读取 ...

  4. C#当中的多线程_任务并行库(下)

    4.8 处理任务中的异常 下面这个例子讨论了任务当中抛出异常,以及任务异常的获取     class Program     {         static void Main(string[] a ...

  5. 利用查询提示优化SQL

    数据库环境:SQL SERVER 2005 我们来看一下SQL语句及对应的数据量 SELECT COUNT(*) FROM cinvout_02 a WHERE ( a.dept_id IN ( SE ...

  6. AngularJS 路由:ui-router

    UI-Router是Angular-UI提供的客户端路由框架,它解决了原生的ng-route的很多不足:视图不能嵌套.这意味着$scope会发生不必要的重新载入.这也是我们在Onboard中引入ui- ...

  7. C语言带参数的main函数

    C语言带参数的main函数 #include<stdio.h> int main(int argc,char*argv[]) { int i; ;i<argc;i++) printf ...

  8. php之工厂模式

    工厂类是指包含一个专门用来创建其他对象的方法的类,工厂类在多态性编程实践中是至关重要的,它允许动态的替换类,修改配置,通常会使应用程序更加灵活,熟练掌握工厂模式高级PHP开发人员是很重要的. 工厂模式 ...

  9. ie9以上浏览器input文本框/密码框后面的小叉子/小眼睛问题

    找了很久不知什么属性控制的这个东西,经过群友的指点重要找到.

  10. php运用curl触发后台脚本不超时执行某项任务

    运用curl 设置超时,触发后台脚本执行 例如一些需要长时间等待的任务,如创建数据库,下载网络图片等 $ch = curl_init();//$ch资源可以请求多个连接 curl_setopt($ch ...