Loading core/java/android/security/net/config/ManifestConfigSource.java +16 −24 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.content.Context; import android.content.pm.ApplicationInfo; import android.util.Log; import android.util.Pair; import java.util.Set; /** @hide */ Loading @@ -29,21 +30,14 @@ public class ManifestConfigSource implements ConfigSource { private final Object mLock = new Object(); private final Context mContext; private final int mApplicationInfoFlags; private final int mTargetSdkVersion; private final int mConfigResourceId; private final int mTargetSandboxVesrsion; private final ApplicationInfo mApplicationInfo; private ConfigSource mConfigSource; public ManifestConfigSource(Context context) { mContext = context; // Cache values because ApplicationInfo is mutable and apps do modify it :( ApplicationInfo info = context.getApplicationInfo(); mApplicationInfoFlags = info.flags; mTargetSdkVersion = info.targetSdkVersion; mConfigResourceId = info.networkSecurityConfigRes; mTargetSandboxVesrsion = info.targetSandboxVersion; // Cache the info because ApplicationInfo is mutable and apps do modify it :( mApplicationInfo = new ApplicationInfo(context.getApplicationInfo()); } @Override Loading @@ -61,17 +55,18 @@ public class ManifestConfigSource implements ConfigSource { if (mConfigSource != null) { return mConfigSource; } int configResource = mApplicationInfo.networkSecurityConfigRes; ConfigSource source; if (mConfigResourceId != 0) { boolean debugBuild = (mApplicationInfoFlags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; if (configResource != 0) { boolean debugBuild = (mApplicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; if (DBG) { Log.d(LOG_TAG, "Using Network Security Config from resource " + mContext.getResources().getResourceEntryName(mConfigResourceId) + mContext.getResources() .getResourceEntryName(configResource) + " debugBuild: " + debugBuild); } source = new XmlConfigSource(mContext, mConfigResourceId, debugBuild, mTargetSdkVersion, mTargetSandboxVesrsion); source = new XmlConfigSource(mContext, configResource, mApplicationInfo); } else { if (DBG) { Log.d(LOG_TAG, "No Network Security Config specified, using platform default"); Loading @@ -79,10 +74,9 @@ public class ManifestConfigSource implements ConfigSource { // the legacy FLAG_USES_CLEARTEXT_TRAFFIC is not supported for Ephemeral apps, they // should use the network security config. boolean usesCleartextTraffic = (mApplicationInfoFlags & ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC) != 0 && mTargetSandboxVesrsion < 2; source = new DefaultConfigSource(usesCleartextTraffic, mTargetSdkVersion, mTargetSandboxVesrsion); (mApplicationInfo.flags & ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC) != 0 && mApplicationInfo.targetSandboxVersion < 2; source = new DefaultConfigSource(usesCleartextTraffic, mApplicationInfo); } mConfigSource = source; return mConfigSource; Loading @@ -93,10 +87,8 @@ public class ManifestConfigSource implements ConfigSource { private final NetworkSecurityConfig mDefaultConfig; public DefaultConfigSource(boolean usesCleartextTraffic, int targetSdkVersion, int targetSandboxVesrsion) { mDefaultConfig = NetworkSecurityConfig.getDefaultBuilder(targetSdkVersion, targetSandboxVesrsion) DefaultConfigSource(boolean usesCleartextTraffic, ApplicationInfo info) { mDefaultConfig = NetworkSecurityConfig.getDefaultBuilder(info) .setCleartextTrafficPermitted(usesCleartextTraffic) .build(); } Loading core/java/android/security/net/config/NetworkSecurityConfig.java +8 −6 Original line number Diff line number Diff line Loading @@ -16,9 +16,11 @@ package android.security.net.config; import android.content.pm.ApplicationInfo; import android.os.Build; import android.util.ArrayMap; import android.util.ArraySet; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collection; Loading @@ -28,8 +30,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import javax.net.ssl.X509TrustManager; /** * @hide */ Loading Loading @@ -170,22 +170,24 @@ public final class NetworkSecurityConfig { * <li>No certificate pinning is used.</li> * <li>The system certificate store is trusted for connections.</li> * <li>If the application targets API level 23 (Android M) or lower then the user certificate * store is trusted by default as well.</li> * store is trusted by default as well for non-privileged applications.</li> * <li>Privileged applications do not trust the user certificate store on Android P and higher. * </li> * </ol> * * @hide */ public static final Builder getDefaultBuilder(int targetSdkVersion, int targetSandboxVesrsion) { public static Builder getDefaultBuilder(ApplicationInfo info) { Builder builder = new Builder() .setHstsEnforced(DEFAULT_HSTS_ENFORCED) // System certificate store, does not bypass static pins. .addCertificatesEntryRef( new CertificatesEntryRef(SystemCertificateSource.getInstance(), false)); final boolean cleartextTrafficPermitted = targetSandboxVesrsion < 2; final boolean cleartextTrafficPermitted = info.targetSandboxVersion < 2; builder.setCleartextTrafficPermitted(cleartextTrafficPermitted); // Applications targeting N and above must opt in into trusting the user added certificate // store. if (targetSdkVersion <= Build.VERSION_CODES.M) { if (info.targetSdkVersion <= Build.VERSION_CODES.M && !info.isPrivilegedApp()) { // User certificate store, does not bypass static pins. builder.addCertificatesEntryRef( new CertificatesEntryRef(UserCertificateSource.getInstance(), false)); Loading core/java/android/security/net/config/XmlConfigSource.java +9 −27 Original line number Diff line number Diff line package android.security.net.config; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.res.Resources; import android.content.res.XmlResourceParser; import android.os.Build; import android.util.ArraySet; import android.util.Base64; import android.util.Pair; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.XmlUtils; import org.xmlpull.v1.XmlPullParser; Loading Loading @@ -36,37 +36,19 @@ public class XmlConfigSource implements ConfigSource { private final Object mLock = new Object(); private final int mResourceId; private final boolean mDebugBuild; private final int mTargetSdkVersion; private final int mTargetSandboxVesrsion; private final ApplicationInfo mApplicationInfo; private boolean mInitialized; private NetworkSecurityConfig mDefaultConfig; private Set<Pair<Domain, NetworkSecurityConfig>> mDomainMap; private Context mContext; @VisibleForTesting public XmlConfigSource(Context context, int resourceId) { this(context, resourceId, false); } @VisibleForTesting public XmlConfigSource(Context context, int resourceId, boolean debugBuild) { this(context, resourceId, debugBuild, Build.VERSION_CODES.CUR_DEVELOPMENT); } @VisibleForTesting public XmlConfigSource(Context context, int resourceId, boolean debugBuild, int targetSdkVersion) { this(context, resourceId, debugBuild, targetSdkVersion, 1 /*targetSandboxVersion*/); } public XmlConfigSource(Context context, int resourceId, boolean debugBuild, int targetSdkVersion, int targetSandboxVesrsion) { mResourceId = resourceId; public XmlConfigSource(Context context, int resourceId, ApplicationInfo info) { mContext = context; mDebugBuild = debugBuild; mTargetSdkVersion = targetSdkVersion; mTargetSandboxVesrsion = targetSandboxVesrsion; mResourceId = resourceId; mApplicationInfo = new ApplicationInfo(info); mDebugBuild = (mApplicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; } public Set<Pair<Domain, NetworkSecurityConfig>> getPerDomainConfigs() { Loading Loading @@ -365,7 +347,7 @@ public class XmlConfigSource implements ConfigSource { // Use the platform default as the parent of the base config for any values not provided // there. If there is no base config use the platform default. NetworkSecurityConfig.Builder platformDefaultBuilder = NetworkSecurityConfig.getDefaultBuilder(mTargetSdkVersion, mTargetSandboxVesrsion); NetworkSecurityConfig.getDefaultBuilder(mApplicationInfo); addDebugAnchorsIfNeeded(debugConfigBuilder, platformDefaultBuilder); if (baseConfigBuilder != null) { baseConfigBuilder.setParent(platformDefaultBuilder); Loading tests/NetworkSecurityConfigTest/src/android/security/net/config/NetworkSecurityConfigTests.java +21 −3 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.security.net.config; import android.app.Activity; import android.content.pm.ApplicationInfo; import android.os.Build; import android.test.ActivityUnitTestCase; import android.util.ArraySet; Loading Loading @@ -227,7 +228,8 @@ public class NetworkSecurityConfigTests extends ActivityUnitTestCase<Activity> { public void testConfigBuilderUsesParents() throws Exception { // Check that a builder with a parent uses the parent's values when non is set. NetworkSecurityConfig config = new NetworkSecurityConfig.Builder() .setParent(NetworkSecurityConfig.getDefaultBuilder(Build.VERSION_CODES.N, 1)) .setParent(NetworkSecurityConfig .getDefaultBuilder(TestUtils.makeApplicationInfo())) .build(); assert(!config.getTrustAnchors().isEmpty()); } Loading Loading @@ -268,11 +270,22 @@ public class NetworkSecurityConfigTests extends ActivityUnitTestCase<Activity> { // Install the test CA. store.installCertificate(TEST_CA_CERT); NetworkSecurityConfig preNConfig = NetworkSecurityConfig.getDefaultBuilder(Build.VERSION_CODES.M, 1).build(); NetworkSecurityConfig .getDefaultBuilder(TestUtils.makeApplicationInfo(Build.VERSION_CODES.M)) .build(); NetworkSecurityConfig nConfig = NetworkSecurityConfig.getDefaultBuilder(Build.VERSION_CODES.N, 1).build(); NetworkSecurityConfig .getDefaultBuilder(TestUtils.makeApplicationInfo(Build.VERSION_CODES.N)) .build(); ApplicationInfo privInfo = TestUtils.makeApplicationInfo(Build.VERSION_CODES.M); privInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED; NetworkSecurityConfig privConfig = NetworkSecurityConfig .getDefaultBuilder(privInfo) .build(); Set<TrustAnchor> preNAnchors = preNConfig.getTrustAnchors(); Set<TrustAnchor> nAnchors = nConfig.getTrustAnchors(); Set<TrustAnchor> privAnchors = privConfig.getTrustAnchors(); Set<X509Certificate> preNCerts = new HashSet<X509Certificate>(); for (TrustAnchor anchor : preNAnchors) { preNCerts.add(anchor.certificate); Loading @@ -281,8 +294,13 @@ public class NetworkSecurityConfigTests extends ActivityUnitTestCase<Activity> { for (TrustAnchor anchor : nAnchors) { nCerts.add(anchor.certificate); } Set<X509Certificate> privCerts = new HashSet<X509Certificate>(); for (TrustAnchor anchor : privAnchors) { privCerts.add(anchor.certificate); } assertTrue(preNCerts.contains(TEST_CA_CERT)); assertFalse(nCerts.contains(TEST_CA_CERT)); assertFalse(privCerts.contains(TEST_CA_CERT)); } finally { // Delete the user added CA. We don't know the alias so just delete them all. for (String alias : store.aliases()) { Loading tests/NetworkSecurityConfigTest/src/android/security/net/config/TestUtils.java +15 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package android.security.net.config; import android.content.pm.ApplicationInfo; import android.os.Build; import java.net.Socket; import java.net.URL; import javax.net.ssl.HttpsURLConnection; Loading Loading @@ -77,4 +79,17 @@ public final class TestUtils extends Assert { context.init(null, tmf.getTrustManagers(), null); return context; } public static ApplicationInfo makeApplicationInfo() { ApplicationInfo info = new ApplicationInfo(); info.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT; info.targetSandboxVersion = 1; return info; } public static ApplicationInfo makeApplicationInfo(int targetSdkVersion) { ApplicationInfo info = makeApplicationInfo(); info.targetSdkVersion = targetSdkVersion; return info; } } Loading
core/java/android/security/net/config/ManifestConfigSource.java +16 −24 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.content.Context; import android.content.pm.ApplicationInfo; import android.util.Log; import android.util.Pair; import java.util.Set; /** @hide */ Loading @@ -29,21 +30,14 @@ public class ManifestConfigSource implements ConfigSource { private final Object mLock = new Object(); private final Context mContext; private final int mApplicationInfoFlags; private final int mTargetSdkVersion; private final int mConfigResourceId; private final int mTargetSandboxVesrsion; private final ApplicationInfo mApplicationInfo; private ConfigSource mConfigSource; public ManifestConfigSource(Context context) { mContext = context; // Cache values because ApplicationInfo is mutable and apps do modify it :( ApplicationInfo info = context.getApplicationInfo(); mApplicationInfoFlags = info.flags; mTargetSdkVersion = info.targetSdkVersion; mConfigResourceId = info.networkSecurityConfigRes; mTargetSandboxVesrsion = info.targetSandboxVersion; // Cache the info because ApplicationInfo is mutable and apps do modify it :( mApplicationInfo = new ApplicationInfo(context.getApplicationInfo()); } @Override Loading @@ -61,17 +55,18 @@ public class ManifestConfigSource implements ConfigSource { if (mConfigSource != null) { return mConfigSource; } int configResource = mApplicationInfo.networkSecurityConfigRes; ConfigSource source; if (mConfigResourceId != 0) { boolean debugBuild = (mApplicationInfoFlags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; if (configResource != 0) { boolean debugBuild = (mApplicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; if (DBG) { Log.d(LOG_TAG, "Using Network Security Config from resource " + mContext.getResources().getResourceEntryName(mConfigResourceId) + mContext.getResources() .getResourceEntryName(configResource) + " debugBuild: " + debugBuild); } source = new XmlConfigSource(mContext, mConfigResourceId, debugBuild, mTargetSdkVersion, mTargetSandboxVesrsion); source = new XmlConfigSource(mContext, configResource, mApplicationInfo); } else { if (DBG) { Log.d(LOG_TAG, "No Network Security Config specified, using platform default"); Loading @@ -79,10 +74,9 @@ public class ManifestConfigSource implements ConfigSource { // the legacy FLAG_USES_CLEARTEXT_TRAFFIC is not supported for Ephemeral apps, they // should use the network security config. boolean usesCleartextTraffic = (mApplicationInfoFlags & ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC) != 0 && mTargetSandboxVesrsion < 2; source = new DefaultConfigSource(usesCleartextTraffic, mTargetSdkVersion, mTargetSandboxVesrsion); (mApplicationInfo.flags & ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC) != 0 && mApplicationInfo.targetSandboxVersion < 2; source = new DefaultConfigSource(usesCleartextTraffic, mApplicationInfo); } mConfigSource = source; return mConfigSource; Loading @@ -93,10 +87,8 @@ public class ManifestConfigSource implements ConfigSource { private final NetworkSecurityConfig mDefaultConfig; public DefaultConfigSource(boolean usesCleartextTraffic, int targetSdkVersion, int targetSandboxVesrsion) { mDefaultConfig = NetworkSecurityConfig.getDefaultBuilder(targetSdkVersion, targetSandboxVesrsion) DefaultConfigSource(boolean usesCleartextTraffic, ApplicationInfo info) { mDefaultConfig = NetworkSecurityConfig.getDefaultBuilder(info) .setCleartextTrafficPermitted(usesCleartextTraffic) .build(); } Loading
core/java/android/security/net/config/NetworkSecurityConfig.java +8 −6 Original line number Diff line number Diff line Loading @@ -16,9 +16,11 @@ package android.security.net.config; import android.content.pm.ApplicationInfo; import android.os.Build; import android.util.ArrayMap; import android.util.ArraySet; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collection; Loading @@ -28,8 +30,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import javax.net.ssl.X509TrustManager; /** * @hide */ Loading Loading @@ -170,22 +170,24 @@ public final class NetworkSecurityConfig { * <li>No certificate pinning is used.</li> * <li>The system certificate store is trusted for connections.</li> * <li>If the application targets API level 23 (Android M) or lower then the user certificate * store is trusted by default as well.</li> * store is trusted by default as well for non-privileged applications.</li> * <li>Privileged applications do not trust the user certificate store on Android P and higher. * </li> * </ol> * * @hide */ public static final Builder getDefaultBuilder(int targetSdkVersion, int targetSandboxVesrsion) { public static Builder getDefaultBuilder(ApplicationInfo info) { Builder builder = new Builder() .setHstsEnforced(DEFAULT_HSTS_ENFORCED) // System certificate store, does not bypass static pins. .addCertificatesEntryRef( new CertificatesEntryRef(SystemCertificateSource.getInstance(), false)); final boolean cleartextTrafficPermitted = targetSandboxVesrsion < 2; final boolean cleartextTrafficPermitted = info.targetSandboxVersion < 2; builder.setCleartextTrafficPermitted(cleartextTrafficPermitted); // Applications targeting N and above must opt in into trusting the user added certificate // store. if (targetSdkVersion <= Build.VERSION_CODES.M) { if (info.targetSdkVersion <= Build.VERSION_CODES.M && !info.isPrivilegedApp()) { // User certificate store, does not bypass static pins. builder.addCertificatesEntryRef( new CertificatesEntryRef(UserCertificateSource.getInstance(), false)); Loading
core/java/android/security/net/config/XmlConfigSource.java +9 −27 Original line number Diff line number Diff line package android.security.net.config; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.res.Resources; import android.content.res.XmlResourceParser; import android.os.Build; import android.util.ArraySet; import android.util.Base64; import android.util.Pair; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.XmlUtils; import org.xmlpull.v1.XmlPullParser; Loading Loading @@ -36,37 +36,19 @@ public class XmlConfigSource implements ConfigSource { private final Object mLock = new Object(); private final int mResourceId; private final boolean mDebugBuild; private final int mTargetSdkVersion; private final int mTargetSandboxVesrsion; private final ApplicationInfo mApplicationInfo; private boolean mInitialized; private NetworkSecurityConfig mDefaultConfig; private Set<Pair<Domain, NetworkSecurityConfig>> mDomainMap; private Context mContext; @VisibleForTesting public XmlConfigSource(Context context, int resourceId) { this(context, resourceId, false); } @VisibleForTesting public XmlConfigSource(Context context, int resourceId, boolean debugBuild) { this(context, resourceId, debugBuild, Build.VERSION_CODES.CUR_DEVELOPMENT); } @VisibleForTesting public XmlConfigSource(Context context, int resourceId, boolean debugBuild, int targetSdkVersion) { this(context, resourceId, debugBuild, targetSdkVersion, 1 /*targetSandboxVersion*/); } public XmlConfigSource(Context context, int resourceId, boolean debugBuild, int targetSdkVersion, int targetSandboxVesrsion) { mResourceId = resourceId; public XmlConfigSource(Context context, int resourceId, ApplicationInfo info) { mContext = context; mDebugBuild = debugBuild; mTargetSdkVersion = targetSdkVersion; mTargetSandboxVesrsion = targetSandboxVesrsion; mResourceId = resourceId; mApplicationInfo = new ApplicationInfo(info); mDebugBuild = (mApplicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; } public Set<Pair<Domain, NetworkSecurityConfig>> getPerDomainConfigs() { Loading Loading @@ -365,7 +347,7 @@ public class XmlConfigSource implements ConfigSource { // Use the platform default as the parent of the base config for any values not provided // there. If there is no base config use the platform default. NetworkSecurityConfig.Builder platformDefaultBuilder = NetworkSecurityConfig.getDefaultBuilder(mTargetSdkVersion, mTargetSandboxVesrsion); NetworkSecurityConfig.getDefaultBuilder(mApplicationInfo); addDebugAnchorsIfNeeded(debugConfigBuilder, platformDefaultBuilder); if (baseConfigBuilder != null) { baseConfigBuilder.setParent(platformDefaultBuilder); Loading
tests/NetworkSecurityConfigTest/src/android/security/net/config/NetworkSecurityConfigTests.java +21 −3 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.security.net.config; import android.app.Activity; import android.content.pm.ApplicationInfo; import android.os.Build; import android.test.ActivityUnitTestCase; import android.util.ArraySet; Loading Loading @@ -227,7 +228,8 @@ public class NetworkSecurityConfigTests extends ActivityUnitTestCase<Activity> { public void testConfigBuilderUsesParents() throws Exception { // Check that a builder with a parent uses the parent's values when non is set. NetworkSecurityConfig config = new NetworkSecurityConfig.Builder() .setParent(NetworkSecurityConfig.getDefaultBuilder(Build.VERSION_CODES.N, 1)) .setParent(NetworkSecurityConfig .getDefaultBuilder(TestUtils.makeApplicationInfo())) .build(); assert(!config.getTrustAnchors().isEmpty()); } Loading Loading @@ -268,11 +270,22 @@ public class NetworkSecurityConfigTests extends ActivityUnitTestCase<Activity> { // Install the test CA. store.installCertificate(TEST_CA_CERT); NetworkSecurityConfig preNConfig = NetworkSecurityConfig.getDefaultBuilder(Build.VERSION_CODES.M, 1).build(); NetworkSecurityConfig .getDefaultBuilder(TestUtils.makeApplicationInfo(Build.VERSION_CODES.M)) .build(); NetworkSecurityConfig nConfig = NetworkSecurityConfig.getDefaultBuilder(Build.VERSION_CODES.N, 1).build(); NetworkSecurityConfig .getDefaultBuilder(TestUtils.makeApplicationInfo(Build.VERSION_CODES.N)) .build(); ApplicationInfo privInfo = TestUtils.makeApplicationInfo(Build.VERSION_CODES.M); privInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED; NetworkSecurityConfig privConfig = NetworkSecurityConfig .getDefaultBuilder(privInfo) .build(); Set<TrustAnchor> preNAnchors = preNConfig.getTrustAnchors(); Set<TrustAnchor> nAnchors = nConfig.getTrustAnchors(); Set<TrustAnchor> privAnchors = privConfig.getTrustAnchors(); Set<X509Certificate> preNCerts = new HashSet<X509Certificate>(); for (TrustAnchor anchor : preNAnchors) { preNCerts.add(anchor.certificate); Loading @@ -281,8 +294,13 @@ public class NetworkSecurityConfigTests extends ActivityUnitTestCase<Activity> { for (TrustAnchor anchor : nAnchors) { nCerts.add(anchor.certificate); } Set<X509Certificate> privCerts = new HashSet<X509Certificate>(); for (TrustAnchor anchor : privAnchors) { privCerts.add(anchor.certificate); } assertTrue(preNCerts.contains(TEST_CA_CERT)); assertFalse(nCerts.contains(TEST_CA_CERT)); assertFalse(privCerts.contains(TEST_CA_CERT)); } finally { // Delete the user added CA. We don't know the alias so just delete them all. for (String alias : store.aliases()) { Loading
tests/NetworkSecurityConfigTest/src/android/security/net/config/TestUtils.java +15 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package android.security.net.config; import android.content.pm.ApplicationInfo; import android.os.Build; import java.net.Socket; import java.net.URL; import javax.net.ssl.HttpsURLConnection; Loading Loading @@ -77,4 +79,17 @@ public final class TestUtils extends Assert { context.init(null, tmf.getTrustManagers(), null); return context; } public static ApplicationInfo makeApplicationInfo() { ApplicationInfo info = new ApplicationInfo(); info.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT; info.targetSandboxVersion = 1; return info; } public static ApplicationInfo makeApplicationInfo(int targetSdkVersion) { ApplicationInfo info = makeApplicationInfo(); info.targetSdkVersion = targetSdkVersion; return info; } }