diff options
10 files changed, 138 insertions, 67 deletions
diff --git a/core/java/android/os/Handler.java b/core/java/android/os/Handler.java index 77853683b2e5..4e2b5c0a892d 100644 --- a/core/java/android/os/Handler.java +++ b/core/java/android/os/Handler.java @@ -101,37 +101,88 @@ public class Handler { } /** - * Default constructor associates this handler with the queue for the + * Default constructor associates this handler with the {@link Looper} for the * current thread. * - * If there isn't one, this handler won't be able to receive messages. + * If this thread does not have a looper, this handler won't be able to receive messages + * so an exception is thrown. */ public Handler() { - if (FIND_POTENTIAL_LEAKS) { - final Class<? extends Handler> klass = getClass(); - if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && - (klass.getModifiers() & Modifier.STATIC) == 0) { - Log.w(TAG, "The following Handler class should be static or leaks might occur: " + - klass.getCanonicalName()); - } - } - - mLooper = Looper.myLooper(); - if (mLooper == null) { - throw new RuntimeException( - "Can't create handler inside thread that has not called Looper.prepare()"); - } - mQueue = mLooper.mQueue; - mCallback = null; - mAsynchronous = false; + this(null, false); } /** - * Constructor associates this handler with the queue for the + * Constructor associates this handler with the {@link Looper} for the * current thread and takes a callback interface in which you can handle * messages. + * + * If this thread does not have a looper, this handler won't be able to receive messages + * so an exception is thrown. + * + * @param callback The callback interface in which to handle messages, or null. */ public Handler(Callback callback) { + this(callback, false); + } + + /** + * Use the provided {@link Looper} instead of the default one. + * + * @param looper The looper, must not be null. + */ + public Handler(Looper looper) { + this(looper, null, false); + } + + /** + * Use the provided {@link Looper} instead of the default one and take a callback + * interface in which to handle messages. + * + * @param looper The looper, must not be null. + * @param callback The callback interface in which to handle messages, or null. + */ + public Handler(Looper looper, Callback callback) { + this(looper, callback, false); + } + + /** + * Use the {@link Looper} for the current thread + * and set whether the handler should be asynchronous. + * + * Handlers are synchronous by default unless this constructor is used to make + * one that is strictly asynchronous. + * + * Asynchronous messages represent interrupts or events that do not require global ordering + * with represent to synchronous messages. Asynchronous messages are not subject to + * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}. + * + * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for + * each {@link Message} that is sent to it or {@link Runnable} that is posted to it. + * + * @hide + */ + public Handler(boolean async) { + this(null, async); + } + + /** + * Use the {@link Looper} for the current thread with the specified callback interface + * and set whether the handler should be asynchronous. + * + * Handlers are synchronous by default unless this constructor is used to make + * one that is strictly asynchronous. + * + * Asynchronous messages represent interrupts or events that do not require global ordering + * with represent to synchronous messages. Asynchronous messages are not subject to + * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}. + * + * @param callback The callback interface in which to handle messages, or null. + * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for + * each {@link Message} that is sent to it or {@link Runnable} that is posted to it. + * + * @hide + */ + public Handler(Callback callback, boolean async) { if (FIND_POTENTIAL_LEAKS) { final Class<? extends Handler> klass = getClass(); if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && @@ -148,32 +199,11 @@ public class Handler { } mQueue = mLooper.mQueue; mCallback = callback; - mAsynchronous = false; - } - - /** - * Use the provided queue instead of the default one. - */ - public Handler(Looper looper) { - mLooper = looper; - mQueue = looper.mQueue; - mCallback = null; - mAsynchronous = false; - } - - /** - * Use the provided queue instead of the default one and take a callback - * interface in which to handle messages. - */ - public Handler(Looper looper, Callback callback) { - mLooper = looper; - mQueue = looper.mQueue; - mCallback = callback; - mAsynchronous = false; + mAsynchronous = async; } /** - * Use the provided queue instead of the default one and take a callback + * Use the provided {@link Looper} instead of the default one and take a callback * interface in which to handle messages. Also set whether the handler * should be asynchronous. * @@ -184,6 +214,8 @@ public class Handler { * with represent to synchronous messages. Asynchronous messages are not subject to * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}. * + * @param looper The looper, must not be null. + * @param callback The callback interface in which to handle messages, or null. * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for * each {@link Message} that is sent to it or {@link Runnable} that is posted to it. * diff --git a/core/java/android/service/dreams/DreamManagerService.java b/core/java/android/service/dreams/DreamManagerService.java index 4b0f7c528819..2cec6c3dff54 100644 --- a/core/java/android/service/dreams/DreamManagerService.java +++ b/core/java/android/service/dreams/DreamManagerService.java @@ -105,7 +105,7 @@ public class DreamManagerService public ComponentName[] getDreamComponents() { // TODO(dsandler) don't load this every time, watch the value String names = Settings.Secure.getString(mContext.getContentResolver(), SCREENSAVER_COMPONENTS); - return componentsFromString(names); + return names == null ? null : componentsFromString(names); } // IDreamManager method diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java index 3ea50201502f..236a4ea48350 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java @@ -971,7 +971,7 @@ public class KeyguardViewMediator implements KeyguardViewCallback { * interacts with the keyguard ui should be posted to this handler, rather * than called directly. */ - private Handler mHandler = new Handler(Looper.myLooper(), null, true /*async*/) { + private Handler mHandler = new Handler(true /*async*/) { @Override public void handleMessage(Message msg) { switch (msg.what) { diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java index 2bed95732a29..f1ff27ff351b 100644 --- a/services/java/com/android/server/DockObserver.java +++ b/services/java/com/android/server/DockObserver.java @@ -241,7 +241,7 @@ final class DockObserver extends UEventObserver { SCREENSAVER_ACTIVATE_ON_DOCK, DEFAULT_SCREENSAVER_ACTIVATED_ON_DOCK) != 0; } - private final Handler mHandler = new Handler(Looper.myLooper(), null, true) { + private final Handler mHandler = new Handler(true /*async*/) { @Override public void handleMessage(Message msg) { switch (msg.what) { diff --git a/services/java/com/android/server/input/InputManagerService.java b/services/java/com/android/server/input/InputManagerService.java index 0b8ff620c4cc..29c68ebf0424 100644 --- a/services/java/com/android/server/input/InputManagerService.java +++ b/services/java/com/android/server/input/InputManagerService.java @@ -1438,6 +1438,10 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog. * Private handler for the input manager. */ private final class InputManagerHandler extends Handler { + public InputManagerHandler() { + super(true /*async*/); + } + @Override public void handleMessage(Message msg) { switch (msg.what) { diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java index 32b3597fa4aa..c2c0a71f218d 100755 --- a/services/java/com/android/server/location/GpsLocationProvider.java +++ b/services/java/com/android/server/location/GpsLocationProvider.java @@ -598,6 +598,8 @@ public class GpsLocationProvider implements LocationProviderInterface { } mInjectNtpTimePending = STATE_DOWNLOADING; + // hold wake lock while task runs + mWakeLock.acquire(); AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() { @Override public void run() { @@ -628,14 +630,16 @@ public class GpsLocationProvider implements LocationProviderInterface { delay = RETRY_INTERVAL; } - mHandler.sendMessage(Message.obtain(mHandler, INJECT_NTP_TIME_FINISHED)); + sendMessage(INJECT_NTP_TIME_FINISHED, 0, null); if (mPeriodicTimeInjection) { // send delayed message for next NTP injection // since this is delayed and not urgent we do not hold a wake lock here - mHandler.removeMessages(INJECT_NTP_TIME); - mHandler.sendMessageDelayed(Message.obtain(mHandler, INJECT_NTP_TIME), delay); + mHandler.sendEmptyMessageDelayed(INJECT_NTP_TIME, delay); } + + // release wake lock held by task + mWakeLock.release(); } }); } @@ -652,6 +656,8 @@ public class GpsLocationProvider implements LocationProviderInterface { } mDownloadXtraDataPending = STATE_DOWNLOADING; + // hold wake lock while task runs + mWakeLock.acquire(); AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() { @Override public void run() { @@ -664,17 +670,17 @@ public class GpsLocationProvider implements LocationProviderInterface { native_inject_xtra_data(data, data.length); } - mHandler.sendMessage(Message.obtain(mHandler, DOWNLOAD_XTRA_DATA_FINISHED)); + sendMessage(DOWNLOAD_XTRA_DATA_FINISHED, 0, null); if (data == null) { // try again later // since this is delayed and not urgent we do not hold a wake lock here - mHandler.removeMessages(DOWNLOAD_XTRA_DATA); - mHandler.sendMessageDelayed(Message.obtain(mHandler, DOWNLOAD_XTRA_DATA), - RETRY_INTERVAL); + mHandler.sendEmptyMessageDelayed(DOWNLOAD_XTRA_DATA, RETRY_INTERVAL); } - } + // release wake lock held by task + mWakeLock.release(); + } }); } @@ -1475,11 +1481,17 @@ public class GpsLocationProvider implements LocationProviderInterface { private void sendMessage(int message, int arg, Object obj) { // hold a wake lock until this message is delivered + // note that this assumes the message will not be removed from the queue before + // it is handled (otherwise the wake lock would be leaked). mWakeLock.acquire(); mHandler.obtainMessage(message, arg, 1, obj).sendToTarget(); } private final class ProviderHandler extends Handler { + public ProviderHandler() { + super(true /*async*/); + } + @Override public void handleMessage(Message msg) { int message = msg.what; diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index 2a545cd358ea..0345df100b37 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -401,6 +401,7 @@ public class PackageManagerService extends IPackageManager.Stub { // package uri's from external media onto secure containers // or internal storage. private IMediaContainerService mContainerService = null; + private int mContainerServiceUserId; static final int SEND_PENDING_BROADCAST = 1; static final int MCS_BOUND = 3; @@ -469,8 +470,12 @@ public class PackageManagerService extends IPackageManager.Stub { " DefaultContainerService"); Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT); Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); + mContainerServiceUserId = 0; + if (mPendingInstalls.size() > 0) { + mContainerServiceUserId = mPendingInstalls.get(0).getUser().getIdentifier(); + } if (mContext.bindService(service, mDefContainerConn, - Context.BIND_AUTO_CREATE)) { + Context.BIND_AUTO_CREATE, mContainerServiceUserId)) { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); mBound = true; return true; @@ -547,6 +552,12 @@ public class PackageManagerService extends IPackageManager.Stub { } else if (mPendingInstalls.size() > 0) { HandlerParams params = mPendingInstalls.get(0); if (params != null) { + // Check if we're connected to the correct service, if it's an install + // request. + if (params.getUser().getIdentifier() != mContainerServiceUserId) { + mHandler.sendEmptyMessage(MCS_RECONNECT); + return; + } if (params.startCopy()) { // We are done... look for more work or to // go idle. @@ -5850,6 +5861,17 @@ public class PackageManagerService extends IPackageManager.Stub { */ private int mRetries = 0; + /** User handle for the user requesting the information or installation. */ + private final UserHandle mUser; + + HandlerParams(UserHandle user) { + mUser = user; + } + + UserHandle getUser() { + return mUser; + } + final boolean startCopy() { boolean res; try { @@ -5891,6 +5913,7 @@ public class PackageManagerService extends IPackageManager.Stub { private final IPackageStatsObserver mObserver; public MeasureParams(PackageStats stats, IPackageStatsObserver observer) { + super(new UserHandle(stats.userHandle)); mObserver = observer; mStats = stats; } @@ -5969,19 +5992,18 @@ public class PackageManagerService extends IPackageManager.Stub { private int mRet; private File mTempPackage; final ContainerEncryptionParams encryptionParams; - final UserHandle user; InstallParams(Uri packageURI, IPackageInstallObserver observer, int flags, String installerPackageName, VerificationParams verificationParams, ContainerEncryptionParams encryptionParams, UserHandle user) { + super(user); this.mPackageURI = packageURI; this.flags = flags; this.observer = observer; this.installerPackageName = installerPackageName; this.verificationParams = verificationParams; this.encryptionParams = encryptionParams; - this.user = user; } public ManifestDigest getManifestDigest() { @@ -5991,10 +6013,6 @@ public class PackageManagerService extends IPackageManager.Stub { return verificationParams.getManifestDigest(); } - public UserHandle getUser() { - return user; - } - private int installLocationPolicy(PackageInfoLite pkgLite, int flags) { String packageName = pkgLite.packageName; int installLocation = pkgLite.installLocation; @@ -6332,7 +6350,8 @@ public class PackageManagerService extends IPackageManager.Stub { int mRet; MoveParams(InstallArgs srcArgs, IPackageMoveObserver observer, int flags, - String packageName, String dataDir, int uid) { + String packageName, String dataDir, int uid, UserHandle user) { + super(user); this.srcArgs = srcArgs; this.observer = observer; this.flags = flags; @@ -9506,9 +9525,12 @@ public class PackageManagerService extends IPackageManager.Stub { } } + /** Binder call */ + @Override public void movePackage(final String packageName, final IPackageMoveObserver observer, final int flags) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null); + UserHandle user = new UserHandle(UserHandle.getCallingUserId()); int returnCode = PackageManager.MOVE_SUCCEEDED; int currFlags = 0; int newFlags = 0; @@ -9559,14 +9581,15 @@ public class PackageManagerService extends IPackageManager.Stub { * anyway. */ if (returnCode != PackageManager.MOVE_SUCCEEDED) { - processPendingMove(new MoveParams(null, observer, 0, packageName, null, -1), + processPendingMove(new MoveParams(null, observer, 0, packageName, + null, -1, user), returnCode); } else { Message msg = mHandler.obtainMessage(INIT_COPY); InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir, pkg.applicationInfo.publicSourceDir, pkg.applicationInfo.nativeLibraryDir); MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName, - pkg.applicationInfo.dataDir, pkg.applicationInfo.uid); + pkg.applicationInfo.dataDir, pkg.applicationInfo.uid, user); msg.obj = mp; mHandler.sendMessage(msg); } diff --git a/services/java/com/android/server/power/DisplayPowerController.java b/services/java/com/android/server/power/DisplayPowerController.java index 5f917af174ef..cd211da09973 100644 --- a/services/java/com/android/server/power/DisplayPowerController.java +++ b/services/java/com/android/server/power/DisplayPowerController.java @@ -1112,7 +1112,7 @@ final class DisplayPowerController { private final class DisplayControllerHandler extends Handler { public DisplayControllerHandler(Looper looper) { - super(looper); + super(looper, null, true /*async*/); } @Override diff --git a/services/java/com/android/server/power/Notifier.java b/services/java/com/android/server/power/Notifier.java index 9d928e503420..75f84457a143 100644 --- a/services/java/com/android/server/power/Notifier.java +++ b/services/java/com/android/server/power/Notifier.java @@ -422,7 +422,7 @@ final class Notifier { private final class NotifierHandler extends Handler { public NotifierHandler(Looper looper) { - super(looper); + super(looper, null, true /*async*/); } @Override diff --git a/services/java/com/android/server/power/PowerManagerService.java b/services/java/com/android/server/power/PowerManagerService.java index dc900ca57b18..6d681046a2c6 100644 --- a/services/java/com/android/server/power/PowerManagerService.java +++ b/services/java/com/android/server/power/PowerManagerService.java @@ -1961,7 +1961,7 @@ public final class PowerManagerService extends IPowerManager.Stub */ private final class PowerManagerHandler extends Handler { public PowerManagerHandler(Looper looper) { - super(looper); + super(looper, null, true /*async*/); } @Override |