blob: af1f9782ab02b1bbc19fd131b7aa490a3e713334 [file] [log] [blame]
/*
* 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.CVE_2022_20353;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static org.junit.Assert.assertFalse;
import static org.junit.Assume.assumeNoException;
import static org.junit.Assume.assumeTrue;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.res.Resources;
import android.provider.Settings;
import androidx.test.runner.AndroidJUnit4;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.BySelector;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiScrollable;
import androidx.test.uiautomator.UiSelector;
import androidx.test.uiautomator.Until;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
@RunWith(AndroidJUnit4.class)
public class DeviceTest {
Resources mResources;
UiDevice mDevice;
Context mContext;
// Wait for UiObject to appear and click on the UiObject if it is visible
private boolean clickUiObject(BySelector selector) {
boolean objectFound =
mDevice.wait(Until.hasObject(selector), mResources.getInteger(R.integer.timeoutMs));
if (objectFound) {
mDevice.findObject(selector).click();
}
return objectFound;
}
@Test
public void testDefaultRingtonePreference() {
String defaultRingtone = null;
try {
mDevice = UiDevice.getInstance(getInstrumentation());
mContext = getInstrumentation().getContext();
mResources = mContext.getResources();
defaultRingtone =
mDevice.executeShellCommand(mContext.getString(R.string.getRingtoneCmd));
Intent intent = new Intent(Settings.ACTION_SOUND_SETTINGS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
String settingsPackageName =
intent.resolveActivity(mContext.getPackageManager()).getPackageName();
Context settingsContext = mContext.createPackageContext(settingsPackageName,
Context.CONTEXT_IGNORE_SECURITY);
Resources res = settingsContext.getPackageManager()
.getResourcesForApplication(settingsPackageName);
String text = settingsContext
.getString(res.getIdentifier(mContext.getString(R.string.textResId),
mContext.getString(R.string.resType), settingsPackageName));
// scroll until text 'Phone ringtone' is visible
UiScrollable uiScrollable = new UiScrollable(new UiSelector().scrollable(true));
uiScrollable.scrollTextIntoView(text);
// click on 'Phone ringtone'
BySelector selector = By.text(text);
assumeTrue(mContext.getString(R.string.uiObjectNotFoundMsg, text),
clickUiObject(selector));
// select CTS PoC app
text = mContext.getString(R.string.appName);
selector = By.text(text);
assumeTrue(mContext.getString(R.string.uiObjectNotFoundMsg, text),
clickUiObject(selector));
// select 'Always'
String resId = mContext.getString(R.string.alwaysButtonId);
selector = By.res(resId);
assumeTrue(mContext.getString(R.string.uiObjectNotFoundMsg, resId),
clickUiObject(selector));
SharedPreferences sharedPrefs = mContext.getSharedPreferences(
mContext.getString(R.string.sharedPreferences), Context.MODE_APPEND);
Semaphore preferenceChanged = new Semaphore(0);
OnSharedPreferenceChangeListener sharedPrefListener =
new OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
if (key.equals(mContext.getString(R.string.resultKey))) {
preferenceChanged.release();
}
}
};
sharedPrefs.registerOnSharedPreferenceChangeListener(sharedPrefListener);
// wait for PocActivity to complete
assumeTrue(preferenceChanged.tryAcquire(mResources.getInteger(R.integer.timeoutMs),
TimeUnit.MILLISECONDS));
int result = sharedPrefs.getInt(mContext.getString(R.string.resultKey),
mResources.getInteger(R.integer.assumptionFailure));
String message = sharedPrefs.getString(mContext.getString(R.string.messageKey),
mContext.getString(R.string.defaultSemaphoreMsg));
assumeTrue(message, result != mResources.getInteger(R.integer.assumptionFailure));
String ringtoneUri = "";
boolean isVulnerable = false;
long startTime = System.currentTimeMillis();
while ((System.currentTimeMillis() - startTime) < mResources
.getInteger(R.integer.timeoutMs)) {
ringtoneUri =
mDevice.executeShellCommand(mContext.getString(R.string.getRingtoneCmd));
if (ringtoneUri.contains(mContext.getString(R.string.fileName))) {
isVulnerable = true;
break;
}
}
assertFalse(mContext.getString(R.string.failureMessage), isVulnerable);
} catch (Exception e) {
assumeNoException(e);
} finally {
try {
// reset ringtone to default (other than 'null') present before test
mDevice.executeShellCommand(
mContext.getString(R.string.setRingtoneCmd) + " " + defaultRingtone);
mDevice.pressHome();
} catch (Exception e) {
// ignore exception here
}
}
}
}