blob: 62e512c3289bf287d45e5a114579ad575119412d [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.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
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.concurrent.CountDownLatch;
/**
* Collect device information on target device and write to a JSON file.
*/
public abstract class DeviceInfoActivity extends Activity {
/** Device info result code: collector failed to complete. */
private static final int DEVICE_INFO_RESULT_FAILED = -2;
/** Device info result code: collector completed with error. */
private static final int DEVICE_INFO_RESULT_ERROR = -1;
/** Device info result code: collector has started but not completed. */
private static final int DEVICE_INFO_RESULT_STARTED = 0;
/** Device info result code: collector completed success. */
private static final int DEVICE_INFO_RESULT_OK = 1;
private static final int MAX_STRING_VALUE_LENGTH = 1000;
private static final int MAX_ARRAY_LENGTH = 1000;
private static final String LOG_TAG = "DeviceInfoActivity";
private CountDownLatch mDone = new CountDownLatch(1);
private JsonWriter mJsonWriter = null;
private String mResultFilePath = null;
private String mErrorMessage = "Collector has started.";
private int mResultCode = DEVICE_INFO_RESULT_STARTED;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (createFilePath()) {
createJsonWriter();
startJsonWriter();
collectDeviceInfo();
closeJsonWriter();
if (mResultCode == DEVICE_INFO_RESULT_STARTED) {
mResultCode = DEVICE_INFO_RESULT_OK;
}
}
Intent data = new Intent();
if (mResultCode == DEVICE_INFO_RESULT_OK) {
data.setData(Uri.parse(mResultFilePath));
setResult(RESULT_OK, data);
} else {
data.setData(Uri.parse(mErrorMessage));
setResult(RESULT_CANCELED, data);
}
mDone.countDown();
finish();
}
/**
* Method to collect device information.
*/
protected abstract void collectDeviceInfo();
void waitForActivityToFinish() {
try {
mDone.await();
} catch (Exception e) {
failed("Exception while waiting for activity to finish: " + e.getMessage());
}
}
/**
* Returns the error message if collector did not complete successfully.
*/
String getErrorMessage() {
if (mResultCode == DEVICE_INFO_RESULT_OK) {
return null;
}
return mErrorMessage;
}
/**
* Returns the path to the json file if collector completed successfully.
*/
String getResultFilePath() {
if (mResultCode == DEVICE_INFO_RESULT_OK) {
return mResultFilePath;
}
return null;
}
private void error(String message) {
mResultCode = DEVICE_INFO_RESULT_ERROR;
mErrorMessage = message;
Log.e(LOG_TAG, message);
}
private void failed(String message) {
mResultCode = DEVICE_INFO_RESULT_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(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());
}
}
/**
* 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;
}
}