Start combining threads in system process.

This introduces four generic thread that services can
use in the system process:

- Background: part of the framework for all processes, for
work that is purely background (no timing constraint).
- UI: for time-critical display of UI.
- Foreground: normal foreground work.
- IO: performing IO operations.

I went through and moved services into these threads in the
places I felt relatively comfortable about understanding what
they are doing.  There are still a bunch more we need to look
at -- lots of networking stuff left, 3 or so different native
daemon connectors which I didn't know how much would block,
audio stuff, etc.

Also updated Watchdog to be aware of and check these new
threads, with a new API for other threads to also participate
in this checking.

Change-Id: Ie2f11061cebde5f018d7383b3a910fbbd11d5e11
This commit is contained in:
Dianne Hackborn
2013-04-30 17:24:15 -07:00
parent 34761434a0
commit 8d044e8bc2
23 changed files with 410 additions and 170 deletions

View File

@@ -25,6 +25,7 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.UserHandle;
import com.android.internal.os.BackgroundThread;
import java.util.HashSet;
@@ -37,10 +38,6 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver {
static final IntentFilter sNonDataFilt = new IntentFilter();
static final IntentFilter sExternalFilt = new IntentFilter();
static final Object sLock = new Object();
static HandlerThread sBackgroundThread;
static Handler sBackgroundHandler;
static {
sPackageFilt.addAction(Intent.ACTION_PACKAGE_ADDED);
sPackageFilt.addAction(Intent.ACTION_PACKAGE_REMOVED);
@@ -79,15 +76,7 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver {
}
mRegisteredContext = context;
if (thread == null) {
synchronized (sLock) {
if (sBackgroundThread == null) {
sBackgroundThread = new HandlerThread("PackageMonitor",
android.os.Process.THREAD_PRIORITY_BACKGROUND);
sBackgroundThread.start();
sBackgroundHandler = new Handler(sBackgroundThread.getLooper());
}
mRegisteredHandler = sBackgroundHandler;
}
mRegisteredHandler = BackgroundThread.getHandler();
} else {
mRegisteredHandler = new Handler(thread);
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (C) 2013 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.internal.os;
import android.os.Handler;
import android.os.HandlerThread;
/**
* Shared singleton background thread for each process.
*/
public final class BackgroundThread extends HandlerThread {
private static BackgroundThread sInstance;
private static Handler sHandler;
private BackgroundThread() {
super("android.bg", android.os.Process.THREAD_PRIORITY_BACKGROUND);
}
private static void ensureThreadLocked() {
if (sInstance == null) {
sInstance = new BackgroundThread();
sInstance.start();
sHandler = new Handler(sInstance.getLooper());
}
}
public static BackgroundThread get() {
synchronized (BackgroundThread.class) {
ensureThreadLocked();
return sInstance;
}
}
public static Handler getHandler() {
synchronized (BackgroundThread.class) {
ensureThreadLocked();
return sHandler;
}
}
}

View File

@@ -27,7 +27,6 @@ import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -37,6 +36,7 @@ import android.widget.RemoteViews;
import com.android.internal.appwidget.IAppWidgetHost;
import com.android.internal.appwidget.IAppWidgetService;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.IndentingPrintWriter;
import java.io.FileDescriptor;
@@ -63,9 +63,7 @@ class AppWidgetService extends IAppWidgetService.Stub
AppWidgetService(Context context) {
mContext = context;
HandlerThread handlerThread = new HandlerThread("AppWidgetService -- Save state");
handlerThread.start();
mSaveStateHandler = new Handler(handlerThread.getLooper());
mSaveStateHandler = BackgroundThread.getHandler();
mAppWidgetServices = new SparseArray<AppWidgetServiceImpl>(5);
AppWidgetServiceImpl primary = new AppWidgetServiceImpl(context, 0, mSaveStateHandler);

View File

@@ -33,7 +33,6 @@ import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
@@ -115,7 +114,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
// used inside handler thread
private boolean mEnable;
private int mState;
private HandlerThread mThread;
private final BluetoothHandler mHandler;
private void registerForAirplaneMode(IntentFilter filter) {
@@ -188,9 +186,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
};
BluetoothManagerService(Context context) {
mThread = new HandlerThread("BluetoothManager");
mThread.start();
mHandler = new BluetoothHandler(mThread.getLooper());
mHandler = new BluetoothHandler(IoThread.get().getLooper());
mContext = context;
mBluetooth = null;

View File

@@ -20,6 +20,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.HashMap;
import com.android.internal.os.BackgroundThread;
import com.android.server.location.ComprehensiveCountryDetector;
import android.content.Context;
@@ -29,8 +30,6 @@ import android.location.ICountryDetector;
import android.location.ICountryListener;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Process;
import android.os.RemoteException;
import android.util.PrintWriterPrinter;
import android.util.Printer;
@@ -169,8 +168,7 @@ public class CountryDetectorService extends ICountryDetector.Stub implements Run
void systemReady() {
// Shall we wait for the initialization finish.
Thread thread = new Thread(this, "CountryDetectorService");
thread.start();
BackgroundThread.getHandler().post(this);
}
private void initialize() {
@@ -187,12 +185,9 @@ public class CountryDetectorService extends ICountryDetector.Stub implements Run
}
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Looper.prepare();
mHandler = new Handler();
initialize();
mSystemReady = true;
Looper.loop();
}
protected void setCountryListener(final CountryListener listener) {

View File

@@ -0,0 +1,65 @@
/*
* Copyright (C) 2013 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.server;
import android.os.Handler;
import android.os.HandlerThread;
/**
* Shared singleton foreground thread for the system. This is a thread for regular
* foreground service operations, which shouldn't be blocked by anything running in
* the background. In particular, the shared background thread could be doing
* relatively long-running operations like saving state to disk (in addition to
* simply being a background priority), which can cause operations scheduled on it
* to be delayed for a user-noticeable amount of time.
*/
public final class FgThread extends HandlerThread {
private static FgThread sInstance;
private static Handler sHandler;
private FgThread() {
super("android.fg", android.os.Process.THREAD_PRIORITY_DEFAULT);
}
private static void ensureThreadLocked() {
if (sInstance == null) {
sInstance = new FgThread();
sInstance.start();
sHandler = new Handler(sInstance.getLooper());
sHandler.post(new Runnable() {
@Override
public void run() {
android.os.Process.setCanSelfBackground(false);
}
});
}
}
public static FgThread get() {
synchronized (UiThread.class) {
ensureThreadLocked();
return sInstance;
}
}
public static Handler getHandler() {
synchronized (UiThread.class) {
ensureThreadLocked();
return sHandler;
}
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (C) 2013 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.server;
import android.os.Handler;
import android.os.HandlerThread;
/**
* Shared singleton I/O thread for the system. This is a thread for non-background
* service operations that can potential block briefly on network IO operations
* (not waiting for data itself, but communicating with network daemons).
*/
public final class IoThread extends HandlerThread {
private static IoThread sInstance;
private static Handler sHandler;
private IoThread() {
super("android.io", android.os.Process.THREAD_PRIORITY_DEFAULT);
}
private static void ensureThreadLocked() {
if (sInstance == null) {
sInstance = new IoThread();
sInstance.start();
sHandler = new Handler(sInstance.getLooper());
sHandler.post(new Runnable() {
@Override
public void run() {
android.os.Process.setCanSelfBackground(false);
}
});
}
}
public static IoThread get() {
synchronized (UiThread.class) {
ensureThreadLocked();
return sInstance;
}
}
public static Handler getHandler() {
synchronized (UiThread.class) {
ensureThreadLocked();
return sHandler;
}
}
}

View File

@@ -63,6 +63,7 @@ import android.util.Slog;
import com.android.internal.content.PackageMonitor;
import com.android.internal.location.ProviderProperties;
import com.android.internal.location.ProviderRequest;
import com.android.internal.os.BackgroundThread;
import com.android.server.location.GeocoderProxy;
import com.android.server.location.GeofenceProxy;
import com.android.server.location.GeofenceManager;
@@ -93,7 +94,6 @@ public class LocationManagerService extends ILocationManager.Stub {
public static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
private static final String WAKELOCK_KEY = TAG;
private static final String THREAD_NAME = TAG;
// Location resolution level: no location data whatsoever
private static final int RESOLUTION_LEVEL_NONE = 0;
@@ -143,7 +143,6 @@ public class LocationManagerService extends ILocationManager.Stub {
private LocationWorkerHandler mLocationHandler;
private PassiveProvider mPassiveProvider; // track passive provider for special cases
private LocationBlacklist mBlacklist;
private HandlerThread mHandlerThread;
// --- fields below are protected by mWakeLock ---
private int mPendingBroadcasts;
@@ -216,9 +215,7 @@ public class LocationManagerService extends ILocationManager.Stub {
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
// prepare worker thread
mHandlerThread = new HandlerThread(THREAD_NAME, Process.THREAD_PRIORITY_BACKGROUND);
mHandlerThread.start();
mLocationHandler = new LocationWorkerHandler(mHandlerThread.getLooper());
mLocationHandler = new LocationWorkerHandler(BackgroundThread.get().getLooper());
// prepare mLocationHandler's dependents
mLocationFudger = new LocationFudger(mContext, mLocationHandler);

View File

@@ -37,7 +37,6 @@ import android.os.Binder;
import android.os.Environment;
import android.os.Environment.UserEnvironment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
@@ -485,7 +484,6 @@ class MountService extends IMountService.Stub
}
};
private final HandlerThread mHandlerThread;
private final Handler mHandler;
void waitForAsecScan() {
@@ -820,7 +818,7 @@ class MountService extends IMountService.Stub
}
if (code == VoldResponseCode.VolumeDiskInserted) {
new Thread() {
new Thread("MountService#VolumeDiskInserted") {
@Override
public void run() {
try {
@@ -1105,7 +1103,7 @@ class MountService extends IMountService.Stub
/*
* USB mass storage disconnected while enabled
*/
new Thread() {
new Thread("MountService#AvailabilityChange") {
@Override
public void run() {
try {
@@ -1304,9 +1302,7 @@ class MountService extends IMountService.Stub
// XXX: This will go away soon in favor of IMountServiceObserver
mPms = (PackageManagerService) ServiceManager.getService("package");
mHandlerThread = new HandlerThread("MountService");
mHandlerThread.start();
mHandler = new MountServiceHandler(mHandlerThread.getLooper());
mHandler = new MountServiceHandler(IoThread.get().getLooper());
// Watch for user changes
final IntentFilter userFilter = new IntentFilter();
@@ -1328,7 +1324,7 @@ class MountService extends IMountService.Stub
idleMaintenanceFilter, null, mHandler);
// Add OBB Action Handler to MountService thread.
mObbActionHandler = new ObbActionHandler(mHandlerThread.getLooper());
mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper());
/*
* Create the connection to vold with a maximum queue of twice the

View File

@@ -19,7 +19,6 @@ package com.android.server;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.os.SystemClock;
import android.util.LocalLog;
@@ -81,9 +80,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
@Override
public void run() {
HandlerThread thread = new HandlerThread(TAG + ".CallbackHandler");
thread.start();
mCallbackHandler = new Handler(thread.getLooper(), this);
mCallbackHandler = new Handler(FgThread.get().getLooper(), this);
while (true) {
try {

View File

@@ -27,7 +27,6 @@ import android.database.ContentObserver;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
@@ -36,6 +35,7 @@ import android.util.Log;
import android.util.NtpTrustedTime;
import android.util.TrustedTime;
import com.android.internal.os.BackgroundThread;
import com.android.internal.telephony.TelephonyIntents;
/**
@@ -71,7 +71,6 @@ public class NetworkTimeUpdateService {
// NTP lookup is done on this thread and handler
private Handler mHandler;
private HandlerThread mThread;
private AlarmManager mAlarmManager;
private PendingIntent mPendingPollIntent;
private SettingsObserver mSettingsObserver;
@@ -114,9 +113,7 @@ public class NetworkTimeUpdateService {
registerForAlarms();
registerForConnectivityIntents();
mThread = new HandlerThread(TAG);
mThread.start();
mHandler = new MyHandler(mThread.getLooper());
mHandler = new MyHandler(BackgroundThread.get().getLooper());
// Check the network time on the new thread
mHandler.obtainMessage(EVENT_POLL_NETWORK_TIME).sendToTarget();

View File

@@ -154,30 +154,6 @@ class ServerThread extends Thread {
InputManagerService inputManager = null;
TelephonyRegistry telephonyRegistry = null;
// Create a shared handler thread for UI within the system server.
// This thread is used by at least the following components:
// - WindowManagerPolicy
// - KeyguardViewManager
// - DisplayManagerService
HandlerThread uiHandlerThread = new HandlerThread("UI");
uiHandlerThread.start();
Handler uiHandler = new Handler(uiHandlerThread.getLooper());
uiHandler.post(new Runnable() {
@Override
public void run() {
//Looper.myLooper().setMessageLogging(new LogPrinter(
// Log.VERBOSE, "WindowManagerPolicy", Log.LOG_ID_SYSTEM));
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_FOREGROUND);
android.os.Process.setCanSelfBackground(false);
// For debug builds, log event loop stalls to dropbox for analysis.
if (StrictMode.conditionallyEnableDebugLogging()) {
Slog.i(TAG, "Enabled StrictMode logging for UI Looper");
}
}
});
// Create a handler thread just for the window manager to enjoy.
HandlerThread wmHandlerThread = new HandlerThread("WindowManager");
wmHandlerThread.start();
@@ -231,7 +207,7 @@ class ServerThread extends Thread {
try {
Slog.i(TAG, "Display Manager");
display = new DisplayManagerService(context, wmHandler, uiHandler);
display = new DisplayManagerService(context, wmHandler);
ServiceManager.addService(Context.DISPLAY_SERVICE, display, true);
Slog.i(TAG, "Telephony Registry");
@@ -319,14 +295,14 @@ class ServerThread extends Thread {
Slog.i(TAG, "Init Watchdog");
Watchdog.getInstance().init(context, battery, power, alarm,
ActivityManagerService.self());
Watchdog.getInstance().addThread(wmHandler, "WindowManager thread");
Slog.i(TAG, "Input Manager");
inputManager = new InputManagerService(context, wmHandler);
Slog.i(TAG, "Window Manager");
wm = WindowManagerService.main(context, power, display, inputManager,
uiHandler, wmHandler,
factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL,
wmHandler, factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL,
!firstBoot, onlyCore);
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);

View File

@@ -0,0 +1,71 @@
/*
* Copyright (C) 2013 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.server;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.StrictMode;
import android.util.Slog;
/**
* Shared singleton thread for showing UI. This is a foreground thread, and in
* additional should not have operations that can take more than a few ms scheduled
* on it to avoid UI jank.
*/
public final class UiThread extends HandlerThread {
private static UiThread sInstance;
private static Handler sHandler;
private UiThread() {
super("android.ui", android.os.Process.THREAD_PRIORITY_FOREGROUND);
}
private static void ensureThreadLocked() {
if (sInstance == null) {
sInstance = new UiThread();
sInstance.start();
sHandler = new Handler(sInstance.getLooper());
sHandler.post(new Runnable() {
@Override
public void run() {
//Looper.myLooper().setMessageLogging(new LogPrinter(
// Log.VERBOSE, "WindowManagerPolicy", Log.LOG_ID_SYSTEM));
android.os.Process.setCanSelfBackground(false);
// For debug builds, log event loop stalls to dropbox for analysis.
if (StrictMode.conditionallyEnableDebugLogging()) {
Slog.i("UiThread", "Enabled StrictMode logging for UI thread");
}
}
});
}
}
public static UiThread get() {
synchronized (UiThread.class) {
ensureThreadLocked();
return sInstance;
}
}
public static Handler getHandler() {
synchronized (UiThread.class) {
ensureThreadLocked();
return sHandler;
}
}
}

View File

@@ -80,15 +80,13 @@ public class Watchdog extends Thread {
static Watchdog sWatchdog;
/* This handler will be used to post message back onto the main thread */
final Handler mHandler;
final ArrayList<Monitor> mMonitors = new ArrayList<Monitor>();
final ArrayList<HandlerChecker> mHandlerCheckers = new ArrayList<HandlerChecker>();
final HandlerChecker mMonitorChecker;
ContentResolver mResolver;
BatteryService mBattery;
PowerManagerService mPower;
AlarmManagerService mAlarm;
ActivityManagerService mActivity;
boolean mCompleted;
Monitor mCurrentMonitor;
int mPhonePid;
@@ -111,40 +109,65 @@ public class Watchdog extends Thread {
int mReqRecheckInterval= -1; // >= 0 if a specific recheck interval has been requested
/**
* Used for scheduling monitor callbacks and checking memory usage.
* Used for checking status of handle threads and scheduling monitor callbacks.
*/
final class HeartbeatHandler extends Handler {
HeartbeatHandler(Looper looper) {
super(looper);
public final class HandlerChecker implements Runnable {
private final Handler mHandler;
private final String mName;
private final ArrayList<Monitor> mMonitors = new ArrayList<Monitor>();
private final boolean mCheckReboot;
private boolean mCompleted;
private Monitor mCurrentMonitor;
HandlerChecker(Handler handler, String name, boolean checkReboot) {
mHandler = handler;
mName = name;
mCheckReboot = checkReboot;
}
public void addMonitor(Monitor monitor) {
mMonitors.add(monitor);
}
public void scheduleCheckLocked() {
mCompleted = false;
mCurrentMonitor = null;
mHandler.postAtFrontOfQueue(this);
}
public boolean isCompletedLocked() {
return mCompleted;
}
public String describeBlockedStateLocked() {
return mCurrentMonitor == null ? mName : mCurrentMonitor.getClass().getName();
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MONITOR: {
// See if we should force a reboot.
int rebootInterval = mReqRebootInterval >= 0
? mReqRebootInterval : REBOOT_DEFAULT_INTERVAL;
if (mRebootInterval != rebootInterval) {
mRebootInterval = rebootInterval;
// We have been running long enough that a reboot can
// be considered...
checkReboot(false);
}
public void run() {
// See if we should force a reboot.
if (mCheckReboot) {
int rebootInterval = mReqRebootInterval >= 0
? mReqRebootInterval : REBOOT_DEFAULT_INTERVAL;
if (mRebootInterval != rebootInterval) {
mRebootInterval = rebootInterval;
// We have been running long enough that a reboot can
// be considered...
checkReboot(false);
}
}
final int size = mMonitors.size();
for (int i = 0 ; i < size ; i++) {
synchronized (Watchdog.this) {
mCurrentMonitor = mMonitors.get(i);
}
mCurrentMonitor.monitor();
}
final int size = mMonitors.size();
for (int i = 0 ; i < size ; i++) {
synchronized (Watchdog.this) {
mCurrentMonitor = mMonitors.get(i);
}
mCurrentMonitor.monitor();
}
synchronized (Watchdog.this) {
mCompleted = true;
mCurrentMonitor = null;
}
} break;
synchronized (Watchdog.this) {
mCompleted = true;
mCurrentMonitor = null;
}
}
}
@@ -189,9 +212,23 @@ public class Watchdog extends Thread {
private Watchdog() {
super("watchdog");
// Explicitly bind the HeartbeatHandler to run on the ServerThread, so
// that it can't get accidentally bound to another thread.
mHandler = new HeartbeatHandler(Looper.getMainLooper());
// Initialize handler checkers for each common thread we want to check. Note
// that we are not currently checking the background thread, since it can
// potentially hold longer running operations with no guarantees about the timeliness
// of operations there.
// The shared foreground thread is the main checker. It is where we
// will also dispatch monitor checks and do other work.
mMonitorChecker = new HandlerChecker(FgThread.getHandler(), "foreground thread", true);
mHandlerCheckers.add(mMonitorChecker);
// Add checker for main thread. We only do a quick check since there
// can be UI running on the thread.
mHandlerCheckers.add(new HandlerChecker(new Handler(Looper.getMainLooper()),
"main thread", false));
// Add checker for shared UI thread.
mHandlerCheckers.add(new HandlerChecker(UiThread.getHandler(), "ui thread", false));
// And also check IO thread.
mHandlerCheckers.add(new HandlerChecker(IoThread.getHandler(), "i/o thread", false));
}
public void init(Context context, BatteryService battery,
@@ -226,9 +263,18 @@ public class Watchdog extends Thread {
public void addMonitor(Monitor monitor) {
synchronized (this) {
if (isAlive()) {
throw new RuntimeException("Monitors can't be added while the Watchdog is running");
throw new RuntimeException("Monitors can't be added once the Watchdog is running");
}
mMonitors.add(monitor);
mMonitorChecker.addMonitor(monitor);
}
}
public void addThread(Handler thread, String name) {
synchronized (this) {
if (isAlive()) {
throw new RuntimeException("Threads can't be added once the Watchdog is running");
}
mHandlerCheckers.add(new HandlerChecker(thread, name, false));
}
}
@@ -382,6 +428,30 @@ public class Watchdog extends Thread {
return newTime;
}
private boolean haveAllCheckersCompletedLocked() {
for (int i=0; i<mHandlerCheckers.size(); i++) {
HandlerChecker hc = mHandlerCheckers.get(i);
if (!hc.isCompletedLocked()) {
return false;
}
}
return true;
}
private String describeBlockedCheckersLocked() {
StringBuilder builder = new StringBuilder(128);
for (int i=0; i<mHandlerCheckers.size(); i++) {
HandlerChecker hc = mHandlerCheckers.get(i);
if (!hc.isCompletedLocked()) {
if (builder.length() > 0) {
builder.append(", ");
}
builder.append(hc.describeBlockedStateLocked());
}
}
return builder.toString();
}
@Override
public void run() {
boolean waitedHalf = false;
@@ -389,8 +459,14 @@ public class Watchdog extends Thread {
final String name;
synchronized (this) {
long timeout = TIME_TO_WAIT;
mCompleted = false;
mHandler.sendEmptyMessage(MONITOR);
if (!waitedHalf) {
// If we are not at the half-point of waiting, perform a
// new set of checks. Otherwise we are still waiting for a previous set.
for (int i=0; i<mHandlerCheckers.size(); i++) {
HandlerChecker hc = mHandlerCheckers.get(i);
hc.scheduleCheckLocked();
}
}
// NOTE: We use uptimeMillis() here because we do not want to increment the time we
// wait while asleep. If the device is asleep then the thing that we are waiting
@@ -406,7 +482,7 @@ public class Watchdog extends Thread {
timeout = TIME_TO_WAIT - (SystemClock.uptimeMillis() - start);
}
if (mCompleted) {
if (haveAllCheckersCompletedLocked()) {
// The monitors have returned.
waitedHalf = false;
continue;
@@ -423,8 +499,7 @@ public class Watchdog extends Thread {
continue;
}
name = (mCurrentMonitor != null) ?
mCurrentMonitor.getClass().getName() : "main thread blocked";
name = describeBlockedCheckersLocked();
}
// If we got here, that means that the system is most likely hung.

View File

@@ -56,7 +56,6 @@ import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
@@ -74,6 +73,7 @@ import android.util.SparseArray;
import com.android.internal.R;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.FgThread;
import com.google.android.collect.Lists;
import com.google.android.collect.Sets;
@@ -113,7 +113,6 @@ public class AccountManagerService
private final PackageManager mPackageManager;
private UserManager mUserManager;
private HandlerThread mMessageThread;
private final MessageHandler mMessageHandler;
// Messages that can be sent on mHandler
@@ -234,9 +233,7 @@ public class AccountManagerService
mContext = context;
mPackageManager = packageManager;
mMessageThread = new HandlerThread("AccountManagerService");
mMessageThread.start();
mMessageHandler = new MessageHandler(mMessageThread.getLooper());
mMessageHandler = new MessageHandler(FgThread.get().getLooper());
mAuthenticatorCache = authenticatorCache;
mAuthenticatorCache.setListener(this, null /* Handler */);

View File

@@ -37,13 +37,10 @@ import android.net.NetworkInfo;
import android.net.NetworkUtils;
import android.net.RouteInfo;
import android.os.Binder;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
@@ -53,6 +50,7 @@ import com.android.internal.telephony.PhoneConstants;
import com.android.internal.util.IState;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import com.android.server.IoThread;
import com.google.android.collect.Lists;
import java.io.FileDescriptor;
@@ -100,7 +98,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
private final INetworkStatsService mStatsService;
private final IConnectivityManager mConnService;
private Looper mLooper;
private HandlerThread mThread;
private HashMap<String, TetherInterfaceSM> mIfaces; // all tethered/tetherable ifaces
@@ -147,9 +144,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
mIfaces = new HashMap<String, TetherInterfaceSM>();
// make our own thread so we don't anr the system
mThread = new HandlerThread("Tethering");
mThread.start();
mLooper = mThread.getLooper();
mLooper = IoThread.get().getLooper();
mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper);
mTetherMasterSM.start();

View File

@@ -53,12 +53,10 @@ import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
@@ -74,6 +72,7 @@ import android.util.Pair;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.accounts.AccountManagerService;
import com.android.server.content.SyncStorageEngine.OnSyncRequestListener;
@@ -82,7 +81,6 @@ import com.google.android.collect.Maps;
import com.google.android.collect.Sets;
import java.io.FileDescriptor;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
@@ -381,10 +379,7 @@ public class SyncManager {
mSyncAdapters = new SyncAdaptersCache(mContext);
mSyncQueue = new SyncQueue(mContext.getPackageManager(), mSyncStorageEngine, mSyncAdapters);
HandlerThread syncThread = new HandlerThread("SyncHandlerThread",
Process.THREAD_PRIORITY_BACKGROUND);
syncThread.start();
mSyncHandler = new SyncHandler(syncThread.getLooper());
mSyncHandler = new SyncHandler(BackgroundThread.get().getLooper());
mSyncAdapters.setListener(new RegisteredServicesCacheListener<SyncAdapterType>() {
@Override

View File

@@ -37,6 +37,7 @@ import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
import android.view.DisplayInfo;
import com.android.server.UiThread;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -190,12 +191,12 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
private final DisplayViewport mTempDefaultViewport = new DisplayViewport();
private final DisplayViewport mTempExternalTouchViewport = new DisplayViewport();
public DisplayManagerService(Context context, Handler mainHandler, Handler uiHandler) {
public DisplayManagerService(Context context, Handler mainHandler) {
mContext = context;
mHeadless = SystemProperties.get(SYSTEM_HEADLESS).equals("1");
mHandler = new DisplayManagerHandler(mainHandler.getLooper());
mUiHandler = uiHandler;
mUiHandler = UiThread.getHandler();
mDisplayAdapterListener = new DisplayAdapterListener();
mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);

View File

@@ -106,7 +106,6 @@ import android.net.wifi.WifiManager;
import android.os.Binder;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.INetworkManagementService;
import android.os.IPowerManager;
import android.os.Message;
@@ -134,6 +133,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Objects;
import com.android.server.IoThread;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
import com.google.android.collect.Sets;
@@ -274,7 +274,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private final RemoteCallbackList<INetworkPolicyListener> mListeners = new RemoteCallbackList<
INetworkPolicyListener>();
private final HandlerThread mHandlerThread;
private final Handler mHandler;
private final AtomicFile mPolicyFile;
@@ -306,9 +305,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mNetworkManager = checkNotNull(networkManagement, "missing networkManagement");
mTime = checkNotNull(time, "missing TrustedTime");
mHandlerThread = new HandlerThread(TAG);
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback);
mHandler = new Handler(IoThread.get().getLooper(), mHandlerCallback);
mSuppressDefaultPolicy = suppressDefaultPolicy;

View File

@@ -96,7 +96,6 @@ import android.os.Binder;
import android.os.DropBoxManager;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.INetworkManagementService;
import android.os.Message;
import android.os.PowerManager;
@@ -120,6 +119,7 @@ import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FileRotator;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.EventLogTags;
import com.android.server.IoThread;
import com.android.server.connectivity.Tethering;
import com.google.android.collect.Maps;
@@ -240,7 +240,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
/** Data layer operation counters for splicing into other structures. */
private NetworkStats mUidOperations = new NetworkStats(0L, 10);
private final HandlerThread mHandlerThread;
private final Handler mHandler;
private boolean mSystemReady;
@@ -271,9 +270,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
Context.POWER_SERVICE);
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
mHandlerThread = new HandlerThread(TAG);
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback);
mHandler = new Handler(IoThread.get().getLooper(), mHandlerCallback);
mSystemDir = checkNotNull(systemDir);
mBaseDir = new File(systemDir, "netstats");

View File

@@ -22,15 +22,14 @@ import android.content.Intent;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Environment;
import android.os.FileUtils;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.os.SystemClock;
import android.util.Slog;
import android.util.Base64;
import com.android.server.FgThread;
import java.lang.Thread;
import java.io.File;
@@ -54,7 +53,6 @@ public class UsbDebuggingManager implements Runnable {
private final Context mContext;
private final Handler mHandler;
private final HandlerThread mHandlerThread;
private Thread mThread;
private boolean mAdbEnabled = false;
private String mFingerprints;
@@ -62,9 +60,7 @@ public class UsbDebuggingManager implements Runnable {
private OutputStream mOutputStream = null;
public UsbDebuggingManager(Context context) {
mHandlerThread = new HandlerThread("UsbDebuggingHandler");
mHandlerThread.start();
mHandler = new UsbDebuggingHandler(mHandlerThread.getLooper());
mHandler = new UsbDebuggingHandler(FgThread.get().getLooper());
mContext = context;
}
@@ -165,7 +161,7 @@ public class UsbDebuggingManager implements Runnable {
mAdbEnabled = true;
mThread = new Thread(UsbDebuggingManager.this);
mThread = new Thread(UsbDebuggingManager.this, "UsbDebuggingManager");
mThread.start();
break;

View File

@@ -32,11 +32,9 @@ import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbManager;
import android.os.FileUtils;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UEventObserver;
@@ -48,6 +46,7 @@ import android.util.Pair;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.server.FgThread;
import java.io.File;
import java.io.FileDescriptor;
@@ -158,11 +157,7 @@ public class UsbDeviceManager {
readOemUsbOverrideConfig();
// create a thread for our Handler
HandlerThread thread = new HandlerThread("UsbDeviceManager",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
mHandler = new UsbHandler(thread.getLooper());
mHandler = new UsbHandler(FgThread.get().getLooper());
if (nativeIsStartRequested()) {
if (DEBUG) Slog.d(TAG, "accessory attached at boot");

View File

@@ -34,6 +34,7 @@ import com.android.internal.view.IInputMethodManager;
import com.android.internal.view.WindowManagerPolicyThread;
import com.android.server.AttributeCache;
import com.android.server.EventLogTags;
import com.android.server.UiThread;
import com.android.server.Watchdog;
import com.android.server.am.BatteryStatsService;
import com.android.server.display.DisplayManagerService;
@@ -701,8 +702,7 @@ public class WindowManagerService extends IWindowManager.Stub
public static WindowManagerService main(final Context context,
final PowerManagerService pm, final DisplayManagerService dm,
final InputManagerService im,
final Handler uiHandler, final Handler wmHandler,
final InputManagerService im, final Handler wmHandler,
final boolean haveInputMethods, final boolean showBootMsgs,
final boolean onlyCore) {
final WindowManagerService[] holder = new WindowManagerService[1];
@@ -710,7 +710,7 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public void run() {
holder[0] = new WindowManagerService(context, pm, dm, im,
uiHandler, haveInputMethods, showBootMsgs, onlyCore);
haveInputMethods, showBootMsgs, onlyCore);
}
}, 0);
return holder[0];
@@ -732,7 +732,6 @@ public class WindowManagerService extends IWindowManager.Stub
private WindowManagerService(Context context, PowerManagerService pm,
DisplayManagerService displayManager, InputManagerService inputManager,
Handler uiHandler,
boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) {
mContext = context;
mHaveInputMethods = haveInputMethods;
@@ -795,7 +794,7 @@ public class WindowManagerService extends IWindowManager.Stub
mFxSession = new SurfaceSession();
mAnimator = new WindowAnimator(this);
initPolicy(uiHandler);
initPolicy(UiThread.getHandler());
// Add ourself to the Watchdog monitors.
Watchdog.getInstance().addMonitor(this);