diff options
Diffstat (limited to 'core/java/android/view')
-rw-r--r-- | core/java/android/view/HardwareRenderer.java | 17 | ||||
-rw-r--r-- | core/java/android/view/ViewGroup.java | 11 | ||||
-rw-r--r-- | core/java/android/view/ViewRootImpl.java | 3 | ||||
-rw-r--r-- | core/java/android/view/VolumePanel.java | 2 | ||||
-rw-r--r-- | core/java/android/view/Window.java | 3 | ||||
-rw-r--r-- | core/java/android/view/WindowManager.java | 10 | ||||
-rw-r--r-- | core/java/android/view/WindowManagerPolicy.java | 8 | ||||
-rw-r--r-- | core/java/android/view/textservice/SpellCheckerSession.java | 222 |
8 files changed, 163 insertions, 113 deletions
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index 443acf6..3f793bb 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -441,6 +441,8 @@ public abstract class HardwareRenderer { } boolean mDirtyRegionsEnabled; + boolean mUpdateDirtyRegions; + final boolean mVsyncDisabled; final int mGlVersion; @@ -675,6 +677,12 @@ public abstract class HardwareRenderer { initCaches(); + enableDirtyRegions(); + + return mEglContext.getGL(); + } + + private void enableDirtyRegions() { // If mDirtyRegions is set, this means we have an EGL configuration // with EGL_SWAP_BEHAVIOR_PRESERVED_BIT set if (sDirtyRegions) { @@ -690,8 +698,6 @@ public abstract class HardwareRenderer { // configuration (see RENDER_DIRTY_REGIONS) mDirtyRegionsEnabled = GLES20Canvas.isBackBufferPreserved(); } - - return mEglContext.getGL(); } abstract void initCaches(); @@ -745,6 +751,9 @@ public abstract class HardwareRenderer { if (!createSurface(holder)) { return; } + + mUpdateDirtyRegions = true; + if (mCanvas != null) { setEnabled(true); } @@ -943,6 +952,10 @@ public abstract class HardwareRenderer { fallback(true); return SURFACE_STATE_ERROR; } else { + if (mUpdateDirtyRegions) { + enableDirtyRegions(); + mUpdateDirtyRegions = false; + } return SURFACE_STATE_UPDATED; } } diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 1102a47..0d34b90 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -4190,10 +4190,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * {@inheritDoc} */ public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset) { - // The View is not attached to a window, 'visible' does not make sense, return false - if (mAttachInfo == null) return false; - - final RectF rect = mAttachInfo.mTmpTransformRect; + // It doesn't make a whole lot of sense to call this on a view that isn't attached, + // but for some simple tests it can be useful. If we don't have attach info this + // will allocate memory. + final RectF rect = mAttachInfo != null ? mAttachInfo.mTmpTransformRect : new RectF(); rect.set(r); if (!child.hasIdentityMatrix()) { @@ -4207,7 +4207,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager if (offset != null) { if (!child.hasIdentityMatrix()) { - float[] position = mAttachInfo.mTmpTransformLocation; + float[] position = mAttachInfo != null ? mAttachInfo.mTmpTransformLocation + : new float[2]; position[0] = offset.x; position[1] = offset.y; child.getMatrix().mapPoints(position); diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 7a9d82c..72966ef 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -3257,8 +3257,9 @@ public final class ViewRootImpl extends Handler implements ViewParent, } // If the Control modifier is held, try to interpret the key as a shortcut. - if (event.getAction() == KeyEvent.ACTION_UP + if (event.getAction() == KeyEvent.ACTION_DOWN && event.isCtrlPressed() + && event.getRepeatCount() == 0 && !KeyEvent.isModifierKey(event.getKeyCode())) { if (mView.dispatchKeyShortcutEvent(event)) { finishInputEvent(q, true); diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java index 48fe0df..24a3066 100644 --- a/core/java/android/view/VolumePanel.java +++ b/core/java/android/view/VolumePanel.java @@ -400,7 +400,7 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie if (LOGD) Log.d(TAG, "onVolumeChanged(streamType: " + streamType + ", flags: " + flags + ")"); if ((flags & AudioManager.FLAG_SHOW_UI) != 0) { - if (mActiveStreamType == -1) { + if (mActiveStreamType != streamType) { reorderSliders(streamType); } onShowVolumeChanged(streamType, flags); diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index d0841dd..a99ac03 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -743,6 +743,9 @@ public abstract class Window { public void setFlags(int flags, int mask) { final WindowManager.LayoutParams attrs = getAttributes(); attrs.flags = (attrs.flags&~mask) | (flags&mask); + if ((mask&WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY) != 0) { + attrs.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY; + } mForcedWindowFlags |= mask; if (mCallback != null) { mCallback.onWindowAttributesChanged(attrs); diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index e74fec6..c0eb65b 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -824,6 +824,16 @@ public interface WindowManager extends ViewManager { public static final int PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS = 0x00000004; /** + * This is set for a window that has explicitly specified its + * FLAG_NEEDS_MENU_KEY, so we know the value on this window is the + * appropriate one to use. If this is not set, we should look at + * windows behind it to determine the appropriate value. + * + * @hide + */ + public static final int PRIVATE_FLAG_SET_NEEDS_MENU_KEY = 0x00000008; + + /** * Control flags that are private to the platform. * @hide */ diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index 7d729c6..c7cd662 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -238,6 +238,14 @@ public interface WindowManagerPolicy { public WindowManager.LayoutParams getAttrs(); /** + * Return whether this window needs the menu key shown. Must be called + * with window lock held, because it may need to traverse down through + * window list to determine the result. + * @param bottom The bottom-most window to consider when determining this. + */ + public boolean getNeedsMenuLw(WindowState bottom); + + /** * Retrieve the current system UI visibility flags associated with * this window. */ diff --git a/core/java/android/view/textservice/SpellCheckerSession.java b/core/java/android/view/textservice/SpellCheckerSession.java index 1d66cbe..f6418ce 100644 --- a/core/java/android/view/textservice/SpellCheckerSession.java +++ b/core/java/android/view/textservice/SpellCheckerSession.java @@ -21,8 +21,11 @@ import com.android.internal.textservice.ISpellCheckerSessionListener; import com.android.internal.textservice.ITextServicesManager; import com.android.internal.textservice.ITextServicesSessionListener; +import android.os.Binder; import android.os.Handler; +import android.os.HandlerThread; import android.os.Message; +import android.os.Process; import android.os.RemoteException; import android.util.Log; import android.view.textservice.SpellCheckerInfo; @@ -226,6 +229,8 @@ public class SpellCheckerSession { private boolean mOpened; private ISpellCheckerSession mISpellCheckerSession; + private HandlerThread mThread; + private Handler mAsyncHandler; public SpellCheckerSessionListenerImpl(Handler handler) { mOpened = false; @@ -237,6 +242,7 @@ public class SpellCheckerSession { public final TextInfo[] mTextInfos; public final int mSuggestionsLimit; public final boolean mSequentialWords; + public ISpellCheckerSession mSession; public SpellCheckerParams(int what, TextInfo[] textInfos, int suggestionsLimit, boolean sequentialWords) { mWhat = what; @@ -246,30 +252,100 @@ public class SpellCheckerSession { } } - private void processTask(SpellCheckerParams scp) { - switch (scp.mWhat) { - case TASK_CANCEL: - processCancel(); - break; - case TASK_GET_SUGGESTIONS_MULTIPLE: - processGetSuggestionsMultiple(scp); - break; - case TASK_CLOSE: - processClose(); - break; - case TASK_GET_SUGGESTIONS_MULTIPLE_FOR_SENTENCE: - processGetSuggestionsMultipleForSentence(scp); - break; + private void processTask(ISpellCheckerSession session, SpellCheckerParams scp, + boolean async) { + if (async || mAsyncHandler == null) { + switch (scp.mWhat) { + case TASK_CANCEL: + if (DBG) { + Log.w(TAG, "Cancel spell checker tasks."); + } + try { + session.onCancel(); + } catch (RemoteException e) { + Log.e(TAG, "Failed to cancel " + e); + } + break; + case TASK_GET_SUGGESTIONS_MULTIPLE: + if (DBG) { + Log.w(TAG, "Get suggestions from the spell checker."); + } + try { + session.onGetSuggestionsMultiple(scp.mTextInfos, + scp.mSuggestionsLimit, scp.mSequentialWords); + } catch (RemoteException e) { + Log.e(TAG, "Failed to get suggestions " + e); + } + break; + case TASK_GET_SUGGESTIONS_MULTIPLE_FOR_SENTENCE: + if (DBG) { + Log.w(TAG, "Get suggestions from the spell checker."); + } + if (scp.mTextInfos.length != 1) { + throw new IllegalArgumentException(); + } + try { + session.onGetSuggestionsMultipleForSentence( + scp.mTextInfos, scp.mSuggestionsLimit); + } catch (RemoteException e) { + Log.e(TAG, "Failed to get suggestions " + e); + } + break; + case TASK_CLOSE: + if (DBG) { + Log.w(TAG, "Close spell checker tasks."); + } + try { + session.onClose(); + } catch (RemoteException e) { + Log.e(TAG, "Failed to close " + e); + } + break; + } + } else { + // The interface is to a local object, so need to execute it + // asynchronously. + scp.mSession = session; + mAsyncHandler.sendMessage(Message.obtain(mAsyncHandler, 1, scp)); + } + + if (scp.mWhat == TASK_CLOSE) { + // If we are closing, we want to clean up our state now even + // if it is pending as an async operation. + synchronized (this) { + mISpellCheckerSession = null; + mHandler = null; + if (mThread != null) { + mThread.quit(); + } + mThread = null; + mAsyncHandler = null; + } } } public synchronized void onServiceConnected(ISpellCheckerSession session) { - mISpellCheckerSession = session; - mOpened = true; + synchronized (this) { + mISpellCheckerSession = session; + if (session.asBinder() instanceof Binder && mThread == null) { + // If this is a local object, we need to do our own threading + // to make sure we handle it asynchronously. + mThread = new HandlerThread("SpellCheckerSession", + Process.THREAD_PRIORITY_BACKGROUND); + mThread.start(); + mAsyncHandler = new Handler(mThread.getLooper()) { + @Override public void handleMessage(Message msg) { + SpellCheckerParams scp = (SpellCheckerParams)msg.obj; + processTask(scp.mSession, scp, true); + } + }; + } + mOpened = true; + } if (DBG) Log.d(TAG, "onServiceConnected - Success"); while (!mPendingTasks.isEmpty()) { - processTask(mPendingTasks.poll()); + processTask(session, mPendingTasks.poll(), false); } } @@ -310,105 +386,43 @@ public class SpellCheckerSession { return mOpened && mISpellCheckerSession == null; } - public boolean checkOpenConnection() { - if (mISpellCheckerSession != null) { - return true; - } - Log.e(TAG, "not connected to the spellchecker service."); - return false; - } - private void processOrEnqueueTask(SpellCheckerParams scp) { if (DBG) { Log.d(TAG, "process or enqueue task: " + mISpellCheckerSession); } - SpellCheckerParams closeTask = null; - if (mISpellCheckerSession == null) { - if (scp.mWhat == TASK_CANCEL) { - while (!mPendingTasks.isEmpty()) { - final SpellCheckerParams tmp = mPendingTasks.poll(); - if (tmp.mWhat == TASK_CLOSE) { - // Only one close task should be processed, while we need to remove all - // close tasks from the queue - closeTask = tmp; + ISpellCheckerSession session; + synchronized (this) { + session = mISpellCheckerSession; + if (session == null) { + SpellCheckerParams closeTask = null; + if (scp.mWhat == TASK_CANCEL) { + while (!mPendingTasks.isEmpty()) { + final SpellCheckerParams tmp = mPendingTasks.poll(); + if (tmp.mWhat == TASK_CLOSE) { + // Only one close task should be processed, while we need to remove all + // close tasks from the queue + closeTask = tmp; + } } } + mPendingTasks.offer(scp); + if (closeTask != null) { + mPendingTasks.offer(closeTask); + } + return; } - mPendingTasks.offer(scp); - if (closeTask != null) { - mPendingTasks.offer(closeTask); - } - } else { - processTask(scp); - } - } - - private void processCancel() { - if (!checkOpenConnection()) { - return; - } - if (DBG) { - Log.w(TAG, "Cancel spell checker tasks."); - } - try { - mISpellCheckerSession.onCancel(); - } catch (RemoteException e) { - Log.e(TAG, "Failed to cancel " + e); - } - } - - private void processClose() { - if (!checkOpenConnection()) { - return; - } - if (DBG) { - Log.w(TAG, "Close spell checker tasks."); - } - try { - mISpellCheckerSession.onClose(); - mISpellCheckerSession = null; - mHandler = null; - } catch (RemoteException e) { - Log.e(TAG, "Failed to close " + e); - } - } - - private void processGetSuggestionsMultiple(SpellCheckerParams scp) { - if (!checkOpenConnection()) { - return; - } - if (DBG) { - Log.w(TAG, "Get suggestions from the spell checker."); - } - try { - mISpellCheckerSession.onGetSuggestionsMultiple( - scp.mTextInfos, scp.mSuggestionsLimit, scp.mSequentialWords); - } catch (RemoteException e) { - Log.e(TAG, "Failed to get suggestions " + e); - } - } - - private void processGetSuggestionsMultipleForSentence(SpellCheckerParams scp) { - if (!checkOpenConnection()) { - return; - } - if (DBG) { - Log.w(TAG, "Get suggestions from the spell checker."); - } - if (scp.mTextInfos.length != 1) { - throw new IllegalArgumentException(); - } - try { - mISpellCheckerSession.onGetSuggestionsMultipleForSentence( - scp.mTextInfos, scp.mSuggestionsLimit); - } catch (RemoteException e) { - Log.e(TAG, "Failed to get suggestions " + e); } + processTask(session, scp, false); } @Override public void onGetSuggestions(SuggestionsInfo[] results) { - mHandler.sendMessage(Message.obtain(mHandler, MSG_ON_GET_SUGGESTION_MULTIPLE, results)); + synchronized (this) { + if (mHandler != null) { + mHandler.sendMessage(Message.obtain(mHandler, + MSG_ON_GET_SUGGESTION_MULTIPLE, results)); + } + } } @Override |