1 package org.robolectric.internal; 2 3 import android.os.Build; 4 import java.util.ArrayList; 5 import java.util.Collection; 6 import java.util.Collections; 7 import java.util.HashMap; 8 import java.util.Map; 9 import java.util.Objects; 10 import java.util.Set; 11 import javax.annotation.Nonnull; 12 import org.robolectric.internal.dependency.DependencyJar; 13 14 public class SdkConfig implements Comparable<SdkConfig> { 15 16 private static final Map<Integer, SdkVersion> SUPPORTED_APIS = 17 Collections.unmodifiableMap( 18 new HashMap<Integer, SdkVersion>() { 19 { 20 addSdk(Build.VERSION_CODES.JELLY_BEAN, "4.1.2_r1", "r1", "REL"); 21 addSdk(Build.VERSION_CODES.JELLY_BEAN_MR1, "4.2.2_r1.2", "r1", "REL"); 22 addSdk(Build.VERSION_CODES.JELLY_BEAN_MR2, "4.3_r2", "r1", "REL"); 23 addSdk(Build.VERSION_CODES.KITKAT, "4.4_r1", "r2", "REL"); 24 addSdk(Build.VERSION_CODES.LOLLIPOP, "5.0.2_r3", "r0", "REL"); 25 addSdk(Build.VERSION_CODES.LOLLIPOP_MR1, "5.1.1_r9", "r2", "REL"); 26 addSdk(Build.VERSION_CODES.M, "6.0.1_r3", "r1", "REL"); 27 addSdk(Build.VERSION_CODES.N, "7.0.0_r1", "r1", "REL"); 28 addSdk(Build.VERSION_CODES.N_MR1, "7.1.0_r7", "r1", "REL"); 29 addSdk(Build.VERSION_CODES.O, "8.0.0_r4", "r1", "REL"); 30 addSdk(Build.VERSION_CODES.O_MR1, "8.1.0", "4611349", "REL"); 31 addSdk(Build.VERSION_CODES.P, "9", "4913185-2", "REL"); 32 addSdk(Build.VERSION_CODES.Q, "10", "5803371", "REL"); 33 // BEGIN-INTERNAL 34 // TODO: Update jar with final R release. 35 addSdk(Build.VERSION_CODES.R, "R-beta2", "6625208", "REL"); 36 addSdk(Build.VERSION_CODES.S, "S", "r0", "S"); 37 // END-INTERNAL 38 } 39 40 private void addSdk( 41 int sdkVersion, 42 String androidVersion, 43 String frameworkSdkBuildVersion, 44 String codeName) { 45 put(sdkVersion, new SdkVersion(androidVersion, frameworkSdkBuildVersion, codeName)); 46 } 47 }); 48 49 public static final int FALLBACK_SDK_VERSION = Build.VERSION_CODES.JELLY_BEAN; 50 public static final int MAX_SDK_VERSION = Collections.max(getSupportedApis()); 51 52 private final int apiLevel; 53 getSupportedApis()54 public static Set<Integer> getSupportedApis() { 55 return SUPPORTED_APIS.keySet(); 56 } 57 getSupportedSdkConfigs()58 public static Collection<SdkConfig> getSupportedSdkConfigs() { 59 ArrayList<SdkConfig> sdkConfigs = new ArrayList<>(); 60 for (int sdkVersion : getSupportedApis()) { 61 sdkConfigs.add(new SdkConfig(sdkVersion)); 62 } 63 return sdkConfigs; 64 } 65 SdkConfig(int apiLevel)66 public SdkConfig(int apiLevel) { 67 this.apiLevel = apiLevel; 68 } 69 getApiLevel()70 public int getApiLevel() { 71 return apiLevel; 72 } 73 getAndroidVersion()74 public String getAndroidVersion() { 75 return getSdkVersion().androidVersion; 76 } 77 getAndroidCodeName()78 public String getAndroidCodeName() { 79 return getSdkVersion().codeName; 80 } 81 getAndroidSdkDependency()82 public DependencyJar getAndroidSdkDependency() { 83 return createDependency("org.robolectric", "android-all", getSdkVersion().getAndroidVersion() + "-robolectric-" + getSdkVersion().getRobolectricVersion(), null); 84 } 85 86 @Override equals(Object that)87 public boolean equals(Object that) { 88 return that == this || (that instanceof SdkConfig && ((SdkConfig) that).apiLevel == (apiLevel)); 89 } 90 91 @Override hashCode()92 public int hashCode() { 93 return apiLevel; 94 } 95 96 @Override toString()97 public String toString() { 98 return "API Level " + apiLevel; 99 } 100 101 @Override compareTo(@onnull SdkConfig o)102 public int compareTo(@Nonnull SdkConfig o) { 103 return apiLevel - o.apiLevel; 104 } 105 getSdkVersion()106 private SdkVersion getSdkVersion() { 107 final SdkVersion sdkVersion = SUPPORTED_APIS.get(apiLevel); 108 if (sdkVersion == null) { 109 throw new UnsupportedOperationException("Robolectric does not support API level " + apiLevel + "."); 110 } 111 return sdkVersion; 112 } 113 createDependency(String groupId, String artifactId, String version, String classifier)114 private DependencyJar createDependency(String groupId, String artifactId, String version, String classifier) { 115 return new DependencyJar(groupId, artifactId, version, classifier); 116 } 117 118 private static final class SdkVersion { 119 private final String androidVersion; 120 private final String robolectricVersion; 121 private final String codeName; 122 SdkVersion(String androidVersion, String robolectricVersion, String codeName)123 SdkVersion(String androidVersion, String robolectricVersion, String codeName) { 124 this.androidVersion = androidVersion; 125 this.robolectricVersion = robolectricVersion; 126 this.codeName = codeName; 127 } 128 129 @Override equals(Object that)130 public boolean equals(Object that) { 131 return that == this || (that instanceof SdkVersion && isEqualTo((SdkVersion) that)); 132 } 133 134 @SuppressWarnings("ReferenceEquality") isEqualTo(SdkVersion that)135 public boolean isEqualTo(SdkVersion that) { 136 return that == this || 137 (Objects.equals(that.androidVersion, androidVersion) && 138 Objects.equals(that.robolectricVersion, robolectricVersion)); 139 } 140 141 @Override hashCode()142 public int hashCode() { 143 return androidVersion.hashCode() * 31 + robolectricVersion.hashCode(); 144 } 145 getAndroidVersion()146 public String getAndroidVersion() { 147 return androidVersion; 148 } 149 getRobolectricVersion()150 public String getRobolectricVersion() { 151 return robolectricVersion; 152 } 153 } 154 } 155