1 package com.android.settings.testutils.shadow;
2 
3 import static org.robolectric.RuntimeEnvironment.application;
4 import static org.robolectric.shadow.api.Shadow.directlyOn;
5 
6 import android.content.res.Resources;
7 import android.content.res.Resources.NotFoundException;
8 import android.util.SparseArray;
9 
10 import androidx.annotation.ArrayRes;
11 
12 import org.robolectric.annotation.Implementation;
13 import org.robolectric.annotation.Implements;
14 import org.robolectric.annotation.RealObject;
15 import org.robolectric.annotation.Resetter;
16 import org.robolectric.shadows.ShadowResources;
17 import org.robolectric.util.ReflectionHelpers.ClassParameter;
18 
19 /**
20  * Shadow Resources and Theme classes to handle resource references that Robolectric shadows cannot
21  * handle because they are too new or private.
22  */
23 @Implements(value = Resources.class)
24 public class SettingsShadowResources extends ShadowResources {
25 
26     @RealObject
27     public Resources realResources;
28 
29     private static SparseArray<Object> sResourceOverrides = new SparseArray<>();
30 
overrideResource(int id, Object value)31     public static void overrideResource(int id, Object value) {
32         sResourceOverrides.put(id, value);
33     }
34 
overrideResource(String name, Object value)35     public static void overrideResource(String name, Object value) {
36         final Resources res = application.getResources();
37         final int resId = res.getIdentifier(name, null, null);
38         if (resId == 0) {
39             throw new Resources.NotFoundException("Cannot override \"" + name + "\"");
40         }
41         overrideResource(resId, value);
42     }
43 
44     @Resetter
reset()45     public static void reset() {
46         sResourceOverrides.clear();
47     }
48 
49     @Implementation
getIntArray(@rrayRes int id)50     protected int[] getIntArray(@ArrayRes int id) throws NotFoundException {
51         final Object override = sResourceOverrides.get(id);
52         if (override instanceof int[]) {
53             return (int[]) override;
54         }
55         return directlyOn(realResources, Resources.class).getIntArray(id);
56     }
57 
58     @Implementation
getString(int id)59     protected String getString(int id) {
60         final Object override = sResourceOverrides.get(id);
61         if (override instanceof String) {
62             return (String) override;
63         }
64         return directlyOn(
65                 realResources, Resources.class, "getString", ClassParameter.from(int.class, id));
66     }
67 
68     @Implementation
getInteger(int id)69     protected int getInteger(int id) {
70         final Object override = sResourceOverrides.get(id);
71         if (override instanceof Integer) {
72             return (Integer) override;
73         }
74         return directlyOn(
75                 realResources, Resources.class, "getInteger", ClassParameter.from(int.class, id));
76     }
77 
78     @Implementation
getBoolean(int id)79     protected boolean getBoolean(int id) {
80         final Object override = sResourceOverrides.get(id);
81         if (override instanceof Boolean) {
82             return (boolean) override;
83         }
84         return directlyOn(realResources, Resources.class, "getBoolean",
85                 ClassParameter.from(int.class, id));
86     }
87 }
88