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