SdkConfig.java revision f7833779cfddea9bb9afb1b3bf6c84ae267a68bf
1package org.robolectric.internal;
2
3import android.os.Build;
4import org.robolectric.internal.dependency.DependencyJar;
5import org.robolectric.util.Logger;
6
7import java.io.IOException;
8import java.io.InputStream;
9import java.util.Collections;
10import java.util.HashMap;
11import java.util.Map;
12import java.util.Objects;
13import java.util.Properties;
14import java.util.Set;
15
16public class SdkConfig {
17  private static final String ROBOLECTRIC_VERSION = getRobolectricVersion();
18
19  private static final Map<Integer, SdkVersion> SUPPORTED_APIS = Collections.unmodifiableMap(new HashMap<Integer, SdkVersion>() {
20    private final double jdkVersion = Double.parseDouble(System.getProperty("java.specification.version"));
21
22    {
23      addSdk(Build.VERSION_CODES.JELLY_BEAN, "4.1.2_r1", "0", "1.6");
24      addSdk(Build.VERSION_CODES.JELLY_BEAN_MR1, "4.2.2_r1.2", "0", "1.6");
25      addSdk(Build.VERSION_CODES.JELLY_BEAN_MR2, "4.3_r2", "0", "1.6");
26      addSdk(Build.VERSION_CODES.KITKAT, "4.4_r1", "1", "1.7");
27      addSdk(Build.VERSION_CODES.LOLLIPOP, "5.0.0_r2", "1", "1.7");
28      addSdk(Build.VERSION_CODES.LOLLIPOP_MR1, "5.1.1_r9", "1", "1.7");
29      addSdk(Build.VERSION_CODES.M, "6.0.1_r3", "0", "1.7");
30      addSdk(Build.VERSION_CODES.N, "7.0.0_r1", "0", "1.8");
31    }
32
33    private void addSdk(int sdkVersion, String androidVersion, String frameworkSdkBuildVersion, String minJdkVersion) {
34      if (jdkVersion >= Double.parseDouble(minJdkVersion)) {
35        put(sdkVersion, new SdkVersion(androidVersion, frameworkSdkBuildVersion));
36      } else {
37        Logger.info("Android SDK %s not supported on JDK %s (it requires %s)", sdkVersion, jdkVersion, minJdkVersion);
38      }
39    }
40  });
41
42  public static final int FALLBACK_SDK_VERSION = Build.VERSION_CODES.JELLY_BEAN;
43  public static final int MAX_SDK_VERSION = Collections.max(getSupportedApis());
44
45  private final int apiLevel;
46  private final SdkVersion sdkVersion;
47
48  public static Set<Integer> getSupportedApis() {
49    return SUPPORTED_APIS.keySet();
50  }
51
52  public SdkConfig(int apiLevel) {
53    this.apiLevel = apiLevel;
54    sdkVersion = SUPPORTED_APIS.get(apiLevel);
55    if (sdkVersion == null) {
56      throw new UnsupportedOperationException("Robolectric does not support API level " + apiLevel + ".");
57    }
58  }
59
60  public int getApiLevel() {
61    return apiLevel;
62  }
63
64  public String getAndroidVersion() {
65    return sdkVersion.androidVersion;
66  }
67
68  public DependencyJar getAndroidSdkDependency() {
69    return createDependency("org.robolectric", "android-all", sdkVersion.toString(), null);
70  }
71
72  public DependencyJar getCoreShadowsDependency() {
73    return createDependency("org.robolectric", "shadows-core", ROBOLECTRIC_VERSION, null);
74  }
75
76  @Override
77  public boolean equals(Object that) {
78    return that == this || that instanceof SdkConfig && ((SdkConfig) that).sdkVersion.equals(sdkVersion);
79  }
80
81  @Override
82  public String toString() {
83    return "API Level " + apiLevel;
84  }
85
86  @Override
87  public int hashCode() {
88    return sdkVersion.hashCode();
89  }
90
91  private DependencyJar createDependency(String groupId, String artifactId, String version, String classifier) {
92    return new DependencyJar(groupId, artifactId, version, classifier);
93  }
94
95  private static String getRobolectricVersion() {
96    ClassLoader classLoader = SdkVersion.class.getClassLoader();
97    try (InputStream is = classLoader.getResourceAsStream("robolectric-version.properties")) {
98      final Properties properties = new Properties();
99      properties.load(is);
100      return properties.getProperty("robolectric.version");
101    } catch (IOException e) {
102      throw new RuntimeException("Error determining Robolectric version: " + e.getMessage());
103    }
104  }
105
106  private static final class SdkVersion {
107    private final String androidVersion;
108    private final String robolectricVersion;
109
110    SdkVersion(String androidVersion, String robolectricVersion) {
111      this.androidVersion = androidVersion;
112      this.robolectricVersion = robolectricVersion;
113    }
114
115    @Override
116    public boolean equals(Object that) {
117      return that == this || that instanceof SdkVersion && equals((SdkVersion) that);
118    }
119
120    public boolean equals(SdkVersion that) {
121      return that == this ||
122          Objects.equals(that.androidVersion, androidVersion) &&
123              Objects.equals(that.robolectricVersion, robolectricVersion);
124    }
125
126    @Override
127    public int hashCode() {
128      return androidVersion.hashCode() * 31 + robolectricVersion.hashCode();
129    }
130
131    @Override
132    public String toString() {
133      return androidVersion + "-robolectric-" + robolectricVersion;
134    }
135  }
136}
137