@Override public List<PermissionGroupInfo> getAllPermissionGroups(int flags) throws RemoteException { waitForReadyInner(); try { enforcePluginFileExists(); List<PermissionGroupInfo> list = new ArrayList<PermissionGroupInfo>(); if (shouldNotBlockOtherInfo()) { for (PluginPackageParser pluginPackageParser : mPluginCache.values()) { List<PermissionGroupInfo> permissionGroupInfos = pluginPackageParser.getPermissionGroups(); for (PermissionGroupInfo permissionGroupInfo : permissionGroupInfos) { if (!list.contains(permissionGroupInfo)) { list.add(permissionGroupInfo); } } } } else { List<String> pkgs = mActivityManagerService.getPackageNamesByPid(Binder.getCallingPid()); for (PluginPackageParser pluginPackageParser : mPluginCache.values()) { List<PermissionGroupInfo> permissionGroupInfos = pluginPackageParser.getPermissionGroups(); for (PermissionGroupInfo permissionGroupInfo : permissionGroupInfos) { if (!list.contains(permissionGroupInfo) && pkgs.contains(permissionGroupInfo.packageName)) { list.add(permissionGroupInfo); } } } } return list; } catch (Exception e) { handleException(e); } return null; }
@Override public ProviderInfo resolveContentProvider(String name, int flags) throws RemoteException { waitForReadyInner(); try { enforcePluginFileExists(); if (shouldNotBlockOtherInfo()) { for (PluginPackageParser pluginPackageParser : mPluginCache.values()) { List<ProviderInfo> providerInfos = pluginPackageParser.getProviders(); for (ProviderInfo providerInfo : providerInfos) { if (TextUtils.equals(providerInfo.authority, name)) { return providerInfo; } } } } else { List<String> pkgs = mActivityManagerService.getPackageNamesByPid(Binder.getCallingPid()); for (PluginPackageParser pluginPackageParser : mPluginCache.values()) { List<ProviderInfo> providerInfos = pluginPackageParser.getProviders(); for (ProviderInfo providerInfo : providerInfos) { if (TextUtils.equals(providerInfo.authority, name) && pkgs.contains(providerInfo.packageName)) { return providerInfo; } } } } } catch (Exception e) { handleException(e); } return null; }
@Override public ApplicationInfo getApplicationInfo(String packageName, int flags) throws RemoteException { waitForReadyInner(); try { PluginPackageParser parser = mPluginCache.get(packageName); if (parser != null) { return parser.getApplicationInfo(flags); } } catch (Exception e) { handleException(e); } return null; }
private void enforcePluginFileExists() throws RemoteException { List<String> removedPkg = new ArrayList<>(); for (String pkg : mPluginCache.keySet()) { PluginPackageParser parser = mPluginCache.get(pkg); File pluginFile = parser.getPluginFile(); if (pluginFile != null && pluginFile.exists()) { // DO NOTHING } else { removedPkg.add(pkg); } } for (String pkg : removedPkg) { deletePackage(pkg, 0); } }
private void loadAllPlugin(Context context) { long b = System.currentTimeMillis(); ArrayList<File> apkfiles = new ArrayList<File>(); File baseDir = new File(PluginDirHelper.getBaseDir(context)); File[] dirs = baseDir.listFiles(); for (File dir : dirs) { if (dir.isDirectory()) { File file = new File(dir, "apk/base-1.apk"); if (file.exists()) { apkfiles.add(file); } } } Log.i(TAG, "Search apk cost %s ms", (System.currentTimeMillis() - b)); b = System.currentTimeMillis(); if (apkfiles != null && apkfiles.size() > 0) { for (File pluginFile : apkfiles) { long b1 = System.currentTimeMillis(); try { PluginPackageParser pluginPackageParser = new PluginPackageParser(mContext, pluginFile); Signature[] signatures = readSignatures(pluginPackageParser.getPackageName()); if (signatures == null || signatures.length <= 0) { pluginPackageParser.collectCertificates(0); PackageInfo info = pluginPackageParser.getPackageInfo(PackageManager.GET_SIGNATURES); saveSignatures(info); } else { mSignatureCache.put(pluginPackageParser.getPackageName(), signatures); pluginPackageParser.writeSignature(signatures); } if (!mPluginCache.containsKey(pluginPackageParser.getPackageName())) { mPluginCache.put(pluginPackageParser.getPackageName(), pluginPackageParser); } } catch (Throwable e) { Log.e(TAG, "parse a apk file error %s", e, pluginFile.getPath()); } finally { Log.i( TAG, "Parse %s apk cost %s ms", pluginFile.getPath(), (System.currentTimeMillis() - b1)); } } } Log.i(TAG, "Parse all apk cost %s ms", (System.currentTimeMillis() - b)); b = System.currentTimeMillis(); try { mActivityManagerService.onCreate(IPluginManagerImpl.this); } catch (Exception e) { Log.e(TAG, "mActivityManagerService.onCreate", e); } Log.i(TAG, "ActivityManagerService.onCreate %s ms", (System.currentTimeMillis() - b)); }
@Override public ProviderInfo getProviderInfo(ComponentName className, int flags) throws RemoteException { waitForReadyInner(); try { String pkg = getAndCheckCallingPkg(className.getPackageName()); if (pkg != null) { enforcePluginFileExists(); PluginPackageParser parser = mPluginCache.get(className.getPackageName()); if (parser != null) { return parser.getProviderInfo(className, flags); } } } catch (Exception e) { handleException(e); } return null; }
@Override public List<ActivityInfo> getReceivers(String packageName, int flags) throws RemoteException { try { String pkg = getAndCheckCallingPkg(packageName); if (pkg != null) { PluginPackageParser parser = mPluginCache.get(packageName); if (parser != null) { return new ArrayList<ActivityInfo>(parser.getReceivers()); } } } catch (Exception e) { RemoteException remoteException = new RemoteException(); remoteException.setStackTrace(e.getStackTrace()); throw remoteException; } return new ArrayList<ActivityInfo>(0); }
@Override public List<IntentFilter> getReceiverIntentFilter(ActivityInfo info) throws RemoteException { try { String pkg = getAndCheckCallingPkg(info.packageName); if (pkg != null) { PluginPackageParser parser = mPluginCache.get(info.packageName); if (parser != null) { List<IntentFilter> filters = parser.getReceiverIntentFilter(info); if (filters != null && filters.size() > 0) { return new ArrayList<IntentFilter>(filters); } } } return new ArrayList<IntentFilter>(0); } catch (Exception e) { RemoteException remoteException = new RemoteException(); remoteException.setStackTrace(e.getStackTrace()); throw remoteException; } }
private void dexOpt(Context hostContext, String apkfile, PluginPackageParser parser) throws Exception { String packageName = parser.getPackageName(); String optimizedDirectory = PluginDirHelper.getPluginDalvikCacheDir(hostContext, packageName); String libraryPath = PluginDirHelper.getPluginNativeLibraryDir(hostContext, packageName); ClassLoader classloader = new PluginClassLoader( apkfile, optimizedDirectory, libraryPath, ClassLoader.getSystemClassLoader()); // DexFile dexFile = DexFile.loadDex(apkfile, // PluginDirHelper.getPluginDalvikCacheFile(mContext, parser.getPackageName()), 0); // Log.e(TAG, "dexFile=%s,1=%s,2=%s", dexFile, DexFile.isDexOptNeeded(apkfile), // DexFile.isDexOptNeeded(PluginDirHelper.getPluginDalvikCacheFile(mContext, // parser.getPackageName()))); }
@Override public PackageInfo getPackageInfo(String packageName, int flags) throws RemoteException { waitForReadyInner(); try { String pkg = getAndCheckCallingPkg(packageName); if (pkg != null) { enforcePluginFileExists(); PluginPackageParser parser = mPluginCache.get(pkg); if (parser != null) { PackageInfo packageInfo = parser.getPackageInfo(flags); if (packageInfo != null && (flags & PackageManager.GET_SIGNATURES) != 0 && packageInfo.signatures == null) { packageInfo.signatures = mSignatureCache.get(packageName); } return packageInfo; } } } catch (Exception e) { handleException(e); } return null; }
@Override public void clearApplicationUserData(String packageName, IPackageDataObserver observer) throws RemoteException { boolean success = false; try { if (TextUtils.isEmpty(packageName)) { return; } PluginPackageParser parser = mPluginCache.get(packageName); if (parser == null) { return; } ApplicationInfo applicationInfo = parser.getApplicationInfo(0); Utils.deleteDir(applicationInfo.dataDir); success = true; } catch (Exception e) { handleException(e); } finally { if (observer != null) { observer.onRemoveCompleted(packageName, success); } } }
@Override public List<ApplicationInfo> getInstalledApplications(int flags) throws RemoteException { waitForReadyInner(); try { enforcePluginFileExists(); List<ApplicationInfo> infos = new ArrayList<ApplicationInfo>(mPluginCache.size()); if (shouldNotBlockOtherInfo()) { for (PluginPackageParser pluginPackageParser : mPluginCache.values()) { infos.add(pluginPackageParser.getApplicationInfo(flags)); } } else { List<String> pkgs = mActivityManagerService.getPackageNamesByPid(Binder.getCallingPid()); for (PluginPackageParser pluginPackageParser : mPluginCache.values()) { if (pkgs.contains(pluginPackageParser.getPackageName())) { infos.add(pluginPackageParser.getApplicationInfo(flags)); } } } return infos; } catch (Exception e) { handleException(e); } return null; }
@Override public int installPackage(String filepath, int flags) throws RemoteException { // install plugin String apkfile = null; try { PackageManager pm = mContext.getPackageManager(); PackageInfo info = pm.getPackageArchiveInfo(filepath, 0); if (info == null) { return PackageManagerCompat.INSTALL_FAILED_INVALID_APK; } apkfile = PluginDirHelper.getPluginApkFile(mContext, info.packageName); if ((flags & PackageManagerCompat.INSTALL_REPLACE_EXISTING) != 0) { forceStopPackage(info.packageName); if (mPluginCache.containsKey(info.packageName)) { deleteApplicationCacheFiles(info.packageName, null); } new File(apkfile).delete(); Utils.copyFile(filepath, apkfile); PluginPackageParser parser = new PluginPackageParser(mContext, new File(apkfile)); parser.collectCertificates(0); PackageInfo pkgInfo = parser.getPackageInfo(PackageManager.GET_PERMISSIONS | PackageManager.GET_SIGNATURES); if (pkgInfo != null && pkgInfo.requestedPermissions != null && pkgInfo.requestedPermissions.length > 0) { for (String requestedPermission : pkgInfo.requestedPermissions) { boolean b = false; try { b = pm.getPermissionInfo(requestedPermission, 0) != null; } catch (NameNotFoundException e) { } if (!mHostRequestedPermission.contains(requestedPermission) && b) { Log.e(TAG, "No Permission %s", requestedPermission); new File(apkfile).delete(); return PluginManager.INSTALL_FAILED_NO_REQUESTEDPERMISSION; } } } saveSignatures(pkgInfo); // if (pkgInfo.reqFeatures != null && pkgInfo.reqFeatures.length > 0) { // for (FeatureInfo reqFeature : pkgInfo.reqFeatures) { // Log.e(TAG, "reqFeature name=%s,flags=%s,glesVersion=%s", // reqFeature.name, reqFeature.flags, reqFeature.getGlEsVersion()); // } // } copyNativeLibs(mContext, apkfile, parser.getApplicationInfo(0)); dexOpt(mContext, apkfile, parser); mPluginCache.put(parser.getPackageName(), parser); mActivityManagerService.onPkgInstalled(mPluginCache, parser, parser.getPackageName()); sendInstalledBroadcast(info.packageName); return PackageManagerCompat.INSTALL_SUCCEEDED; } else { if (mPluginCache.containsKey(info.packageName)) { return PackageManagerCompat.INSTALL_FAILED_ALREADY_EXISTS; } else { forceStopPackage(info.packageName); new File(apkfile).delete(); Utils.copyFile(filepath, apkfile); PluginPackageParser parser = new PluginPackageParser(mContext, new File(apkfile)); parser.collectCertificates(0); PackageInfo pkgInfo = parser.getPackageInfo(PackageManager.GET_PERMISSIONS | PackageManager.GET_SIGNATURES); if (pkgInfo != null && pkgInfo.requestedPermissions != null && pkgInfo.requestedPermissions.length > 0) { for (String requestedPermission : pkgInfo.requestedPermissions) { boolean b = false; try { b = pm.getPermissionInfo(requestedPermission, 0) != null; } catch (NameNotFoundException e) { } if (!mHostRequestedPermission.contains(requestedPermission) && b) { Log.e(TAG, "No Permission %s", requestedPermission); new File(apkfile).delete(); return PluginManager.INSTALL_FAILED_NO_REQUESTEDPERMISSION; } } } saveSignatures(pkgInfo); // if (pkgInfo.reqFeatures != null && pkgInfo.reqFeatures.length > 0) { // for (FeatureInfo reqFeature : pkgInfo.reqFeatures) { // Log.e(TAG, "reqFeature name=%s,flags=%s,glesVersion=%s", // reqFeature.name, reqFeature.flags, reqFeature.getGlEsVersion()); // } // } copyNativeLibs(mContext, apkfile, parser.getApplicationInfo(0)); dexOpt(mContext, apkfile, parser); mPluginCache.put(parser.getPackageName(), parser); mActivityManagerService.onPkgInstalled(mPluginCache, parser, parser.getPackageName()); sendInstalledBroadcast(info.packageName); return PackageManagerCompat.INSTALL_SUCCEEDED; } } } catch (Exception e) { if (apkfile != null) { new File(apkfile).delete(); } handleException(e); return PackageManagerCompat.INSTALL_FAILED_INTERNAL_ERROR; } }