// Path: afservice/src/main/java/com/example/android/autofill/service/data/source/PackageVerificationDataSource.java
// public interface PackageVerificationDataSource {
// 
//     /**
//      * Verifies that the signatures in the passed {@code Context} match what is currently in
//      * storage. If there are no current signatures in storage for this packageName, it will store
//      * the signatures from the passed {@code Context}.
//      *
//      * @return {@code true} if signatures for this packageName are not currently in storage
//      * or if the signatures in the passed {@code Context} match what is currently in storage;
//      * {@code false} if the signatures in the passed {@code Context} do not match what is
//      * currently in storage or if an {@code Exception} was thrown while generating the signatures.
//      */
//     boolean putPackageSignatures(String packageName);
// 
//     /**
//      * Clears all signature data currently in storage.
//      */
//     void clear();
// }
// 
// Path: afservice/src/main/java/com/example/android/autofill/service/util/SecurityHelper.java
// public final class SecurityHelper {
// 
//     private SecurityHelper() {
//         throw new UnsupportedOperationException("Provides static methods only.");
//     }
// 
//     /**
//      * Gets the fingerprint of the signed certificate of a package.
//      */
//     public static String getFingerprint(PackageInfo packageInfo, String packageName) throws
//             PackageManager.NameNotFoundException, IOException, NoSuchAlgorithmException,
//             CertificateException {
//         Signature[] signatures = packageInfo.signatures;
//         if (signatures.length != 1) {
//             throw new SecurityException(packageName + " has " + signatures.length + " signatures");
//         }
//         byte[] cert = signatures[0].toByteArray();
//         try (InputStream input = new ByteArrayInputStream(cert)) {
//             CertificateFactory factory = CertificateFactory.getInstance("X509");
//             X509Certificate x509 = (X509Certificate) factory.generateCertificate(input);
//             MessageDigest md = MessageDigest.getInstance("SHA256");
//             byte[] publicKey = md.digest(x509.getEncoded());
//             return toHexFormat(publicKey);
//         }
//     }
// 
//     private static String toHexFormat(byte[] bytes) {
//         StringBuilder builder = new StringBuilder(bytes.length * 2);
//         for (int i = 0; i < bytes.length; i++) {
//             String hex = Integer.toHexString(bytes[i]);
//             int length = hex.length();
//             if (length == 1) {
//                 hex = "0" + hex;
//             }
//             if (length > 2) {
//                 hex = hex.substring(length - 2, length);
//             }
//             builder.append(hex.toUpperCase());
//             if (i < (bytes.length - 1)) {
//                 builder.append(':');
//             }
//         }
//         return builder.toString();
//     }
// }
// 
// Path: afservice/src/main/java/com/example/android/autofill/service/util/Util.java
// public static void logd(String message, Object... params) {
//     if (logDebugEnabled()) {
//         Log.d(TAG, String.format(message, params));
//     }
// }
// 
// Path: afservice/src/main/java/com/example/android/autofill/service/util/Util.java
// public static void logw(String message, Object... params) {
//     Log.w(TAG, String.format(message, params));
// }


import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import com.example.android.autofill.service.data.source.PackageVerificationDataSource;
import com.example.android.autofill.service.util.SecurityHelper;
import static com.example.android.autofill.service.util.Util.logd;
import static com.example.android.autofill.service.util.Util.logw;

    private SharedPrefsPackageVerificationRepository(Context context) {
        mSharedPrefs = context.getApplicationContext()
                .getSharedPreferences(SHARED_PREF_KEY, Context.MODE_PRIVATE);
        mContext = context.getApplicationContext();
    }

    public static PackageVerificationDataSource getInstance(Context context) {
        if (sInstance == null) {
            sInstance = new SharedPrefsPackageVerificationRepository(
                    context.getApplicationContext());
        }
        return sInstance;
    }

    @Override
    public void clear() {
        mSharedPrefs.edit().clear().apply();
    }

    @Override
    public boolean putPackageSignatures(String packageName) {
        String hash;
        try {
            PackageManager pm = mContext.getPackageManager();
            PackageInfo packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
            hash = SecurityHelper.getFingerprint(packageInfo, packageName);
            logd("Hash for %s: %s", packageName, hash);
        } catch (Exception e) {
            logw(e, "Error getting hash for %s.", packageName);
// Path: afservice/src/main/java/com/example/android/autofill/service/data/source/PackageVerificationDataSource.java
// public interface PackageVerificationDataSource {
// 
//     /**
//      * Verifies that the signatures in the passed {@code Context} match what is currently in
//      * storage. If there are no current signatures in storage for this packageName, it will store
//      * the signatures from the passed {@code Context}.
//      *
//      * @return {@code true} if signatures for this packageName are not currently in storage
//      * or if the signatures in the passed {@code Context} match what is currently in storage;
//      * {@code false} if the signatures in the passed {@code Context} do not match what is
//      * currently in storage or if an {@code Exception} was thrown while generating the signatures.
//      */
//     boolean putPackageSignatures(String packageName);
// 
//     /**
//      * Clears all signature data currently in storage.
//      */
//     void clear();
// }
// 
// Path: afservice/src/main/java/com/example/android/autofill/service/util/SecurityHelper.java
// public final class SecurityHelper {
// 
//     private SecurityHelper() {
//         throw new UnsupportedOperationException("Provides static methods only.");
//     }
// 
//     /**
//      * Gets the fingerprint of the signed certificate of a package.
//      */
//     public static String getFingerprint(PackageInfo packageInfo, String packageName) throws
//             PackageManager.NameNotFoundException, IOException, NoSuchAlgorithmException,
//             CertificateException {
//         Signature[] signatures = packageInfo.signatures;
//         if (signatures.length != 1) {
//             throw new SecurityException(packageName + " has " + signatures.length + " signatures");
//         }
//         byte[] cert = signatures[0].toByteArray();
//         try (InputStream input = new ByteArrayInputStream(cert)) {
//             CertificateFactory factory = CertificateFactory.getInstance("X509");
//             X509Certificate x509 = (X509Certificate) factory.generateCertificate(input);
//             MessageDigest md = MessageDigest.getInstance("SHA256");
//             byte[] publicKey = md.digest(x509.getEncoded());
//             return toHexFormat(publicKey);
//         }
//     }
// 
//     private static String toHexFormat(byte[] bytes) {
//         StringBuilder builder = new StringBuilder(bytes.length * 2);
//         for (int i = 0; i < bytes.length; i++) {
//             String hex = Integer.toHexString(bytes[i]);
//             int length = hex.length();
//             if (length == 1) {
//                 hex = "0" + hex;
//             }
//             if (length > 2) {
//                 hex = hex.substring(length - 2, length);
//             }
//             builder.append(hex.toUpperCase());
//             if (i < (bytes.length - 1)) {
//                 builder.append(':');
//             }
//         }
//         return builder.toString();
//     }
// }
// 
// Path: afservice/src/main/java/com/example/android/autofill/service/util/Util.java
// public static void logd(String message, Object... params) {
//     if (logDebugEnabled()) {
//         Log.d(TAG, String.format(message, params));
//     }
// }
// 
// Path: afservice/src/main/java/com/example/android/autofill/service/util/Util.java
// public static void logw(String message, Object... params) {
//     Log.w(TAG, String.format(message, params));
// }


// Path: afservice/src/main/java/com/example/android/autofill/service/data/source/local/SharedPrefsPackageVerificationRepository.java
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import com.example.android.autofill.service.data.source.PackageVerificationDataSource;
import com.example.android.autofill.service.util.SecurityHelper;
import static com.example.android.autofill.service.util.Util.logd;
import static com.example.android.autofill.service.util.Util.logw;


    private SharedPrefsPackageVerificationRepository(Context context) {
        mSharedPrefs = context.getApplicationContext()
                .getSharedPreferences(SHARED_PREF_KEY, Context.MODE_PRIVATE);
        mContext = context.getApplicationContext();
    }

    public static PackageVerificationDataSource getInstance(Context context) {
        if (sInstance == null) {
            sInstance = new SharedPrefsPackageVerificationRepository(
                    context.getApplicationContext());
        }
        return sInstance;
    }

    @Override
    public void clear() {
        mSharedPrefs.edit().clear().apply();
    }

    @Override
    public boolean putPackageSignatures(String packageName) {
        String hash;
        try {
            PackageManager pm = mContext.getPackageManager();
            PackageInfo packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
            hash = SecurityHelper.getFingerprint(packageInfo, packageName);
            logd("Hash for %s: %s", packageName, hash);
        } catch (Exception e) {
            logw(e, "Error getting hash for %s.", packageName);
            return false;