Merge "Help for the debugging help for issue #8734824." into jb-mr2-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
d43a71dad8
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
Reference in New Issue
Block a user