diff options
Diffstat (limited to 'core/java')
-rw-r--r-- | core/java/android/service/dreams/Sandman.java | 122 | ||||
-rw-r--r-- | core/java/android/webkit/AccessibilityInjector.java | 29 | ||||
-rw-r--r-- | core/java/android/webkit/WebView.java | 1 | ||||
-rw-r--r-- | core/java/android/webkit/WebViewClassic.java | 41 |
4 files changed, 176 insertions, 17 deletions
diff --git a/core/java/android/service/dreams/Sandman.java b/core/java/android/service/dreams/Sandman.java new file mode 100644 index 0000000..70142ce --- /dev/null +++ b/core/java/android/service/dreams/Sandman.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2012 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 android.service.dreams; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.os.PowerManager; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.SystemClock; +import android.os.UserHandle; +import android.provider.Settings; +import android.util.Slog; + +/** + * Internal helper for launching dreams to ensure consistency between the + * <code>UiModeManagerService</code> system service and the <code>Somnambulator</code> activity. + * + * @hide + */ +public final class Sandman { + private static final String TAG = "Sandman"; + + private static final int DEFAULT_SCREENSAVER_ENABLED = 1; + private static final int DEFAULT_SCREENSAVER_ACTIVATED_ON_DOCK = 1; + + // The component name of a special dock app that merely launches a dream. + // We don't want to launch this app when docked because it causes an unnecessary + // activity transition. We just want to start the dream. + private static final ComponentName SOMNAMBULATOR_COMPONENT = + new ComponentName("com.android.systemui", "com.android.systemui.Somnambulator"); + + + // The sandman is eternal. No one instantiates him. + private Sandman() { + } + + /** + * Returns true if the specified dock app intent should be started. + * False if we should dream instead, if appropriate. + */ + public static boolean shouldStartDockApp(Context context, Intent intent) { + ComponentName name = intent.resolveActivity(context.getPackageManager()); + return name != null && !name.equals(SOMNAMBULATOR_COMPONENT); + } + + /** + * Starts a dream manually. + */ + public static void startDreamByUserRequest(Context context) { + startDream(context, false); + } + + /** + * Starts a dream when docked if the system has been configured to do so, + * otherwise does nothing. + */ + public static void startDreamWhenDockedIfAppropriate(Context context) { + if (!isScreenSaverEnabled(context) + || !isScreenSaverActivatedOnDock(context)) { + Slog.i(TAG, "Dreams currently disabled for docks."); + return; + } + + startDream(context, true); + } + + private static void startDream(Context context, boolean docked) { + try { + IDreamManager dreamManagerService = IDreamManager.Stub.asInterface( + ServiceManager.getService(DreamService.DREAM_SERVICE)); + if (dreamManagerService != null && !dreamManagerService.isDreaming()) { + if (docked) { + Slog.i(TAG, "Activating dream while docked."); + + // Wake up. + // The power manager will wake up the system automatically when it starts + // receiving power from a dock but there is a race between that happening + // and the UI mode manager starting a dream. We want the system to already + // be awake by the time this happens. Otherwise the dream may not start. + PowerManager powerManager = + (PowerManager)context.getSystemService(Context.POWER_SERVICE); + powerManager.wakeUp(SystemClock.uptimeMillis()); + } else { + Slog.i(TAG, "Activating dream by user request."); + } + + // Dream. + dreamManagerService.dream(); + } + } catch (RemoteException ex) { + Slog.e(TAG, "Could not start dream when docked.", ex); + } + } + + private static boolean isScreenSaverEnabled(Context context) { + return Settings.Secure.getIntForUser(context.getContentResolver(), + Settings.Secure.SCREENSAVER_ENABLED, DEFAULT_SCREENSAVER_ENABLED, + UserHandle.USER_CURRENT) != 0; + } + + private static boolean isScreenSaverActivatedOnDock(Context context) { + return Settings.Secure.getIntForUser(context.getContentResolver(), + Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, + DEFAULT_SCREENSAVER_ACTIVATED_ON_DOCK, UserHandle.USER_CURRENT) != 0; + } +} diff --git a/core/java/android/webkit/AccessibilityInjector.java b/core/java/android/webkit/AccessibilityInjector.java index d6576e1..357a16e 100644 --- a/core/java/android/webkit/AccessibilityInjector.java +++ b/core/java/android/webkit/AccessibilityInjector.java @@ -96,11 +96,26 @@ class AccessibilityInjector { // Template for JavaScript that performs AndroidVox actions. private static final String ACCESSIBILITY_ANDROIDVOX_TEMPLATE = - "cvox.AndroidVox.performAction('%1s')"; + "(function() {" + + " if ((typeof(cvox) != 'undefined')"+ + " && (typeof(cvox.ChromeVox) != 'undefined')" + + " && (typeof(cvox.AndroidVox) != 'undefined')" + + " && cvox.ChromeVox.isActive) {" + + " return cvox.AndroidVox.performAction('%1s');" + + " } else {" + + " return false;" + + " }" + + "})()"; // JS code used to shut down an active AndroidVox instance. private static final String TOGGLE_CVOX_TEMPLATE = - "javascript:(function() { cvox.ChromeVox.host.activateOrDeactivateChromeVox(%b); })();"; + "javascript:(function() {" + + " if ((typeof(cvox) != 'undefined')"+ + " && (typeof(cvox.ChromeVox) != 'undefined')" + + " && (typeof(cvox.ChromeVox.host) != 'undefined')) {" + + " cvox.ChromeVox.host.activateOrDeactivateChromeVox(%b);" + + " }" + + "})();"; /** * Creates an instance of the AccessibilityInjector based on @@ -776,20 +791,26 @@ class AccessibilityInjector { while (true) { try { if (mResultId == resultId) { + if (DEBUG) + Log.w(TAG, "Received CVOX result"); return true; } if (mResultId > resultId) { + if (DEBUG) + Log.w(TAG, "Obsolete CVOX result"); return false; } final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis; waitTimeMillis = RESULT_TIMEOUT - elapsedTimeMillis; if (waitTimeMillis <= 0) { + if (DEBUG) + Log.w(TAG, "Timed out while waiting for CVOX result"); return false; } mResultLock.wait(waitTimeMillis); } catch (InterruptedException ie) { if (DEBUG) - Log.w(TAG, "Timed out while waiting for CVOX result"); + Log.w(TAG, "Interrupted while waiting for CVOX result"); /* ignore */ } } @@ -805,6 +826,8 @@ class AccessibilityInjector { @JavascriptInterface @SuppressWarnings("unused") public void onResult(String id, String result) { + if (DEBUG) + Log.w(TAG, "Saw CVOX result of '" + result + "'"); final long resultId; try { diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 4202a7f..6df7820 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -1480,7 +1480,6 @@ public class WebView extends AbsoluteLayout * * @param listener an implementation of WebView.PictureListener * @deprecated This method is now obsolete. - * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1} */ @Deprecated public void setPictureListener(PictureListener listener) { diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java index d68511c..7d0d0ba 100644 --- a/core/java/android/webkit/WebViewClassic.java +++ b/core/java/android/webkit/WebViewClassic.java @@ -5185,7 +5185,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc if (cm.hasPrimaryClip()) { Point cursorPoint = new Point(contentToViewX(mSelectCursorBase.x), contentToViewY(mSelectCursorBase.y)); - Point cursorTop = calculateCaretTop(); + Point cursorTop = calculateBaseCaretTop(); cursorTop.set(contentToViewX(cursorTop.x), contentToViewY(cursorTop.y)); @@ -5229,17 +5229,22 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc return scale; } + private Point calculateBaseCaretTop() { + return calculateCaretTop(mSelectCursorBase, mSelectCursorBaseTextQuad); + } + + private Point calculateDraggingCaretTop() { + return calculateCaretTop(mSelectDraggingCursor, mSelectDraggingTextQuad); + } + /** * Assuming arbitrary shape of a quadralateral forming text bounds, this * calculates the top of a caret. */ - private Point calculateCaretTop() { - float scale = scaleAlongSegment(mSelectCursorBase.x, mSelectCursorBase.y, - mSelectCursorBaseTextQuad.p4, mSelectCursorBaseTextQuad.p3); - int x = Math.round(scaleCoordinate(scale, - mSelectCursorBaseTextQuad.p1.x, mSelectCursorBaseTextQuad.p2.x)); - int y = Math.round(scaleCoordinate(scale, - mSelectCursorBaseTextQuad.p1.y, mSelectCursorBaseTextQuad.p2.y)); + private static Point calculateCaretTop(Point base, QuadF quad) { + float scale = scaleAlongSegment(base.x, base.y, quad.p4, quad.p3); + int x = Math.round(scaleCoordinate(scale, quad.p1.x, quad.p2.x)); + int y = Math.round(scaleCoordinate(scale, quad.p1.y, quad.p2.y)); return new Point(x, y); } @@ -5269,12 +5274,20 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc return true; } - private void updateWebkitSelection() { + private void updateWebkitSelection(boolean isSnapped) { int handleId = (mSelectDraggingCursor == mSelectCursorBase) ? HANDLE_ID_BASE : HANDLE_ID_EXTENT; + int x = mSelectDraggingCursor.x; + int y = mSelectDraggingCursor.y; + if (isSnapped) { + // "center" the cursor in the snapping quad + Point top = calculateDraggingCaretTop(); + x = Math.round((top.x + x) / 2); + y = Math.round((top.y + y) / 2); + } mWebViewCore.removeMessages(EventHub.SELECT_TEXT); mWebViewCore.sendMessageAtFrontOfQueue(EventHub.SELECT_TEXT, - mSelectDraggingCursor.x, mSelectDraggingCursor.y, (Integer)handleId); + x, y, (Integer)handleId); } private void resetCaretTimer() { @@ -5616,7 +5629,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc Math.max(0, mEditTextContentBounds.top - buffer), mEditTextContentBounds.right + buffer, mEditTextContentBounds.bottom + buffer); - Point caretTop = calculateCaretTop(); + Point caretTop = calculateBaseCaretTop(); if (visibleRect.width() < mEditTextContentBounds.width()) { // The whole edit won't fit in the width, so use the caret rect if (mSelectCursorBase.x < caretTop.x) { @@ -5947,10 +5960,12 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc } else { endScrollEdit(); } + boolean snapped = false; if (inCursorText || (mIsEditingText && !inEditBounds)) { snapDraggingCursor(); + snapped = true; } - updateWebkitSelection(); + updateWebkitSelection(snapped); if (!inCursorText && mIsEditingText && inEditBounds) { // Visually snap even if we have moved the handle. snapDraggingCursor(); @@ -6277,7 +6292,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc int oldX = mSelectDraggingCursor.x; int oldY = mSelectDraggingCursor.y; mSelectDraggingCursor.set(selectionX, selectionY); - updateWebkitSelection(); + updateWebkitSelection(false); scrollEditText(scrollX, scrollY); mSelectDraggingCursor.set(oldX, oldY); } |