Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d07b87cb authored by Todd Kennedy's avatar Todd Kennedy Committed by Android (Google) Code Review
Browse files

Merge "New API w/ multiple prefixes" into nyc-mr1-dev

parents a581e786 a97045b2
Loading
Loading
Loading
Loading
+122 −26
Original line number Diff line number Diff line
@@ -37,10 +37,7 @@ public final class EphemeralResolveInfo implements Parcelable {
    /** Algorithm that will be used to generate the domain digest */
    public static final String SHA_ALGORITHM = "SHA-256";

    /** Full digest of the domain hash */
    private final byte[] mDigestBytes;
    /** The first 4 bytes of the domain hash */
    private final int mDigestPrefix;
    private final EphemeralDigest mDigest;
    private final String mPackageName;
    /** The filters used to match domain */
    private final List<IntentFilter> mFilters = new ArrayList<IntentFilter>();
@@ -55,29 +52,23 @@ public final class EphemeralResolveInfo implements Parcelable {
            throw new IllegalArgumentException();
        }

        mDigestBytes = generateDigest(uri);
        mDigestPrefix =
                (mDigestBytes[0] & 0xFF) << 24
                | (mDigestBytes[1] & 0xFF) << 16
                | (mDigestBytes[2] & 0xFF) << 8
                | (mDigestBytes[3] & 0xFF) << 0;
        mDigest = new EphemeralDigest(uri, -1);
        mFilters.addAll(filters);
        mPackageName = packageName;
    }

    EphemeralResolveInfo(Parcel in) {
        mDigestBytes = in.createByteArray();
        mDigestPrefix = in.readInt();
        mDigest = in.readParcelable(null /*loader*/);
        mPackageName = in.readString();
        in.readList(mFilters, null /*loader*/);
    }

    public byte[] getDigestBytes() {
        return mDigestBytes;
        return mDigest.getDigestBytes()[0];
    }

    public int getDigestPrefix() {
        return mDigestPrefix;
        return mDigest.getDigestPrefix()[0];
    }

    public String getPackageName() {
@@ -88,16 +79,6 @@ public final class EphemeralResolveInfo implements Parcelable {
        return mFilters;
    }

    private static byte[] generateDigest(Uri uri) {
        try {
            final MessageDigest digest = MessageDigest.getInstance(SHA_ALGORITHM);
            final byte[] hostBytes = uri.getHost().getBytes();
            return digest.digest(hostBytes);
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException("could not find digest algorithm");
        }
    }

    @Override
    public int describeContents() {
        return 0;
@@ -105,8 +86,7 @@ public final class EphemeralResolveInfo implements Parcelable {

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeByteArray(mDigestBytes);
        out.writeInt(mDigestPrefix);
        out.writeParcelable(mDigest, flags);
        out.writeString(mPackageName);
        out.writeList(mFilters);
    }
@@ -136,4 +116,120 @@ public final class EphemeralResolveInfo implements Parcelable {
            return mResolveInfo;
        }
    }

    /**
     * Helper class to generate and store each of the digests and prefixes
     * sent to the Ephemeral Resolver.
     * <p>
     * Since intent filters may want to handle multiple hosts within a
     * domain [eg “*.google.com”], the resolver is presented with multiple
     * hash prefixes. For example, "a.b.c.d.e" generates digests for
     * "d.e", "c.d.e", "b.c.d.e" and "a.b.c.d.e".
     *
     * @hide
     */
    public static final class EphemeralDigest implements Parcelable {
        /** Full digest of the domain hashes */
        private final byte[][] mDigestBytes;
        /** The first 4 bytes of the domain hashes */
        private final int[] mDigestPrefix;

        public EphemeralDigest(@NonNull Uri uri, int maxDigests) {
            if (uri == null) {
                throw new IllegalArgumentException();
            }
            mDigestBytes = generateDigest(uri, maxDigests);
            mDigestPrefix = new int[mDigestBytes.length];
            for (int i = 0; i < mDigestBytes.length; i++) {
                mDigestPrefix[i] =
                        (mDigestBytes[i][0] & 0xFF) << 24
                        | (mDigestBytes[i][1] & 0xFF) << 16
                        | (mDigestBytes[i][2] & 0xFF) << 8
                        | (mDigestBytes[i][3] & 0xFF) << 0;
            }
        }

        private static byte[][] generateDigest(Uri uri, int maxDigests) {
            ArrayList<byte[]> digests = new ArrayList<>();
            try {
                final String host = uri.getHost();
                final MessageDigest digest = MessageDigest.getInstance(SHA_ALGORITHM);
                if (maxDigests <= 0) {
                    final byte[] hostBytes = host.getBytes();
                    digests.add(digest.digest(hostBytes));
                } else {
                    int prevDot = host.lastIndexOf('.');
                    prevDot = host.lastIndexOf('.', prevDot - 1);
                    // shortcut for short URLs
                    if (prevDot < 0) {
                        digests.add(digest.digest(host.getBytes()));
                    } else {
                        byte[] hostBytes = host.substring(prevDot + 1, host.length()).getBytes();
                        digests.add(digest.digest(hostBytes));
                        int digestCount = 1;
                        while (prevDot >= 0 && digestCount < maxDigests) {
                            prevDot = host.lastIndexOf('.', prevDot - 1);
                            hostBytes = host.substring(prevDot + 1, host.length()).getBytes();
                            digests.add(digest.digest(hostBytes));
                            digestCount++;
                        }
                    }
                }
            } catch (NoSuchAlgorithmException e) {
                throw new IllegalStateException("could not find digest algorithm");
            }
            return digests.toArray(new byte[digests.size()][]);
        }

        EphemeralDigest(Parcel in) {
            final int digestCount = in.readInt();
            if (digestCount == -1) {
                mDigestBytes = null;
            } else {
                mDigestBytes = new byte[digestCount][];
                for (int i = 0; i < digestCount; i++) {
                    mDigestBytes[i] = in.createByteArray();
                }
            }
            mDigestPrefix = in.createIntArray();
        }

        public byte[][] getDigestBytes() {
            return mDigestBytes;
        }

        public int[] getDigestPrefix() {
            return mDigestPrefix;
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel out, int flags) {
            if (mDigestBytes == null) {
                out.writeInt(-1);
            } else {
                out.writeInt(mDigestBytes.length);
                for (int i = 0; i < mDigestBytes.length; i++) {
                    out.writeByteArray(mDigestBytes[i]);
                }
            }
            out.writeIntArray(mDigestPrefix);
        }

        @SuppressWarnings("hiding")
        public static final Parcelable.Creator<EphemeralDigest> CREATOR =
                new Parcelable.Creator<EphemeralDigest>() {
            public EphemeralDigest createFromParcel(Parcel in) {
                return new EphemeralDigest(in);
            }

            public EphemeralDigest[] newArray(int size) {
                return new EphemeralDigest[size];
            }
        };
    }
}
+18 −0
Original line number Diff line number Diff line
@@ -8582,6 +8582,24 @@ public final class Settings {
        public static final String EPHEMERAL_COOKIE_MAX_SIZE_BYTES =
                "ephemeral_cookie_max_size_bytes";

        /**
         * A mask applied to the ephemeral hash to generate the hash prefix.
         * <p>
         * Type: int
         *
         * @hide
         */
        public static final String EPHEMERAL_HASH_PREFIX_MASK = "ephemeral_hash_prefix_mask";

        /**
         * Number of hash prefixes to send during ephemeral resolution.
         * <p>
         * Type: int
         *
         * @hide
         */
        public static final String EPHEMERAL_HASH_PREFIX_COUNT = "ephemeral_hash_prefix_count";

        /**
         * The duration for caching uninstalled ephemeral apps.
         * <p>
+15 −6
Original line number Diff line number Diff line
@@ -39,14 +39,19 @@ import java.util.List;
public abstract class EphemeralResolverService extends Service {
    public static final String EXTRA_RESOLVE_INFO = "com.android.internal.app.RESOLVE_INFO";
    public static final String EXTRA_SEQUENCE = "com.android.internal.app.SEQUENCE";
    private static final String EXTRA_PREFIX = "com.android.internal.app.PREFIX";
    private Handler mHandler;

    /**
     * Called to retrieve resolve info for ephemeral applications.
     *
     * @param digestPrefix The hash prefix of the ephemeral's domain.
     * @param prefixMask A mask that was applied to each digest prefix. This should
     *      be used when comparing against the digest prefixes as all bits might
     *      not be set.
     */
    protected abstract List<EphemeralResolveInfo> getEphemeralResolveInfoList(int digestPrefix);
    protected abstract List<EphemeralResolveInfo> getEphemeralResolveInfoList(
            int digestPrefix[], int prefixMask);

    @Override
    protected final void attachBaseContext(Context base) {
@@ -59,10 +64,13 @@ public abstract class EphemeralResolverService extends Service {
        return new IEphemeralResolver.Stub() {
            @Override
            public void getEphemeralResolveInfoList(
                    IRemoteCallback callback, int digestPrefix, int sequence) {
                mHandler.obtainMessage(ServiceHandler.MSG_GET_EPHEMERAL_RESOLVE_INFO,
                        digestPrefix, sequence, callback)
                    .sendToTarget();
                    IRemoteCallback callback, int digestPrefix[], int prefixMask, int sequence) {
                final Message msg = mHandler.obtainMessage(
                        ServiceHandler.MSG_GET_EPHEMERAL_RESOLVE_INFO, prefixMask, sequence, callback);
                final Bundle data = new Bundle();
                data.putIntArray(EXTRA_PREFIX, digestPrefix);
                msg.setData(data);
                msg.sendToTarget();
            }
        };
    }
@@ -81,8 +89,9 @@ public abstract class EphemeralResolverService extends Service {
            switch (action) {
                case MSG_GET_EPHEMERAL_RESOLVE_INFO: {
                    final IRemoteCallback callback = (IRemoteCallback) message.obj;
                    final int[] digestPrefix = message.getData().getIntArray(EXTRA_PREFIX);
                    final List<EphemeralResolveInfo> resolveInfo =
                            getEphemeralResolveInfoList(message.arg1);
                            getEphemeralResolveInfoList(digestPrefix, message.arg1);
                    final Bundle data = new Bundle();
                    data.putInt(EXTRA_SEQUENCE, message.arg2);
                    data.putParcelableList(EXTRA_RESOLVE_INFO, resolveInfo);
+2 −1
Original line number Diff line number Diff line
@@ -20,5 +20,6 @@ import android.content.Intent;
import android.os.IRemoteCallback;

oneway interface IEphemeralResolver {
    void getEphemeralResolveInfoList(IRemoteCallback callback, int digestPrefix, int sequence);
    void getEphemeralResolveInfoList(IRemoteCallback callback, in int[] digestPrefix,
            int prefixMask, int sequence);
}
+5 −4
Original line number Diff line number Diff line
@@ -64,11 +64,12 @@ final class EphemeralResolverConnection {
        mIntent = new Intent().setComponent(componentName);
    }

    public final List<EphemeralResolveInfo> getEphemeralResolveInfoList(int hashPrefix) {
    public final List<EphemeralResolveInfo> getEphemeralResolveInfoList(
            int hashPrefix[], int prefixMask) {
        throwIfCalledOnMainThread();
        try {
            return mGetEphemeralResolveInfoCaller.getEphemeralResolveInfoList(
                    getRemoteInstanceLazy(), hashPrefix);
                    getRemoteInstanceLazy(), hashPrefix, prefixMask);
        } catch (RemoteException re) {
        } catch (TimeoutException te) {
        } finally {
@@ -177,10 +178,10 @@ final class EphemeralResolverConnection {
        }

        public List<EphemeralResolveInfo> getEphemeralResolveInfoList(
                IEphemeralResolver target, int hashPrefix)
                IEphemeralResolver target, int hashPrefix[], int prefixMask)
                        throws RemoteException, TimeoutException {
            final int sequence = onBeforeRemoteCall();
            target.getEphemeralResolveInfoList(mCallback, hashPrefix, sequence);
            target.getEphemeralResolveInfoList(mCallback, hashPrefix, prefixMask, sequence);
            return getResultTimed(sequence);
        }
    }
Loading