1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.content.pm;
18
19import android.annotation.NonNull;
20import android.annotation.SystemApi;
21import android.content.IntentFilter;
22import android.net.Uri;
23import android.os.Parcel;
24import android.os.Parcelable;
25
26import java.security.MessageDigest;
27import java.security.NoSuchAlgorithmException;
28import java.util.ArrayList;
29import java.util.List;
30
31/**
32 * Information about an ephemeral application.
33 * @hide
34 */
35@SystemApi
36public final class EphemeralResolveInfo implements Parcelable {
37    /** Algorithm that will be used to generate the domain digest */
38    public static final String SHA_ALGORITHM = "SHA-256";
39
40    /** Full digest of the domain hash */
41    private final byte[] mDigestBytes;
42    /** The first 4 bytes of the domain hash */
43    private final int mDigestPrefix;
44    private final String mPackageName;
45    /** The filters used to match domain */
46    private final List<IntentFilter> mFilters = new ArrayList<IntentFilter>();
47
48    public EphemeralResolveInfo(@NonNull Uri uri, @NonNull String packageName,
49            @NonNull List<IntentFilter> filters) {
50        // validate arguments
51        if (uri == null
52                || packageName == null
53                || filters == null
54                || filters.size() == 0) {
55            throw new IllegalArgumentException();
56        }
57
58        mDigestBytes = generateDigest(uri);
59        mDigestPrefix =
60                mDigestBytes[0] << 24
61                | mDigestBytes[1] << 16
62                | mDigestBytes[2] << 8
63                | mDigestBytes[3] << 0;
64        mFilters.addAll(filters);
65        mPackageName = packageName;
66    }
67
68    EphemeralResolveInfo(Parcel in) {
69        mDigestBytes = in.createByteArray();
70        mDigestPrefix = in.readInt();
71        mPackageName = in.readString();
72        in.readList(mFilters, null /*loader*/);
73    }
74
75    public byte[] getDigestBytes() {
76        return mDigestBytes;
77    }
78
79    public int getDigestPrefix() {
80        return mDigestPrefix;
81    }
82
83    public String getPackageName() {
84        return mPackageName;
85    }
86
87    public List<IntentFilter> getFilters() {
88        return mFilters;
89    }
90
91    private static byte[] generateDigest(Uri uri) {
92        try {
93            final MessageDigest digest = MessageDigest.getInstance(SHA_ALGORITHM);
94            final byte[] hostBytes = uri.getHost().getBytes();
95            return digest.digest(hostBytes);
96        } catch (NoSuchAlgorithmException e) {
97            throw new IllegalStateException("could not find digest algorithm");
98        }
99    }
100
101    @Override
102    public int describeContents() {
103        return 0;
104    }
105
106    @Override
107    public void writeToParcel(Parcel out, int flags) {
108        out.writeByteArray(mDigestBytes);
109        out.writeInt(mDigestPrefix);
110        out.writeString(mPackageName);
111        out.writeList(mFilters);
112    }
113
114    public static final Parcelable.Creator<EphemeralResolveInfo> CREATOR
115            = new Parcelable.Creator<EphemeralResolveInfo>() {
116        public EphemeralResolveInfo createFromParcel(Parcel in) {
117            return new EphemeralResolveInfo(in);
118        }
119
120        public EphemeralResolveInfo[] newArray(int size) {
121            return new EphemeralResolveInfo[size];
122        }
123    };
124
125    /** @hide */
126    public static final class EphemeralResolveIntentInfo extends IntentFilter {
127        private final EphemeralResolveInfo mResolveInfo;
128
129        public EphemeralResolveIntentInfo(@NonNull IntentFilter orig,
130                @NonNull EphemeralResolveInfo resolveInfo) {
131            super(orig);
132            this.mResolveInfo = resolveInfo;
133        }
134
135        public EphemeralResolveInfo getEphemeralResolveInfo() {
136            return mResolveInfo;
137        }
138    }
139}
140