blob: 0a9b3f805d3a9fa940ebd154bafa1ca8a096ae02 [file] [log] [blame]
/*
* 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.bugreport.cts;
import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
import static com.google.common.truth.Truth.assertThat;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BugreportManager;
import android.os.BugreportParams;
import android.util.Pair;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* Device-side tests for Bugreport Manager API
*/
@RunWith(AndroidJUnit4.class)
public class BugreportManagerTest {
private static final long BUGREPORT_TIMEOUT_MS = TimeUnit.MINUTES.toMillis(4);
// Sent by Shell when bugreport finishes (contains final bugreport/screenshot file name
// associated to this bugreport)
private static final String INTENT_BUGREPORT_FINISHED =
"com.android.internal.intent.action.BUGREPORT_FINISHED";
private static final String EXTRA_BUGREPORT = "android.intent.extra.BUGREPORT";
private static final String EXTRA_SCREENSHOT = "android.intent.extra.SCREENSHOT";
private static final String BUGREPORT_SERVICE = "bugreportd";
private Context mContext;
@Before
public void setup() {
mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
// Kill current bugreport, so that it does not interfere with future bugreports.
runShellCommand("setprop ctl.stop " + BUGREPORT_SERVICE);
}
@After
public void tearDown() {
// Kill current bugreport, so that it does not interfere with future bugreports.
runShellCommand("setprop ctl.stop " + BUGREPORT_SERVICE);
}
@Test
public void testBugreportParams_getMode() throws Exception {
int expected_mode = BugreportParams.BUGREPORT_MODE_FULL;
BugreportParams bp = new BugreportParams(expected_mode);
assertThat(bp.getMode()).isEqualTo(expected_mode);
}
@Test
public void testTelephonyBugreport() throws Exception {
Pair<String, String> brFiles = triggerBugreport(BugreportParams.BUGREPORT_MODE_TELEPHONY);
String bugreport = brFiles.first;
String screenshot = brFiles.second;
assertThat(bugreport).startsWith(
"/data/user_de/0/com.android.shell/files/bugreports/bugreport-");
assertThat(bugreport).endsWith(".zip");
// telephony bugreport contains "telephony" in the bugreport name
assertThat(bugreport).contains("-telephony-");
assertThatFileisNotEmpty(bugreport);
// telephony bugreport does not take any screenshot
assertThat(screenshot).isNull();
}
@Test
public void testFullBugreport() throws Exception {
Pair<String, String> brFiles = triggerBugreport(BugreportParams.BUGREPORT_MODE_FULL);
String bugreport = brFiles.first;
String screenshot = brFiles.second;
assertThat(bugreport).startsWith(
"/data/user_de/0/com.android.shell/files/bugreports/bugreport-");
assertThat(bugreport).endsWith(".zip");
assertThatFileisNotEmpty(bugreport);
// full bugreport takes a default screenshot
assertThat(screenshot).startsWith(
"/data/user_de/0/com.android.shell/files/bugreports/screenshot-");
assertThat(screenshot).endsWith("-default.png");
assertThatFileisNotEmpty(screenshot);
}
private void assertThatFileisNotEmpty(String file) throws Exception {
String[] fileInfo = runShellCommand("ls -l " + file).split(" ");
// Example output of ls -l: -rw------- 1 shell shell 27039619 2020-04-27 12:36 fileName.zip
assertThat(fileInfo.length).isEqualTo(8);
long fileSize = Long.parseLong(fileInfo[4]);
assertThat(fileSize).isGreaterThan(0L);
}
private class BugreportBroadcastReceiver extends BroadcastReceiver {
Intent bugreportFinishedIntent = null;
final CountDownLatch latch;
BugreportBroadcastReceiver() {
latch = new CountDownLatch(1);
}
@Override
public void onReceive(Context context, Intent intent) {
setBugreportFinishedIntent(intent);
latch.countDown();
}
private void setBugreportFinishedIntent(Intent intent) {
bugreportFinishedIntent = intent;
}
public Intent getBugreportFinishedIntent() {
return bugreportFinishedIntent;
}
public void waitForBugreportFinished() throws Exception {
if (!latch.await(BUGREPORT_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
throw new Exception("Failed to receive BUGREPORT_FINISHED in "
+ BUGREPORT_TIMEOUT_MS + " ms.");
}
}
}
private Pair<String, String> triggerBugreport(int type) throws Exception {
BugreportBroadcastReceiver br = new BugreportBroadcastReceiver();
mContext.registerReceiver(br, new IntentFilter(INTENT_BUGREPORT_FINISHED));
String shellCommand = "am bug-report";
switch (type) {
case BugreportParams.BUGREPORT_MODE_TELEPHONY:
shellCommand = shellCommand.concat(" --telephony");
case BugreportParams.BUGREPORT_MODE_FULL:
// default (no arg) takes full bugreport
break;
}
String res = runShellCommand(shellCommand).trim();
assertThat(res).isEqualTo("Your lovely bug report is being created; please be patient.");
try {
br.waitForBugreportFinished();
} finally {
// The latch may fail for a number of reasons but we still need to unregister the
// BroadcastReceiver.
mContext.unregisterReceiver(br);
}
Intent response = br.getBugreportFinishedIntent();
String bugreport = response.getStringExtra(EXTRA_BUGREPORT);
String screenshot = response.getStringExtra(EXTRA_SCREENSHOT);
return new Pair<String, String>(bugreport, screenshot);
}
}