diff options
21 files changed, 198 insertions, 90 deletions
diff --git a/core/java/android/speech/tts/AudioPlaybackHandler.java b/core/java/android/speech/tts/AudioPlaybackHandler.java index f8d014232ba8..75dcd6e87015 100644 --- a/core/java/android/speech/tts/AudioPlaybackHandler.java +++ b/core/java/android/speech/tts/AudioPlaybackHandler.java @@ -415,6 +415,9 @@ class AudioPlaybackHandler { } if (params.mBytesWritten < params.mAudioBufferSize) { + if (DBG) Log.d(TAG, "Stopping audio track to flush audio, state was : " + + audioTrack.getPlayState()); + params.mIsShortUtterance = true; audioTrack.stop(); } @@ -452,10 +455,40 @@ class AudioPlaybackHandler { return; } + if (params.mIsShortUtterance) { + // In this case we would have called AudioTrack#stop() to flush + // buffers to the mixer. This makes the playback head position + // unobservable and notification markers do not work reliably. We + // have no option but to wait until we think the track would finish + // playing and release it after. + // + // This isn't as bad as it looks because (a) We won't end up waiting + // for much longer than we should because even at 4khz mono, a short + // utterance weighs in at about 2 seconds, and (b) such short utterances + // are expected to be relatively infrequent and in a stream of utterances + // this shows up as a slightly longer pause. + blockUntilEstimatedCompletion(params); + } else { + blockUntilCompletion(params); + } + } + + private static void blockUntilEstimatedCompletion(SynthesisMessageParams params) { + final int lengthInFrames = params.mBytesWritten / params.mBytesPerFrame; + final long estimatedTimeMs = (lengthInFrames * 1000 / params.mSampleRateInHz); + + if (DBG) Log.d(TAG, "About to sleep for: " + estimatedTimeMs + "ms for a short utterance"); + + try { + Thread.sleep(estimatedTimeMs); + } catch (InterruptedException ie) { + // Do nothing. + } + } + + private static void blockUntilCompletion(SynthesisMessageParams params) { final AudioTrack audioTrack = params.mAudioTrack; - final int bytesPerFrame = params.mBytesPerFrame; - final int lengthInBytes = params.mBytesWritten; - final int lengthInFrames = lengthInBytes / bytesPerFrame; + final int lengthInFrames = params.mBytesWritten / params.mBytesPerFrame; int currentPosition = 0; while ((currentPosition = audioTrack.getPlaybackHeadPosition()) < lengthInFrames) { diff --git a/core/java/android/speech/tts/SynthesisMessageParams.java b/core/java/android/speech/tts/SynthesisMessageParams.java index 3e905d6cc5dd..779721eb1c5e 100644 --- a/core/java/android/speech/tts/SynthesisMessageParams.java +++ b/core/java/android/speech/tts/SynthesisMessageParams.java @@ -41,7 +41,13 @@ final class SynthesisMessageParams extends MessageParams { // Written by the synthesis thread, but read on the audio playback // thread. volatile int mBytesWritten; + // A "short utterance" is one that uses less bytes than the audio + // track buffer size (mAudioBufferSize). In this case, we need to call + // AudioTrack#stop() to send pending buffers to the mixer, and slightly + // different logic is required to wait for the track to finish. + // // Not volatile, accessed only from the audio playback thread. + boolean mIsShortUtterance; int mAudioBufferSize; // Always synchronized on "this". int mUnconsumedBytes; diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index ae815373371e..3880bc45b4f3 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -446,7 +446,9 @@ public class Surface implements Parcelable { /** @hide */ public native void setLayer(int zorder); /** @hide */ - public native void setPosition(int x, int y); + public void setPosition(int x, int y) { setPosition((float)x, (float)y); } + /** @hide */ + public native void setPosition(float x, float y); /** @hide */ public native void setSize(int w, int h); /** @hide */ diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index da5baf86a97c..302be57d54af 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -1583,6 +1583,14 @@ public final class InputMethodManager { /** * Set additional input method subtypes. Only a process which shares the same uid with the IME * can add additional input method subtypes to the IME. + * Please note that a subtype's status is stored in the system. + * For example, enabled subtypes are remembered by the framework even after they are removed + * by using this method. If you re-add the same subtypes again, + * they will just get enabled. If you want to avoid such conflicts, for instance, you may + * want to create a "different" new subtype even with the same locale and mode, + * by changing its extra value. The different subtype won't get affected by the stored past + * status. (You may want to take a look at {@link InputMethodSubtype#hashCode()} to refer + * to the current implementation.) * @param imiId Id of InputMethodInfo which additional input method subtypes will be added to. * @param subtypes subtypes will be added as additional subtypes of the current input method. * @return true if the additional input method subtypes are successfully added. diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java index c85b2d93c3d1..01587aac7d2a 100644 --- a/core/java/android/view/textservice/TextServicesManager.java +++ b/core/java/android/view/textservice/TextServicesManager.java @@ -66,7 +66,13 @@ public final class TextServicesManager { /** * Get a spell checker session for the specified spell checker - * @param locale the locale for the spell checker + * @param locale the locale for the spell checker. If {@param locale} is null and + * referToSpellCheckerLanguageSettings is true, the locale specified in Settings will be + * returned. If {@param locale} is not null and referToSpellCheckerLanguageSettings is true, + * the locale specified in Settings will be returned only when it is same as {@param locale}. + * Exceptionally, when referToSpellCheckerLanguageSettings is true and {@param locale} is + * only language (e.g. "en"), the specified locale in Settings (e.g. "en_US") will be + * selected. * @param listener a spell checker session lister for getting results from a spell checker. * @param referToSpellCheckerLanguageSettings if true, the session for one of enabled * languages in settings will be returned. @@ -81,6 +87,11 @@ public final class TextServicesManager { throw new IllegalArgumentException("Locale should not be null if you don't refer" + " settings."); } + + if (referToSpellCheckerLanguageSettings && !isSpellCheckerEnabled()) { + return null; + } + final SpellCheckerInfo sci; try { sci = sService.getCurrentSpellChecker(null); @@ -108,7 +119,12 @@ public final class TextServicesManager { final String localeStr = locale.toString(); for (int i = 0; i < sci.getSubtypeCount(); ++i) { final SpellCheckerSubtype subtype = sci.getSubtypeAt(i); - if (subtype.getLocale().equals(localeStr)) { + final String tempSubtypeLocale = subtype.getLocale(); + if (tempSubtypeLocale.equals(localeStr)) { + subtypeInUse = subtype; + break; + } else if (localeStr.length() >= 2 && tempSubtypeLocale.length() >= 2 + && localeStr.startsWith(tempSubtypeLocale)) { subtypeInUse = subtype; } } diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index 4c1ca313feff..49441ebc9f7c 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -589,7 +589,7 @@ static void Surface_setLayer( } static void Surface_setPosition( - JNIEnv* env, jobject clazz, jint x, jint y) + JNIEnv* env, jobject clazz, jfloat x, jfloat y) { const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); if (surface == 0) return; @@ -832,7 +832,7 @@ static JNINativeMethod gSurfaceMethods[] = { {"screenshot", "(II)Landroid/graphics/Bitmap;", (void*)Surface_screenshotAll }, {"screenshot", "(IIII)Landroid/graphics/Bitmap;", (void*)Surface_screenshot }, {"setLayer", "(I)V", (void*)Surface_setLayer }, - {"setPosition", "(II)V",(void*)Surface_setPosition }, + {"setPosition", "(FF)V",(void*)Surface_setPosition }, {"setSize", "(II)V",(void*)Surface_setSize }, {"hide", "()V", (void*)Surface_hide }, {"show", "()V", (void*)Surface_show }, diff --git a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java index 94a848800906..7c4e147cc49c 100644 --- a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java @@ -55,7 +55,7 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac private void init() { final AnimatedRotateState state = mState; - mIncrement = 360.0f / (float) state.mFramesCount; + mIncrement = 360.0f / state.mFramesCount; final Drawable drawable = state.mDrawable; if (drawable != null) { drawable.setFilterBitmap(true); @@ -65,6 +65,7 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac } } + @Override public void draw(Canvas canvas) { int saveCount = canvas.save(); @@ -146,14 +147,17 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac | mState.mDrawable.getChangingConfigurations(); } + @Override public void setAlpha(int alpha) { mState.mDrawable.setAlpha(alpha); } + @Override public void setColorFilter(ColorFilter cf) { mState.mDrawable.setColorFilter(cf); } + @Override public int getOpacity() { return mState.mDrawable.getOpacity(); } @@ -228,10 +232,10 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotY); final boolean pivotYRel = tv.type == TypedValue.TYPE_FRACTION; final float pivotY = pivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat(); - - final int framesCount = a.getInt(R.styleable.AnimatedRotateDrawable_framesCount, 12); - final int frameDuration = a.getInt(R.styleable.AnimatedRotateDrawable_frameDuration, 150); - + + setFramesCount(a.getInt(R.styleable.AnimatedRotateDrawable_framesCount, 12)); + setFramesDuration(a.getInt(R.styleable.AnimatedRotateDrawable_frameDuration, 150)); + final int res = a.getResourceId(R.styleable.AnimatedRotateDrawable_drawable, 0); Drawable drawable = null; if (res > 0) { @@ -265,8 +269,6 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac rotateState.mPivotX = pivotX; rotateState.mPivotYRel = pivotYRel; rotateState.mPivotY = pivotY; - rotateState.mFramesCount = framesCount; - rotateState.mFrameDuration = frameDuration; init(); @@ -275,6 +277,15 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac } } + public void setFramesCount(int framesCount) { + mState.mFramesCount = framesCount; + mIncrement = 360.0f / mState.mFramesCount; + } + + public void setFramesDuration(int framesDuration) { + mState.mFrameDuration = framesDuration; + } + @Override public Drawable mutate() { if (!mMutated && super.mutate() == this) { diff --git a/include/private/surfaceflinger/LayerState.h b/include/private/surfaceflinger/LayerState.h index d2fed418f0d3..3eb5c99f6f57 100644 --- a/include/private/surfaceflinger/LayerState.h +++ b/include/private/surfaceflinger/LayerState.h @@ -54,8 +54,8 @@ struct layer_state_t { }; SurfaceID surface; uint32_t what; - int32_t x; - int32_t y; + float x; + float y; uint32_t z; uint32_t w; uint32_t h; diff --git a/include/surfaceflinger/SurfaceComposerClient.h b/include/surfaceflinger/SurfaceComposerClient.h index 7fbbfb24f03a..ace0735c664e 100644 --- a/include/surfaceflinger/SurfaceComposerClient.h +++ b/include/surfaceflinger/SurfaceComposerClient.h @@ -145,7 +145,7 @@ public: status_t setAlpha(SurfaceID id, float alpha=1.0f); status_t setFreezeTint(SurfaceID id, uint32_t tint); status_t setMatrix(SurfaceID id, float dsdx, float dtdx, float dsdy, float dtdy); - status_t setPosition(SurfaceID id, int32_t x, int32_t y); + status_t setPosition(SurfaceID id, float x, float y); status_t setSize(SurfaceID id, uint32_t w, uint32_t h); status_t destroySurface(SurfaceID sid); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 3b0ffea0ff1f..00a4bf63cafc 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -102,7 +102,7 @@ class Composer : public Singleton<Composer> public: status_t setPosition(const sp<SurfaceComposerClient>& client, SurfaceID id, - int32_t x, int32_t y); + float x, float y); status_t setSize(const sp<SurfaceComposerClient>& client, SurfaceID id, uint32_t w, uint32_t h); status_t setLayer(const sp<SurfaceComposerClient>& client, SurfaceID id, @@ -161,7 +161,7 @@ layer_state_t* Composer::getLayerStateLocked( } status_t Composer::setPosition(const sp<SurfaceComposerClient>& client, - SurfaceID id, int32_t x, int32_t y) { + SurfaceID id, float x, float y) { Mutex::Autolock _l(mLock); layer_state_t* s = getLayerStateLocked(client, id); if (!s) @@ -372,7 +372,7 @@ status_t SurfaceComposerClient::setFreezeTint(SurfaceID id, uint32_t tint) { return getComposer().setFreezeTint(this, id, tint); } -status_t SurfaceComposerClient::setPosition(SurfaceID id, int32_t x, int32_t y) { +status_t SurfaceComposerClient::setPosition(SurfaceID id, float x, float y) { return getComposer().setPosition(this, id, x, y); } diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml index ed13ace30b31..f3d0bee3ed4d 100644 --- a/packages/SystemUI/res/layout/status_bar.xml +++ b/packages/SystemUI/res/layout/status_bar.xml @@ -71,6 +71,7 @@ </LinearLayout> <com.android.systemui.statusbar.policy.Clock + android:id="@+id/clock" android:textAppearance="@*android:style/TextAppearance.StatusBar.Icon" android:layout_width="wrap_content" android:layout_height="match_parent" diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 6e6567bf1f08..e3ea0de5d606 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -1060,6 +1060,12 @@ public class PhoneStatusBar extends StatusBar { */ } + public void showClock(boolean show) { + View clock = mStatusBarView.findViewById(R.id.clock); + if (clock != null) { + clock.setVisibility(show ? View.VISIBLE : View.GONE); + } + } /** * State is one or more of the DISABLE constants from StatusBarManager. @@ -1074,6 +1080,10 @@ public class PhoneStatusBar extends StatusBar { old, state, diff)); } + if ((diff & StatusBarManager.DISABLE_CLOCK) != 0) { + boolean show = (state & StatusBarManager.DISABLE_CLOCK) == 0; + showClock(show); + } if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) { if ((state & StatusBarManager.DISABLE_EXPAND) != 0) { Slog.d(TAG, "DISABLE_EXPAND: yes"); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java index 1e417acdd41c..5911378ea25b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java @@ -428,7 +428,7 @@ public class InputMethodsPanel extends LinearLayout implements StatusBarPanel, private CharSequence getIMIName(InputMethodInfo imi) { if (imi == null) return null; - return mPackageManager.getApplicationLabel(imi.getServiceInfo().applicationInfo); + return imi.loadLabel(mPackageManager); } private CharSequence getSubtypeName(InputMethodInfo imi, InputMethodSubtype subtype) { diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java index 56611169899b..162381d0d429 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java @@ -145,10 +145,10 @@ public class KeyguardViewMediator implements KeyguardViewCallback, private static final int KEYGUARD_DONE_DRAWING_TIMEOUT_MS = 2000; /** - * Allow the user to operate the status bar when the keyguard is engaged (without a pattern or - * password). + * Allow the user to expand the status bar when the keyguard is engaged + * (without a pattern or password). */ - private static final boolean ENABLE_STATUS_BAR_IN_KEYGUARD = true; + private static final boolean ENABLE_INSECURE_STATUS_BAR_EXPAND = true; private Context mContext; private AlarmManager mAlarmManager; @@ -1184,19 +1184,25 @@ public class KeyguardViewMediator implements KeyguardViewCallback, } } - // if the keyguard is shown, allow the status bar to open only if the keyguard is - // insecure and (is covered by another window OR this feature is enabled in general) - boolean enable = !mShowing - || ((ENABLE_STATUS_BAR_IN_KEYGUARD || mHidden) && !isSecure()); + int flags = StatusBarManager.DISABLE_NONE; + if (mShowing && !mHidden) { + // showing lockscreen exclusively; disable various extra + // statusbar components. + flags |= StatusBarManager.DISABLE_NAVIGATION; + flags |= StatusBarManager.DISABLE_CLOCK; + } + if (mShowing && (isSecure() || !ENABLE_INSECURE_STATUS_BAR_EXPAND)) { + // showing secure lockscreen; disable expanding. + flags |= StatusBarManager.DISABLE_EXPAND; + } + if (DEBUG) { - Log.d(TAG, "adjustStatusBarLocked: mShowing=" + mShowing + " mHidden=" + mHidden - + " isSecure=" + isSecure() + " --> enable=" + enable); + Log.d(TAG, + "adjustStatusBarLocked: mShowing=" + mShowing + " mHidden=" + mHidden + + " isSecure=" + isSecure() + " --> flags=" + flags); } - mStatusBarManager.disable(enable ? - StatusBarManager.DISABLE_NONE : - ( StatusBarManager.DISABLE_EXPAND - | StatusBarManager.DISABLE_NAVIGATION - | StatusBarManager.DISABLE_CLOCK)); + + mStatusBarManager.disable(flags); } } diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java index 38bcebc15053..bb831f51d07d 100644 --- a/services/java/com/android/server/InputMethodManagerService.java +++ b/services/java/com/android/server/InputMethodManagerService.java @@ -1682,7 +1682,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub for (int i = 0; i < packageNum; ++i) { if (packageInfos[i].equals(imi.getPackageName())) { mFileManager.addInputMethodSubtypes(imi, subtypes); - buildInputMethodListLocked(mMethodList, mMethodMap); + final long ident = Binder.clearCallingIdentity(); + try { + buildInputMethodListLocked(mMethodList, mMethodMap); + } finally { + Binder.restoreCallingIdentity(ident); + } return true; } } @@ -1707,7 +1712,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return; } - long ident = Binder.clearCallingIdentity(); + final long ident = Binder.clearCallingIdentity(); try { setInputMethodLocked(id, subtypeId); } finally { @@ -3065,17 +3070,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub public void addInputMethodSubtypes( InputMethodInfo imi, InputMethodSubtype[] additionalSubtypes) { synchronized (mMethodMap) { - final HashSet<InputMethodSubtype> existingSubtypes = - new HashSet<InputMethodSubtype>(); - for (int i = 0; i < imi.getSubtypeCount(); ++i) { - existingSubtypes.add(imi.getSubtypeAt(i)); - } - final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); final int N = additionalSubtypes.length; for (int i = 0; i < N; ++i) { final InputMethodSubtype subtype = additionalSubtypes[i]; - if (!subtypes.contains(subtype) && !existingSubtypes.contains(subtype)) { + if (!subtypes.contains(subtype)) { subtypes.add(subtype); } } diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java index f6c369eacddf..c792b33bf2b4 100644 --- a/services/java/com/android/server/TextServicesManagerService.java +++ b/services/java/com/android/server/TextServicesManagerService.java @@ -201,7 +201,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { Settings.Secure.getString(mContext.getContentResolver(), Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE); if (DBG) { - Slog.w(TAG, "getCurrentSpellChecker: " + subtypeHashCodeStr); + Slog.w(TAG, "getCurrentSpellCheckerSubtype: " + subtypeHashCodeStr); } final SpellCheckerInfo sci = getCurrentSpellChecker(null); if (sci == null || sci.getSubtypeCount() == 0) { @@ -509,7 +509,8 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { listener.mScLocale, listener.mScListener, listener.mBundle); listener.mTsListener.onServiceConnected(session); } catch (RemoteException e) { - Slog.e(TAG, "Exception in getting the spell checker session: " + e); + Slog.e(TAG, "Exception in getting the spell checker session." + + "Reconnect to the spellchecker. ", e); removeAll(); return; } @@ -579,8 +580,12 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { Slog.d(TAG, "cleanLocked"); } if (mListeners.isEmpty()) { - if (mSpellCheckerBindGroups.containsKey(this)) { - mSpellCheckerBindGroups.remove(this); + final String sciId = mInternalConnection.mSciId; + if (mSpellCheckerBindGroups.containsKey(sciId)) { + if (DBG) { + Slog.d(TAG, "Remove bind group."); + } + mSpellCheckerBindGroups.remove(sciId); } // Unbind service when there is no active clients. mContext.unbindService(mInternalConnection); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f8925b840f7a..edbc7b023503 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -212,19 +212,6 @@ void Layer::setGeometry(hwc_layer_t* hwcl) } else { hwcl->transform = finalTransform; } -} - -void Layer::setPerFrameData(hwc_layer_t* hwcl) { - const sp<GraphicBuffer>& buffer(mActiveBuffer); - if (buffer == NULL) { - // this can happen if the client never drew into this layer yet, - // or if we ran out of memory. In that case, don't let - // HWC handle it. - hwcl->flags |= HWC_SKIP_LAYER; - hwcl->handle = NULL; - } else { - hwcl->handle = buffer->handle; - } if (isCropped()) { hwcl->sourceCrop.left = mCurrentCrop.left; @@ -232,6 +219,7 @@ void Layer::setPerFrameData(hwc_layer_t* hwcl) { hwcl->sourceCrop.right = mCurrentCrop.right; hwcl->sourceCrop.bottom = mCurrentCrop.bottom; } else { + const sp<GraphicBuffer>& buffer(mActiveBuffer); hwcl->sourceCrop.left = 0; hwcl->sourceCrop.top = 0; if (buffer != NULL) { @@ -244,6 +232,19 @@ void Layer::setPerFrameData(hwc_layer_t* hwcl) { } } +void Layer::setPerFrameData(hwc_layer_t* hwcl) { + const sp<GraphicBuffer>& buffer(mActiveBuffer); + if (buffer == NULL) { + // this can happen if the client never drew into this layer yet, + // or if we ran out of memory. In that case, don't let + // HWC handle it. + hwcl->flags |= HWC_SKIP_LAYER; + hwcl->handle = NULL; + } else { + hwcl->handle = buffer->handle; + } +} + void Layer::onDraw(const Region& clip) const { if (CC_UNLIKELY(mActiveBuffer == 0)) { @@ -416,8 +417,7 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) return; } - mActiveBuffer = mSurfaceTexture->getCurrentBuffer(); - mSurfaceTexture->getTransformMatrix(mTextureMatrix); + sp<GraphicBuffer> newFrontBuffer(mSurfaceTexture->getCurrentBuffer()); const Rect crop(mSurfaceTexture->getCurrentCrop()); const uint32_t transform(mSurfaceTexture->getCurrentTransform()); @@ -432,7 +432,23 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) mFlinger->invalidateHwcGeometry(); } - mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format); + GLfloat textureMatrix[16]; + mSurfaceTexture->getTransformMatrix(textureMatrix); + if (memcmp(textureMatrix, mTextureMatrix, sizeof(textureMatrix))) { + memcpy(mTextureMatrix, textureMatrix, sizeof(textureMatrix)); + mFlinger->invalidateHwcGeometry(); + } + + uint32_t bufWidth = newFrontBuffer->getWidth(); + uint32_t bufHeight = newFrontBuffer->getHeight(); + if (mActiveBuffer != NULL) { + if (bufWidth != uint32_t(mActiveBuffer->width) || + bufHeight != uint32_t(mActiveBuffer->height)) { + mFlinger->invalidateHwcGeometry(); + } + } + + mCurrentOpacity = getOpacityForFormat(newFrontBuffer->format); if (oldOpacity != isOpaque()) { recomputeVisibleRegions = true; } @@ -446,15 +462,14 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) // FIXME: mPostedDirtyRegion = dirty & bounds mPostedDirtyRegion.set(front.w, front.h); + // update active buffer + mActiveBuffer = newFrontBuffer; if ((front.w != front.requested_w) || (front.h != front.requested_h)) { // check that we received a buffer of the right size // (Take the buffer's orientation into account) - sp<GraphicBuffer> newFrontBuffer(mActiveBuffer); - uint32_t bufWidth = newFrontBuffer->getWidth(); - uint32_t bufHeight = newFrontBuffer->getHeight(); if (mCurrentTransform & Transform::ROT_90) { swap(bufWidth, bufHeight); } diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp index 4cc245a11076..603fb607bae1 100644 --- a/services/surfaceflinger/LayerBase.cpp +++ b/services/surfaceflinger/LayerBase.cpp @@ -45,7 +45,6 @@ LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display) mFlinger(flinger), mFiltering(false), mNeedsFiltering(false), mOrientation(0), - mLeft(0), mTop(0), mTransactionFlags(0), mPremultipliedAlpha(true), mName("unnamed"), mDebug(false), mInvalidate(0) @@ -119,7 +118,7 @@ uint32_t LayerBase::setTransactionFlags(uint32_t flags) { return android_atomic_or(flags, &mTransactionFlags); } -bool LayerBase::setPosition(int32_t x, int32_t y) { +bool LayerBase::setPosition(float x, float y) { if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y) return false; mCurrentState.sequence++; @@ -259,8 +258,6 @@ void LayerBase::validateVisibility(const Transform& planeTransform) mOrientation = tr.getOrientation(); mTransform = tr; mTransformedBounds = tr.makeBounds(w, h); - mLeft = tr.tx(); - mTop = tr.ty(); } void LayerBase::lockPageFlip(bool& recomputeVisibleRegions) @@ -335,17 +332,18 @@ void LayerBase::setGeometry(hwc_layer_t* hwcl) reinterpret_cast<hwc_rect_t const *>( visibleRegionScreen.getArray( &hwcl->visibleRegionScreen.numRects)); -} -void LayerBase::setPerFrameData(hwc_layer_t* hwcl) { - hwcl->compositionType = HWC_FRAMEBUFFER; - hwcl->handle = NULL; hwcl->sourceCrop.left = 0; hwcl->sourceCrop.top = 0; hwcl->sourceCrop.right = mTransformedBounds.width(); hwcl->sourceCrop.bottom = mTransformedBounds.height(); } +void LayerBase::setPerFrameData(hwc_layer_t* hwcl) { + hwcl->compositionType = HWC_FRAMEBUFFER; + hwcl->handle = NULL; +} + void LayerBase::setFiltering(bool filtering) { mFiltering = filtering; @@ -476,10 +474,10 @@ void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const snprintf(buffer, SIZE, "+ %s %p\n" " " - "z=%9d, pos=(%4d,%4d), size=(%4d,%4d), " + "z=%9d, pos=(%g,%g), size=(%4d,%4d), " "isOpaque=%1d, needsDithering=%1d, invalidate=%1d, " "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n", - getTypeId(), this, s.z, tx(), ty(), s.w, s.h, + getTypeId(), this, s.z, s.transform.tx(), s.transform.ty(), s.w, s.h, isOpaque(), needsDithering(), contentDirty, s.alpha, s.flags, s.transform[0][0], s.transform[0][1], diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h index 2cd3a9435e91..d20f06ac87b9 100644 --- a/services/surfaceflinger/LayerBase.h +++ b/services/surfaceflinger/LayerBase.h @@ -84,7 +84,7 @@ public: String8 getName() const; // modify current state - bool setPosition(int32_t x, int32_t y); + bool setPosition(float x, float y); bool setLayer(uint32_t z); bool setSize(uint32_t w, uint32_t h); bool setAlpha(uint8_t alpha); @@ -217,8 +217,6 @@ public: inline State& currentState() { return mCurrentState; } int32_t getOrientation() const { return mOrientation; } - int tx() const { return mLeft; } - int ty() const { return mTop; } protected: const GraphicPlane& graphicPlane(int dpy) const; @@ -250,8 +248,6 @@ protected: Transform mTransform; GLfloat mVertices[4][2]; Rect mTransformedBounds; - int mLeft; - int mTop; // these are protected by an external lock State mCurrentState; diff --git a/services/surfaceflinger/Transform.cpp b/services/surfaceflinger/Transform.cpp index 05b7527563fa..ba345ce45b7a 100644 --- a/services/surfaceflinger/Transform.cpp +++ b/services/surfaceflinger/Transform.cpp @@ -91,12 +91,12 @@ bool Transform::transformed() const { return type() > TRANSLATE; } -int Transform::tx() const { - return floorf(mMatrix[2][0] + 0.5f); +float Transform::tx() const { + return mMatrix[2][0]; } -int Transform::ty() const { - return floorf(mMatrix[2][1] + 0.5f); +float Transform::ty() const { + return mMatrix[2][1]; } void Transform::reset() { @@ -239,7 +239,9 @@ Region Transform::transform(const Region& reg) const out.set(transform(reg.bounds())); } } else { - out = reg.translate(tx(), ty()); + int xpos = floorf(tx() + 0.5f); + int ypos = floorf(ty() + 0.5f); + out = reg.translate(xpos, ypos); } return out; } diff --git a/services/surfaceflinger/Transform.h b/services/surfaceflinger/Transform.h index 8fa5b86ffa43..ec74243d2d18 100644 --- a/services/surfaceflinger/Transform.h +++ b/services/surfaceflinger/Transform.h @@ -64,8 +64,8 @@ public: uint32_t getOrientation() const; float const* operator [] (int i) const; // returns column i - int tx() const; - int ty() const; + float tx() const; + float ty() const; // modify the transform void reset(); |