diff options
Diffstat (limited to 'services/java')
21 files changed, 354 insertions, 157 deletions
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java index d5715a5..5b76f39 100644 --- a/services/java/com/android/server/AppWidgetService.java +++ b/services/java/com/android/server/AppWidgetService.java @@ -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); diff --git a/services/java/com/android/server/BluetoothManagerService.java b/services/java/com/android/server/BluetoothManagerService.java index ea7b696..8684e5b 100644 --- a/services/java/com/android/server/BluetoothManagerService.java +++ b/services/java/com/android/server/BluetoothManagerService.java @@ -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; diff --git a/services/java/com/android/server/CountryDetectorService.java b/services/java/com/android/server/CountryDetectorService.java index fc76277..8407fa4 100644 --- a/services/java/com/android/server/CountryDetectorService.java +++ b/services/java/com/android/server/CountryDetectorService.java @@ -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) { diff --git a/services/java/com/android/server/FgThread.java b/services/java/com/android/server/FgThread.java new file mode 100644 index 0000000..3b655f2 --- /dev/null +++ b/services/java/com/android/server/FgThread.java @@ -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; + } + } +} diff --git a/services/java/com/android/server/IoThread.java b/services/java/com/android/server/IoThread.java new file mode 100644 index 0000000..b443578 --- /dev/null +++ b/services/java/com/android/server/IoThread.java @@ -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; + } + } +} diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java index 2675309..b162c6b 100644 --- a/services/java/com/android/server/LocationManagerService.java +++ b/services/java/com/android/server/LocationManagerService.java @@ -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); diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java index e8d7882..9f40000 100644 --- a/services/java/com/android/server/MountService.java +++ b/services/java/com/android/server/MountService.java @@ -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 diff --git a/services/java/com/android/server/NativeDaemonConnector.java b/services/java/com/android/server/NativeDaemonConnector.java index c3f2afa..abcd8ee 100644 --- a/services/java/com/android/server/NativeDaemonConnector.java +++ b/services/java/com/android/server/NativeDaemonConnector.java @@ -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 { diff --git a/services/java/com/android/server/NetworkTimeUpdateService.java b/services/java/com/android/server/NetworkTimeUpdateService.java index 3bfd190..02b42b8 100644 --- a/services/java/com/android/server/NetworkTimeUpdateService.java +++ b/services/java/com/android/server/NetworkTimeUpdateService.java @@ -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(); diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index b263680..3f9d666 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -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); diff --git a/services/java/com/android/server/UiThread.java b/services/java/com/android/server/UiThread.java new file mode 100644 index 0000000..60d73aa --- /dev/null +++ b/services/java/com/android/server/UiThread.java @@ -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; + } + } +} diff --git a/services/java/com/android/server/Watchdog.java b/services/java/com/android/server/Watchdog.java index d4d3850..fc95790 100644 --- a/services/java/com/android/server/Watchdog.java +++ b/services/java/com/android/server/Watchdog.java @@ -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. diff --git a/services/java/com/android/server/accounts/AccountManagerService.java b/services/java/com/android/server/accounts/AccountManagerService.java index 2e8d6df..d1236c1 100644 --- a/services/java/com/android/server/accounts/AccountManagerService.java +++ b/services/java/com/android/server/accounts/AccountManagerService.java @@ -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 */); diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java index 32f39b7..87263b3 100644 --- a/services/java/com/android/server/connectivity/Tethering.java +++ b/services/java/com/android/server/connectivity/Tethering.java @@ -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(); diff --git a/services/java/com/android/server/content/SyncManager.java b/services/java/com/android/server/content/SyncManager.java index 1c883ec..cf593ce 100644 --- a/services/java/com/android/server/content/SyncManager.java +++ b/services/java/com/android/server/content/SyncManager.java @@ -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 diff --git a/services/java/com/android/server/display/DisplayManagerService.java b/services/java/com/android/server/display/DisplayManagerService.java index 17b0662..ca85e42 100644 --- a/services/java/com/android/server/display/DisplayManagerService.java +++ b/services/java/com/android/server/display/DisplayManagerService.java @@ -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); diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java index a82f421..5ca7242 100644 --- a/services/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java @@ -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; diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java index 74be472..5074409 100644 --- a/services/java/com/android/server/net/NetworkStatsService.java +++ b/services/java/com/android/server/net/NetworkStatsService.java @@ -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"); diff --git a/services/java/com/android/server/usb/UsbDebuggingManager.java b/services/java/com/android/server/usb/UsbDebuggingManager.java index 93d3114..ba3f1d1 100644 --- a/services/java/com/android/server/usb/UsbDebuggingManager.java +++ b/services/java/com/android/server/usb/UsbDebuggingManager.java @@ -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; diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java index 87aa8cce..3a5357a 100644 --- a/services/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/java/com/android/server/usb/UsbDeviceManager.java @@ -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"); diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index 6a2d3e2..24f8cf1 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -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); |