diff options
Diffstat (limited to 'services')
24 files changed, 351 insertions, 131 deletions
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java index 9607624..b2de963 100644 --- a/services/java/com/android/server/DevicePolicyManagerService.java +++ b/services/java/com/android/server/DevicePolicyManagerService.java @@ -401,6 +401,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } else if ("disable-camera".equals(tag)) { disableCamera = Boolean.parseBoolean( parser.getAttributeValue(null, "value")); + } else if ("disable-keyguard-features".equals(tag)) { + disabledKeyguardFeatures = Integer.parseInt( + parser.getAttributeValue(null, "value")); } else { Slog.w(TAG, "Unknown admin tag: " + tag); } @@ -457,6 +460,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { pw.println(encryptionRequested); pw.print(prefix); pw.print("disableCamera="); pw.println(disableCamera); + pw.print(prefix); pw.print("disabledKeyguardFeatures="); + pw.println(disabledKeyguardFeatures); } } diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java index ae95c4c..0087b57 100644 --- a/services/java/com/android/server/LocationManagerService.java +++ b/services/java/com/android/server/LocationManagerService.java @@ -325,6 +325,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run * @param userId the new active user's UserId */ private void switchUser(int userId) { + mBlacklist.switchUser(userId); //Log.d("LocationManagerService", "switchUser(" + mCurrentUserId + " -> " + userId + ")"); // TODO: remove this synchronized (mLock) { // TODO: inform previous user's Receivers that they will no longer receive updates @@ -639,7 +640,27 @@ public class LocationManagerService extends ILocationManager.Stub implements Run == PackageManager.PERMISSION_GRANTED) || (mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED); + } else { + // mock providers + LocationProviderInterface lp = mMockProviders.get(provider); + if (lp != null) { + ProviderProperties properties = lp.getProperties(); + if (properties != null) { + if (properties.mRequiresSatellite) { + // provider requiring satellites require FINE permission + return mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION) + == PackageManager.PERMISSION_GRANTED; + } else if (properties.mRequiresNetwork || properties.mRequiresCell) { + // provider requiring network and or cell require COARSE or FINE + return (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION) + == PackageManager.PERMISSION_GRANTED) || + (mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION) + == PackageManager.PERMISSION_GRANTED); + } + } + } } + return false; } @@ -1292,8 +1313,13 @@ public class LocationManagerService extends ILocationManager.Stub implements Run @Override public boolean isProviderEnabled(String provider) { - checkPermission(); + String perms = checkPermission(); if (LocationManager.FUSED_PROVIDER.equals(provider)) return false; + if (ACCESS_COARSE_LOCATION.equals(perms) && + !isProviderAllowedByCoarsePermission(provider)) { + throw new SecurityException("The \"" + provider + + "\" provider requires ACCESS_FINE_LOCATION permission"); + } synchronized (mLock) { LocationProviderInterface p = mProvidersByName.get(provider); diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java index 5d5f8d3..8d6c604 100755 --- a/services/java/com/android/server/NotificationManagerService.java +++ b/services/java/com/android/server/NotificationManagerService.java @@ -1240,7 +1240,7 @@ public class NotificationManagerService extends INotificationManager.Stub if ((r.notification.flags & mustNotHaveFlags) != 0) { continue; } - if (!r.pkg.equals(pkg)) { + if (pkg != null && !r.pkg.equals(pkg)) { continue; } canceledSomething = true; diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/java/com/android/server/StatusBarManagerService.java index 5d9441b..439eebe 100644 --- a/services/java/com/android/server/StatusBarManagerService.java +++ b/services/java/com/android/server/StatusBarManagerService.java @@ -544,7 +544,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub int i; for (i=0; i<N; i++) { DisableRecord t = mDisableRecords.get(i); - if (t.token == token) { + if (t.token == token && t.userId == userId) { tok = t; break; } diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java index 4225913..98f561c 100644 --- a/services/java/com/android/server/WallpaperManagerService.java +++ b/services/java/com/android/server/WallpaperManagerService.java @@ -38,6 +38,7 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.UserInfo; import android.content.res.Resources; import android.os.Binder; import android.os.Bundle; @@ -53,6 +54,7 @@ import android.os.SELinux; import android.os.ServiceManager; import android.os.SystemClock; import android.os.UserHandle; +import android.os.UserManager; import android.service.wallpaper.IWallpaperConnection; import android.service.wallpaper.IWallpaperEngine; import android.service.wallpaper.IWallpaperService; @@ -511,6 +513,9 @@ class WallpaperManagerService extends IWallpaperManager.Stub { wallpaper = new WallpaperData(userId); mWallpaperMap.put(userId, wallpaper); loadSettingsLocked(userId); + } + // Not started watching yet, in case wallpaper data was loaded for other reasons. + if (wallpaper.wallpaperObserver == null) { wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper); wallpaper.wallpaperObserver.startWatching(); } @@ -580,9 +585,21 @@ class WallpaperManagerService extends IWallpaperManager.Stub { public boolean hasNamedWallpaper(String name) { synchronized (mLock) { - for (int i=0; i<mWallpaperMap.size(); i++) { - WallpaperData wd = mWallpaperMap.valueAt(i); - if (name.equals(wd.name)) { + List<UserInfo> users; + long ident = Binder.clearCallingIdentity(); + try { + users = ((UserManager) mContext.getSystemService(Context.USER_SERVICE)).getUsers(); + } finally { + Binder.restoreCallingIdentity(ident); + } + for (UserInfo user: users) { + WallpaperData wd = mWallpaperMap.get(user.id); + if (wd == null) { + // User hasn't started yet, so load her settings to peek at the wallpaper + loadSettingsLocked(user.id); + wd = mWallpaperMap.get(user.id); + } + if (wd != null && name.equals(wd.name)) { return true; } } diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java index 2d81b6c..b3bf6fe 100644 --- a/services/java/com/android/server/accessibility/TouchExplorer.java +++ b/services/java/com/android/server/accessibility/TouchExplorer.java @@ -102,10 +102,6 @@ class TouchExplorer implements EventStreamTransformation { // The timeout after which we are no longer trying to detect a gesture. private static final int EXIT_GESTURE_DETECTION_TIMEOUT = 2000; - // The timeout to send interaction end events in case we did not - // receive the expected hover exit event due to a misbehaving app. - private static final int SEND_INTERACTION_END_EVENTS_TIMEOUT = 200; - // Temporary array for storing pointer IDs. private final int[] mTempPointerIds = new int[MAX_POINTER_COUNT]; @@ -139,8 +135,11 @@ class TouchExplorer implements EventStreamTransformation { // Command for delayed sending of a hover exit event. private final SendHoverDelayed mSendHoverExitDelayed; - // Command for delayed sending of interaction ending events. - private final SendInteractionEndEventsDelayed mSendInteractionEndEventsDelayed; + // Command for delayed sending of touch exploration end events. + private final SendAccessibilityEventDelayed mSendTouchExplorationEndDelayed; + + // Command for delayed sending of touch interaction end events. + private final SendAccessibilityEventDelayed mSendTouchInteractionEndDelayed; // Command for delayed sending of a long press. private final PerformLongPressDelayed mPerformLongPressDelayed; @@ -209,11 +208,8 @@ class TouchExplorer implements EventStreamTransformation { // The id of the last touch explored window. private int mLastTouchedWindowId; - // Whether touch exploration gesture has ended. - private boolean mTouchExplorationGestureEnded; - - // Whether touch interaction has ended. - private boolean mTouchInteractionEnded; + // Whether touch exploration is in progress. + private boolean mTouchExplorationInProgress; /** * Creates a new instance. @@ -240,7 +236,12 @@ class TouchExplorer implements EventStreamTransformation { mGestureLibrary.load(); mSendHoverEnterDelayed = new SendHoverDelayed(MotionEvent.ACTION_HOVER_ENTER, true); mSendHoverExitDelayed = new SendHoverDelayed(MotionEvent.ACTION_HOVER_EXIT, false); - mSendInteractionEndEventsDelayed = new SendInteractionEndEventsDelayed(); + mSendTouchExplorationEndDelayed = new SendAccessibilityEventDelayed( + AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END, + mDetermineUserIntentTimeout); + mSendTouchInteractionEndDelayed = new SendAccessibilityEventDelayed( + AccessibilityEvent.TYPE_TOUCH_INTERACTION_END, + mDetermineUserIntentTimeout); mDoubleTapDetector = new DoubleTapDetector(); final float density = context.getResources().getDisplayMetrics().density; mScaledMinPointerDistanceToUseMiddleLocation = @@ -265,7 +266,7 @@ class TouchExplorer implements EventStreamTransformation { switch (mCurrentState) { case STATE_TOUCH_EXPLORING: { // If a touch exploration gesture is in progress send events for its end. - sendExitEventsIfNeeded(policyFlags); + sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags); } break; case STATE_DRAGGING: { mDraggingPointerId = INVALID_POINTER_ID; @@ -286,7 +287,8 @@ class TouchExplorer implements EventStreamTransformation { mSendHoverExitDelayed.remove(); mPerformLongPressDelayed.remove(); mExitGestureDetectionModeDelayed.remove(); - mSendInteractionEndEventsDelayed.remove(); + mSendTouchExplorationEndDelayed.remove(); + mSendTouchInteractionEndDelayed.remove(); // Reset the pointer trackers. mReceivedPointerTracker.clear(); mInjectedPointerTracker.clear(); @@ -301,6 +303,7 @@ class TouchExplorer implements EventStreamTransformation { if (mNext != null) { mNext.clear(); } + mTouchExplorationInProgress = false; } @Override @@ -341,19 +344,17 @@ class TouchExplorer implements EventStreamTransformation { // The event for gesture end should be strictly after the // last hover exit event. - if (mTouchExplorationGestureEnded + if (mSendTouchExplorationEndDelayed.isPending() && eventType == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT) { - mSendInteractionEndEventsDelayed.remove(); - mTouchExplorationGestureEnded = false; + mSendTouchExplorationEndDelayed.remove(); sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END); } // The event for touch interaction end should be strictly after the // last hover exit and the touch exploration gesture end events. - if (mTouchInteractionEnded + if (mSendTouchInteractionEndDelayed.isPending() && eventType == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT) { - mSendInteractionEndEventsDelayed.remove(); - mTouchInteractionEnded = false; + mSendTouchInteractionEndDelayed.remove(); sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END); } @@ -396,15 +397,6 @@ class TouchExplorer implements EventStreamTransformation { switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: - // The delayed enter not delivered implies that we have delivered - // TYPE_TOUCH_INTERACTION_START and not TYPE_TOUCH_INTERACTION_END, - // therefore we need to deliver the interaction end event here. - if (mSendHoverEnterDelayed.isPending()) { - sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END); - } - // Announce the start of a new touch interaction. - sendAccessibilityEvent( - AccessibilityEvent.TYPE_TOUCH_INTERACTION_START); // Pre-feed the motion events to the gesture detector since we // have a distance slop before getting into gesture detection // mode and not using the points within this slop significantly @@ -426,8 +418,20 @@ class TouchExplorer implements EventStreamTransformation { mSendHoverExitDelayed.remove(); } - if (mSendInteractionEndEventsDelayed.isPending()) { - mSendInteractionEndEventsDelayed.forceSendAndRemove(); + if (mSendTouchExplorationEndDelayed.isPending()) { + mSendTouchExplorationEndDelayed.forceSendAndRemove(); + } + + if (mSendTouchInteractionEndDelayed.isPending()) { + mSendTouchInteractionEndDelayed.forceSendAndRemove(); + } + + // Every pointer that goes down is active until it moves or + // another one goes down. Hence, having more than one pointer + // down we have already send the interaction start event. + if (event.getPointerCount() == 1) { + sendAccessibilityEvent( + AccessibilityEvent.TYPE_TOUCH_INTERACTION_START); } mPerformLongPressDelayed.remove(); @@ -443,11 +447,13 @@ class TouchExplorer implements EventStreamTransformation { mPerformLongPressDelayed.post(event, policyFlags); break; } - // Deliver hover enter with a delay to have a chance - // to detect what the user is trying to do. - final int pointerId = receivedTracker.getPrimaryActivePointerId(); - final int pointerIdBits = (1 << pointerId); - mSendHoverEnterDelayed.post(event, true, pointerIdBits, policyFlags); + if (!mTouchExplorationInProgress) { + // Deliver hover enter with a delay to have a chance + // to detect what the user is trying to do. + final int pointerId = receivedTracker.getPrimaryActivePointerId(); + final int pointerIdBits = (1 << pointerId); + mSendHoverEnterDelayed.post(event, true, pointerIdBits, policyFlags); + } } break; default: { /* do nothing - let the code for ACTION_MOVE decide what to do */ @@ -512,12 +518,27 @@ class TouchExplorer implements EventStreamTransformation { break; } } else { + // Cancel the long press if pending and the user + // moved more than the slop. + if (mPerformLongPressDelayed.isPending()) { + final float deltaX = + receivedTracker.getReceivedPointerDownX(pointerId) + - rawEvent.getX(pointerIndex); + final float deltaY = + receivedTracker.getReceivedPointerDownY(pointerId) + - rawEvent.getY(pointerIndex); + final double moveDelta = Math.hypot(deltaX, deltaY); + // The user has moved enough for us to decide. + if (moveDelta > mTouchSlop) { + mPerformLongPressDelayed.remove(); + } + } // The user is wither double tapping or performing long // press so do not send move events yet. if (mDoubleTapDetector.firstTapDetected()) { break; } - sendEnterEventsIfNeeded(policyFlags); + sendTouchExplorationGestureStartAndHoverEnterIfNeeded(policyFlags); sendMotionEvent(event, MotionEvent.ACTION_HOVER_MOVE, pointerIdBits, policyFlags); } @@ -548,7 +569,7 @@ class TouchExplorer implements EventStreamTransformation { } // We are sending events so send exit and gesture // end since we transition to another state. - sendExitEventsIfNeeded(policyFlags); + sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags); } // We know that a new state transition is to happen and the @@ -583,7 +604,7 @@ class TouchExplorer implements EventStreamTransformation { mPerformLongPressDelayed.remove(); // We are sending events so send exit and gesture // end since we transition to another state. - sendExitEventsIfNeeded(policyFlags); + sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags); } // More than two pointers are delegated to the view hierarchy. @@ -612,11 +633,14 @@ class TouchExplorer implements EventStreamTransformation { // If we have not delivered the enter schedule exit. if (mSendHoverEnterDelayed.isPending()) { - mSendHoverEnterDelayed.mTouchExplorationInProgress = false; mSendHoverExitDelayed.post(event, false, pointerIdBits, policyFlags); } else { // The user is touch exploring so we send events for end. - sendExitEventsIfNeeded(policyFlags); + sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags); + } + + if (!mSendTouchInteractionEndDelayed.isPending()) { + mSendTouchInteractionEndDelayed.post(); } } break; } @@ -846,6 +870,14 @@ class TouchExplorer implements EventStreamTransformation { if (accessibilityManager.isEnabled()) { AccessibilityEvent event = AccessibilityEvent.obtain(type); accessibilityManager.sendAccessibilityEvent(event); + switch (type) { + case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START: { + mTouchExplorationInProgress = true; + } break; + case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END: { + mTouchExplorationInProgress = false; + } break; + } } } @@ -893,14 +925,12 @@ class TouchExplorer implements EventStreamTransformation { * * @param policyFlags The policy flags associated with the event. */ - private void sendExitEventsIfNeeded(int policyFlags) { + private void sendHoverExitAndTouchExplorationGestureEndIfNeeded(int policyFlags) { MotionEvent event = mInjectedPointerTracker.getLastInjectedHoverEvent(); if (event != null && event.getActionMasked() != MotionEvent.ACTION_HOVER_EXIT) { final int pointerIdBits = event.getPointerIdBits(); - mTouchExplorationGestureEnded = true; - mTouchInteractionEnded = true; - if (!mSendInteractionEndEventsDelayed.isPending()) { - mSendInteractionEndEventsDelayed.post(); + if (!mSendTouchExplorationEndDelayed.isPending()) { + mSendTouchExplorationEndDelayed.post(); } sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT, pointerIdBits, policyFlags); } @@ -912,10 +942,11 @@ class TouchExplorer implements EventStreamTransformation { * * @param policyFlags The policy flags associated with the event. */ - private void sendEnterEventsIfNeeded(int policyFlags) { + private void sendTouchExplorationGestureStartAndHoverEnterIfNeeded(int policyFlags) { MotionEvent event = mInjectedPointerTracker.getLastInjectedHoverEvent(); if (event != null && event.getActionMasked() == MotionEvent.ACTION_HOVER_EXIT) { final int pointerIdBits = event.getPointerIdBits(); + sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START); sendMotionEvent(event, MotionEvent.ACTION_HOVER_ENTER, pointerIdBits, policyFlags); } } @@ -1181,8 +1212,12 @@ class TouchExplorer implements EventStreamTransformation { mSendHoverExitDelayed.remove(); mPerformLongPressDelayed.remove(); - // The touch interaction has ended since we will send a click. - sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END); + if (mSendTouchExplorationEndDelayed.isPending()) { + mSendTouchExplorationEndDelayed.forceSendAndRemove(); + } + if (mSendTouchInteractionEndDelayed.isPending()) { + mSendTouchInteractionEndDelayed.forceSendAndRemove(); + } int clickLocationX; int clickLocationY; @@ -1416,7 +1451,7 @@ class TouchExplorer implements EventStreamTransformation { mLongPressingPointerDeltaX = (int) mEvent.getX(pointerIndex) - clickLocationX; mLongPressingPointerDeltaY = (int) mEvent.getY(pointerIndex) - clickLocationY; - sendExitEventsIfNeeded(mPolicyFlags); + sendHoverExitAndTouchExplorationGestureEndIfNeeded(mPolicyFlags); mCurrentState = STATE_DELEGATING; sendDownForAllActiveNotInjectedPointers(mEvent, mPolicyFlags); @@ -1445,7 +1480,6 @@ class TouchExplorer implements EventStreamTransformation { private MotionEvent mPrototype; private int mPointerIdBits; private int mPolicyFlags; - private boolean mTouchExplorationInProgress; public SendHoverDelayed(int hoverAction, boolean gestureStarted) { mHoverAction = hoverAction; @@ -1456,7 +1490,6 @@ class TouchExplorer implements EventStreamTransformation { int pointerIdBits, int policyFlags) { remove(); mPrototype = MotionEvent.obtain(prototype); - mTouchExplorationInProgress = touchExplorationInProgress; mPointerIdBits = pointerIdBits; mPolicyFlags = policyFlags; mHandler.postDelayed(this, mDetermineUserIntentTimeout); @@ -1493,7 +1526,6 @@ class TouchExplorer implements EventStreamTransformation { mPrototype = null; mPointerIdBits = -1; mPolicyFlags = 0; - mTouchExplorationInProgress = false; } public void forceSendAndRemove() { @@ -1510,22 +1542,15 @@ class TouchExplorer implements EventStreamTransformation { Slog.d(LOG_TAG_SEND_HOVER_DELAYED, mGestureStarted ? "touchExplorationGestureStarted" : "touchExplorationGestureEnded"); } - if (mTouchExplorationInProgress) { - if (mGestureStarted) { - sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START); - } else { - mTouchExplorationGestureEnded = true; - mTouchInteractionEnded = true; - if (!mSendInteractionEndEventsDelayed.isPending()) { - mSendInteractionEndEventsDelayed.post(); - } - } + if (mGestureStarted) { + sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START); } else { - if (!mGestureStarted) { - mTouchInteractionEnded = true; - if (!mSendInteractionEndEventsDelayed.isPending()) { - mSendInteractionEndEventsDelayed.post(); - } + if (!mSendTouchExplorationEndDelayed.isPending()) { + mSendTouchExplorationEndDelayed.post(); + } + if (mSendTouchInteractionEndDelayed.isPending()) { + mSendTouchInteractionEndDelayed.remove(); + mSendTouchInteractionEndDelayed.post(); } } sendMotionEvent(mPrototype, mHoverAction, mPointerIdBits, mPolicyFlags); @@ -1533,14 +1558,21 @@ class TouchExplorer implements EventStreamTransformation { } } - private class SendInteractionEndEventsDelayed implements Runnable { + private class SendAccessibilityEventDelayed implements Runnable { + private final int mEventType; + private final int mDelay; + + public SendAccessibilityEventDelayed(int eventType, int delay) { + mEventType = eventType; + mDelay = delay; + } public void remove() { mHandler.removeCallbacks(this); } public void post() { - mHandler.postDelayed(this, SEND_INTERACTION_END_EVENTS_TIMEOUT); + mHandler.postDelayed(this, mDelay); } public boolean isPending() { @@ -1556,14 +1588,7 @@ class TouchExplorer implements EventStreamTransformation { @Override public void run() { - if (mTouchExplorationGestureEnded) { - mTouchExplorationGestureEnded = false; - sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END); - } - if (mTouchInteractionEnded) { - mTouchInteractionEnded = false; - sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END); - } + sendAccessibilityEvent(mEventType); } } diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java index 1269433..7e3fdbd 100644 --- a/services/java/com/android/server/am/ActiveServices.java +++ b/services/java/com/android/server/am/ActiveServices.java @@ -1850,7 +1850,7 @@ public class ActiveServices { } if (anrMessage != null) { - mAm.appNotResponding(proc, null, null, anrMessage); + mAm.appNotResponding(proc, null, null, false, anrMessage); } } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index e90eef9..3ef6767 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -970,7 +970,8 @@ public final class ActivityManagerService extends ActivityManagerNative if (mShowDialogs) { Dialog d = new AppNotRespondingDialog(ActivityManagerService.this, - mContext, proc, (ActivityRecord)data.get("activity")); + mContext, proc, (ActivityRecord)data.get("activity"), + msg.arg1 != 0); d.show(); proc.anrDialog = d; } else { @@ -3247,7 +3248,7 @@ public final class ActivityManagerService extends ActivityManagerNative } final void appNotResponding(ProcessRecord app, ActivityRecord activity, - ActivityRecord parent, final String annotation) { + ActivityRecord parent, boolean aboveSystem, final String annotation) { ArrayList<Integer> firstPids = new ArrayList<Integer>(5); SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20); @@ -3388,6 +3389,7 @@ public final class ActivityManagerService extends ActivityManagerNative HashMap map = new HashMap(); msg.what = SHOW_NOT_RESPONDING_MSG; msg.obj = map; + msg.arg1 = aboveSystem ? 1 : 0; map.put("app", app); if (activity != null) { map.put("activity", activity); @@ -7340,6 +7342,51 @@ public final class ActivityManagerService extends ActivityManagerNative SystemProperties.set("ctl.start", "bugreport"); } + public long inputDispatchingTimedOut(int pid, boolean aboveSystem) { + if (checkCallingPermission(android.Manifest.permission.FILTER_EVENTS) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Requires permission " + + android.Manifest.permission.FILTER_EVENTS); + } + + ProcessRecord proc; + + // TODO: Unify this code with ActivityRecord.keyDispatchingTimedOut(). + synchronized (this) { + synchronized (mPidsSelfLocked) { + proc = mPidsSelfLocked.get(pid); + } + if (proc != null) { + if (proc.debugging) { + return -1; + } + + if (mDidDexOpt) { + // Give more time since we were dexopting. + mDidDexOpt = false; + return -1; + } + + if (proc.instrumentationClass != null) { + Bundle info = new Bundle(); + info.putString("shortMsg", "keyDispatchingTimedOut"); + info.putString("longMsg", "Timed out while dispatching key event"); + finishInstrumentationLocked(proc, Activity.RESULT_CANCELED, info); + proc = null; + } + } + } + + if (proc != null) { + appNotResponding(proc, null, null, aboveSystem, "keyDispatchingTimedOut"); + if (proc.instrumentationClass != null || proc.usingWrapper) { + return INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT; + } + } + + return KEY_DISPATCHING_TIMEOUT; + } + public void registerProcessObserver(IProcessObserver observer) { enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER, "registerProcessObserver()"); diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java index 6cd86fd..b9f5b5b 100644 --- a/services/java/com/android/server/am/ActivityRecord.java +++ b/services/java/com/android/server/am/ActivityRecord.java @@ -841,6 +841,7 @@ final class ActivityRecord { } public boolean keyDispatchingTimedOut() { + // TODO: Unify this code with ActivityManagerService.inputDispatchingTimedOut(). ActivityRecord r; ProcessRecord anrApp = null; synchronized(service) { @@ -869,8 +870,7 @@ final class ActivityRecord { } if (anrApp != null) { - service.appNotResponding(anrApp, r, this, - "keyDispatchingTimedOut"); + service.appNotResponding(anrApp, r, this, false, "keyDispatchingTimedOut"); } return true; diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index 90a7abc..a6dc867 100755 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -2436,8 +2436,8 @@ final class ActivityStack { if (err == ActivityManager.START_SUCCESS) { final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0; - Slog.i(TAG, "START {" + intent.toShortString(true, true, true, false) - + " u=" + userId + "} from pid " + (callerApp != null ? callerApp.pid : callingPid)); + Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false) + + "} from pid " + (callerApp != null ? callerApp.pid : callingPid)); } ActivityRecord sourceRecord = null; diff --git a/services/java/com/android/server/am/AppErrorDialog.java b/services/java/com/android/server/am/AppErrorDialog.java index 0ebbe3b..a9c77fc 100644 --- a/services/java/com/android/server/am/AppErrorDialog.java +++ b/services/java/com/android/server/am/AppErrorDialog.java @@ -23,12 +23,9 @@ import android.content.DialogInterface; import android.content.res.Resources; import android.os.Handler; import android.os.Message; -import android.util.Slog; import android.view.WindowManager; class AppErrorDialog extends BaseErrorDialog { - private final static String TAG = "AppErrorDialog"; - private final ActivityManagerService mService; private final AppErrorResult mResult; private final ProcessRecord mProc; @@ -76,7 +73,9 @@ class AppErrorDialog extends BaseErrorDialog { setTitle(res.getText(com.android.internal.R.string.aerr_title)); getWindow().addFlags(FLAG_SYSTEM_ERROR); - getWindow().setTitle("Application Error: " + app.info.processName); + WindowManager.LayoutParams attrs = getWindow().getAttributes(); + attrs.setTitle("Application Error: " + app.info.processName); + getWindow().setAttributes(attrs); if (app.persistent) { getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR); } diff --git a/services/java/com/android/server/am/AppNotRespondingDialog.java b/services/java/com/android/server/am/AppNotRespondingDialog.java index b546ae7..58e533b 100644 --- a/services/java/com/android/server/am/AppNotRespondingDialog.java +++ b/services/java/com/android/server/am/AppNotRespondingDialog.java @@ -25,8 +25,8 @@ import android.content.Intent; import android.content.res.Resources; import android.os.Handler; import android.os.Message; -import android.os.Process; import android.util.Slog; +import android.view.WindowManager; class AppNotRespondingDialog extends BaseErrorDialog { private static final String TAG = "AppNotRespondingDialog"; @@ -40,7 +40,7 @@ class AppNotRespondingDialog extends BaseErrorDialog { private final ProcessRecord mProc; public AppNotRespondingDialog(ActivityManagerService service, Context context, - ProcessRecord app, ActivityRecord activity) { + ProcessRecord app, ActivityRecord activity, boolean aboveSystem) { super(context); mService = service; @@ -91,8 +91,13 @@ class AppNotRespondingDialog extends BaseErrorDialog { } setTitle(res.getText(com.android.internal.R.string.anr_title)); + if (aboveSystem) { + getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR); + } getWindow().addFlags(FLAG_SYSTEM_ERROR); - getWindow().setTitle("Application Not Responding: " + app.info.processName); + WindowManager.LayoutParams attrs = getWindow().getAttributes(); + attrs.setTitle("Application Not Responding: " + app.info.processName); + getWindow().setAttributes(attrs); } public void onStop() { diff --git a/services/java/com/android/server/am/AppWaitingForDebuggerDialog.java b/services/java/com/android/server/am/AppWaitingForDebuggerDialog.java index 9fb48b3..d08bb10 100644 --- a/services/java/com/android/server/am/AppWaitingForDebuggerDialog.java +++ b/services/java/com/android/server/am/AppWaitingForDebuggerDialog.java @@ -20,6 +20,7 @@ import android.content.Context; import android.content.DialogInterface; import android.os.Handler; import android.os.Message; +import android.view.WindowManager; class AppWaitingForDebuggerDialog extends BaseErrorDialog { final ActivityManagerService mService; @@ -52,7 +53,9 @@ class AppWaitingForDebuggerDialog extends BaseErrorDialog { setMessage(text.toString()); setButton(DialogInterface.BUTTON_POSITIVE, "Force Close", mHandler.obtainMessage(1, app)); setTitle("Waiting For Debugger"); - getWindow().setTitle("Waiting For Debugger: " + app.info.processName); + WindowManager.LayoutParams attrs = getWindow().getAttributes(); + attrs.setTitle("Waiting For Debugger: " + app.info.processName); + getWindow().setAttributes(attrs); } public void onStop() { diff --git a/services/java/com/android/server/am/BaseErrorDialog.java b/services/java/com/android/server/am/BaseErrorDialog.java index d1e89bc..6ede8f8 100644 --- a/services/java/com/android/server/am/BaseErrorDialog.java +++ b/services/java/com/android/server/am/BaseErrorDialog.java @@ -33,7 +33,9 @@ class BaseErrorDialog extends AlertDialog { getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); - getWindow().setTitle("Error Dialog"); + WindowManager.LayoutParams attrs = getWindow().getAttributes(); + attrs.setTitle("Error Dialog"); + getWindow().setAttributes(attrs); setIconAttribute(R.attr.alertDialogIcon); } diff --git a/services/java/com/android/server/am/BroadcastQueue.java b/services/java/com/android/server/am/BroadcastQueue.java index 9f27994..95c22ec 100644 --- a/services/java/com/android/server/am/BroadcastQueue.java +++ b/services/java/com/android/server/am/BroadcastQueue.java @@ -151,7 +151,7 @@ public class BroadcastQueue { @Override public void run() { - mService.appNotResponding(mApp, null, null, mAnnotation); + mService.appNotResponding(mApp, null, null, false, mAnnotation); } } diff --git a/services/java/com/android/server/am/FactoryErrorDialog.java b/services/java/com/android/server/am/FactoryErrorDialog.java index b19bb5c..0ffb588 100644 --- a/services/java/com/android/server/am/FactoryErrorDialog.java +++ b/services/java/com/android/server/am/FactoryErrorDialog.java @@ -20,6 +20,7 @@ import android.content.Context; import android.content.DialogInterface; import android.os.Handler; import android.os.Message; +import android.view.WindowManager; class FactoryErrorDialog extends BaseErrorDialog { public FactoryErrorDialog(Context context, CharSequence msg) { @@ -30,7 +31,9 @@ class FactoryErrorDialog extends BaseErrorDialog { setButton(DialogInterface.BUTTON_POSITIVE, context.getText(com.android.internal.R.string.factorytest_reboot), mHandler.obtainMessage(0)); - getWindow().setTitle("Factory Error"); + WindowManager.LayoutParams attrs = getWindow().getAttributes(); + attrs.setTitle("Factory Error"); + getWindow().setAttributes(attrs); } public void onStop() { diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java index 652fdb5..7fbab04 100644 --- a/services/java/com/android/server/am/ProcessRecord.java +++ b/services/java/com/android/server/am/ProcessRecord.java @@ -407,7 +407,7 @@ class ProcessRecord { sb.append('u'); sb.append(userId); sb.append('a'); - sb.append(info.uid%Process.FIRST_APPLICATION_UID); + sb.append(UserHandle.getAppId(info.uid)); if (uid != info.uid) { sb.append('i'); sb.append(UserHandle.getAppId(uid) - Process.FIRST_ISOLATED_UID); diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java index b38d617..e4a7ead 100644 --- a/services/java/com/android/server/connectivity/Tethering.java +++ b/services/java/com/android/server/connectivity/Tethering.java @@ -454,7 +454,8 @@ public class Tethering extends INetworkManagementEventObserver.Stub { if (mTetheredNotification.icon == icon) { return; } - notificationManager.cancel(mTetheredNotification.icon); + notificationManager.cancelAsUser(null, mTetheredNotification.icon, + UserHandle.ALL); } Intent intent = new Intent(); diff --git a/services/java/com/android/server/location/LocationBlacklist.java b/services/java/com/android/server/location/LocationBlacklist.java index 6ad1a92..2437a37 100644 --- a/services/java/com/android/server/location/LocationBlacklist.java +++ b/services/java/com/android/server/location/LocationBlacklist.java @@ -20,6 +20,7 @@ package com.android.server.location; import android.content.Context; import android.database.ContentObserver; import android.os.Handler; +import android.os.UserHandle; import android.provider.Settings; import android.util.Log; import android.util.Slog; @@ -48,6 +49,8 @@ public final class LocationBlacklist extends ContentObserver { // all fields below synchronized on mLock private String[] mWhitelist = new String[0]; private String[] mBlacklist = new String[0]; + + private int mCurrentUserId = UserHandle.USER_OWNER; public LocationBlacklist(Context context, Handler handler) { super(handler); @@ -56,20 +59,22 @@ public final class LocationBlacklist extends ContentObserver { public void init() { mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor( - BLACKLIST_CONFIG_NAME), false, this); + BLACKLIST_CONFIG_NAME), false, this, UserHandle.USER_ALL); // mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor( -// WHITELIST_CONFIG_NAME), false, this); +// WHITELIST_CONFIG_NAME), false, this, UserHandle.USER_ALL); reloadBlacklist(); } + private void reloadBlacklistLocked() { + mWhitelist = getStringArrayLocked(WHITELIST_CONFIG_NAME); + Slog.i(TAG, "whitelist: " + Arrays.toString(mWhitelist)); + mBlacklist = getStringArrayLocked(BLACKLIST_CONFIG_NAME); + Slog.i(TAG, "blacklist: " + Arrays.toString(mBlacklist)); + } + private void reloadBlacklist() { - String blacklist[] = getStringArray(BLACKLIST_CONFIG_NAME); - String whitelist[] = getStringArray(WHITELIST_CONFIG_NAME); synchronized (mLock) { - mWhitelist = whitelist; - Slog.i(TAG, "whitelist: " + Arrays.toString(mWhitelist)); - mBlacklist = blacklist; - Slog.i(TAG, "blacklist: " + Arrays.toString(mBlacklist)); + reloadBlacklistLocked(); } } @@ -78,7 +83,6 @@ public final class LocationBlacklist extends ContentObserver { * (package name matches blacklist, and does not match whitelist) */ public boolean isBlacklisted(String packageName) { - /* synchronized (mLock) { for (String black : mBlacklist) { if (packageName.startsWith(black)) { @@ -92,7 +96,6 @@ public final class LocationBlacklist extends ContentObserver { } } } - */ return false; } @@ -113,8 +116,19 @@ public final class LocationBlacklist extends ContentObserver { reloadBlacklist(); } - private String[] getStringArray(String key) { - String flatString = Settings.Secure.getString(mContext.getContentResolver(), key); + public void switchUser(int userId) { + synchronized(mLock) { + mCurrentUserId = userId; + reloadBlacklistLocked(); + } + } + + private String[] getStringArrayLocked(String key) { + String flatString; + synchronized(mLock) { + flatString = Settings.Secure.getStringForUser(mContext.getContentResolver(), key, + mCurrentUserId); + } if (flatString == null) { return new String[0]; } diff --git a/services/java/com/android/server/power/DisplayPowerController.java b/services/java/com/android/server/power/DisplayPowerController.java index 4f8cdde..d0e758f 100644 --- a/services/java/com/android/server/power/DisplayPowerController.java +++ b/services/java/com/android/server/power/DisplayPowerController.java @@ -117,8 +117,9 @@ final class DisplayPowerController { private static final int PROXIMITY_NEGATIVE = 0; private static final int PROXIMITY_POSITIVE = 1; - // Proximity sensor debounce delay in milliseconds. - private static final int PROXIMITY_SENSOR_DEBOUNCE_DELAY = 250; + // Proximity sensor debounce delay in milliseconds for positive or negative transitions. + private static final int PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY = 0; + private static final int PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY = 500; // Trigger proximity if distance is less than 5 cm. private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f; @@ -562,6 +563,7 @@ final class DisplayPowerController { if (!mScreenOffBecauseOfProximity && mProximity == PROXIMITY_POSITIVE) { mScreenOffBecauseOfProximity = true; + sendOnProximityPositive(); setScreenOn(false); } } else if (mWaitingForNegativeProximity @@ -734,8 +736,13 @@ final class DisplayPowerController { // Only accept a proximity sensor reading if it remains // stable for the entire debounce delay. mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED); - mPendingProximity = positive ? PROXIMITY_POSITIVE : PROXIMITY_NEGATIVE; - mPendingProximityDebounceTime = time + PROXIMITY_SENSOR_DEBOUNCE_DELAY; + if (positive) { + mPendingProximity = PROXIMITY_POSITIVE; + mPendingProximityDebounceTime = time + PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY; + } else { + mPendingProximity = PROXIMITY_NEGATIVE; + mPendingProximityDebounceTime = time + PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY; + } debounceProximitySensor(); } @@ -973,6 +980,17 @@ final class DisplayPowerController { } }; + private void sendOnProximityPositive() { + mCallbackHandler.post(mOnProximityPositiveRunnable); + } + + private final Runnable mOnProximityPositiveRunnable = new Runnable() { + @Override + public void run() { + mCallbacks.onProximityPositive(); + } + }; + private void sendOnProximityNegative() { mCallbackHandler.post(mOnProximityNegativeRunnable); } @@ -1090,6 +1108,7 @@ final class DisplayPowerController { */ public interface Callbacks { void onStateChanged(); + void onProximityPositive(); void onProximityNegative(); } diff --git a/services/java/com/android/server/power/PowerManagerService.java b/services/java/com/android/server/power/PowerManagerService.java index 9a01022..eecac07 100644 --- a/services/java/com/android/server/power/PowerManagerService.java +++ b/services/java/com/android/server/power/PowerManagerService.java @@ -98,6 +98,8 @@ public final class PowerManagerService extends IPowerManager.Stub private static final int DIRTY_STAY_ON = 1 << 7; // Dirty bit: battery state changed private static final int DIRTY_BATTERY_STATE = 1 << 8; + // Dirty bit: proximity state changed + private static final int DIRTY_PROXIMITY_POSITIVE = 1 << 9; // Wakefulness: The device is asleep and can only be awoken by a call to wakeUp(). // The screen should be off or in the process of being turned off by the display controller. @@ -258,6 +260,9 @@ public final class PowerManagerService extends IPowerManager.Stub // True if the device should stay on. private boolean mStayOn; + // True if the proximity sensor reads a positive result. + private boolean mProximityPositive; + // Screen brightness setting limits. private int mScreenBrightnessSettingMinimum; private int mScreenBrightnessSettingMaximum; @@ -1101,12 +1106,17 @@ public final class PowerManagerService extends IPowerManager.Stub */ private void updateStayOnLocked(int dirty) { if ((dirty & (DIRTY_BATTERY_STATE | DIRTY_SETTINGS)) != 0) { + final boolean wasStayOn = mStayOn; if (mStayOnWhilePluggedInSetting != 0 && !isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) { mStayOn = mBatteryService.isPowered(mStayOnWhilePluggedInSetting); } else { mStayOn = false; } + + if (mStayOn != wasStayOn) { + mDirty |= DIRTY_STAY_ON; + } } } @@ -1265,7 +1275,7 @@ public final class PowerManagerService extends IPowerManager.Stub private boolean updateWakefulnessLocked(int dirty) { boolean changed = false; if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_BOOT_COMPLETED - | DIRTY_WAKEFULNESS | DIRTY_STAY_ON)) != 0) { + | DIRTY_WAKEFULNESS | DIRTY_STAY_ON | DIRTY_PROXIMITY_POSITIVE)) != 0) { if (mWakefulness == WAKEFULNESS_AWAKE && isItBedTimeYetLocked()) { if (DEBUG_SPEW) { Slog.d(TAG, "updateWakefulnessLocked: Bed time..."); @@ -1288,17 +1298,17 @@ public final class PowerManagerService extends IPowerManager.Stub * to being fully awake or else go to sleep for good. */ private boolean isItBedTimeYetLocked() { - return mBootCompleted && !isScreenBeingKeptOnLocked(); + return mBootCompleted && !isBeingKeptAwakeLocked(); } /** - * Returns true if the screen is being kept on by a wake lock, user activity + * Returns true if the device is being kept awake by a wake lock, user activity * or the stay on while powered setting. */ - private boolean isScreenBeingKeptOnLocked() { + private boolean isBeingKeptAwakeLocked() { return mStayOn - || (mWakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM - | WAKE_LOCK_PROXIMITY_SCREEN_OFF)) != 0 + || mProximityPositive + || (mWakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM)) != 0 || (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT | USER_ACTIVITY_SCREEN_DIM)) != 0; } @@ -1314,6 +1324,7 @@ public final class PowerManagerService extends IPowerManager.Stub | DIRTY_SETTINGS | DIRTY_IS_POWERED | DIRTY_STAY_ON + | DIRTY_PROXIMITY_POSITIVE | DIRTY_BATTERY_STATE)) != 0) { scheduleSandmanLocked(); } @@ -1401,7 +1412,7 @@ public final class PowerManagerService extends IPowerManager.Stub && mDreamsEnabledSetting && mDisplayPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF && mBootCompleted - && (mIsPowered || isScreenBeingKeptOnLocked()); + && (mIsPowered || isBeingKeptAwakeLocked()); } /** @@ -1528,7 +1539,16 @@ public final class PowerManagerService extends IPowerManager.Stub } @Override + public void onProximityPositive() { + mProximityPositive = true; + mDirty |= DIRTY_PROXIMITY_POSITIVE; + updatePowerStateLocked(); + } + + @Override public void onProximityNegative() { + mProximityPositive = false; + mDirty |= DIRTY_PROXIMITY_POSITIVE; userActivityNoUpdateLocked(SystemClock.uptimeMillis(), PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID); updatePowerStateLocked(); @@ -1986,6 +2006,7 @@ public final class PowerManagerService extends IPowerManager.Stub pw.println(" mIsPowered=" + mIsPowered); pw.println(" mPlugType=" + mPlugType); pw.println(" mStayOn=" + mStayOn); + pw.println(" mProximityPositive=" + mProximityPositive); pw.println(" mBootCompleted=" + mBootCompleted); pw.println(" mSystemReady=" + mSystemReady); pw.println(" mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary)); diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java index 61310ca..d966001 100644 --- a/services/java/com/android/server/wm/InputMonitor.java +++ b/services/java/com/android/server/wm/InputMonitor.java @@ -21,6 +21,7 @@ import com.android.server.input.InputApplicationHandle; import com.android.server.input.InputWindowHandle; import com.android.server.wm.WindowManagerService.AllWindowsIterator; +import android.app.ActivityManagerNative; import android.graphics.Rect; import android.os.RemoteException; import android.util.Log; @@ -89,8 +90,9 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { public long notifyANR(InputApplicationHandle inputApplicationHandle, InputWindowHandle inputWindowHandle) { AppWindowToken appWindowToken = null; + WindowState windowState = null; + boolean aboveSystem = false; synchronized (mService.mWindowMap) { - WindowState windowState = null; if (inputWindowHandle != null) { windowState = (WindowState) inputWindowHandle.windowState; if (windowState != null) { @@ -104,6 +106,12 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { if (windowState != null) { Slog.i(WindowManagerService.TAG, "Input event dispatching timed out " + "sending to " + windowState.mAttrs.getTitle()); + // Figure out whether this window is layered above system windows. + // We need to do this here to help the activity manager know how to + // layer its ANR dialog. + int systemAlertLayer = mService.mPolicy.windowTypeToLayerLw( + WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); + aboveSystem = windowState.mBaseLayer > systemAlertLayer; } else if (appWindowToken != null) { Slog.i(WindowManagerService.TAG, "Input event dispatching timed out " + "sending to application " + appWindowToken.stringName); @@ -126,6 +134,19 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { } } catch (RemoteException ex) { } + } else if (windowState != null) { + try { + // Notify the activity manager about the timeout and let it decide whether + // to abort dispatching or keep waiting. + long timeout = ActivityManagerNative.getDefault().inputDispatchingTimedOut( + windowState.mSession.mPid, aboveSystem); + if (timeout >= 0) { + // The activity manager declined to abort dispatching. + // Wait a bit longer and timeout again later. + return timeout; + } + } catch (RemoteException ex) { + } } return 0; // abort dispatching } diff --git a/services/java/com/android/server/wm/Session.java b/services/java/com/android/server/wm/Session.java index d84a52b..3b4c1ab 100644 --- a/services/java/com/android/server/wm/Session.java +++ b/services/java/com/android/server/wm/Session.java @@ -30,8 +30,10 @@ import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.Parcel; +import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.UserHandle; import android.util.Slog; import android.view.Display; import android.view.IWindow; @@ -69,8 +71,17 @@ final class Session extends IWindowSession.Stub StringBuilder sb = new StringBuilder(); sb.append("Session{"); sb.append(Integer.toHexString(System.identityHashCode(this))); - sb.append(" uid "); - sb.append(mUid); + sb.append(" "); + sb.append(mPid); + if (mUid < Process.FIRST_APPLICATION_UID) { + sb.append(":"); + sb.append(mUid); + } else { + sb.append(":u"); + sb.append(UserHandle.getUserId(mUid)); + sb.append('a'); + sb.append(UserHandle.getAppId(mUid)); + } sb.append("}"); mStringName = sb.toString(); diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java index 9963d14..d23448b 100644 --- a/services/java/com/android/server/wm/WindowState.java +++ b/services/java/com/android/server/wm/WindowState.java @@ -1219,7 +1219,8 @@ final class WindowState implements WindowManagerPolicy.WindowState { mLastTitle = mAttrs.getTitle(); mWasPaused = mToken.paused; mStringNameCache = "Window{" + Integer.toHexString(System.identityHashCode(this)) - + " " + mLastTitle + " paused=" + mWasPaused + "}"; + + " u" + UserHandle.getUserId(mSession.mUid) + + " " + mLastTitle + (mWasPaused ? " PAUSED}" : "}"); } return mStringNameCache; } |