Merge "Help for the debugging help for issue #8734824." into jb-mr2-dev

This commit is contained in:
Dianne Hackborn
2013-05-06 23:46:57 +00:00
committed by Android (Google) Code Review
5 changed files with 100 additions and 3 deletions

View File

@ -31,6 +31,7 @@ import android.content.Intent;
import android.content.pm.IPackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
@ -94,6 +95,7 @@ public class Am extends BaseCommand {
" am set-debug-app [-w] [--persistent] <PACKAGE>\n" +
" am clear-debug-app\n" +
" am monitor [--gdb <port>]\n" +
" am hang [--allow-restart]\n" +
" am screen-compat [on|off] <PACKAGE>\n" +
" am to-uri [INTENT]\n" +
" am to-intent-uri [INTENT]\n" +
@ -169,6 +171,9 @@ public class Am extends BaseCommand {
"am monitor: start monitoring for crashes or ANRs.\n" +
" --gdb: start gdbserv on the given port at crash/ANR\n" +
"\n" +
"am hang: hang the system.\n" +
" --allow-restart: allow watchdog to perform normal system restart\n" +
"\n" +
"am screen-compat: control screen compatibility mode of <PACKAGE>.\n" +
"\n" +
"am to-uri: print the given Intent specification as a URI.\n" +
@ -249,6 +254,8 @@ public class Am extends BaseCommand {
runBugReport();
} else if (op.equals("monitor")) {
runMonitor();
} else if (op.equals("hang")) {
runHang();
} else if (op.equals("screen-compat")) {
runScreenCompat();
} else if (op.equals("to-uri")) {
@ -1304,6 +1311,22 @@ public class Am extends BaseCommand {
controller.run();
}
private void runHang() throws Exception {
String opt;
boolean allowRestart = false;
while ((opt=nextOption()) != null) {
if (opt.equals("--allow-restart")) {
allowRestart = true;
} else {
System.err.println("Error: Unknown option: " + opt);
return;
}
}
System.out.println("Hanging the system...");
mAm.hang(new Binder(), allowRestart);
}
private void runScreenCompat() throws Exception {
String mode = nextArgRequired();
boolean enabled;

View File

@ -1870,6 +1870,15 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
case HANG_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder who = data.readStrongBinder();
boolean allowRestart = data.readInt() != 0;
hang(who, allowRestart);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
@ -4270,5 +4279,17 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
}
public void hang(IBinder who, boolean allowRestart) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(who);
data.writeInt(allowRestart ? 1 : 0);
mRemote.transact(HANG_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
}
private IBinder mRemote;
}

View File

@ -377,6 +377,8 @@ public interface IActivityManager extends IInterface {
public void killUid(int uid, String reason) throws RemoteException;
public void hang(IBinder who, boolean allowRestart) throws RemoteException;
/*
* Private non-Binder interfaces
*/
@ -638,4 +640,5 @@ public interface IActivityManager extends IInterface {
int GET_LAUNCHED_FROM_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+163;
int KILL_UID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+164;
int SET_USER_IS_MONKEY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+165;
int HANG_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+166;
}

View File

@ -95,6 +95,7 @@ public class Watchdog extends Thread {
int mPhonePid;
IActivityController mController;
boolean mAllowRestart = true;
final Calendar mCalendar = Calendar.getInstance();
int mMinScreenOff = MEMCHECK_DEFAULT_MIN_SCREEN_OFF;
@ -233,6 +234,12 @@ public class Watchdog extends Thread {
}
}
public void setAllowRestart(boolean allowRestart) {
synchronized (this) {
mAllowRestart = allowRestart;
}
}
public void addMonitor(Monitor monitor) {
synchronized (this) {
if (isAlive()) {
@ -401,6 +408,7 @@ public class Watchdog extends Thread {
final String name;
final boolean allowRestart;
synchronized (this) {
long timeout = TIME_TO_WAIT;
@ -437,6 +445,7 @@ public class Watchdog extends Thread {
name = (mCurrentMonitor != null) ?
mCurrentMonitor.getClass().getName() : "null";
allowRestart = mAllowRestart;
}
// If we got here, that means that the system is most likely hung.
@ -506,12 +515,14 @@ public class Watchdog extends Thread {
}
// Only kill the process if the debugger is not attached.
if (!Debug.isDebuggerConnected()) {
if (Debug.isDebuggerConnected()) {
Slog.w(TAG, "Debugger connected: Watchdog is *not* killing the system process");
} else if (!allowRestart) {
Slog.w(TAG, "Restart not allowed: Watchdog is *not* killing the system process");
} else {
Slog.w(TAG, "*** WATCHDOG KILLING SYSTEM PROCESS: " + name);
Process.killProcess(Process.myPid());
System.exit(10);
} else {
Slog.w(TAG, "Debugger connected: Watchdog is *not* killing the system process");
}
waitedHalf = false;

View File

@ -7813,6 +7813,45 @@ public final class ActivityManagerService extends ActivityManagerNative
return killed;
}
@Override
public void hang(final IBinder who, boolean allowRestart) {
if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires permission "
+ android.Manifest.permission.SET_ACTIVITY_WATCHER);
}
final IBinder.DeathRecipient death = new DeathRecipient() {
@Override
public void binderDied() {
synchronized (this) {
notifyAll();
}
}
};
try {
who.linkToDeath(death, 0);
} catch (RemoteException e) {
Slog.w(TAG, "hang: given caller IBinder is already dead.");
return;
}
synchronized (this) {
Watchdog.getInstance().setAllowRestart(allowRestart);
Slog.i(TAG, "Hanging system process at request of pid " + Binder.getCallingPid());
synchronized (death) {
while (who.isBinderAlive()) {
try {
death.wait();
} catch (InterruptedException e) {
}
}
}
Watchdog.getInstance().setAllowRestart(true);
}
}
public final void startRunning(String pkg, String cls, String action,
String data) {
synchronized(this) {