diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-12-07 13:12:10 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-12-07 13:12:10 +0000 |
commit | 73250509175de6422c69ec7fa408c3708a1a88ea (patch) | |
tree | cabfe6a838b8c985a9a68c087c32c16d2c8ce4d4 | |
parent | 8430ad874b565aecd536155a420c1618c9f1000f (diff) | |
parent | f493096743e1fc2e8d3d68ecd296ef485db3c883 (diff) | |
download | cts-aml_art_331413030.tar.gz |
Snap for 9379409 from f493096743e1fc2e8d3d68ecd296ef485db3c883 to mainline-art-releaseaml_art_331413030
Change-Id: Ia894fe717eb85332ba30422ca599a4c789696dc3
6 files changed, 294 insertions, 63 deletions
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20197.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20197.java index 3d31cee17c7..98befd4884a 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20197.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20197.java @@ -16,18 +16,18 @@ package android.security.cts; +import static com.android.sts.common.SystemUtil.withSetting; + import static org.junit.Assume.assumeNoException; import android.platform.test.annotations.AsbSecurityTest; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; -import com.android.tradefed.device.ITestDevice; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; import org.junit.runner.RunWith; - @RunWith(DeviceJUnit4ClassRunner.class) public class CVE_2022_20197 extends NonRootSecurityTestCase { private static final String TEST_PKG = "android.security.cts.CVE_2022_20197"; @@ -35,37 +35,11 @@ public class CVE_2022_20197 extends NonRootSecurityTestCase { @AsbSecurityTest(cveBugId = 208279300) @Test public void testPocCVE_2022_20197() { - ITestDevice device = null; - boolean isPolicyPresent = true; - boolean isHiddenApiEnabled = true; - String status = ""; - try { - device = getDevice(); + try (AutoCloseable a = withSetting(getDevice(), "global", "hidden_api_policy", "1")) { installPackage("CVE-2022-20197.apk"); - - status = AdbUtils.runCommandLine("settings get global hidden_api_policy", device); - if (status.toLowerCase().contains("null")) { - isPolicyPresent = false; - } else if (!status.toLowerCase().contains("1")) { - isHiddenApiEnabled = false; - } - if (!isPolicyPresent || !isHiddenApiEnabled) { - AdbUtils.runCommandLine("settings put global hidden_api_policy 1", device); - } runDeviceTests(TEST_PKG, TEST_PKG + ".DeviceTest", "testParcel"); } catch (Exception e) { assumeNoException(e); - } finally { - try { - if (!isPolicyPresent) { - AdbUtils.runCommandLine("settings delete global hidden_api_policy", device); - } else if (!isHiddenApiEnabled) { - AdbUtils.runCommandLine("settings put global hidden_api_policy " + status, - device); - } - } catch (Exception e) { - // ignore all exceptions. - } } } } diff --git a/tests/tests/permission4/Android.bp b/tests/tests/permission4/Android.bp index 2ff3bee8b9a..72908e284dc 100644 --- a/tests/tests/permission4/Android.bp +++ b/tests/tests/permission4/Android.bp @@ -34,6 +34,7 @@ android_test { ], test_suites: [ "cts", + "sts", "vts10", "general-tests", "mts-permission", diff --git a/tests/tests/permission4/AppThatAccessesCameraAndMic/Android.bp b/tests/tests/permission4/AppThatAccessesCameraAndMic/Android.bp index a7e0ab6b6ec..9dc1b45cc7f 100644 --- a/tests/tests/permission4/AppThatAccessesCameraAndMic/Android.bp +++ b/tests/tests/permission4/AppThatAccessesCameraAndMic/Android.bp @@ -25,6 +25,7 @@ android_test_helper_app { // Tag this module as a cts test artifact test_suites: [ "cts", + "sts", "vts10", "general-tests", ], @@ -36,6 +37,6 @@ android_test_helper_app { ], srcs: [ - "src/**/*.kt" + "src/**/*.kt", ], } diff --git a/tests/tests/permission4/AppThatAccessesCameraAndMic/src/android/permission4/cts/appthataccessescameraandmic/AccessCameraOrMicActivity.kt b/tests/tests/permission4/AppThatAccessesCameraAndMic/src/android/permission4/cts/appthataccessescameraandmic/AccessCameraOrMicActivity.kt index 659f2284e7a..f7a5c31149e 100644 --- a/tests/tests/permission4/AppThatAccessesCameraAndMic/src/android/permission4/cts/appthataccessescameraandmic/AccessCameraOrMicActivity.kt +++ b/tests/tests/permission4/AppThatAccessesCameraAndMic/src/android/permission4/cts/appthataccessescameraandmic/AccessCameraOrMicActivity.kt @@ -42,6 +42,7 @@ import kotlinx.coroutines.launch private const val USE_CAMERA = "use_camera" private const val USE_MICROPHONE = "use_microphone" private const val USE_HOTWORD = "use_hotword" +private const val FINISH_EARLY = "finish_early" private const val USE_DURATION_MS = 10000L private const val SAMPLE_RATE_HZ = 44100 @@ -62,12 +63,14 @@ class AccessCameraOrMicActivity : Activity() { private var runMic = false private var hotwordFinished = false private var runHotword = false + private var finishEarly = false override fun onStart() { super.onStart() runCamera = intent.getBooleanExtra(USE_CAMERA, false) runMic = intent.getBooleanExtra(USE_MICROPHONE, false) runHotword = intent.getBooleanExtra(USE_HOTWORD, false) + finishEarly = intent.getBooleanExtra(FINISH_EARLY, false) if (runMic) { useMic() @@ -193,6 +196,11 @@ class AccessCameraOrMicActivity : Activity() { AudioRecord.getMinBufferSize(SAMPLE_RATE_HZ, CHANNEL_IN_MONO, ENCODING_PCM_16BIT) recorder = AudioRecord(MIC, SAMPLE_RATE_HZ, CHANNEL_IN_MONO, ENCODING_PCM_16BIT, minSize) recorder?.startRecording() + if (finishEarly) { + appOpsManager = getSystemService(AppOpsManager::class.java) + appOpsManager?.finishOp(AppOpsManager.OPSTR_RECORD_AUDIO, Process.myUid(), packageName) + return + } GlobalScope.launch { delay(USE_DURATION_MS) micFinished = true diff --git a/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt b/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt index 47faaa65c46..08a611e2843 100644 --- a/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt +++ b/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt @@ -28,6 +28,7 @@ import android.os.Build import android.os.Process import android.os.SystemClock import android.permission.PermissionManager +import android.platform.test.annotations.AsbSecurityTest import android.provider.DeviceConfig import android.provider.Settings import android.safetycenter.SafetyCenterManager @@ -66,6 +67,7 @@ private const val SHELL_PKG = "com.android.shell" private const val USE_CAMERA = "use_camera" private const val USE_MICROPHONE = "use_microphone" private const val USE_HOTWORD = "use_hotword" +private const val FINISH_EARLY = "finish_early" private const val INTENT_ACTION = "test.action.USE_CAMERA_OR_MIC" private const val PRIVACY_CHIP_ID = "com.android.systemui:id/privacy_chip" private const val CAR_MIC_PRIVACY_CHIP_ID = "com.android.systemui:id/mic_privacy_chip" @@ -175,11 +177,17 @@ class CameraMicIndicatorsPermissionTest { Thread.sleep(DELAY_MILLIS) } - private fun openApp(useMic: Boolean, useCamera: Boolean, useHotword: Boolean) { + private fun openApp( + useMic: Boolean, + useCamera: Boolean, + useHotword: Boolean, + finishEarly: Boolean = false + ) { context.startActivity(Intent(INTENT_ACTION).apply { putExtra(USE_CAMERA, useCamera) putExtra(USE_MICROPHONE, useMic) putExtra(USE_HOTWORD, useHotword) + putExtra(FINISH_EARLY, finishEarly) addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) }) } @@ -199,6 +207,13 @@ class CameraMicIndicatorsPermissionTest { } @Test + @AsbSecurityTest(cveBugId = [242537498]) + fun testMicIndicatorWithManualFinishOpStillShows() { + changeSafetyCenterFlag(false.toString()) + testCameraAndMicIndicator(useMic = true, useCamera = false, finishEarly = true) + } + + @Test fun testHotwordIndicatorBehavior() { changeSafetyCenterFlag(false.toString()) testCameraAndMicIndicator(useMic = false, useCamera = false, useHotword = true) @@ -272,10 +287,11 @@ class CameraMicIndicatorsPermissionTest { useCamera: Boolean, useHotword: Boolean = false, chainUsage: Boolean = false, - safetyCenterEnabled: Boolean = false + safetyCenterEnabled: Boolean = false, + finishEarly: Boolean = false ) { var chainAttribution: AttributionSource? = null - openApp(useMic, useCamera, useHotword) + openApp(useMic, useCamera, useHotword, finishEarly) try { eventually { val appView = uiDevice.findObject(UiSelector().textContains(APP_LABEL)) @@ -290,20 +306,23 @@ class CameraMicIndicatorsPermissionTest { } } - if (isTv) { - assertTvIndicatorsShown(useMic, useCamera, useHotword) - } else if (isCar) { - assertCarIndicatorsShown(useMic, useCamera, useHotword, chainUsage) - } else { - // Hotword gets remapped to RECORD_AUDIO on handheld, so handheld should show a mic - // indicator + if (!isTv && !isCar) { uiDevice.openQuickSettings() - assertPrivacyChipAndIndicatorsPresent( - useMic, - useCamera, - chainUsage, - safetyCenterEnabled - ) + } + assertIndicatorsShown(useMic, useCamera, useHotword, chainUsage, + safetyCenterEnabled) + + if (finishEarly) { + // Assert that the indicator doesn't go away + val indicatorGoneException: Exception? = try { + eventually { + assertIndicatorsShown(false, false, false) + } + null + } catch (e: Exception) { + e + } + assertNotNull("Expected the indicator to be present", indicatorGoneException) } } finally { if (chainAttribution != null) { @@ -313,8 +332,25 @@ class CameraMicIndicatorsPermissionTest { } } + private fun assertIndicatorsShown( + useMic: Boolean, + useCamera: Boolean, + useHotword: Boolean = false, + chainUsage: Boolean = false, + safetyCenterEnabled: Boolean = false, + ) { + if (isTv) { + assertTvIndicatorsShown(useMic, useCamera, useHotword) + } else if (isCar) { + assertCarIndicatorsShown(useMic, useCamera, useHotword, chainUsage) + } else { + assertPrivacyChipAndIndicatorsPresent(useMic, useCamera, chainUsage, + safetyCenterEnabled) + } + } + private fun assertTvIndicatorsShown(useMic: Boolean, useCamera: Boolean, useHotword: Boolean) { - if (useMic || useHotword) { + if (useMic || useHotword || (!useMic && !useCamera && !useHotword)) { val found = WindowManagerStateHelper() .waitFor("Waiting for the mic indicator window to come up") { it.containsWindow(TV_MIC_INDICATOR_WINDOW_TITLE) && @@ -349,7 +385,7 @@ class CameraMicIndicatorsPermissionTest { assertNotNull("Did not find camera chip", cameraPrivacyChip) // Click to chip to show the panel. cameraPrivacyChip.click() - } else if (useHotword) { + } else { assertNull("Found mic chip, but did not expect to", micPrivacyChip) assertNull("Found camera chip, but did not expect to", cameraPrivacyChip) } @@ -361,18 +397,7 @@ class CameraMicIndicatorsPermissionTest { assertChainMicAndOtherCameraUsed(false) return@eventually } - if (useHotword) { - // There should be no privacy panel when using hot word - val micLabelView = uiDevice.findObject(UiSelector().textContains(micLabel)) - assertFalse("View with text $micLabel found, but did not expect to", - micLabelView.exists()) - val cameraLabelView = uiDevice.findObject(UiSelector().textContains(cameraLabel)) - assertFalse("View with text $cameraLabel found, but did not expect to", - cameraLabelView.exists()) - val appView = uiDevice.findObject(UiSelector().textContains(APP_LABEL)) - assertFalse("View with text $APP_LABEL found, but did not expect to", - appView.exists()) - } else if (useMic) { + if (useMic) { // There should be a mic privacy panel after mic privacy chip is clicked val micLabelView = uiDevice.findObject(UiSelector().textContains(micLabel)) assertTrue("View with text $micLabel not found", micLabelView.exists()) @@ -384,6 +409,17 @@ class CameraMicIndicatorsPermissionTest { assertTrue("View with text $cameraLabel not found", cameraLabelView.exists()) val appView = uiDevice.findObject(UiSelector().textContains(APP_LABEL)) assertTrue("View with text $APP_LABEL not found", appView.exists()) + } else { + // There should be no privacy panel when using hot word + val micLabelView = uiDevice.findObject(UiSelector().textContains(micLabel)) + assertFalse("View with text $micLabel found, but did not expect to", + micLabelView.exists()) + val cameraLabelView = uiDevice.findObject(UiSelector().textContains(cameraLabel)) + assertFalse("View with text $cameraLabel found, but did not expect to", + cameraLabelView.exists()) + val appView = uiDevice.findObject(UiSelector().textContains(APP_LABEL)) + assertFalse("View with text $APP_LABEL found, but did not expect to", + appView.exists()) } } } @@ -395,7 +431,7 @@ class CameraMicIndicatorsPermissionTest { safetyCenterEnabled: Boolean = false ) { // Ensure the privacy chip is present (or not) - val chipFound = isChipPresent() + val chipFound = isChipPresent(useMic || useCamera) if (useMic || useCamera) { assertTrue("Did not find chip", chipFound) } else { // hotword @@ -437,6 +473,7 @@ class CameraMicIndicatorsPermissionTest { uiDevice.findObjects(By.res(SAFETY_CENTER_ITEM_ID)).size > 0) } } + uiDevice.pressBack() } private fun createChainAttribution(): AttributionSource? { @@ -480,13 +517,15 @@ class CameraMicIndicatorsPermissionTest { } } - private fun isChipPresent(): Boolean { + private fun isChipPresent(clickChip: Boolean): Boolean { var chipFound = false try { eventually { val privacyChip = uiDevice.findObject(By.res(PRIVACY_CHIP_ID)) assertNotNull("view with id $PRIVACY_CHIP_ID not found", privacyChip) - privacyChip.click() + if (clickChip) { + privacyChip.click() + } chipFound = true } } catch (e: Exception) { diff --git a/tests/tests/security/src/android/security/cts/CVE_2022_20456.java b/tests/tests/security/src/android/security/cts/CVE_2022_20456.java new file mode 100644 index 00000000000..26434336a3e --- /dev/null +++ b/tests/tests/security/src/android/security/cts/CVE_2022_20456.java @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.cts; + +import static android.app.NotificationManager.INTERRUPTION_FILTER_UNKNOWN; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeNoException; + +import android.app.AutomaticZenRule; +import android.content.ComponentName; +import android.net.Uri; +import android.os.Parcel; +import android.platform.test.annotations.AsbSecurityTest; + +import androidx.test.runner.AndroidJUnit4; + +import com.android.sts.common.util.StsExtraBusinessLogicTestCase; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + + +// This CTS test has been created taking reference from the tests present in +// frameworks/base/core/tests/coretests/src/android/app/AutomaticZenRuleTest.java +@RunWith(AndroidJUnit4.class) +public class CVE_2022_20456 extends StsExtraBusinessLogicTestCase { + private static final int INPUT_STRING_LENGTH = 2000; // 2 * 'MAX_STRING_LENGTH' + private static final String CLASS_NAME = "className"; + private static final String PACKAGE_NAME = "packageName"; + private static final String URI_STRING = "condition://android"; + private static final String ZEN_RULE_NAME = "ZenRuleName"; + private ComponentName mComponentNameWithLongFields; + private ComponentName mValidComponentName; + private String mLongString; + private Uri mLongUri; + private Uri mValidUri; + private List<String> mViolations; + + private void checkFields(AutomaticZenRule rule, boolean ownerFlag, boolean configActivityFlag, + String tag) { + // Check all fields + if (INPUT_STRING_LENGTH <= rule.getName().length()) { + mViolations.add(tag + "input string length <= rule name length"); + } + if (mLongUri.toString().length() <= rule.getConditionId().toString().length()) { + mViolations.add(tag + "input uri length <= rule conditionId length"); + } + if (ownerFlag) { + if (INPUT_STRING_LENGTH <= rule.getOwner().getPackageName().length()) { + mViolations.add(tag + "input string length <= rule owner package name length"); + } + if (INPUT_STRING_LENGTH <= rule.getOwner().getClassName().length()) { + mViolations.add(tag + "input string length <= rule owner class name length"); + } + } + if (configActivityFlag) { + if (INPUT_STRING_LENGTH <= rule.getConfigurationActivity().getPackageName().length()) { + mViolations.add(tag + + "input string length <= rule configurationActivity package name length"); + } + if (INPUT_STRING_LENGTH <= rule.getConfigurationActivity().getClassName().length()) { + mViolations.add(tag + + "input string length <= rule configurationActivity class name length"); + } + } + } + + private void checkConstructor(boolean ownerFlag, boolean configActivityFlag) { + ComponentName owner = ownerFlag ? mComponentNameWithLongFields : null; + ComponentName configActivity = configActivityFlag ? mComponentNameWithLongFields : null; + AutomaticZenRule rule = new AutomaticZenRule(mLongString, owner, configActivity, mLongUri, + null, INTERRUPTION_FILTER_UNKNOWN, /* enabled */ true); + checkFields(rule, ownerFlag, configActivityFlag, "\ncheckConstructor (owner=" + ownerFlag + + ", configActivity=" + configActivityFlag + "): "); + } + + private void testIsConstructorVulnerable() { + // Check all three variants i.e. with owner, with configuration activity and with both + // owner and configuration activity. Although third case is mostly redundant, adding it to + // complete checks on all possible variants. + checkConstructor(/* ownerFlag */ true, /* configActivityFlag */ false); + checkConstructor(/* ownerFlag */ false, /* configActivityFlag */ true); + checkConstructor(/* ownerFlag */ true, /* configActivityFlag */ true); + } + + private void checkFieldSetters(boolean ownerFlag, boolean configActivityFlag) { + ComponentName owner = ownerFlag ? mValidComponentName : null; + ComponentName configActivity = configActivityFlag ? mValidComponentName : null; + AutomaticZenRule rule = new AutomaticZenRule(ZEN_RULE_NAME, owner, configActivity, + mValidUri, null, INTERRUPTION_FILTER_UNKNOWN, /* enabled */ true); + + // Check all fields that can be set via setter methods of AutomaticZenRule class + rule.setName(mLongString); + rule.setConditionId(mLongUri); + rule.setConfigurationActivity(mComponentNameWithLongFields); + checkFields(rule, /* ownerFlag */ false, /* configActivityFlag */ true, + "\ncheckFieldSetters (owner=" + ownerFlag + ", configActivity=" + configActivityFlag + + "): "); + } + + private void testIsFieldSetterVulnerable() { + checkFieldSetters(/* ownerFlag */ true, /* configActivityFlag */ false); + checkFieldSetters(/* ownerFlag */ false, /* configActivityFlag */ true); + checkFieldSetters(/* ownerFlag */ true, /* configActivityFlag */ true); + } + + private void checkParcelInput(boolean ownerFlag, boolean configActivityFlag) + throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException { + ComponentName owner = ownerFlag ? mValidComponentName : null; + ComponentName configActivity = configActivityFlag ? mValidComponentName : null; + AutomaticZenRule rule = new AutomaticZenRule(ZEN_RULE_NAME, owner, configActivity, + mValidUri, null, INTERRUPTION_FILTER_UNKNOWN, /* enabled */ true); + + // Create rules with long fields set directly via reflection so that we can confirm that a + // rule with too-long fields that comes in via a parcel has its fields truncated directly. + Class automaticZenRuleClass = Class.forName("android.app.AutomaticZenRule"); + Field fieldName = automaticZenRuleClass.getDeclaredField("name"); + fieldName.setAccessible(/* flag */ true); + fieldName.set(rule, mLongString); + Field fieldConditionId = automaticZenRuleClass.getDeclaredField("conditionId"); + fieldConditionId.setAccessible(/* flag */ true); + fieldConditionId.set(rule, mLongUri); + if (ownerFlag) { + Field fieldOwner = automaticZenRuleClass.getDeclaredField("owner"); + fieldOwner.setAccessible(/* flag */ true); + fieldOwner.set(rule, mComponentNameWithLongFields); + } + if (configActivityFlag) { + Field fieldConfigActivity = + automaticZenRuleClass.getDeclaredField("configurationActivity"); + fieldConfigActivity.setAccessible(/* flag */ true); + fieldConfigActivity.set(rule, mComponentNameWithLongFields); + } + + // Write AutomaticZenRule object to parcel + Parcel parcel = Parcel.obtain(); + rule.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + + // Instantiate AutomaticZenRule object using parcel + AutomaticZenRule ruleFromParcel = new AutomaticZenRule(parcel); + + checkFields(ruleFromParcel, ownerFlag, configActivityFlag, "\ncheckParcelInput (owner=" + + ownerFlag + ", configActivity=" + configActivityFlag + "): "); + } + + private void testIsInputFromParcelVulnerable() + throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException { + checkParcelInput(/* ownerFlag */ true, /* configActivityFlag */ false); + checkParcelInput(/* ownerFlag */ false, /* configActivityFlag */ true); + checkParcelInput(/* ownerFlag */ true, /* configActivityFlag */ true); + } + + // b/242703460, b/242703505, b/242703780, b/242704043, b/243794204 + // Vulnerable library : framework.jar + // Vulnerable module : Not applicable + // Is Play managed : No + @AsbSecurityTest(cveBugId = {242703460, 242703505, 242703780, 242704043, 243794204}) + @Test + public void testPocCVE_2022_20456() { + try { + mLongString = String.join("", Collections.nCopies(INPUT_STRING_LENGTH, "A")); + mComponentNameWithLongFields = new ComponentName(mLongString, mLongString); + mValidComponentName = new ComponentName(PACKAGE_NAME, CLASS_NAME); + mLongUri = Uri.parse("condition://" + mLongString); + mValidUri = Uri.parse(URI_STRING); + mViolations = new ArrayList<String>(); + + // Check AutomaticZenRule constructor + testIsConstructorVulnerable(); + + // Check AutomaticZenRule field setters + testIsFieldSetterVulnerable(); + + // Check AutomaticZenRule constructor using parcel input + testIsInputFromParcelVulnerable(); + + assertTrue("Device is vulnerable to at least one of the following vulnerabilities : " + + "b/242703460(CVE-2022-20489), b/242703505(CVE-2022-20490), b/242703780" + + "(CVE-2022-20456), b/242704043(CVE-2022-20492), b/243794204(CVE-2022-20494)" + + " due to these violations where input string length=" + INPUT_STRING_LENGTH + + " and input uri length=" + mLongUri.toString().length() + ":" + mViolations, + mViolations.isEmpty()); + } catch (Exception e) { + assumeNoException(e); + } + } +} |