content: package org.adaway.model.update;
  
  import android.annotation.SuppressLint;
  import android.content.Context;
  import android.content.pm.PackageManager;
  import android.content.pm.Signature;
  
  import java.security.MessageDigest;
  import java.security.NoSuchAlgorithmException;
  
  import static android.content.pm.PackageManager.GET_SIGNATURES;
  import static android.content.pm.PackageManager.GET_SIGNING_CERTIFICATES;
  import static android.os.Build.VERSION.SDK_INT;
  import static android.os.Build.VERSION_CODES.P;
  
  import timber.log.Timber;
  
  /**
   * This enumerates represents the stores to get AdAway updates.
   *
   * @author Bruce BUJON (bruce.bujon(at)gmail(dot)com)
   */
  public enum UpdateStore {
      /**
       * The official store (usually GitHub releases) with AdAway signing key.
       */
      ADAWAY("adaway", "D647FDAC42961502AC78F99919B8E1901747E8DA78FE13E1EABA688FECC4C99E"),
      /**
       * The F-Droid store with F-Droid signing key.
       */
      F_DROID("fdroid", "42203F1AC857426D1496E971DB96FBE1F88C25C9E1F895A5C98D703891292277"),
      /**
       * An unknown store.
       */
      UNKNOWN("unknown", "");
      /**
       * The store name.
       */
      public final String storeName;
      /**
       * The store singing certificate digest.
       */
      public final String sign;
  
      UpdateStore(String name, String sign) {
          this.storeName = name;
          this.sign = sign;
      }
  
      /**
       * Get the store of the running application.
       *
       * @param context The application context.
       * @return The application store, {@link #UNKNOWN} if store can't be defined.
       */
      @SuppressLint("PackageManagerGetSignatures")
      public static UpdateStore getApkStore(Context context) {
          PackageManager packageManager = context.getPackageManager();
          String packageName = context.getPackageName();
          Signature[] signatures;
          try {
              if (SDK_INT >= P) {
                  signatures = packageManager.getPackageInfo(
                          packageName,
                          GET_SIGNING_CERTIFICATES
                  ).signingInfo.getSigningCertificateHistory();
              } else {
                  // Signatures are not used for security reason. Only to guess the flavor of the app.
                  signatures = packageManager.getPackageInfo(
                          packageName,
                          GET_SIGNATURES
                  ).signatures;
              }
          } catch (PackageManager.NameNotFoundException e) {
              Timber.w(e, "Failed to get application package info.");
              return UpdateStore.UNKNOWN;
          }
          return UpdateStore.getFromSigns(signatures);
      }
  
      private static UpdateStore getFromSigns(Signature[] signatures) {
          try {
              MessageDigest md = MessageDigest.getInstance("SHA-256");
              for (Signature signature : signatures) {
                  md.update(signature.toByteArray());
                  String sign = bytesToHex(md.digest());
                  for (UpdateStore store : UpdateStore.values()) {
                      if (store.sign.equals(sign)) {
                          return store;
                      }
                  }
              }
          } catch (NoSuchAlgorithmException e) {
              Timber.w(e, "SHA-256 algorithm is no supported.");
          }
          return UpdateStore.UNKNOWN;
      }
  
      private static String bytesToHex(byte[] bytes) {
          final char[] hexArray = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
                  '9', 'A', 'B', 'C', 'D', 'E', 'F'};
          char[] hexChars = new char[bytes.length * 2];
          int v;
          for (int j = 0; j < bytes.length; j++) {
              v = bytes[j] & 0xFF;
              hexChars[j * 2] = hexArray[v >>> 4];
              hexChars[j * 2 + 1] = hexArray[v & 0x0F];
          }
          return new String(hexChars);
      }
  
      /**
       * Get the store name.
       *
       * @return The store name.
       */
      public String getName() {
          return this.storeName;
      }
  }
  