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-beta3", "7541949", "REL"); 37 addSdk(Build.VERSION_CODES.CUR_DEVELOPMENT, "current", "r0", "ZZZ"); 38 // END-INTERNAL 39 } 40 41 private void addSdk( 42 int sdkVersion, 43 String androidVersion, 44 String frameworkSdkBuildVersion, 45 String codeName) { 46 put(sdkVersion, new SdkVersion(androidVersion, frameworkSdkBuildVersion, codeName)); 47 } 48 }); 49 50 public static final int FALLBACK_SDK_VERSION = Build.VERSION_CODES.JELLY_BEAN; 51 public static final int MAX_SDK_VERSION = Collections.max(getSupportedApis()); 52 53 private final int apiLevel; 54 getSupportedApis()55 public static Set<Integer> getSupportedApis() { 56 return SUPPORTED_APIS.keySet(); 57 } 58 getSupportedSdkConfigs()59 public static Collection<SdkConfig> getSupportedSdkConfigs() { 60 ArrayList<SdkConfig> sdkConfigs = new ArrayList<>(); 61 for (int sdkVersion : getSupportedApis()) { 62 sdkConfigs.add(new SdkConfig(sdkVersion)); 63 } 64 return sdkConfigs; 65 } 66 SdkConfig(int apiLevel)67 public SdkConfig(int apiLevel) { 68 this.apiLevel = apiLevel; 69 } 70 getApiLevel()71 public int getApiLevel() { 72 return apiLevel; 73 } 74 getAndroidVersion()75 public String getAndroidVersion() { 76 return getSdkVersion().androidVersion; 77 } 78 getAndroidCodeName()79 public String getAndroidCodeName() { 80 return getSdkVersion().codeName; 81 } 82 getAndroidSdkDependency()83 public DependencyJar getAndroidSdkDependency() { 84 return createDependency("org.robolectric", "android-all", getSdkVersion().getAndroidVersion() + "-robolectric-" + getSdkVersion().getRobolectricVersion(), null); 85 } 86 87 @Override equals(Object that)88 public boolean equals(Object that) { 89 return that == this || (that instanceof SdkConfig && ((SdkConfig) that).apiLevel == (apiLevel)); 90 } 91 92 @Override hashCode()93 public int hashCode() { 94 return apiLevel; 95 } 96 97 @Override toString()98 public String toString() { 99 return "API Level " + apiLevel; 100 } 101 102 @Override compareTo(@onnull SdkConfig o)103 public int compareTo(@Nonnull SdkConfig o) { 104 return apiLevel - o.apiLevel; 105 } 106 getSdkVersion()107 private SdkVersion getSdkVersion() { 108 final SdkVersion sdkVersion = SUPPORTED_APIS.get(apiLevel); 109 if (sdkVersion == null) { 110 throw new UnsupportedOperationException("Robolectric does not support API level " + apiLevel + "."); 111 } 112 return sdkVersion; 113 } 114 createDependency(String groupId, String artifactId, String version, String classifier)115 private DependencyJar createDependency(String groupId, String artifactId, String version, String classifier) { 116 return new DependencyJar(groupId, artifactId, version, classifier); 117 } 118 119 private static final class SdkVersion { 120 private final String androidVersion; 121 private final String robolectricVersion; 122 private final String codeName; 123 SdkVersion(String androidVersion, String robolectricVersion, String codeName)124 SdkVersion(String androidVersion, String robolectricVersion, String codeName) { 125 this.androidVersion = androidVersion; 126 this.robolectricVersion = robolectricVersion; 127 this.codeName = codeName; 128 } 129 130 @Override equals(Object that)131 public boolean equals(Object that) { 132 return that == this || (that instanceof SdkVersion && isEqualTo((SdkVersion) that)); 133 } 134 135 @SuppressWarnings("ReferenceEquality") isEqualTo(SdkVersion that)136 public boolean isEqualTo(SdkVersion that) { 137 return that == this || 138 (Objects.equals(that.androidVersion, androidVersion) && 139 Objects.equals(that.robolectricVersion, robolectricVersion)); 140 } 141 142 @Override hashCode()143 public int hashCode() { 144 return androidVersion.hashCode() * 31 + robolectricVersion.hashCode(); 145 } 146 getAndroidVersion()147 public String getAndroidVersion() { 148 return androidVersion; 149 } 150 getRobolectricVersion()151 public String getRobolectricVersion() { 152 return robolectricVersion; 153 } 154 } 155 } 156