1/*
2 * Copyright (C) 2013 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.res;
18
19import android.annotation.NonNull;
20import android.annotation.Nullable;
21import android.text.TextUtils;
22
23import java.util.Arrays;
24import java.util.Objects;
25
26/** @hide */
27public final class ResourcesKey {
28    @Nullable
29    public final String mResDir;
30
31    @Nullable
32    public final String[] mSplitResDirs;
33
34    @Nullable
35    public final String[] mOverlayDirs;
36
37    @Nullable
38    public final String[] mLibDirs;
39
40    public final int mDisplayId;
41
42    @NonNull
43    public final Configuration mOverrideConfiguration;
44
45    @NonNull
46    public final CompatibilityInfo mCompatInfo;
47
48    private final int mHash;
49
50    public ResourcesKey(@Nullable String resDir,
51                        @Nullable String[] splitResDirs,
52                        @Nullable String[] overlayDirs,
53                        @Nullable String[] libDirs,
54                        int displayId,
55                        @Nullable Configuration overrideConfig,
56                        @Nullable CompatibilityInfo compatInfo) {
57        mResDir = resDir;
58        mSplitResDirs = splitResDirs;
59        mOverlayDirs = overlayDirs;
60        mLibDirs = libDirs;
61        mDisplayId = displayId;
62        mOverrideConfiguration = overrideConfig != null ? overrideConfig : Configuration.EMPTY;
63        mCompatInfo = compatInfo != null ? compatInfo : CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
64
65        int hash = 17;
66        hash = 31 * hash + Objects.hashCode(mResDir);
67        hash = 31 * hash + Arrays.hashCode(mSplitResDirs);
68        hash = 31 * hash + Arrays.hashCode(mOverlayDirs);
69        hash = 31 * hash + Arrays.hashCode(mLibDirs);
70        hash = 31 * hash + mDisplayId;
71        hash = 31 * hash + Objects.hashCode(mOverrideConfiguration);
72        hash = 31 * hash + Objects.hashCode(mCompatInfo);
73        mHash = hash;
74    }
75
76    public boolean hasOverrideConfiguration() {
77        return !Configuration.EMPTY.equals(mOverrideConfiguration);
78    }
79
80    public boolean isPathReferenced(String path) {
81        if (mResDir != null && mResDir.startsWith(path)) {
82            return true;
83        } else {
84            return anyStartsWith(mSplitResDirs, path) || anyStartsWith(mOverlayDirs, path)
85                    || anyStartsWith(mLibDirs, path);
86        }
87    }
88
89    private static boolean anyStartsWith(String[] list, String prefix) {
90        if (list != null) {
91            for (String s : list) {
92                if (s != null && s.startsWith(prefix)) {
93                    return true;
94                }
95            }
96        }
97        return false;
98    }
99
100    @Override
101    public int hashCode() {
102        return mHash;
103    }
104
105    @Override
106    public boolean equals(Object obj) {
107        if (!(obj instanceof ResourcesKey)) {
108            return false;
109        }
110
111        ResourcesKey peer = (ResourcesKey) obj;
112        if (mHash != peer.mHash) {
113            // If the hashes don't match, the objects can't match.
114            return false;
115        }
116
117        if (!Objects.equals(mResDir, peer.mResDir)) {
118            return false;
119        }
120        if (!Arrays.equals(mSplitResDirs, peer.mSplitResDirs)) {
121            return false;
122        }
123        if (!Arrays.equals(mOverlayDirs, peer.mOverlayDirs)) {
124            return false;
125        }
126        if (!Arrays.equals(mLibDirs, peer.mLibDirs)) {
127            return false;
128        }
129        if (mDisplayId != peer.mDisplayId) {
130            return false;
131        }
132        if (!Objects.equals(mOverrideConfiguration, peer.mOverrideConfiguration)) {
133            return false;
134        }
135        if (!Objects.equals(mCompatInfo, peer.mCompatInfo)) {
136            return false;
137        }
138        return true;
139    }
140
141    @Override
142    public String toString() {
143        StringBuilder builder = new StringBuilder().append("ResourcesKey{");
144        builder.append(" mHash=").append(Integer.toHexString(mHash));
145        builder.append(" mResDir=").append(mResDir);
146        builder.append(" mSplitDirs=[");
147        if (mSplitResDirs != null) {
148            builder.append(TextUtils.join(",", mSplitResDirs));
149        }
150        builder.append("]");
151        builder.append(" mOverlayDirs=[");
152        if (mOverlayDirs != null) {
153            builder.append(TextUtils.join(",", mOverlayDirs));
154        }
155        builder.append("]");
156        builder.append(" mLibDirs=[");
157        if (mLibDirs != null) {
158            builder.append(TextUtils.join(",", mLibDirs));
159        }
160        builder.append("]");
161        builder.append(" mDisplayId=").append(mDisplayId);
162        builder.append(" mOverrideConfig=").append(Configuration.resourceQualifierString(
163                mOverrideConfiguration));
164        builder.append(" mCompatInfo=").append(mCompatInfo);
165        builder.append("}");
166        return builder.toString();
167    }
168}
169