gecko-dev/mobile/android/base/ANRReporter.java

115 lines
3.5 KiB
Java

/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
public final class ANRReporter extends BroadcastReceiver
{
private static final boolean DEBUG = false;
private static final String LOGTAG = "GeckoANRReporter";
private static final String ANR_ACTION = "android.intent.action.ANR";
private static final ANRReporter sInstance = new ANRReporter();
private static int sRegisteredCount;
private Handler mHandler;
public static void register(Context context) {
if (sRegisteredCount++ != 0) {
// Already registered
return;
}
sInstance.start(context);
}
public static void unregister() {
if (sRegisteredCount == 0) {
Log.w(LOGTAG, "register/unregister mismatch");
return;
}
if (--sRegisteredCount != 0) {
// Should still be registered
return;
}
sInstance.stop();
}
private void start(final Context context) {
Thread receiverThread = new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
synchronized (ANRReporter.this) {
mHandler = new Handler();
ANRReporter.this.notify();
}
if (DEBUG) {
Log.d(LOGTAG, "registering receiver");
}
context.registerReceiver(ANRReporter.this,
new IntentFilter(ANR_ACTION),
null,
mHandler);
Looper.loop();
if (DEBUG) {
Log.d(LOGTAG, "unregistering receiver");
}
context.unregisterReceiver(ANRReporter.this);
mHandler = null;
}
}, LOGTAG);
receiverThread.setDaemon(true);
receiverThread.start();
}
private void stop() {
synchronized (this) {
while (mHandler == null) {
try {
wait(1000);
if (mHandler == null) {
// We timed out; just give up. The process is probably
// quitting anyways, so we let the OS do the clean up
Log.w(LOGTAG, "timed out waiting for handler");
return;
}
} catch (InterruptedException e) {
}
}
}
Looper looper = mHandler.getLooper();
looper.quit();
try {
looper.getThread().join();
} catch (InterruptedException e) {
}
}
private ANRReporter() {
}
@Override
public void onReceive(Context context, Intent intent) {
if (DEBUG) {
Log.d(LOGTAG, "receiving " + String.valueOf(intent));
}
if (!ANR_ACTION.equals(intent.getAction())) {
return;
}
Log.i(LOGTAG, "processing Gecko ANR");
}
}