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 17 package android.content.res; 18 19 import static android.os.Build.VERSION_CODES.O; 20 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.compat.annotation.UnsupportedAppUsage; 24 import android.content.res.loader.ResourcesLoader; 25 import android.text.TextUtils; 26 27 import java.util.Arrays; 28 import java.util.Objects; 29 30 /** @hide */ 31 public final class ResourcesKey { 32 @Nullable 33 @UnsupportedAppUsage 34 public final String mResDir; 35 36 @Nullable 37 @UnsupportedAppUsage 38 public final String[] mSplitResDirs; 39 40 @Nullable 41 public final String[] mOverlayPaths; 42 43 @Nullable 44 public final String[] mLibDirs; 45 46 /** 47 * The display ID that overrides the global resources display to produce the Resources display. 48 * If set to something other than {@link android.view.Display#INVALID_DISPLAY} this will 49 * override the global resources display for this key. 50 */ 51 @UnsupportedAppUsage(maxTargetSdk = O) 52 public int mDisplayId; 53 54 /** 55 * The configuration applied to the global configuration to produce the Resources configuration. 56 */ 57 @NonNull 58 public final Configuration mOverrideConfiguration; 59 60 @NonNull 61 public final CompatibilityInfo mCompatInfo; 62 63 @Nullable 64 public final ResourcesLoader[] mLoaders; 65 66 private final int mHash; 67 ResourcesKey(@ullable String resDir, @Nullable String[] splitResDirs, @Nullable String[] overlayPaths, @Nullable String[] libDirs, int overrideDisplayId, @Nullable Configuration overrideConfig, @Nullable CompatibilityInfo compatInfo, @Nullable ResourcesLoader[] loader)68 public ResourcesKey(@Nullable String resDir, 69 @Nullable String[] splitResDirs, 70 @Nullable String[] overlayPaths, 71 @Nullable String[] libDirs, 72 int overrideDisplayId, 73 @Nullable Configuration overrideConfig, 74 @Nullable CompatibilityInfo compatInfo, 75 @Nullable ResourcesLoader[] loader) { 76 mResDir = resDir; 77 mSplitResDirs = splitResDirs; 78 mOverlayPaths = overlayPaths; 79 mLibDirs = libDirs; 80 mLoaders = (loader != null && loader.length == 0) ? null : loader; 81 mDisplayId = overrideDisplayId; 82 mOverrideConfiguration = new Configuration(overrideConfig != null 83 ? overrideConfig : Configuration.EMPTY); 84 mCompatInfo = compatInfo != null ? compatInfo : CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO; 85 86 int hash = 17; 87 hash = 31 * hash + Objects.hashCode(mResDir); 88 hash = 31 * hash + Arrays.hashCode(mSplitResDirs); 89 hash = 31 * hash + Arrays.hashCode(mOverlayPaths); 90 hash = 31 * hash + Arrays.hashCode(mLibDirs); 91 hash = 31 * hash + Objects.hashCode(mDisplayId); 92 hash = 31 * hash + Objects.hashCode(mOverrideConfiguration); 93 hash = 31 * hash + Objects.hashCode(mCompatInfo); 94 hash = 31 * hash + Arrays.hashCode(mLoaders); 95 mHash = hash; 96 } 97 98 @UnsupportedAppUsage ResourcesKey(@ullable String resDir, @Nullable String[] splitResDirs, @Nullable String[] overlayPaths, @Nullable String[] libDirs, int displayId, @Nullable Configuration overrideConfig, @Nullable CompatibilityInfo compatInfo)99 public ResourcesKey(@Nullable String resDir, 100 @Nullable String[] splitResDirs, 101 @Nullable String[] overlayPaths, 102 @Nullable String[] libDirs, 103 int displayId, 104 @Nullable Configuration overrideConfig, 105 @Nullable CompatibilityInfo compatInfo) { 106 this(resDir, splitResDirs, overlayPaths, libDirs, displayId, overrideConfig, compatInfo, 107 null); 108 } 109 hasOverrideConfiguration()110 public boolean hasOverrideConfiguration() { 111 return !Configuration.EMPTY.equals(mOverrideConfiguration); 112 } 113 isPathReferenced(String path)114 public boolean isPathReferenced(String path) { 115 if (mResDir != null && mResDir.startsWith(path)) { 116 return true; 117 } else { 118 return anyStartsWith(mSplitResDirs, path) || anyStartsWith(mOverlayPaths, path) 119 || anyStartsWith(mLibDirs, path); 120 } 121 } 122 anyStartsWith(String[] list, String prefix)123 private static boolean anyStartsWith(String[] list, String prefix) { 124 if (list != null) { 125 for (String s : list) { 126 if (s != null && s.startsWith(prefix)) { 127 return true; 128 } 129 } 130 } 131 return false; 132 } 133 134 @Override hashCode()135 public int hashCode() { 136 return mHash; 137 } 138 139 @Override equals(@ullable Object obj)140 public boolean equals(@Nullable Object obj) { 141 if (!(obj instanceof ResourcesKey)) { 142 return false; 143 } 144 145 ResourcesKey peer = (ResourcesKey) obj; 146 if (mHash != peer.mHash) { 147 // If the hashes don't match, the objects can't match. 148 return false; 149 } 150 151 if (!Objects.equals(mResDir, peer.mResDir)) { 152 return false; 153 } 154 if (!Arrays.equals(mSplitResDirs, peer.mSplitResDirs)) { 155 return false; 156 } 157 if (!Arrays.equals(mOverlayPaths, peer.mOverlayPaths)) { 158 return false; 159 } 160 if (!Arrays.equals(mLibDirs, peer.mLibDirs)) { 161 return false; 162 } 163 if (mDisplayId != peer.mDisplayId) { 164 return false; 165 } 166 if (!Objects.equals(mOverrideConfiguration, peer.mOverrideConfiguration)) { 167 return false; 168 } 169 if (!Objects.equals(mCompatInfo, peer.mCompatInfo)) { 170 return false; 171 } 172 if (!Arrays.equals(mLoaders, peer.mLoaders)) { 173 return false; 174 } 175 return true; 176 } 177 178 @Override toString()179 public String toString() { 180 StringBuilder builder = new StringBuilder().append("ResourcesKey{"); 181 builder.append(" mHash=").append(Integer.toHexString(mHash)); 182 builder.append(" mResDir=").append(mResDir); 183 builder.append(" mSplitDirs=["); 184 if (mSplitResDirs != null) { 185 builder.append(TextUtils.join(",", mSplitResDirs)); 186 } 187 builder.append("]"); 188 builder.append(" mOverlayDirs=["); 189 if (mOverlayPaths != null) { 190 builder.append(TextUtils.join(",", mOverlayPaths)); 191 } 192 builder.append("]"); 193 builder.append(" mLibDirs=["); 194 if (mLibDirs != null) { 195 builder.append(TextUtils.join(",", mLibDirs)); 196 } 197 builder.append("]"); 198 builder.append(" mDisplayId=").append(mDisplayId); 199 builder.append(" mOverrideConfig=").append(Configuration.resourceQualifierString( 200 mOverrideConfiguration)); 201 builder.append(" mCompatInfo=").append(mCompatInfo); 202 builder.append(" mLoaders=["); 203 if (mLoaders != null) { 204 builder.append(TextUtils.join(",", mLoaders)); 205 } 206 builder.append("]}"); 207 return builder.toString(); 208 } 209 } 210