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 = new Configuration(overrideConfig != null
63                ? overrideConfig : Configuration.EMPTY);
64        mCompatInfo = compatInfo != null ? compatInfo : CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
65
66        int hash = 17;
67        hash = 31 * hash + Objects.hashCode(mResDir);
68        hash = 31 * hash + Arrays.hashCode(mSplitResDirs);
69        hash = 31 * hash + Arrays.hashCode(mOverlayDirs);
70        hash = 31 * hash + Arrays.hashCode(mLibDirs);
71        hash = 31 * hash + mDisplayId;
72        hash = 31 * hash + Objects.hashCode(mOverrideConfiguration);
73        hash = 31 * hash + Objects.hashCode(mCompatInfo);
74        mHash = hash;
75    }
76
77    public boolean hasOverrideConfiguration() {
78        return !Configuration.EMPTY.equals(mOverrideConfiguration);
79    }
80
81    public boolean isPathReferenced(String path) {
82        if (mResDir != null && mResDir.startsWith(path)) {
83            return true;
84        } else {
85            return anyStartsWith(mSplitResDirs, path) || anyStartsWith(mOverlayDirs, path)
86                    || anyStartsWith(mLibDirs, path);
87        }
88    }
89
90    private static boolean anyStartsWith(String[] list, String prefix) {
91        if (list != null) {
92            for (String s : list) {
93                if (s != null && s.startsWith(prefix)) {
94                    return true;
95                }
96            }
97        }
98        return false;
99    }
100
101    @Override
102    public int hashCode() {
103        return mHash;
104    }
105
106    @Override
107    public boolean equals(Object obj) {
108        if (!(obj instanceof ResourcesKey)) {
109            return false;
110        }
111
112        ResourcesKey peer = (ResourcesKey) obj;
113        if (mHash != peer.mHash) {
114            // If the hashes don't match, the objects can't match.
115            return false;
116        }
117
118        if (!Objects.equals(mResDir, peer.mResDir)) {
119            return false;
120        }
121        if (!Arrays.equals(mSplitResDirs, peer.mSplitResDirs)) {
122            return false;
123        }
124        if (!Arrays.equals(mOverlayDirs, peer.mOverlayDirs)) {
125            return false;
126        }
127        if (!Arrays.equals(mLibDirs, peer.mLibDirs)) {
128            return false;
129        }
130        if (mDisplayId != peer.mDisplayId) {
131            return false;
132        }
133        if (!Objects.equals(mOverrideConfiguration, peer.mOverrideConfiguration)) {
134            return false;
135        }
136        if (!Objects.equals(mCompatInfo, peer.mCompatInfo)) {
137            return false;
138        }
139        return true;
140    }
141
142    @Override
143    public String toString() {
144        StringBuilder builder = new StringBuilder().append("ResourcesKey{");
145        builder.append(" mHash=").append(Integer.toHexString(mHash));
146        builder.append(" mResDir=").append(mResDir);
147        builder.append(" mSplitDirs=[");
148        if (mSplitResDirs != null) {
149            builder.append(TextUtils.join(",", mSplitResDirs));
150        }
151        builder.append("]");
152        builder.append(" mOverlayDirs=[");
153        if (mOverlayDirs != null) {
154            builder.append(TextUtils.join(",", mOverlayDirs));
155        }
156        builder.append("]");
157        builder.append(" mLibDirs=[");
158        if (mLibDirs != null) {
159            builder.append(TextUtils.join(",", mLibDirs));
160        }
161        builder.append("]");
162        builder.append(" mDisplayId=").append(mDisplayId);
163        builder.append(" mOverrideConfig=").append(Configuration.resourceQualifierString(
164                mOverrideConfiguration));
165        builder.append(" mCompatInfo=").append(mCompatInfo);
166        builder.append("}");
167        return builder.toString();
168    }
169}
170