/*
* This file is part of the RootTools Project: http://code.google.com/p/roottools/
*
* Copyright (c) 2012 Stephen Erickson, Chris Ravenscroft, Dominik Schuermann, Adam Shanks
*
* This code is dual-licensed under the terms of the Apache License Version 2.0 and
* the terms of the General Public License (GPL) Version 2.
* You may use this code according to either of these licenses as is most appropriate
* for your project on a case-by-case basis.
*
* The terms of each license can be found in the root directory of this project's repository as well as at:
*
* * http://www.apache.org/licenses/LICENSE-2.0
* * http://www.gnu.org/licenses/gpl-2.0.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under these Licenses is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See each License for the specific language governing permissions and
* limitations under that License.
*/
package com.stericson.RootTools.test;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeoutException;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.StrictMode;
import android.widget.ScrollView;
import android.widget.TextView;
import com.stericson.RootTools.RootTools;
import com.stericson.RootTools.containers.Permissions;
import com.stericson.RootTools.exceptions.RootDeniedException;
import com.stericson.RootTools.execution.CommandCapture;
import com.stericson.RootTools.execution.JavaCommandCapture;
import com.stericson.RootTools.execution.Shell;
public class SanityCheckRootTools extends Activity {
private ScrollView mScrollView;
private TextView mTextView;
private ProgressDialog mPDialog;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/*StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork() // or .detectAll() for all detectable problems
.penaltyLog()
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()
.penaltyLog()
.penaltyDeath()
.build());*/
RootTools.debugMode = true;
mTextView = new TextView(this);
mTextView.setText("");
mScrollView = new ScrollView(this);
mScrollView.addView(mTextView);
setContentView(mScrollView);
// Great the user with our version number
String version = "?";
try {
PackageInfo packageInfo =
this.getPackageManager().getPackageInfo(this.getPackageName(), 0);
version = packageInfo.versionName;
} catch (PackageManager.NameNotFoundException e) {
}
print("SanityCheckRootTools v " + version + "\n\n");
if(RootTools.isRootAvailable()) {
print("Root found.\n");
}
else
{
print("Root not found");
}
try {
Shell.startRootShell();
} catch (IOException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
} catch (TimeoutException e) {
print("[ TIMEOUT EXCEPTION! ]\n");
e.printStackTrace();
} catch (RootDeniedException e) {
print("[ ROOT DENIED EXCEPTION! ]\n");
e.printStackTrace();
}
try {
if (!RootTools.isAccessGiven()) {
print("ERROR: No root access to this device.\n");
return;
}
} catch (Exception e) {
print("ERROR: could not determine root access to this device.\n");
return;
}
// Display infinite progress bar
mPDialog = new ProgressDialog(this);
mPDialog.setCancelable(false);
mPDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
new SanityCheckThread(this, new TestHandler()).start();
}
protected void print(CharSequence text) {
mTextView.append(text);
mScrollView.post(new Runnable() {
public void run() {
mScrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
});
}
// Run our long-running tests in their separate thread so as to
// not interfere with proper rendering.
private class SanityCheckThread extends Thread {
private Handler mHandler;
public SanityCheckThread(Context context, Handler handler) {
mHandler = handler;
}
public void run() {
visualUpdate(TestHandler.ACTION_SHOW, null);
// First test: Install a binary file for future use
// if it wasn't already installed.
/*
visualUpdate(TestHandler.ACTION_PDISPLAY, "Installing binary if needed");
if(false == RootTools.installBinary(mContext, R.raw.nes, "nes_binary")) {
visualUpdate(TestHandler.ACTION_HIDE, "ERROR: Failed to install binary. Please see log file.");
return;
}
*/
boolean result;
visualUpdate(TestHandler.ACTION_PDISPLAY, "Testing getPath");
visualUpdate(TestHandler.ACTION_DISPLAY, "[ getPath ]\n");
try {
List<String> paths = RootTools.getPath();
for(String path : paths)
{
visualUpdate(TestHandler.ACTION_DISPLAY, path + " k\n\n");
}
} catch (Exception e) {
e.printStackTrace();
}
visualUpdate(TestHandler.ACTION_PDISPLAY, "Testing A ton of commands");
visualUpdate(TestHandler.ACTION_DISPLAY, "[ Ton of Commands ]\n");
for (int i = 0; i < 100; i++) {
RootTools.exists("/system/xbin/busybox");
}
visualUpdate(TestHandler.ACTION_PDISPLAY, "Testing Find Binary");
result = RootTools.isRootAvailable();
visualUpdate(TestHandler.ACTION_DISPLAY, "[ Checking Root ]\n");
visualUpdate(TestHandler.ACTION_DISPLAY, result + " k\n\n");
visualUpdate(TestHandler.ACTION_PDISPLAY, "Testing file exists");
visualUpdate(TestHandler.ACTION_DISPLAY, "[ Checking Exists() ]\n");
visualUpdate(TestHandler.ACTION_DISPLAY, RootTools.exists("/system/sbin/[") + " k\n\n");
visualUpdate(TestHandler.ACTION_PDISPLAY, "Testing Is Access Given");
result = RootTools.isAccessGiven();
visualUpdate(TestHandler.ACTION_DISPLAY, "[ Checking for Access to Root ]\n");
visualUpdate(TestHandler.ACTION_DISPLAY, result + " k\n\n");
visualUpdate(TestHandler.ACTION_PDISPLAY, "Testing Remount");
result = RootTools.remount("/system", "rw");
visualUpdate(TestHandler.ACTION_DISPLAY, "[ Remounting System as RW ]\n");
visualUpdate(TestHandler.ACTION_DISPLAY, result + " k\n\n");
visualUpdate(TestHandler.ACTION_PDISPLAY, "Testing CheckUtil");
visualUpdate(TestHandler.ACTION_DISPLAY, "[ Checking busybox is setup ]\n");
visualUpdate(TestHandler.ACTION_DISPLAY, RootTools.checkUtil("busybox") + " k\n\n");
visualUpdate(TestHandler.ACTION_PDISPLAY, "Testing getBusyBoxVersion");
visualUpdate(TestHandler.ACTION_DISPLAY, "[ Checking busybox version ]\n");
visualUpdate(TestHandler.ACTION_DISPLAY, RootTools.getBusyBoxVersion("/system/bin/") + " k\n\n");
try {
visualUpdate(TestHandler.ACTION_PDISPLAY, "Testing fixUtils");
visualUpdate(TestHandler.ACTION_DISPLAY, "[ Checking Utils ]\n");
visualUpdate(TestHandler.ACTION_DISPLAY, RootTools.fixUtils(new String[]{"ls", "rm", "ln", "dd", "chmod", "mount"}) + " k\n\n");
} catch (Exception e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
try {
visualUpdate(TestHandler.ACTION_PDISPLAY, "Testing getSymlink");
visualUpdate(TestHandler.ACTION_DISPLAY, "[ Checking [[ for symlink ]\n");
visualUpdate(TestHandler.ACTION_DISPLAY, RootTools.getSymlink("/system/bin/[[") + " k\n\n");
} catch (Exception e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
visualUpdate(TestHandler.ACTION_PDISPLAY, "Testing getInode");
visualUpdate(TestHandler.ACTION_DISPLAY, "[ Checking Inodes ]\n");
visualUpdate(TestHandler.ACTION_DISPLAY, RootTools.getInode("/system/bin/busybox") + " k\n\n");
visualUpdate(TestHandler.ACTION_PDISPLAY, "Testing GetBusyBoxapplets");
try {
visualUpdate(TestHandler.ACTION_DISPLAY, "[ Getting all available Busybox applets ]\n");
for (String applet : RootTools.getBusyBoxApplets("/data/data/stericson.busybox.donate/files/bb")) {
visualUpdate(TestHandler.ACTION_DISPLAY, applet + " k\n\n");
}
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
visualUpdate(TestHandler.ACTION_PDISPLAY, "Testing getFilePermissionsSymlinks");
Permissions permissions = RootTools.getFilePermissionsSymlinks("/system/bin/busybox");
visualUpdate(TestHandler.ACTION_DISPLAY, "[ Checking busybox permissions and symlink ]\n");
if (permissions != null) {
visualUpdate(TestHandler.ACTION_DISPLAY, "Symlink: " + permissions.getSymlink() + " k\n\n");
visualUpdate(TestHandler.ACTION_DISPLAY, "Group Permissions: " + permissions.getGroupPermissions() + " k\n\n");
visualUpdate(TestHandler.ACTION_DISPLAY, "Owner Permissions: " + permissions.getOtherPermissions() + " k\n\n");
visualUpdate(TestHandler.ACTION_DISPLAY, "Permissions: " + permissions.getPermissions() + " k\n\n");
visualUpdate(TestHandler.ACTION_DISPLAY, "Type: " + permissions.getType() + " k\n\n");
visualUpdate(TestHandler.ACTION_DISPLAY, "User Permissions: " + permissions.getUserPermissions() + " k\n\n");
} else {
visualUpdate(TestHandler.ACTION_DISPLAY, "Permissions == null k\n\n");
}
visualUpdate(TestHandler.ACTION_PDISPLAY, "JAVA");
visualUpdate(TestHandler.ACTION_DISPLAY, "[ Running some Java code ]\n");
Shell shell;
try {
shell = RootTools.getShell(true);
JavaCommandCapture cmd = new JavaCommandCapture(
43,
false,
SanityCheckRootTools.this,
"com.stericson.RootToolsTests.NativeJavaClass") {
@Override
public void commandOutput(int id, String line) {
super.commandOutput(id, line);
visualUpdate(TestHandler.ACTION_DISPLAY, line + "\n");
}
};
shell.add(cmd);
} catch (Exception e) {
// Oops. Say, did you run RootClass and move the resulting anbuild.dex " file to res/raw?
// If you don't you will not be able to check root mode Java.
e.printStackTrace();
}
visualUpdate(TestHandler.ACTION_PDISPLAY, "Testing df");
long spaceValue = RootTools.getSpace("/data");
visualUpdate(TestHandler.ACTION_DISPLAY, "[ Checking /data partition size]\n");
visualUpdate(TestHandler.ACTION_DISPLAY, spaceValue + "k\n\n");
try {
shell = RootTools.getShell(true);
CommandCapture cmd = new CommandCapture(42, false, "find /") {
boolean _catch = false;
@Override
public void commandOutput(int id, String line) {
super.commandOutput(id, line);
if (_catch) {
RootTools.log("CAUGHT!!!");
}
}
@Override
public void commandTerminated(int id, String reason) {
synchronized (SanityCheckRootTools.this) {
_catch = true;
visualUpdate(TestHandler.ACTION_PDISPLAY, "All tests complete.");
visualUpdate(TestHandler.ACTION_HIDE, null);
try {
RootTools.closeAllShells();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@Override
public void commandCompleted(int id, int exitCode) {
synchronized (SanityCheckRootTools.this) {
_catch = true;
visualUpdate(TestHandler.ACTION_PDISPLAY, "All tests complete.");
visualUpdate(TestHandler.ACTION_HIDE, null);
try {
RootTools.closeAllShells();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
shell.add(cmd);
} catch (Exception e) {
e.printStackTrace();
}
}
private void visualUpdate(int action, String text) {
Message msg = mHandler.obtainMessage();
Bundle bundle = new Bundle();
bundle.putInt(TestHandler.ACTION, action);
bundle.putString(TestHandler.TEXT, text);
msg.setData(bundle);
mHandler.sendMessage(msg);
}
}
private class TestHandler extends Handler {
static final public String ACTION = "action";
static final public int ACTION_SHOW = 0x01;
static final public int ACTION_HIDE = 0x02;
static final public int ACTION_DISPLAY = 0x03;
static final public int ACTION_PDISPLAY = 0x04;
static final public String TEXT = "text";
public void handleMessage(Message msg) {
int action = msg.getData().getInt(ACTION);
String text = msg.getData().getString(TEXT);
switch (action) {
case ACTION_SHOW:
mPDialog.show();
mPDialog.setMessage("Running Root Library Tests...");
break;
case ACTION_HIDE:
if (null != text)
print(text);
mPDialog.hide();
break;
case ACTION_DISPLAY:
print(text);
break;
case ACTION_PDISPLAY:
mPDialog.setMessage(text);
break;
}
}
}
}