/**
  * get system install location<br>
  * can be set by System Menu Setting->Storage->Prefered install location
  *
  * @return
  * @see {@link IPackageManager#getInstallLocation()}
  */
 public static int getInstallLocation() {
   CommandResult commandResult =
       ShellUtils.execCommand(
           "LD_LIBRARY_PATH=/vendor/lib:/system/lib pm get-install-location", false, true);
   if (commandResult.result == 0
       && commandResult.successMsg != null
       && commandResult.successMsg.length() > 0) {
     try {
       int location = Integer.parseInt(commandResult.successMsg.substring(0, 1));
       switch (location) {
         case APP_INSTALL_INTERNAL:
           return APP_INSTALL_INTERNAL;
         case APP_INSTALL_EXTERNAL:
           return APP_INSTALL_EXTERNAL;
       }
     } catch (NumberFormatException e) {
       e.printStackTrace();
       Log.e(TAG, "pm get-install-location error");
     }
   }
   return APP_INSTALL_AUTO;
 }
  /**
   * uninstall package silent by root
   *
   * <ul>
   *   <strong>Attentions:</strong>
   *   <li>Don't call this on the ui thread, it may costs some times.
   *   <li>You should add <strong>android.permission.DELETE_PACKAGES</strong> in manifest, so no
   *       need to request root permission, if you are system app.
   * </ul>
   *
   * @param context file path of package
   * @param packageName package name of app
   * @param isKeepData whether keep the data and cache directories around after package removal
   * @return
   *     <ul>
   *       <li>{@link #DELETE_SUCCEEDED} means uninstall success
   *       <li>{@link #DELETE_FAILED_INTERNAL_ERROR} means internal error
   *       <li>{@link #DELETE_FAILED_INVALID_PACKAGE} means package name error
   *       <li>{@link #DELETE_FAILED_PERMISSION_DENIED} means permission denied
   */
  public static int uninstallSilent(Context context, String packageName, boolean isKeepData) {
    if (packageName == null || packageName.length() == 0) {
      return DELETE_FAILED_INVALID_PACKAGE;
    }

    /**
     * if context is system app, don't need root permission, but should add <uses-permission
     * android:name="android.permission.DELETE_PACKAGES" /> in mainfest
     */
    StringBuilder command =
        new StringBuilder()
            .append("LD_LIBRARY_PATH=/vendor/lib:/system/lib pm uninstall")
            .append(isKeepData ? " -k " : " ")
            .append(packageName.replace(" ", "\\ "));
    CommandResult commandResult =
        ShellUtils.execCommand(command.toString(), !isSystemApplication(context), true);
    if (commandResult.successMsg != null
        && (commandResult.successMsg.contains("Success")
            || commandResult.successMsg.contains("success"))) {
      return DELETE_SUCCEEDED;
    }
    Log.e(
        TAG,
        new StringBuilder()
            .append("uninstallSilent successMsg:")
            .append(commandResult.successMsg)
            .append(", ErrorMsg:")
            .append(commandResult.errorMsg)
            .toString());
    if (commandResult.errorMsg == null) {
      return DELETE_FAILED_INTERNAL_ERROR;
    }
    if (commandResult.errorMsg.contains("Permission denied")) {
      return DELETE_FAILED_PERMISSION_DENIED;
    }
    return DELETE_FAILED_INTERNAL_ERROR;
  }
  /**
   * install package silent by root
   *
   * <ul>
   *   <strong>Attentions:</strong>
   *   <li>Don't call this on the ui thread, it may costs some times.
   *   <li>You should add <strong>android.permission.INSTALL_PACKAGES</strong> in manifest, so no
   *       need to request root permission, if you are system app.
   * </ul>
   *
   * @param context
   * @param filePath file path of package
   * @param pmParams pm install params
   * @return {@link PackageUtils#INSTALL_SUCCEEDED} means install success, other means failed.
   *     details see {@link PackageUtils}.INSTALL_FAILED_*. same to {@link PackageManager}.INSTALL_*
   */
  public static int installSilent(Context context, String filePath, String pmParams) {
    if (filePath == null || filePath.length() == 0) {
      return INSTALL_FAILED_INVALID_URI;
    }

    File file = new File(filePath);
    if (file == null || file.length() <= 0 || !file.exists() || !file.isFile()) {
      return INSTALL_FAILED_INVALID_URI;
    }

    /**
     * if context is system app, don't need root permission, but should add <uses-permission
     * android:name="android.permission.INSTALL_PACKAGES" /> in mainfest
     */
    StringBuilder command =
        new StringBuilder()
            .append("LD_LIBRARY_PATH=/vendor/lib:/system/lib pm install ")
            .append(pmParams == null ? "" : pmParams)
            .append(" ")
            .append(filePath.replace(" ", "\\ "));
    CommandResult commandResult =
        ShellUtils.execCommand(command.toString(), !isSystemApplication(context), true);
    if (commandResult.successMsg != null
        && (commandResult.successMsg.contains("Success")
            || commandResult.successMsg.contains("success"))) {
      return INSTALL_SUCCEEDED;
    }

    Log.e(
        TAG,
        new StringBuilder()
            .append("installSilent successMsg:")
            .append(commandResult.successMsg)
            .append(", ErrorMsg:")
            .append(commandResult.errorMsg)
            .toString());
    if (commandResult.errorMsg == null) {
      return INSTALL_FAILED_OTHER;
    }
    if (commandResult.errorMsg.contains("INSTALL_FAILED_ALREADY_EXISTS")) {
      return INSTALL_FAILED_ALREADY_EXISTS;
    }
    if (commandResult.errorMsg.contains("INSTALL_FAILED_INVALID_APK")) {
      return INSTALL_FAILED_INVALID_APK;
    }
    if (commandResult.errorMsg.contains("INSTALL_FAILED_INVALID_URI")) {
      return INSTALL_FAILED_INVALID_URI;
    }
    if (commandResult.errorMsg.contains("INSTALL_FAILED_INSUFFICIENT_STORAGE")) {
      return INSTALL_FAILED_INSUFFICIENT_STORAGE;
    }
    if (commandResult.errorMsg.contains("INSTALL_FAILED_DUPLICATE_PACKAGE")) {
      return INSTALL_FAILED_DUPLICATE_PACKAGE;
    }
    if (commandResult.errorMsg.contains("INSTALL_FAILED_NO_SHARED_USER")) {
      return INSTALL_FAILED_NO_SHARED_USER;
    }
    if (commandResult.errorMsg.contains("INSTALL_FAILED_UPDATE_INCOMPATIBLE")) {
      return INSTALL_FAILED_UPDATE_INCOMPATIBLE;
    }
    if (commandResult.errorMsg.contains("INSTALL_FAILED_SHARED_USER_INCOMPATIBLE")) {
      return INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
    }
    if (commandResult.errorMsg.contains("INSTALL_FAILED_MISSING_SHARED_LIBRARY")) {
      return INSTALL_FAILED_MISSING_SHARED_LIBRARY;
    }
    if (commandResult.errorMsg.contains("INSTALL_FAILED_REPLACE_COULDNT_DELETE")) {
      return INSTALL_FAILED_REPLACE_COULDNT_DELETE;
    }
    if (commandResult.errorMsg.contains("INSTALL_FAILED_DEXOPT")) {
      return INSTALL_FAILED_DEXOPT;
    }
    if (commandResult.errorMsg.contains("INSTALL_FAILED_OLDER_SDK")) {
      return INSTALL_FAILED_OLDER_SDK;
    }
    if (commandResult.errorMsg.contains("INSTALL_FAILED_CONFLICTING_PROVIDER")) {
      return INSTALL_FAILED_CONFLICTING_PROVIDER;
    }
    if (commandResult.errorMsg.contains("INSTALL_FAILED_NEWER_SDK")) {
      return INSTALL_FAILED_NEWER_SDK;
    }
    if (commandResult.errorMsg.contains("INSTALL_FAILED_TEST_ONLY")) {
      return INSTALL_FAILED_TEST_ONLY;
    }
    if (commandResult.errorMsg.contains("INSTALL_FAILED_CPU_ABI_INCOMPATIBLE")) {
      return INSTALL_FAILED_CPU_ABI_INCOMPATIBLE;
    }
    if (commandResult.errorMsg.contains("INSTALL_FAILED_MISSING_FEATURE")) {
      return INSTALL_FAILED_MISSING_FEATURE;
    }
    if (commandResult.errorMsg.contains("INSTALL_FAILED_CONTAINER_ERROR")) {
      return INSTALL_FAILED_CONTAINER_ERROR;
    }
    if (commandResult.errorMsg.contains("INSTALL_FAILED_INVALID_INSTALL_LOCATION")) {
      return INSTALL_FAILED_INVALID_INSTALL_LOCATION;
    }
    if (commandResult.errorMsg.contains("INSTALL_FAILED_MEDIA_UNAVAILABLE")) {
      return INSTALL_FAILED_MEDIA_UNAVAILABLE;
    }
    if (commandResult.errorMsg.contains("INSTALL_FAILED_VERIFICATION_TIMEOUT")) {
      return INSTALL_FAILED_VERIFICATION_TIMEOUT;
    }
    if (commandResult.errorMsg.contains("INSTALL_FAILED_VERIFICATION_FAILURE")) {
      return INSTALL_FAILED_VERIFICATION_FAILURE;
    }
    if (commandResult.errorMsg.contains("INSTALL_FAILED_PACKAGE_CHANGED")) {
      return INSTALL_FAILED_PACKAGE_CHANGED;
    }
    if (commandResult.errorMsg.contains("INSTALL_FAILED_UID_CHANGED")) {
      return INSTALL_FAILED_UID_CHANGED;
    }
    if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_NOT_APK")) {
      return INSTALL_PARSE_FAILED_NOT_APK;
    }
    if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_BAD_MANIFEST")) {
      return INSTALL_PARSE_FAILED_BAD_MANIFEST;
    }
    if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION")) {
      return INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
    }
    if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_NO_CERTIFICATES")) {
      return INSTALL_PARSE_FAILED_NO_CERTIFICATES;
    }
    if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES")) {
      return INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
    }
    if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING")) {
      return INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
    }
    if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME")) {
      return INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
    }
    if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID")) {
      return INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
    }
    if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_MANIFEST_MALFORMED")) {
      return INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
    }
    if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_MANIFEST_EMPTY")) {
      return INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
    }
    if (commandResult.errorMsg.contains("INSTALL_FAILED_INTERNAL_ERROR")) {
      return INSTALL_FAILED_INTERNAL_ERROR;
    }
    return INSTALL_FAILED_OTHER;
  }