赞
踩
需求
禁止静默安装install apk
对于应用市场来说,内存大小总是不够大,所以在一定空间后(eg:小于500M后)禁止安装第三方软件。
android/frameworks/base$ git diff diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java index a505a69..1f819b1 100644 --- a/cmds/pm/src/com/android/commands/pm/Pm.java +++ b/cmds/pm/src/com/android/commands/pm/Pm.java @@ -1081,6 +1081,8 @@ public final class Pm { installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE; } else if (opt.equals("-g")) { installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS; + } else if (opt.equals("-c")) { //这步主要是为了区分对应是否是内置的强制推送安装的apk + installFlags |= PackageManager.INSTALL_USE_HEAD_SPACE_400M; } else if (opt.equals("--originating-uri")) { originatingUriString = nextOptionData(); if (originatingUriString == null) { diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 433ab66..eec7a56 100755 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -421,6 +421,9 @@ public abstract class PackageManager { /** {@hide} */ public static final int INSTALL_FORCE_VOLUME_UUID = 0x00000200; + /* {@hide}Force the use of reserved space */ + public static final int INSTALL_USE_HEAD_SPACE_400M = 0x00000400; + diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index dd959ec..12a2bfd 100755 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -147,6 +147,7 @@ import android.net.Uri; import android.os.AsyncTask; import android.os.Debug; import android.os.Binder; +import android.os.StatFs; import android.os.Build; import android.os.Bundle; import android.os.Environment; @@ -10116,10 +10117,38 @@ public class PackageManagerService extends IPackageManager.Stub { verificationParams, packageAbiOverride, UserHandle.getCallingUserId()); } + // get sdcard free + public Boolean SpaceEnough() { + int headspace = 500; // head 500M + Environment.setUserRequired(false); + StatFs emmc_sd_path = new StatFs(Environment.getExternalStorageDirectory().getPath()); + long blockSize = emmc_sd_path.getBlockSize(); + long availableBlocks = emmc_sd_path.getAvailableBlocks(); + long emmc_sd_free = blockSize * availableBlocks; + int sd_free = new Long(emmc_sd_free/1024/1024).intValue(); + if (sd_free < headspace) + return false; + + return true; + } + @Override public void installPackageAsUser(String originPath, IPackageInstallObserver2 observer, int installFlags, String installerPackageName, VerificationParams verificationParams, String packageAbiOverride, int userId) { + int useHeadspaceFlags = PackageManager.INSTALL_USE_HEAD_SPACE_400M | PackageManager.INSTALL_ALL_USERS; // <-- 0x400 | 0x40 + boolean useHeadspace_400M = "true".equals(SystemProperties.get("persist.evideo.use.headspace","false")); + if (installFlags == useHeadspaceFlags) { + installFlags = PackageManager.INSTALL_REPLACE_EXISTING | PackageManager.INSTALL_ALL_USERS ; // <-- 0x2 | 0x04 (install -r 的命令flag) + } else if (useHeadspace_400M && !SpaceEnough()) { + try { + Slog.w(TAG, "data headspace less than 400M ,please release space !!!"); + observer.onPackageInstalled("", INSTALL_FAILED_USER_RESTRICTED, null, null); + return ; + } catch (RemoteException re) { + } + } + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null); final int callingUid = Binder.getCallingUid();
原理:就是将所有的installFlags拦截下来,除了特定设置的标志位(0x400【INSTALL_USE_HEAD_SPACE_400M】 | 0x40 【INSTALL_ALL_USERS】)才可以安装.另外还有一个就是属性值(persist.evideo.use.headspace)设定是用来区分不需要此功能的。如果是特定的标志位那么执行(0x2 【INSTALL_REPLACE_EXISTING】| 0x40 )静默安装apk。
①Pm.java 添加解释:后续补充如何实现pm install到Pm.java的过程。
②PackageManagerService.java添加解释:installPackageAsUser()这个是静默应用安装apk的接口。
由于更新了api接口导致引发的错误,添加{@hide}将其隐藏,对应编译就可以正常编译通过了。
问题二:
安装应用代码: public Installer(Context context) { try { pm = context.getPackageManager(); Class<?>[] types = new Class[] {Uri.class, IPackageInstallObserver.class, int.class, String.class}; method = pm.getClass().getMethod("installPackage", types); method.invoke(pm, apkFile, observer, flag, installerPackageName); } catch (NoSuchMethodException e) { e.printStackTrace(); } } 错误日志: 12-03 09:45:42.578 7898-7913/com.evideo.kmbox.appmarket I/Installer: [BaseAppInstaller(321): Installer.java:411] - --installPath:/storage/emulated/0/market/com.elinkway.tvlive2.69cf8103806614a11da330dee1c614bd_1203987403.apk?r=714734?t=aaaa 12-03 09:45:42.579 7898-7913/com.evideo.kmbox.appmarket D/Installer: [BaseAppInstaller(321): Installer.java:423] - install app with flag 2: com.elinkway.tvlive2 12-03 09:45:42.598 3050-4650/system_process E/Environment: Path requests must specify a user by using UserEnvironment java.lang.Throwable at android.os.Environment.throwIfUserRequired(Environment.java:760) at android.os.Environment.getExternalStorageDirectory(Environment.java:339) at com.android.server.pm.PackageManagerService.SpaceEnough(PackageManagerService.java:10122) at com.android.server.pm.PackageManagerService.installPackageAsUser(PackageManagerService.java:10139) at com.android.server.pm.PackageManagerService.installPackage(PackageManagerService.java:10116) at android.content.pm.IPackageManager$Stub.onTransact(IPackageManager.java:977) at com.android.server.pm.PackageManagerService.onTransact(PackageManagerService.java:2642) at android.os.Binder.execTransact(Binder.java:453) 12-03 09:45:51.650 8177-8177/? W/dex2oat: Compilation of void com.baidu.mobads.production.p.onAdClicked(com.baidu.mobads.interfaces.IXAdContainer, com.baidu.mobads.interfaces.IXAdInstanceInfo, java.lang.Boolean, java.util.HashMap) took 116.046ms 12-03 09:46:01.744 3050-3096/system_process W/PackageManager: Unknown permission android.permission.BROADCAST_PACKAGE_INSTALL in package com.elinkway.tvlive2 12-03 09:46:01.890 3050-3096/system_process W/Settings: Setting install_non_market_apps has moved from android.provider.Settings.Global to android.provider.Settings.Secure, returning read-only value.
解决方法: 添加Environment.setUserRequired(false); 不调用这个方法;
/** {@hide} */ public static void setUserRequired(boolean userRequired) { sUserRequired = userRequired; } private static void throwIfUserRequired() { if (sUserRequired) { Log.wtf(TAG, "Path requests must specify a user by using UserEnvironment", new Throwable()); } } } ## 改进建议 工作记录…
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。