content: package top.niunaijun.blackbox.core.system.pm;
  
  import android.annotation.SuppressLint;
  import android.content.Context;
  import android.content.pm.ActivityInfo;
  import android.content.pm.ApplicationInfo;
  import android.content.pm.ConfigurationInfo;
  import android.content.pm.FeatureInfo;
  import android.content.pm.InstrumentationInfo;
  import android.content.pm.PackageInfo;
  import android.content.pm.PackageManager;
  import android.content.pm.PackageParser;
  import android.content.pm.PermissionInfo;
  import android.content.pm.ProviderInfo;
  import android.content.pm.ServiceInfo;
  import android.content.res.AssetManager;
  import android.content.res.Resources;
  import android.os.Build;
  
  import java.util.HashSet;
  import java.util.Set;
  
  import black.android.content.pm.BRApplicationInfoL;
  import black.android.content.pm.BRApplicationInfoN;
  import black.android.content.pm.BRPackageParserSigningDetails;
  import black.android.content.pm.BRSigningInfo;
  import black.android.content.res.BRAssetManager;
  import top.niunaijun.blackbox.BlackBoxCore;
  import top.niunaijun.blackbox.core.env.AppSystemEnv;
  import top.niunaijun.blackbox.core.env.BEnvironment;
  import top.niunaijun.blackbox.entity.pm.InstallOption;
  import top.niunaijun.blackbox.utils.ArrayUtils;
  import top.niunaijun.blackbox.utils.FileUtils;
  import top.niunaijun.blackbox.utils.compat.BuildCompat;
  
  /**
   * updated by alex5402 on 4/15/21.
   * * ∧＿∧
   * (`･ω･∥
   * 丶　つ０
   * しーＪ
   * TFNQw5HgWUS33Ke1eNmSFTwoQySGU7XNsK (USDT TRC20)
   */
  @SuppressLint({"SdCardPath", "NewApi"})
  public class PackageManagerCompat {
  
      public static PackageInfo generatePackageInfo(BPackageSettings ps, int flags, BPackageUserState state, int userId) {
          if (ps == null) {
              return null;
          }
          BPackage p = ps.pkg;
          if (p != null) {
              PackageInfo packageInfo = null;
              try {
                  packageInfo = generatePackageInfo(p, flags, 0, 0, state, userId);
              } catch (Throwable ignored) {
              }
              return packageInfo;
          }
          return null;
      }
  
      public static PackageInfo generatePackageInfo(BPackage p, int flags, long firstInstallTime, long lastUpdateTime, BPackageUserState state, int userId) {
          if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo)) {
              return null;
          }
  
          PackageInfo pi = new PackageInfo();
          pi.packageName = p.packageName;
          pi.versionCode = p.mVersionCode;
          pi.versionName = p.mVersionName;
          pi.sharedUserId = p.mSharedUserId;
          pi.sharedUserLabel = p.mSharedUserLabel;
          pi.applicationInfo = generateApplicationInfo(p, flags, state, userId);
  
          pi.firstInstallTime = firstInstallTime;
          pi.lastUpdateTime = lastUpdateTime;
          if (!p.requestedPermissions.isEmpty()) {
              String[] requestedPermissions = new String[p.requestedPermissions.size()];
              p.requestedPermissions.toArray(requestedPermissions);
              pi.requestedPermissions = requestedPermissions;
          }
  
          if ((flags & PackageManager.GET_GIDS) != 0) {
              pi.gids = new int[]{};
          }
          if ((flags & PackageManager.GET_CONFIGURATIONS) != 0) {
              int N = p.configPreferences != null ? p.configPreferences.size() : 0;
              if (N > 0) {
                  pi.configPreferences = new ConfigurationInfo[N];
                  p.configPreferences.toArray(pi.configPreferences);
              }
              N = p.reqFeatures != null ? p.reqFeatures.size() : 0;
              if (N > 0) {
                  pi.reqFeatures = new FeatureInfo[N];
                  p.reqFeatures.toArray(pi.reqFeatures);
              }
          }
          if ((flags & PackageManager.GET_ACTIVITIES) != 0) {
              pi.activities = null;
              final int N = p.activities.size();
              if (N > 0) {
                  int num = 0;
                  final ActivityInfo[] res = new ActivityInfo[N];
                  for (int i = 0; i < N; i++) {
                      final BPackage.Activity a = p.activities.get(i);
                      res[num++] = generateActivityInfo(a, flags, state, userId);
                  }
                  pi.activities = ArrayUtils.trimToSize(res, num);
              }
          }
          if ((flags & PackageManager.GET_RECEIVERS) != 0) {
              pi.receivers = null;
              final int N = p.receivers.size();
              if (N > 0) {
                  int num = 0;
                  final ActivityInfo[] res = new ActivityInfo[N];
                  for (int i = 0; i < N; i++) {
                      final BPackage.Activity a = p.receivers.get(i);
                      res[num++] = generateActivityInfo(a, flags, state, userId);
                  }
                  pi.receivers = ArrayUtils.trimToSize(res, num);
              }
          }
          if ((flags & PackageManager.GET_SERVICES) != 0) {
              pi.services = null;
              final int N = p.services.size();
              if (N > 0) {
                  int num = 0;
                  final ServiceInfo[] res = new ServiceInfo[N];
                  for (int i = 0; i < N; i++) {
                      final BPackage.Service s = p.services.get(i);
                      //res[num++] = generateServiceInfo(s, flags, state, userId);
                      ServiceInfo serviceInfo = generateServiceInfo(s, flags, state, userId);
                      if(serviceInfo == null) continue;
                      if ((flags & PackageManager.GET_META_DATA) != 0) {
                          if(serviceInfo.metaData != null){
                              res[num++] = serviceInfo;
                          }
                      }else{
                          res[num++] = serviceInfo;
                      }
                  }
                  pi.services = ArrayUtils.trimToSize(res, num);
              }
          }
          if ((flags & PackageManager.GET_PROVIDERS) != 0) {
              pi.providers = null;
              final int N = p.providers.size();
              if (N > 0) {
                  int num = 0;
                  final ProviderInfo[] res = new ProviderInfo[N];
                  for (int i = 0; i < N; i++) {
                      final BPackage.Provider pr = p.providers.get(i);
                      ProviderInfo providerInfo = generateProviderInfo(pr, flags, state, userId);
                      if (providerInfo != null) {
                          res[num++] = providerInfo;
                      }
                  }
                  pi.providers = ArrayUtils.trimToSize(res, num);
              }
          }
          if ((flags & PackageManager.GET_INSTRUMENTATION) != 0) {
              pi.instrumentation = null;
              int N = p.instrumentation.size();
              if (N > 0) {
                  pi.instrumentation = new InstrumentationInfo[N];
                  for (int i = 0; i < N; i++) {
                      pi.instrumentation[i] = generateInstrumentationInfo(
                              p.instrumentation.get(i), flags);
                  }
              }
          }
          if ((flags & PackageManager.GET_PERMISSIONS) != 0) {
              pi.permissions = null;
              int N = p.permissions.size();
              if (N > 0) {
                  pi.permissions = new PermissionInfo[N];
                  for (int i = 0; i < N; i++) {
                      pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags);
                  }
              }
              pi.requestedPermissions = null;
              N = p.requestedPermissions.size();
              if (N > 0) {
                  pi.requestedPermissions = new String[N];
                  pi.requestedPermissionsFlags = new int[N];
                  for (int i = 0; i < N; i++) {
                      final String perm = p.requestedPermissions.get(i);
                      pi.requestedPermissions[i] = perm;
                      // The notion of required permissions is deprecated but for compatibility.
  //                    pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
  //                    if (grantedPermissions != null && grantedPermissions.contains(perm)) {
  //                        pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
  //                    }
                  }
              }
          }
          PackageInfo base = null;
          try {
              base = BlackBoxCore.getContext().getPackageManager().getPackageInfo(p.packageName, flags);
          } catch (PackageManager.NameNotFoundException ignored) {
          }
          if ((flags & PackageManager.GET_SIGNATURES) != 0) {
              if (base == null) {
                  pi.signatures = p.mSignatures;
              } else {
                  pi.signatures = base.signatures;
              }
          }
          if (BuildCompat.isPie()) {
              if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) {
                  if (base == null) {
                      PackageParser.SigningDetails signingDetails = PackageParser.SigningDetails.UNKNOWN;
                      BRPackageParserSigningDetails.get(signingDetails)._set_signatures(p.mSigningDetails.signatures);
                      pi.signingInfo = BRSigningInfo.get()._new(signingDetails);
                  } else {
                      pi.signingInfo = base.signingInfo;
                  }
              }
          }
          return pi;
      }
  
      public static ActivityInfo generateActivityInfo(BPackage.Activity a, int flags, BPackageUserState state, int userId) {
          if (!checkUseInstalledOrHidden(flags, state, a.info.applicationInfo)) {
              return null;
          }
          // Make shallow copies so we can store the metadata safely
          ActivityInfo ai = new ActivityInfo(a.info);
          ai.metaData = a.metaData;
          ai.processName = BPackageManagerService.fixProcessName(ai.packageName, ai.processName);
          ai.applicationInfo = generateApplicationInfo(a.owner, flags, state, userId);
          return ai;
      }
  
      public static ServiceInfo generateServiceInfo(BPackage.Service s, int flags, BPackageUserState state, int userId) {
          if (!checkUseInstalledOrHidden(flags, state, s.info.applicationInfo)) {
              return null;
          }
          // Make shallow copies so we can store the metadata safely
          ServiceInfo si = new ServiceInfo(s.info);
          si.metaData = s.metaData;
          si.processName = BPackageManagerService.fixProcessName(si.packageName, si.processName);
          si.applicationInfo = generateApplicationInfo(s.owner, flags, state, userId);
          return si;
      }
  
      public static ProviderInfo generateProviderInfo(BPackage.Provider p, int flags, BPackageUserState state, int userId) {
          if (!checkUseInstalledOrHidden(flags, state, p.info.applicationInfo)) {
              return null;
          }
          // Make shallow copies so we can store the metadata safely
          ProviderInfo pi = new ProviderInfo(p.info);
          if (pi.authority == null)
              return null;
          pi.metaData = p.metaData;
          pi.processName = BPackageManagerService.fixProcessName(pi.packageName, pi.processName);
          if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
              pi.uriPermissionPatterns = null;
          }
          pi.applicationInfo = generateApplicationInfo(p.owner, flags, state, userId);
          return pi;
      }
  
      public static PermissionInfo generatePermissionInfo(
              BPackage.Permission p, int flags) {
          if (p == null) return null;
          if ((flags & PackageManager.GET_META_DATA) == 0) {
              return p.info;
          }
          PermissionInfo pi = new PermissionInfo(p.info);
          pi.metaData = p.metaData;
          return pi;
      }
  
      public static InstrumentationInfo generateInstrumentationInfo(
              BPackage.Instrumentation i, int flags) {
          if (i == null) return null;
          if ((flags & PackageManager.GET_META_DATA) == 0) {
              return i.info;
          }
          InstrumentationInfo ii = new InstrumentationInfo(i.info);
          ii.metaData = i.metaData;
          return ii;
      }
  
      public static ApplicationInfo generateApplicationInfo(BPackage p, int flags, BPackageUserState state, int userId) {
          if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo)) {
              return null;
          }
          ApplicationInfo baseApplication;
          try {
              baseApplication = BlackBoxCore.getPackageManager().getApplicationInfo(BlackBoxCore.getHostPkg(), flags);
          } catch (Exception e) {
              return null;
          }
          String sourceDir = p.baseCodePath;
          if (p.applicationInfo == null) {
              p.applicationInfo = BlackBoxCore.getPackageManager()
                      .getPackageArchiveInfo(sourceDir, 0).applicationInfo;
          }
          ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
          if ((flags & PackageManager.GET_META_DATA) != 0) {
              ai.metaData = p.mAppMetaData;
          }
          ai.dataDir = BEnvironment.getDataDir(ai.packageName, userId).getAbsolutePath();
          if (!p.installOption.isFlag(InstallOption.FLAG_SYSTEM)) {
              ai.nativeLibraryDir = BEnvironment.getAppLibDir(ai.packageName).getAbsolutePath();
          }
          ai.processName = BPackageManagerService.fixProcessName(p.packageName, ai.packageName);
          ai.publicSourceDir = sourceDir;
          ai.sourceDir = sourceDir;
          ai.uid = p.mExtras.appId;
  //        ai.uid = baseApplication.uid;
  
          if (BuildCompat.isL()) {
              BRApplicationInfoL.get(ai)._set_primaryCpuAbi(Build.CPU_ABI);
              BRApplicationInfoL.get(ai)._set_scanPublicSourceDir(BRApplicationInfoL.get(baseApplication).scanPublicSourceDir());
              BRApplicationInfoL.get(ai)._set_scanSourceDir(BRApplicationInfoL.get(baseApplication).scanSourceDir());
          }
          if (BuildCompat.isN()) {
              ai.deviceProtectedDataDir = BEnvironment.getDeDataDir(p.packageName, userId).getAbsolutePath();
  
              if (BRApplicationInfoN.get(ai)._check_deviceEncryptedDataDir() != null) {
                  BRApplicationInfoN.get(ai)._set_deviceEncryptedDataDir(ai.deviceProtectedDataDir);
              }
              if (BRApplicationInfoN.get(ai)._check_credentialEncryptedDataDir() != null) {
                  BRApplicationInfoN.get(ai)._set_credentialEncryptedDataDir(ai.dataDir);
              }
              if (BRApplicationInfoN.get(ai)._check_deviceProtectedDataDir() != null) {
                  BRApplicationInfoN.get(ai)._set_deviceProtectedDataDir(ai.deviceProtectedDataDir);
              }
              if (BRApplicationInfoN.get(ai)._check_credentialProtectedDataDir() != null) {
                  BRApplicationInfoN.get(ai)._set_credentialProtectedDataDir(ai.dataDir);
              }
          }
          fixJar(ai);
          return ai;
      }
  
      private static boolean checkUseInstalledOrHidden(int flags, BPackageUserState state,
                                                       ApplicationInfo appInfo) {
          if (AppSystemEnv.isBlackPackage(appInfo.packageName))
              return false;
          // Returns false if the package is hidden system app until installed.
          if (!state.installed || state.hidden) {
              return false;
          }
          return true;
      }
  
      private static void fixJar(ApplicationInfo info) {
          String APACHE_LEGACY_JAR = "/system/framework/org.apache.http.legacy.boot.jar";
          String APACHE_LEGACY_JAR_Q = "/system/framework/org.apache.http.legacy.jar";
          Set<String> sharedLibraryFileList = new HashSet<>();
          if (BuildCompat.isQ()) {
              if (!FileUtils.isExist(APACHE_LEGACY_JAR_Q)) {
                  sharedLibraryFileList.add(APACHE_LEGACY_JAR);
              } else {
                  sharedLibraryFileList.add(APACHE_LEGACY_JAR_Q);
              }
          } else {
              sharedLibraryFileList.add(APACHE_LEGACY_JAR);
          }
  //        if (BXposedManagerService.get().isXPEnable()) {
  //            ApplicationInfo base = BlackBoxCore.getContext().getApplicationInfo();
  //            sharedLibraryFileList.add(base.sourceDir);
  //        }
  //        sharedLibraryFileList.add(BEnvironment.JUNIT_JAR.getAbsolutePath());
          info.sharedLibraryFiles = sharedLibraryFileList.toArray(new String[]{});
      }
  
      public static Resources getResources(Context context, ApplicationInfo appInfo) {
          BPackageSettings ps = BPackageManagerService.get().getBPackageSetting(appInfo.packageName);
          if (ps != null) {
              AssetManager assets = BRAssetManager.get()._new();
              BRAssetManager.get(assets).addAssetPath(ps.pkg.baseCodePath);
              Resources hostRes = context.getResources();
              return new Resources(assets, hostRes.getDisplayMetrics(), hostRes.getConfiguration());
          }
          return null;
      }
  }
  