一、环境
高通 Android 13
注:Android10 和Android13有些差异,代码位置不变,参照修改即可
二、pm简单介绍
pm工具为包管理(package manager)的简称
可以使用pm工具来执行应用的安装和查询应用宝的信息、系统权限、控制应用
pm工具是Android开发与测试过程中必不可少的工具,shell命令格式如下:
pm <command>
kona:/ # which pm
/system/bin/pm
kona:/ #
kona:/ # file system/bin/pm
system/bin/pm: /system/bin/sh script
三、pm命令对应的源码位置如下
frameworks/base/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
这里通过修改源码,达到以下两个效果:
1、pm list packages -3 返回详细应用信息;2、pm install 返回包名和启动Activity
源码修改:
@@ -145,6 +145,11 @@ import java.util.concurrent.CountDownLatch;import java.util.concurrent.LinkedBlockingQueue;import java.util.concurrent.TimeUnit;+import android.app.usage.StorageStats;
+import android.app.usage.StorageStatsManager;
+import java.util.UUID;
+import java.util.HashSet;
+class PackageManagerShellCommand extends ShellCommand {/** Path for streaming APK content */private static final String STDIN_PATH = "-";
@@ -623,6 +628,7 @@ class PackageManagerShellCommand extends ShellCommand {null /* splitApkPaths */, null /* splitRevisionCodes */,apkLite.getTargetSdkVersion(), null /* requiredSplitTypes */,null /* splitTypes */);
+ params.sessionParams.setAppPackageName(pkgLite.getPackageName());sessionSize += InstallLocationUtils.calculateInstalledSize(pkgLite,params.sessionParams.abiOverride, fd.getFileDescriptor());} catch (IOException e) {
@@ -842,7 +848,7 @@ class PackageManagerShellCommand extends ShellCommand {}private int runListPackages(boolean showSourceDir, boolean showSdks) throws RemoteException {
- final String prefix = showSdks ? "sdk:" : "package:";
+ final String prefix = showSdks ? "sdk:" : "PackageName:";final PrintWriter pw = getOutPrintWriter();int getFlags = 0;boolean listDisabled = false, listEnabled = false;
@@ -985,7 +991,7 @@ class PackageManagerShellCommand extends ShellCommand {stringBuilder.append(info.applicationInfo.sourceDir);stringBuilder.append("=");}
- stringBuilder.append(name);
+ stringBuilder.append(name+ ";");if (showVersionCode) {stringBuilder.append(" versionCode:");if (info.applicationInfo != null) {
@@ -998,6 +1004,47 @@ class PackageManagerShellCommand extends ShellCommand {stringBuilder.append(" installer=");stringBuilder.append(mInterface.getInstallerPackageName(info.packageName));}
+
+
+
+ if (listThirdParty) {
+ stringBuilder.append(" Activity:");
+ stringBuilder.append(getClassName(info.packageName) + ";");
+
+ stringBuilder.append(" Label:");
+ stringBuilder.append(mContext.getPackageManager().getApplicationLabel(info.applicationInfo) + ";");
+
+ //app size
+ String sourceDir = info.applicationInfo.sourceDir;
+ StorageStatsManager storageStatsManager = (StorageStatsManager) mContext.getSystemService(Context.STORAGE_STATS_SERVICE);
+ StorageManager storageManager = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);
+ StorageStats storageStats =null;
+ try{
+ UUID uuid = storageManager.getUuidForPath(new File(sourceDir));
+ storageStats = storageStatsManager.queryStatsForPackage(uuid, info.packageName,UserHandle.getUserHandleForUid(info.applicationInfo.uid));
+ }catch(IOException e){
+ e.printStackTrace();
+ }catch(NameNotFoundException e){
+ e.printStackTrace();
+ }
+ if(storageStats != null) {
+ long appSize = storageStats.getAppBytes() + storageStats.getCacheBytes() + storageStats.getDataBytes();
+
+ stringBuilder.append(" Size:");
+ stringBuilder.append(appSize + ";");
+ }
+
+ //version name
+ stringBuilder.append(" VersionName:");
+ stringBuilder.append(info.versionName + ";");
+
+ //Uid
+ stringBuilder.append(" Uid:");
+ stringBuilder.append( info.applicationInfo.uid + ";");
+
+ }
+
+List<String> uids = out.computeIfAbsent(stringBuilder.toString(), k -> new ArrayList<>());
@@ -1006,6 +1053,7 @@ class PackageManagerShellCommand extends ShellCommand {}}}
+for (Map.Entry<String, List<String>> entry : out.entrySet()) {pw.print(entry.getKey());List<String> uids = entry.getValue();
@@ -1018,6 +1066,58 @@ class PackageManagerShellCommand extends ShellCommand {return 0;}+
+ private String getClassName(String packageName){
+ try {
+ Intent intent = new Intent();
+ Intent baseIntent = intent;
+
+ baseIntent = new Intent(Intent.ACTION_MAIN);
+ baseIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+ baseIntent.setPackage(packageName);
+
+ if (baseIntent != null) {
+ Bundle extras = intent.getExtras();
+ intent.replaceExtras((Bundle) null);
+ Bundle uriExtras = baseIntent.getExtras();
+ baseIntent.replaceExtras((Bundle) null);
+ if (intent.getAction() != null && baseIntent.getCategories() != null) {
+ HashSet<String> cats = new HashSet<String>(baseIntent.getCategories());
+ for (String c : cats) {
+ baseIntent.removeCategory(c);
+ }
+ }
+ intent.fillIn(baseIntent, Intent.FILL_IN_COMPONENT | Intent.FILL_IN_SELECTOR);
+ if (extras == null) {
+ extras = uriExtras;
+ } else if (uriExtras != null) {
+ uriExtras.putAll(extras);
+ extras = uriExtras;
+ }
+ intent.replaceExtras(extras);
+ }
+
+ mTargetUser = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
+ Binder.getCallingUid(), mTargetUser, false, false, null, null);
+
+ ResolveInfo ri = mInterface.resolveIntent(intent, intent.getType(), mQueryFlags,
+ mTargetUser);
+ if(ri != null && ri.activityInfo.name != null){
+ return ri.activityInfo.name;
+ }else{
+ return "NULL";
+ }
+ } catch (RemoteException e) {
+ throw new RuntimeException("Failed calling service", e);
+ } catch (Exception e){
+ throw new RuntimeException(e.getMessage(), e);
+ }
+ }
+
+
+
+
+private int runListPermissionGroups() throws RemoteException {final PrintWriter pw = getOutPrintWriter();final List<PermissionGroupInfo> pgs = mPermissionManager.getAllPermissionGroups(0);
@@ -1464,6 +1564,14 @@ class PackageManagerShellCommand extends ShellCommand {}abandonSession = false;//pm install 时,返回指定格式
+ if (params.sessionParams.appPackageName != null) {
+ if (getClassName(params.sessionParams.appPackageName) != null){
+ pw.print(params.sessionParams.appPackageName);
+ pw.println("/" + getClassName(params.sessionParams.appPackageName));
+ }
+ }
+
+if (params.sessionParams.isStaged && params.stagedReadyTimeoutMs > 0) {return doWaitForStagedSessionReady(sessionId, params.stagedReadyTimeoutMs, pw);}