summaryrefslogtreecommitdiffstats
path: root/core/java/android/view
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android/view')
-rw-r--r--core/java/android/view/HardwareRenderer.java17
-rw-r--r--core/java/android/view/ViewGroup.java11
-rw-r--r--core/java/android/view/ViewRootImpl.java3
-rw-r--r--core/java/android/view/VolumePanel.java2
-rw-r--r--core/java/android/view/Window.java3
-rw-r--r--core/java/android/view/WindowManager.java10
-rw-r--r--core/java/android/view/WindowManagerPolicy.java8
-rw-r--r--core/java/android/view/textservice/SpellCheckerSession.java222
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