blob: 151e89ad382382d0e8fd0ffb8d13a9ec459ebf47 [file] [log] [blame]
/*
* Copyright (C) 2015 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.compatibility.common.deviceinfo;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Environment;
import android.test.InstrumentationTestCase;
import android.text.TextUtils;
import android.util.JsonWriter;
import android.util.Log;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/**
* Collect device information on target device and write to a JSON file.
*/
public abstract class DeviceInfo extends InstrumentationTestCase {
private enum ResultCode {
// Collection started.
STARTED,
// Collection completed.
COMPLETED,
// Collection completed with error.
ERROR,
// Collection failed to complete.
FAILED
}
private static final int MAX_STRING_VALUE_LENGTH = 1000;
private static final int MAX_ARRAY_LENGTH = 1000;
private static final String LOG_TAG = "ExtendedDeviceInfo";
private JsonWriter mJsonWriter = null;
private String mResultFilePath = null;
private String mErrorMessage = null;
private ResultCode mResultCode = ResultCode.STARTED;
Set<String> mActivityList = new HashSet<String>();
public void testCollectDeviceInfo() {
if (!mActivityList.contains(getClass().getName())) {
return;
}
if (createFilePath()) {
createJsonWriter();
startJsonWriter();
try {
collectDeviceInfo();
} catch(Exception | Error e) {
error(e.getMessage());
}
closeJsonWriter();
if (mResultCode == ResultCode.STARTED) {
mResultCode = ResultCode.COMPLETED;
}
}
sendStatus();
String message = getClass().getSimpleName() + " collection completed.";
assertEquals(message, ResultCode.COMPLETED, mResultCode);
}
@Override
protected void setUp() throws Exception {
super.setUp();
// Build the list of supported activities that can run collection.
ActivityInfo[] activities = null;
try {
activities = getContext().getPackageManager().getPackageInfo(
getContext().getPackageName(), PackageManager.GET_ACTIVITIES).activities;
} catch (Exception e) {
Log.e(LOG_TAG, "Exception occurred while getting activities.", e);
return;
}
for (ActivityInfo activityInfo : activities) {
mActivityList.add(activityInfo.name);
}
}
/**
* Method to collect device information.
*/
protected abstract void collectDeviceInfo();
protected Context getContext() {
return getInstrumentation().getContext();
}
/**
* Sends status to instrumentation.
*/
void sendStatus() {
Bundle bundle = new Bundle();
String className = getClass().getSimpleName();
if (this instanceof GenericDeviceInfo) {
((GenericDeviceInfo) this).putDeviceInfo(bundle);
}
if (!TextUtils.isEmpty(mErrorMessage)) {
bundle.putString("DEVICE_INFO_ERROR_" + className, mErrorMessage);
}
if (mResultCode == ResultCode.COMPLETED) {
bundle.putString("DEVICE_INFO_FILE_" + className, mResultFilePath);
}
getInstrumentation().sendStatus(Activity.RESULT_OK, bundle);
}
/**
* Returns the path to the json file if collector completed successfully.
*/
String getResultFilePath() {
return mResultFilePath;
}
private void error(String message) {
mResultCode = ResultCode.ERROR;
mErrorMessage = message;
Log.e(LOG_TAG, message);
}
private void failed(String message) {
mResultCode = ResultCode.FAILED;
mErrorMessage = message;
Log.e(LOG_TAG, message);
}
private boolean createFilePath() {
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
failed("External storage is not mounted");
return false;
}
final File dir = new File(Environment.getExternalStorageDirectory(), "device-info-files");
if (!dir.mkdirs() && !dir.isDirectory()) {
failed("Cannot create directory for device info files");
return false;
}
// Create file at /sdcard/device-info-files/<class_name>.deviceinfo.json
final File jsonFile = new File(dir, getClass().getSimpleName() + ".deviceinfo.json");
try {
jsonFile.createNewFile();
} catch (Exception e) {
failed("Cannot create file to collect device info");
return false;
}
mResultFilePath = jsonFile.getAbsolutePath();
return true;
}
private void createJsonWriter() {
try {
FileOutputStream out = new FileOutputStream(mResultFilePath);
mJsonWriter = new JsonWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8));
// TODO(agathaman): remove to make json output less pretty
mJsonWriter.setIndent(" ");
} catch (Exception e) {
failed("Failed to create JSON writer: " + e.getMessage());
}
}
private void startJsonWriter() {
try {
mJsonWriter.beginObject();
} catch (Exception e) {
failed("Failed to begin JSON object: " + e.getMessage());
}
}
private void closeJsonWriter() {
try {
mJsonWriter.endObject();
mJsonWriter.close();
} catch (Exception e) {
failed("Failed to close JSON object: " + e.getMessage());
}
}
/**
* Start a new group of result.
*/
public void startGroup() {
try {
mJsonWriter.beginObject();
} catch (Exception e) {
error("Failed to begin JSON group: " + e.getMessage());
}
}
/**
* Start a new group of result with specified name.
*/
public void startGroup(String name) {
try {
mJsonWriter.name(name);
mJsonWriter.beginObject();
} catch (Exception e) {
error("Failed to begin JSON group: " + e.getMessage());
}
}
/**
* Complete adding result to the last started group.
*/
public void endGroup() {
try {
mJsonWriter.endObject();
} catch (Exception e) {
error("Failed to end JSON group: " + e.getMessage());
}
}
/**
* Start a new array of result.
*/
public void startArray() {
try {
mJsonWriter.beginArray();
} catch (Exception e) {
error("Failed to begin JSON array: " + e.getMessage());
}
}
/**
* Start a new array of result with specified name.
*/
public void startArray(String name) {
checkName(name);
try {
mJsonWriter.name(name);
mJsonWriter.beginArray();
} catch (Exception e) {
error("Failed to begin JSON array: " + e.getMessage());
}
}
/**
* Complete adding result to the last started array.
*/
public void endArray() {
try {
mJsonWriter.endArray();
} catch (Exception e) {
error("Failed to end JSON group: " + e.getMessage());
}
}
/**
* Add a double value result.
*/
public void addResult(String name, double value) {
checkName(name);
try {
mJsonWriter.name(name).value(value);
} catch (Exception e) {
error("Failed to add result for type double: " + e.getMessage());
}
}
/**
* Add a long value result.
*/
public void addResult(String name, long value) {
checkName(name);
try {
mJsonWriter.name(name).value(value);
} catch (Exception e) {
error("Failed to add result for type long: " + e.getMessage());
}
}
/**
* Add an int value result.
*/
public void addResult(String name, int value) {
checkName(name);
try {
mJsonWriter.name(name).value((Number) value);
} catch (Exception e) {
error("Failed to add result for type int: " + e.getMessage());
}
}
/**
* Add a boolean value result.
*/
public void addResult(String name, boolean value) {
checkName(name);
try {
mJsonWriter.name(name).value(value);
} catch (Exception e) {
error("Failed to add result for type boolean: " + e.getMessage());
}
}
/**
* Add a String value result.
*/
public void addResult(String name, String value) {
checkName(name);
try {
mJsonWriter.name(name).value(checkString(value));
} catch (Exception e) {
error("Failed to add result for type String: " + e.getMessage());
}
}
/**
* Add a double array result.
*/
public void addArray(String name, double[] list) {
checkName(name);
try {
mJsonWriter.name(name);
mJsonWriter.beginArray();
for (double value : checkArray(list)) {
mJsonWriter.value(value);
}
mJsonWriter.endArray();
} catch (Exception e) {
error("Failed to add result array for type double: " + e.getMessage());
}
}
/**
* Add a long array result.
*/
public void addArray(String name, long[] list) {
checkName(name);
try {
mJsonWriter.name(name);
mJsonWriter.beginArray();
for (long value : checkArray(list)) {
mJsonWriter.value(value);
}
mJsonWriter.endArray();
} catch (Exception e) {
error("Failed to add result array for type long: " + e.getMessage());
}
}
/**
* Add an int array result.
*/
public void addArray(String name, int[] list) {
checkName(name);
try {
mJsonWriter.name(name);
mJsonWriter.beginArray();
for (int value : checkArray(list)) {
mJsonWriter.value((Number) value);
}
mJsonWriter.endArray();
} catch (Exception e) {
error("Failed to add result array for type int: " + e.getMessage());
}
}
/**
* Add a boolean array result.
*/
public void addArray(String name, boolean[] list) {
checkName(name);
try {
mJsonWriter.name(name);
mJsonWriter.beginArray();
for (boolean value : checkArray(list)) {
mJsonWriter.value(value);
}
mJsonWriter.endArray();
} catch (Exception e) {
error("Failed to add result array for type boolean: " + e.getMessage());
}
}
/**
* Add a String array result.
*/
public void addArray(String name, String[] list) {
checkName(name);
try {
mJsonWriter.name(name);
mJsonWriter.beginArray();
for (String value : checkArray(list)) {
mJsonWriter.value(checkString(value));
}
mJsonWriter.endArray();
} catch (Exception e) {
error("Failed to add result array for type Sting: " + e.getMessage());
}
}
private static boolean[] checkArray(boolean[] values) {
if (values.length > MAX_ARRAY_LENGTH) {
return Arrays.copyOf(values, MAX_ARRAY_LENGTH);
} else {
return values;
}
}
private static double[] checkArray(double[] values) {
if (values.length > MAX_ARRAY_LENGTH) {
return Arrays.copyOf(values, MAX_ARRAY_LENGTH);
} else {
return values;
}
}
private static int[] checkArray(int[] values) {
if (values.length > MAX_ARRAY_LENGTH) {
return Arrays.copyOf(values, MAX_ARRAY_LENGTH);
} else {
return values;
}
}
private static long[] checkArray(long[] values) {
if (values.length > MAX_ARRAY_LENGTH) {
return Arrays.copyOf(values, MAX_ARRAY_LENGTH);
} else {
return values;
}
}
private static String[] checkArray(String[] values) {
if (values.length > MAX_ARRAY_LENGTH) {
return Arrays.copyOf(values, MAX_ARRAY_LENGTH);
} else {
return values;
}
}
private static String checkString(String value) {
if (value.length() > MAX_STRING_VALUE_LENGTH) {
return value.substring(0, MAX_STRING_VALUE_LENGTH);
}
return value;
}
private static String checkName(String value) {
if (TextUtils.isEmpty(value)) {
throw new NullPointerException();
}
return value;
}
}