Merge "Test for improper kernel fusion." into klp-dev
diff --git a/hostsidetests/appsecurity/test-apps/AppAccessData/src/com/android/cts/appaccessdata/AccessPrivateDataTest.java b/hostsidetests/appsecurity/test-apps/AppAccessData/src/com/android/cts/appaccessdata/AccessPrivateDataTest.java
index 8a44dfa..40d3cff 100644
--- a/hostsidetests/appsecurity/test-apps/AppAccessData/src/com/android/cts/appaccessdata/AccessPrivateDataTest.java
+++ b/hostsidetests/appsecurity/test-apps/AppAccessData/src/com/android/cts/appaccessdata/AccessPrivateDataTest.java
@@ -16,21 +16,24 @@
package com.android.cts.appaccessdata;
+import java.io.BufferedReader;
+import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import java.io.FileReader;
import java.io.IOException;
import android.test.AndroidTestCase;
/**
- * Test that another app's private data cannot be accessed.
+ * Test that another app's private data cannot be accessed, while its public data can.
*
- * Assumes that {@link APP_WITH_DATA_PKG} has already created the private data.
+ * Assumes that {@link APP_WITH_DATA_PKG} has already created the private and public data.
*/
public class AccessPrivateDataTest extends AndroidTestCase {
/**
- * The Android package name of the application that owns the private data
+ * The Android package name of the application that owns the data
*/
private static final String APP_WITH_DATA_PKG = "com.android.cts.appwithdata";
@@ -39,9 +42,15 @@
* {@link APP_WITH_DATA_PKG}.
*/
private static final String PRIVATE_FILE_NAME = "private_file.txt";
+ /**
+ * Name of public file to access. This must match the name of the file created by
+ * {@link APP_WITH_DATA_PKG}.
+ */
+ private static final String PUBLIC_FILE_NAME = "public_file.txt";
/**
- * Tests that another app's private file cannot be accessed
+ * Tests that another app's private data cannot be accessed. It includes file
+ * and detailed traffic stats.
* @throws IOException
*/
public void testAccessPrivateData() throws IOException {
@@ -58,5 +67,60 @@
} catch (SecurityException e) {
// also valid
}
+ accessPrivateTrafficStats();
+ }
+
+ /**
+ * Tests that another app's public file can be accessed
+ * @throws IOException
+ */
+ public void testAccessPublicData() throws IOException {
+ try {
+ getOtherAppUid();
+ } catch (FileNotFoundException e) {
+ fail("Was not able to access another app's public file: " + e);
+ } catch (SecurityException e) {
+ fail("Was not able to access another app's public file: " + e);
+ }
+ }
+
+ private int getOtherAppUid() throws IOException, FileNotFoundException, SecurityException {
+ // construct the absolute file path to the other app's public file
+ String publicFilePath = String.format("/data/data/%s/files/%s", APP_WITH_DATA_PKG,
+ PUBLIC_FILE_NAME);
+ DataInputStream inputStream = new DataInputStream(new FileInputStream(publicFilePath));
+ int otherAppUid = (int)inputStream.readInt();
+ inputStream.close();
+ return otherAppUid;
+ }
+
+ private void accessPrivateTrafficStats() throws IOException {
+ int otherAppUid = -1;
+ try {
+ otherAppUid = getOtherAppUid();
+ } catch (FileNotFoundException e) {
+ fail("Was not able to access another app's public file: " + e);
+ } catch (SecurityException e) {
+ fail("Was not able to access another app's public file: " + e);
+ }
+
+ boolean foundOtherStats = false;
+ try {
+ BufferedReader qtaguidReader = new BufferedReader(new FileReader("/proc/net/xt_qtaguid/stats"));
+ String line;
+ while ((line = qtaguidReader.readLine()) != null) {
+ String tokens[] = line.split(" ");
+ if (tokens.length > 3 && tokens[3].equals(String.valueOf(otherAppUid))) {
+ foundOtherStats = true;
+ if (!tokens[2].equals("0x0")) {
+ fail("Other apps detailed traffic stats leaked");
+ }
+ }
+ }
+ qtaguidReader.close();
+ } catch (FileNotFoundException e) {
+ fail("Was not able to access qtaguid/stats: " + e);
+ }
+ assertTrue("Was expecting to find other apps' traffic stats", foundOtherStats);
}
}
diff --git a/hostsidetests/appsecurity/test-apps/AppWithData/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/AppWithData/AndroidManifest.xml
index 4b10030..9decbcd 100644
--- a/hostsidetests/appsecurity/test-apps/AppWithData/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/AppWithData/AndroidManifest.xml
@@ -22,6 +22,7 @@
access.
-->
+ <uses-permission android:name="android.permission.INTERNET" />
<application>
<uses-library android:name="android.test.runner" />
</application>
diff --git a/hostsidetests/appsecurity/test-apps/AppWithData/src/com/android/cts/appwithdata/CreatePrivateDataTest.java b/hostsidetests/appsecurity/test-apps/AppWithData/src/com/android/cts/appwithdata/CreatePrivateDataTest.java
index 1de6464..e11681a 100644
--- a/hostsidetests/appsecurity/test-apps/AppWithData/src/com/android/cts/appwithdata/CreatePrivateDataTest.java
+++ b/hostsidetests/appsecurity/test-apps/AppWithData/src/com/android/cts/appwithdata/CreatePrivateDataTest.java
@@ -22,10 +22,23 @@
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
+import android.net.TrafficStats;
import android.test.AndroidTestCase;
+import android.util.Log;
+import java.net.ServerSocket;
+import java.net.Socket;
+
+import java.io.BufferedReader;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.FileOutputStream;
+import java.io.FileReader;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
/**
* Test that will create private app data.
@@ -36,9 +49,15 @@
public class CreatePrivateDataTest extends AndroidTestCase {
/**
+ * The Android package name of the application that owns the private data
+ */
+ private static final String APP_WITH_DATA_PKG = "com.android.cts.appwithdata";
+
+ /**
* Name of private file to create.
*/
private static final String PRIVATE_FILE_NAME = "private_file.txt";
+ private static final String PUBLIC_FILE_NAME = "public_file.txt";
private static final String PREFERENCES_FILE_NAME = "preferences";
private static final String PREFERENCE_KEY = "preference_key";
@@ -49,7 +68,8 @@
static final String DB_VALUE = "test_value";
/**
- * Creates a file private to this app
+ * Creates the private data for this app, which includes
+ * file, database entries, and traffic stats.
* @throws IOException if any error occurred when creating the file
*/
public void testCreatePrivateData() throws IOException {
@@ -59,8 +79,34 @@
outputStream.close();
assertTrue(getContext().getFileStreamPath(PRIVATE_FILE_NAME).exists());
+ outputStream = getContext().openFileOutput(PUBLIC_FILE_NAME,
+ Context.MODE_WORLD_READABLE);
+ DataOutputStream dataOut = new DataOutputStream(outputStream);
+ dataOut.writeInt(getContext().getApplicationInfo().uid);
+ dataOut.close();
+ outputStream.close();
+ // Ensure that some file will be accessible via the same path that will be used by other app.
+ accessPublicData();
+
writeToPreferences();
writeToDatabase();
+ createTrafficStatsWithTags();
+ }
+
+ private void accessPublicData() throws IOException {
+ try {
+ // construct the absolute file path to the app's public's file the same
+ // way as the appaccessdata package will.
+ String publicFilePath = String.format("/data/data/%s/files/%s", APP_WITH_DATA_PKG,
+ PUBLIC_FILE_NAME);
+ DataInputStream inputStream = new DataInputStream(new FileInputStream(publicFilePath));
+ int otherAppUid = (int)inputStream.readInt();
+ inputStream.close();
+ } catch (FileNotFoundException e) {
+ fail("Was not able to access own public file: " + e);
+ } catch (SecurityException e) {
+ fail("Was not able to access own public file: " + e);
+ }
}
private void writeToPreferences() {
@@ -127,6 +173,76 @@
}
}
+ private void accessOwnTrafficStats() throws IOException {
+ final int ownAppUid = getContext().getApplicationInfo().uid;
+
+ boolean foundOwnDetailedStats = false;
+ try {
+ BufferedReader qtaguidReader = new BufferedReader(new FileReader("/proc/net/xt_qtaguid/stats"));
+ String line;
+ while ((line = qtaguidReader.readLine()) != null) {
+ String tokens[] = line.split(" ");
+ if (tokens.length > 3 && tokens[3].equals(String.valueOf(ownAppUid))) {
+ if (!tokens[2].equals("0x0")) {
+ foundOwnDetailedStats = true;
+ }
+ }
+ }
+ qtaguidReader.close();
+ } catch (FileNotFoundException e) {
+ fail("Was not able to access qtaguid/stats: " + e);
+ }
+ assertTrue("Was expecting to find own traffic stats", foundOwnDetailedStats);
+ }
+
+ private void createTrafficStatsWithTags() throws IOException {
+
+ // Transfer 1MB of data across an explicitly localhost socket.
+ final int byteCount = 1024;
+ final int packetCount = 1024;
+
+ final ServerSocket server = new ServerSocket(0);
+ new Thread("CreatePrivateDataTest.createTrafficStatsWithTags") {
+ @Override
+ public void run() {
+ try {
+ Socket socket = new Socket("localhost", server.getLocalPort());
+ // Make sure that each write()+flush() turns into a packet:
+ // disable Nagle.
+ socket.setTcpNoDelay(true);
+ OutputStream out = socket.getOutputStream();
+ byte[] buf = new byte[byteCount];
+ for (int i = 0; i < packetCount; i++) {
+ TrafficStats.setThreadStatsTag(i % 10);
+ TrafficStats.tagSocket(socket);
+ out.write(buf);
+ out.flush();
+ }
+ out.close();
+ socket.close();
+ } catch (IOException e) {
+ assertTrue("io exception" + e, false);
+ }
+ }
+ }.start();
+
+ try {
+ Socket socket = server.accept();
+ InputStream in = socket.getInputStream();
+ byte[] buf = new byte[byteCount];
+ int read = 0;
+ while (read < byteCount * packetCount) {
+ int n = in.read(buf);
+ assertTrue("Unexpected EOF", n > 0);
+ read += n;
+ }
+ } finally {
+ server.close();
+ }
+
+ accessOwnTrafficStats();
+ }
+
static class TestDatabaseOpenHelper extends SQLiteOpenHelper {
static final String _ID = "_id";
diff --git a/tests/tests/graphics/src/android/graphics/cts/BitmapRegionDecoderTest.java b/tests/tests/graphics/src/android/graphics/cts/BitmapRegionDecoderTest.java
index d51fc72..c981db3 100644
--- a/tests/tests/graphics/src/android/graphics/cts/BitmapRegionDecoderTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/BitmapRegionDecoderTest.java
@@ -186,6 +186,36 @@
}
}
+ public void testDecodeRegionInputStreamInBitmap() throws IOException {
+ Options opts = new BitmapFactory.Options();
+ for (int i = 0; i < NUM_TEST_IMAGES; ++i) {
+ for (int j = 0; j < SAMPLESIZES.length; ++j) {
+ for (int k = 0; k < COLOR_CONFIGS.length; ++k) {
+ opts.inSampleSize = SAMPLESIZES[j];
+ opts.inPreferredConfig = COLOR_CONFIGS[k];
+ opts.inBitmap = null;
+
+ InputStream is1 = obtainInputStream(RES_IDS[i]);
+ BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is1, false);
+ InputStream is2 = obtainInputStream(RES_IDS[i]);
+ Bitmap wholeImage = BitmapFactory.decodeStream(is2, null, opts);
+
+ // setting inBitmap enables several checks within compareRegionByRegion
+ opts.inBitmap = Bitmap.createBitmap(
+ wholeImage.getWidth(), wholeImage.getHeight(), opts.inPreferredConfig);
+
+ if (RES_IDS[i] == R.drawable.webp_test && COLOR_CONFIGS[k] == Config.RGB_565) {
+ compareRegionByRegion(decoder, opts, mMseMarginWebPConfigRgb565,
+ wholeImage);
+ } else {
+ compareRegionByRegion(decoder, opts, mMseMargin, wholeImage);
+ }
+ wholeImage.recycle();
+ }
+ }
+ }
+ }
+
public void testDecodeRegionByteArray() throws IOException {
Options opts = new BitmapFactory.Options();
for (int i = 0; i < NUM_TEST_IMAGES; ++i) {
@@ -292,9 +322,18 @@
actual = decoder.decodeRegion(rect1, opts);
int left = rect1.left / opts.inSampleSize;
int top = rect1.top / opts.inSampleSize;
- Rect rect2 = new Rect(left, top, left + actual.getWidth(),
+ if (opts.inBitmap != null) {
+ // bitmap reuse path - ensure reuse worked
+ assertSame(opts.inBitmap, actual);
+ int currentWidth = rect1.width() / opts.inSampleSize;
+ int currentHeight = rect1.height() / opts.inSampleSize;
+ Rect actualRect = new Rect(0, 0, currentWidth, currentHeight);
+ // crop 'actual' to the size to be tested (and avoid recycling inBitmap)
+ actual = cropBitmap(actual, actualRect);
+ }
+ Rect expectedRect = new Rect(left, top, left + actual.getWidth(),
top + actual.getHeight());
- expected = cropBitmap(wholeImage, rect2);
+ expected = cropBitmap(wholeImage, expectedRect);
compareBitmaps(expected, actual, mseMargin, true);
actual.recycle();
expected.recycle();
diff --git a/tests/tests/media/src/android/media/cts/MediaMuxerTest.java b/tests/tests/media/src/android/media/cts/MediaMuxerTest.java
index 42ae7a7..9cad011 100644
--- a/tests/tests/media/src/android/media/cts/MediaMuxerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaMuxerTest.java
@@ -38,6 +38,11 @@
private static final String TAG = "MediaMuxerTest";
private static final boolean VERBOSE = false;
private static final int MAX_SAMPLE_SIZE = 256 * 1024;
+ private static final float LATITUDE = 0.0000f;
+ private static final float LONGITUDE = -180.0f;
+ private static final float BAD_LATITUDE = 91.0f;
+ private static final float BAD_LONGITUDE = -181.0f;
+ private static final float TOLERANCE = 0.0002f;
private Resources mResources;
@Override
@@ -189,6 +194,25 @@
if (degrees >= 0) {
muxer.setOrientationHint(degrees);
}
+
+ // Test setLocation out of bound cases
+ try {
+ muxer.setLocation(BAD_LATITUDE, LONGITUDE);
+ fail("setLocation succeeded with bad argument: [" + BAD_LATITUDE + "," + LONGITUDE
+ + "]");
+ } catch (IllegalArgumentException e) {
+ // Expected
+ }
+ try {
+ muxer.setLocation(LATITUDE, BAD_LONGITUDE);
+ fail("setLocation succeeded with bad argument: [" + LATITUDE + "," + BAD_LONGITUDE
+ + "]");
+ } catch (IllegalArgumentException e) {
+ // Expected
+ }
+
+ muxer.setLocation(LATITUDE, LONGITUDE);
+
muxer.start();
while (!sawEOS) {
bufferInfo.offset = offset;
@@ -235,6 +259,7 @@
try {
cloneMediaUsingMuxer(srcMedia, outputMediaFile, expectedTrackCount, degrees);
verifyAttributesMatch(srcMedia, outputMediaFile, degrees);
+ verifyLocationInFile(outputMediaFile);
// Check the sample on 1s and 0.5s.
verifySamplesMatch(srcMedia, outputMediaFile, 1000000);
verifySamplesMatch(srcMedia, outputMediaFile, 500000);
@@ -337,5 +362,32 @@
fail("byteBuffer didn't match");
}
}
+
+ private void verifyLocationInFile(String fileName) {
+ MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+ retriever.setDataSource(fileName);
+ String location = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_LOCATION);
+ assertNotNull("No location information found in file " + fileName, location);
+
+ // parsing String location and recover the location inforamtion in floats
+ // Make sure the tolerance is very small - due to rounding errors.
+
+ // Get the position of the -/+ sign in location String, which indicates
+ // the beginning of the longtitude.
+ int index = location.lastIndexOf('-');
+ if (index == -1) {
+ index = location.lastIndexOf('+');
+ }
+ assertTrue("+ or - is not found", index != -1);
+ assertTrue("+ or - is only found at the beginning", index != 0);
+ float latitude = Float.parseFloat(location.substring(0, index - 1));
+ float longitude = Float.parseFloat(location.substring(index));
+ assertTrue("Incorrect latitude: " + latitude,
+ Math.abs(latitude - LATITUDE) <= TOLERANCE);
+ assertTrue("Incorrect longitude: " + longitude,
+ Math.abs(longitude - LONGITUDE) <= TOLERANCE);
+ retriever.release();
+ }
+
}
diff --git a/tests/tests/media/src/android/media/cts/RingtoneManagerTest.java b/tests/tests/media/src/android/media/cts/RingtoneManagerTest.java
index ce3a9c4..dfaabb8 100644
--- a/tests/tests/media/src/android/media/cts/RingtoneManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/RingtoneManagerTest.java
@@ -83,11 +83,6 @@
Cursor c = mRingtoneManager.getCursor();
assertTrue("Must have at least one ring tone available", c.getCount() > 0);
- mRingtoneManager.setIncludeDrm(true);
- assertTrue(mRingtoneManager.getIncludeDrm());
- mRingtoneManager.setIncludeDrm(false);
- assertFalse(mRingtoneManager.getIncludeDrm());
-
assertNotNull(mRingtoneManager.getRingtone(0));
assertNotNull(RingtoneManager.getRingtone(mContext, Settings.System.DEFAULT_RINGTONE_URI));
int expectedPosition = 0;
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
index 3353d50..efd3aef 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
@@ -192,11 +192,19 @@
public void testOnScaleChanged() throws Throwable {
final MockWebViewClient webViewClient = new MockWebViewClient();
mOnUiThread.setWebViewClient(webViewClient);
+ mWebServer = new CtsTestServer(getActivity());
assertFalse(webViewClient.hasOnScaleChangedCalled());
+ String url1 = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
+ mOnUiThread.loadUrlAndWaitForCompletion(url1);
+
mOnUiThread.zoomIn();
- getInstrumentation().waitForIdleSync();
- assertTrue(webViewClient.hasOnScaleChangedCalled());
+ new PollingCheck(TEST_TIMEOUT) {
+ @Override
+ protected boolean check() {
+ return webViewClient.hasOnScaleChangedCalled();
+ }
+ }.run();
}
private void requireLoadedPage() throws Throwable {
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
index 1df71e4..827bf27 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
@@ -854,6 +854,10 @@
mOnUiThread.loadDataWithBaseURLAndWaitForCompletion("data:foo",
HTML_HEADER + "<title>Hello World%21</title></html>", "text/html", "UTF-8", null);
assertEquals("Hello World!", mOnUiThread.getTitle());
+
+ // Check the method is null input safe.
+ mOnUiThread.loadDataWithBaseURLAndWaitForCompletion(null, null, null, null, null);
+ assertEquals("about:blank", mOnUiThread.getUrl());
}
private static class WaitForFindResultsListener extends FutureTask<Integer>
@@ -1108,27 +1112,18 @@
}.run();
getInstrumentation().waitForIdleSync();
- int previousScrollX = mOnUiThread.getScrollX();
- int previousScrollY = mOnUiThread.getScrollY();
+ final int previousScrollX = mOnUiThread.getScrollX();
+ final int previousScrollY = mOnUiThread.getScrollY();
mOnUiThread.flingScroll(100, 100);
- int timeSlice = 500;
- Thread.sleep(timeSlice);
- assertTrue(mOnUiThread.getScrollX() > previousScrollX);
- assertTrue(mOnUiThread.getScrollY() > previousScrollY);
-
- previousScrollY = mOnUiThread.getScrollY();
- previousScrollX = mOnUiThread.getScrollX();
- Thread.sleep(timeSlice);
- assertTrue(mOnUiThread.getScrollX() >= previousScrollX);
- assertTrue(mOnUiThread.getScrollY() >= previousScrollY);
-
- previousScrollY = mOnUiThread.getScrollY();
- previousScrollX = mOnUiThread.getScrollX();
- Thread.sleep(timeSlice);
- assertTrue(mOnUiThread.getScrollX() >= previousScrollX);
- assertTrue(mOnUiThread.getScrollY() >= previousScrollY);
+ new PollingCheck() {
+ @Override
+ protected boolean check() {
+ return mOnUiThread.getScrollX() > previousScrollX &&
+ mOnUiThread.getScrollY() > previousScrollY;
+ }
+ }.run();
}
public void testRequestFocusNodeHref() throws Throwable {
@@ -1487,12 +1482,19 @@
final MockWebViewClient webViewClient = new MockWebViewClient();
mOnUiThread.setWebViewClient(webViewClient);
- getInstrumentation().waitForIdleSync();
+ startWebServer(false);
+
assertFalse(webViewClient.onScaleChangedCalled());
+ String url1 = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
+ mOnUiThread.loadUrlAndWaitForCompletion(url1);
mOnUiThread.zoomIn();
- getInstrumentation().waitForIdleSync();
- assertTrue(webViewClient.onScaleChangedCalled());
+ new PollingCheck() {
+ @Override
+ protected boolean check() {
+ return webViewClient.onScaleChangedCalled();
+ }
+ }.run();
}
@UiThreadTest