private void saveSignatures(PackageInfo pkgInfo) {
   if (pkgInfo != null && pkgInfo.signatures != null) {
     int i = 0;
     for (Signature signature : pkgInfo.signatures) {
       File file =
           new File(PluginDirHelper.getPluginSignatureFile(mContext, pkgInfo.packageName, i));
       try {
         Utils.writeToFile(file, signature.toByteArray());
         Log.i(
             TAG,
             "Save %s signature of %s,md5=%s",
             pkgInfo.packageName,
             i,
             Utils.md5(signature.toByteArray()));
       } catch (Exception e) {
         e.printStackTrace();
         Log.w(TAG, "Save signatures fail", e);
         file.delete();
         Utils.deleteDir(PluginDirHelper.getPluginSignatureDir(mContext, pkgInfo.packageName));
         break;
       }
       i++;
     }
   }
 }
 private Signature[] readSignatures(String packageName) {
   List<String> fils = PluginDirHelper.getPluginSignatureFiles(mContext, packageName);
   List<Signature> signatures = new ArrayList<Signature>(fils.size());
   int i = 0;
   for (String file : fils) {
     try {
       byte[] data = Utils.readFromFile(new File(file));
       if (data != null) {
         Signature sin = new Signature(data);
         signatures.add(sin);
         Log.i(
             TAG, "Read %s signature of %s,md5=%s", packageName, i, Utils.md5(sin.toByteArray()));
       } else {
         Log.i(TAG, "Read %s signature of %s FAIL", packageName, i);
         return null;
       }
       i++;
     } catch (Exception e) {
       Log.i(TAG, "Read %s signature of %s FAIL", e, packageName, i);
       return null;
     }
   }
   return signatures.toArray(new Signature[signatures.size()]);
 }
  @Override
  public int deletePackage(String packageName, int flags) throws RemoteException {
    try {
      if (mPluginCache.containsKey(packageName)) {
        forceStopPackage(packageName);

        PluginPackageParser parser;
        synchronized (mPluginCache) {
          parser = mPluginCache.remove(packageName);
        }
        Utils.deleteDir(PluginDirHelper.makePluginBaseDir(mContext, packageName));
        mActivityManagerService.onPkgDeleted(mPluginCache, parser, packageName);
        mSignatureCache.remove(packageName);
        sendUninstalledBroadcast(packageName);
        return PackageManagerCompat.DELETE_SUCCEEDED;
      }
    } catch (Exception e) {
      handleException(e);
    }
    return PackageManagerCompat.DELETE_FAILED_INTERNAL_ERROR;
  }
  @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 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;
    }
  }