diff options
44 files changed, 1285 insertions, 521 deletions
diff --git a/api/current.xml b/api/current.xml index e9082bc..e9c3b30 100644 --- a/api/current.xml +++ b/api/current.xml @@ -8567,6 +8567,50 @@ visibility="public" > </field> +<field name="wallpaperActivityCloseEnterAnimation" + type="int" + transient="false" + volatile="false" + value="16843412" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="wallpaperActivityCloseExitAnimation" + type="int" + transient="false" + volatile="false" + value="16843413" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="wallpaperActivityOpenEnterAnimation" + type="int" + transient="false" + volatile="false" + value="16843410" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="wallpaperActivityOpenExitAnimation" + type="int" + transient="false" + volatile="false" + value="16843411" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="webViewStyle" type="int" transient="false" @@ -12087,6 +12131,17 @@ visibility="public" > </field> +<field name="Animation_InputMethod" + type="int" + transient="false" + volatile="false" + value="16973910" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="Animation_Toast" type="int" transient="false" @@ -144974,6 +145029,8 @@ > <parameter name="dirty" type="android.graphics.Rect"> </parameter> +<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException"> +</exception> <exception name="Surface.OutOfResourcesException" type="android.view.Surface.OutOfResourcesException"> </exception> </method> @@ -175196,6 +175253,39 @@ deprecated="not deprecated" visibility="public" > +<method name="canPause" + return="boolean" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="canSeekBackward" + return="boolean" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="canSeekForward" + return="boolean" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> <method name="getBufferPercentage" return="int" abstract="true" @@ -183524,6 +183614,39 @@ <parameter name="defStyle" type="int"> </parameter> </constructor> +<method name="canPause" + return="boolean" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="canSeekBackward" + return="boolean" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="canSeekForward" + return="boolean" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> <method name="getBufferPercentage" return="int" abstract="false" diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp index 56f6338..185e6ac 100644 --- a/cmds/stagefright/stagefright.cpp +++ b/cmds/stagefright/stagefright.cpp @@ -70,6 +70,7 @@ static void playSource(OMXClient *client, const sp<MediaSource> &source) { long numIterationsLeft = gNumRepetitions; MediaSource::ReadOptions options; + while (numIterationsLeft-- > 0) { MediaBuffer *buffer; diff --git a/core/java/android/pim/ContactsAsyncHelper.java b/core/java/android/pim/ContactsAsyncHelper.java index a21281e..342d208 100644 --- a/core/java/android/pim/ContactsAsyncHelper.java +++ b/core/java/android/pim/ContactsAsyncHelper.java @@ -27,8 +27,7 @@ import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.Message; -import android.provider.Contacts; -import android.provider.Contacts.People; +import android.provider.ContactsContract.Contacts; import android.util.Log; import android.view.View; import android.widget.ImageView; @@ -39,35 +38,35 @@ import java.io.InputStream; * Helper class for async access of images. */ public class ContactsAsyncHelper extends Handler { - + private static final boolean DBG = false; private static final String LOG_TAG = "ContactsAsyncHelper"; - + /** * Interface for a WorkerHandler result return. */ public interface OnImageLoadCompleteListener { /** * Called when the image load is complete. - * + * * @param imagePresent true if an image was found - */ + */ public void onImageLoadComplete(int token, Object cookie, ImageView iView, boolean imagePresent); } - + // constants private static final int EVENT_LOAD_IMAGE = 1; private static final int DEFAULT_TOKEN = -1; - + // static objects private static Handler sThreadHandler; private static ContactsAsyncHelper sInstance; - + static { sInstance = new ContactsAsyncHelper(); } - + private static final class WorkerArgs { public Context context; public ImageView view; @@ -78,12 +77,12 @@ public class ContactsAsyncHelper extends Handler { public OnImageLoadCompleteListener listener; public CallerInfo info; } - + /** - * public inner class to help out the ContactsAsyncHelper callers - * with tracking the state of the CallerInfo Queries and image + * public inner class to help out the ContactsAsyncHelper callers + * with tracking the state of the CallerInfo Queries and image * loading. - * + * * Logic contained herein is used to remove the race conditions * that exist as the CallerInfo queries run and mix with the image * loads, which then mix with the Phone state changes. @@ -94,11 +93,11 @@ public class ContactsAsyncHelper extends Handler { public static final int DISPLAY_UNDEFINED = 0; public static final int DISPLAY_IMAGE = -1; public static final int DISPLAY_DEFAULT = -2; - + // State of the image on the imageview. private CallerInfo mCurrentCallerInfo; private int displayMode; - + public ImageTracker() { mCurrentCallerInfo = null; displayMode = DISPLAY_UNDEFINED; @@ -107,17 +106,17 @@ public class ContactsAsyncHelper extends Handler { /** * Used to see if the requested call / connection has a * different caller attached to it than the one we currently - * have in the CallCard. + * have in the CallCard. */ public boolean isDifferentImageRequest(CallerInfo ci) { // note, since the connections are around for the lifetime of the - // call, and the CallerInfo-related items as well, we can + // call, and the CallerInfo-related items as well, we can // definitely use a simple != comparison. return (mCurrentCallerInfo != ci); } - + public boolean isDifferentImageRequest(Connection connection) { - // if the connection does not exist, see if the + // if the connection does not exist, see if the // mCurrentCallerInfo is also null to match. if (connection == null) { if (DBG) Log.d(LOG_TAG, "isDifferentImageRequest: connection is null"); @@ -133,57 +132,58 @@ public class ContactsAsyncHelper extends Handler { } return runQuery; } - + /** - * Simple setter for the CallerInfo object. + * Simple setter for the CallerInfo object. */ public void setPhotoRequest(CallerInfo ci) { - mCurrentCallerInfo = ci; + mCurrentCallerInfo = ci; } - + /** - * Convenience method used to retrieve the URI - * representing the Photo file recorded in the attached - * CallerInfo Object. + * Convenience method used to retrieve the URI + * representing the Photo file recorded in the attached + * CallerInfo Object. */ public Uri getPhotoUri() { if (mCurrentCallerInfo != null) { - return ContentUris.withAppendedId(People.CONTENT_URI, + return ContentUris.withAppendedId(Contacts.CONTENT_URI, mCurrentCallerInfo.person_id); } - return null; + return null; } - + /** - * Simple setter for the Photo state. + * Simple setter for the Photo state. */ public void setPhotoState(int state) { displayMode = state; } - + /** - * Simple getter for the Photo state. + * Simple getter for the Photo state. */ public int getPhotoState() { return displayMode; } } - + /** - * Thread worker class that handles the task of opening the stream and loading + * Thread worker class that handles the task of opening the stream and loading * the images. */ private class WorkerHandler extends Handler { public WorkerHandler(Looper looper) { super(looper); } - + + @Override public void handleMessage(Message msg) { WorkerArgs args = (WorkerArgs) msg.obj; - + switch (msg.arg1) { case EVENT_LOAD_IMAGE: - InputStream inputStream = Contacts.People.openContactPhotoInputStream( + InputStream inputStream = Contacts.openContactPhotoInputStream( args.context.getContentResolver(), args.uri); if (inputStream != null) { args.result = Drawable.createFromStream(inputStream, args.uri.toString()); @@ -192,22 +192,22 @@ public class ContactsAsyncHelper extends Handler { " token: " + msg.what + " image URI: " + args.uri); } else { args.result = null; - if (DBG) Log.d(LOG_TAG, "Problem with image: " + msg.arg1 + - " token: " + msg.what + " image URI: " + args.uri + + if (DBG) Log.d(LOG_TAG, "Problem with image: " + msg.arg1 + + " token: " + msg.what + " image URI: " + args.uri + ", using default image."); } break; default: } - - // send the reply to the enclosing class. + + // send the reply to the enclosing class. Message reply = ContactsAsyncHelper.this.obtainMessage(msg.what); reply.arg1 = msg.arg1; reply.obj = msg.obj; reply.sendToTarget(); } } - + /** * Private constructor for static class */ @@ -216,14 +216,14 @@ public class ContactsAsyncHelper extends Handler { thread.start(); sThreadHandler = new WorkerHandler(thread.getLooper()); } - + /** * Convenience method for calls that do not want to deal with listeners and tokens. */ - public static final void updateImageViewWithContactPhotoAsync(Context context, + public static final void updateImageViewWithContactPhotoAsync(Context context, ImageView imageView, Uri person, int placeholderImageResource) { // Added additional Cookie field in the callee. - updateImageViewWithContactPhotoAsync (null, DEFAULT_TOKEN, null, null, context, + updateImageViewWithContactPhotoAsync (null, DEFAULT_TOKEN, null, null, context, imageView, person, placeholderImageResource); } @@ -231,24 +231,24 @@ public class ContactsAsyncHelper extends Handler { * Convenience method for calls that do not want to deal with listeners and tokens, but have * a CallerInfo object to cache the image to. */ - public static final void updateImageViewWithContactPhotoAsync(CallerInfo info, Context context, + public static final void updateImageViewWithContactPhotoAsync(CallerInfo info, Context context, ImageView imageView, Uri person, int placeholderImageResource) { // Added additional Cookie field in the callee. - updateImageViewWithContactPhotoAsync (info, DEFAULT_TOKEN, null, null, context, + updateImageViewWithContactPhotoAsync (info, DEFAULT_TOKEN, null, null, context, imageView, person, placeholderImageResource); } - + /** * Start an image load, attach the result to the specified CallerInfo object. * Note, when the query is started, we make the ImageView INVISIBLE if the * placeholderImageResource value is -1. When we're given a valid (!= -1) * placeholderImageResource value, we make sure the image is visible. */ - public static final void updateImageViewWithContactPhotoAsync(CallerInfo info, int token, - OnImageLoadCompleteListener listener, Object cookie, Context context, + public static final void updateImageViewWithContactPhotoAsync(CallerInfo info, int token, + OnImageLoadCompleteListener listener, Object cookie, Context context, ImageView imageView, Uri person, int placeholderImageResource) { - + // in case the source caller info is null, the URI will be null as well. // just update using the placeholder image in this case. if (person == null) { @@ -257,10 +257,10 @@ public class ContactsAsyncHelper extends Handler { imageView.setImageResource(placeholderImageResource); return; } - + // Added additional Cookie field in the callee to handle arguments // sent to the callback function. - + // setup arguments WorkerArgs args = new WorkerArgs(); args.cookie = cookie; @@ -270,15 +270,15 @@ public class ContactsAsyncHelper extends Handler { args.defaultResource = placeholderImageResource; args.listener = listener; args.info = info; - + // setup message arguments Message msg = sThreadHandler.obtainMessage(token); msg.arg1 = EVENT_LOAD_IMAGE; msg.obj = args; - - if (DBG) Log.d(LOG_TAG, "Begin loading image: " + args.uri + + + if (DBG) Log.d(LOG_TAG, "Begin loading image: " + args.uri + ", displaying default image for now."); - + // set the default image first, when the query is complete, we will // replace the image with the correct one. if (placeholderImageResource != -1) { @@ -287,11 +287,11 @@ public class ContactsAsyncHelper extends Handler { } else { imageView.setVisibility(View.INVISIBLE); } - + // notify the thread to begin working sThreadHandler.sendMessage(msg); } - + /** * Called when loading is done. */ @@ -316,21 +316,21 @@ public class ContactsAsyncHelper extends Handler { args.view.setVisibility(View.VISIBLE); args.view.setImageResource(args.defaultResource); } - + // Note that the data is cached. if (args.info != null) { args.info.isCachedPhotoCurrent = true; } - + // notify the listener if it is there. if (args.listener != null) { - if (DBG) Log.d(LOG_TAG, "Notifying listener: " + args.listener.toString() + + if (DBG) Log.d(LOG_TAG, "Notifying listener: " + args.listener.toString() + " image: " + args.uri + " completed"); args.listener.onImageLoadComplete(msg.what, args.cookie, args.view, imagePresent); } break; - default: + default: } } } diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index 50c9c8c..5932040 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -19,15 +19,21 @@ package android.provider; import android.accounts.Account; import android.content.ContentProviderClient; import android.content.ContentProviderOperation; +import android.content.ContentResolver; +import android.content.ContentUris; import android.content.Context; import android.content.Intent; import android.content.res.Resources; +import android.database.Cursor; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.RemoteException; import android.provider.ContactsContract.CommonDataKinds.GroupMembership; import android.text.TextUtils; +import java.io.ByteArrayInputStream; +import java.io.InputStream; + /** * The contract between the contacts provider and applications. Contains definitions * for the supported URIs and columns. @@ -299,6 +305,55 @@ public final class ContactsContract { */ public static final String CONTENT_DIRECTORY = "suggestions"; } + + /** + * Returns a URI that can be used to retrieve the contact's default photo. + * + * @param contactUri the contact whose photo should be used + */ + public static Uri getPhotoUri(ContentResolver cr, Uri contactUri) { + long photoId = -1; + Cursor cursor = cr.query(contactUri, new String[]{Contacts.PHOTO_ID}, null, null, null); + try { + if (!cursor.moveToNext()) { + return null; + } + + if (cursor.isNull(0)) { + return null; + } + + photoId = cursor.getLong(0); + } finally { + cursor.close(); + } + + return ContentUris.withAppendedId(ContactsContract.Data.CONTENT_URI, photoId); + } + + /** + * Opens an InputStream for the person's default photo and returns the + * photo as a Bitmap stream. + * + * @param contactUri the contact whose photo should be used + */ + public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri contactUri) { + Uri photoUri = getPhotoUri(cr, contactUri); + Cursor cursor = cr.query(photoUri, + new String[]{ContactsContract.CommonDataKinds.Photo.PHOTO}, null, null, null); + try { + if (!cursor.moveToNext()) { + return null; + } + byte[] data = cursor.getBlob(0); + if (data == null) { + return null; + } + return new ByteArrayInputStream(data); + } finally { + cursor.close(); + } + } } private interface RawContactsColumns { @@ -1557,14 +1612,6 @@ public final class ContactsContract { public static final String SHOULD_SYNC = "should_sync"; /** - * Overriding flag indicating if contacts from this source should be - * visible in any user interface. - * <p> - * Type: INTEGER (boolean) - */ - public static final String SOURCE_VISIBLE = "source_visible"; - - /** * Flag indicating if contacts without any {@link GroupMembership} * entries should be visible in any user interface. * <p> diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index 9ec1013..5cecac3 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -246,7 +246,7 @@ public class Surface implements Parcelable { }; /** - * Sets the display metrics used to provide canva's width/height in comaptibility mode. + * Sets the display metrics used to provide canva's width/height in compatibility mode. */ void setCompatibleDisplayMetrics(DisplayMetrics metrics, Translator translator) { mCompatibleDisplayMetrics = metrics; @@ -275,7 +275,8 @@ public class Surface implements Parcelable { public native void clear(); /** draw into a surface */ - public Canvas lockCanvas(Rect dirty) throws OutOfResourcesException { + public Canvas lockCanvas(Rect dirty) throws OutOfResourcesException, IllegalArgumentException + { /* the dirty rectangle may be expanded to the surface's size, if * for instance it has been resized or if the bits were lost, since * the last call. diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index f4e9900..ea08f33 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -344,6 +344,12 @@ public interface WindowManagerPolicy { public final int TRANSIT_TASK_TO_FRONT = 10; /** A window in an existing task is being put below all other tasks. */ public final int TRANSIT_TASK_TO_BACK = 11; + /** A window in a new activity is being opened on top of an existing one, + * and both are on top of the wallpaper. */ + public final int TRANSIT_WALLPAPER_ACTIVITY_OPEN = 12; + /** The window in the top-most activity is being closed to reveal the + * previous activity, and both are on top of he wallpaper. */ + public final int TRANSIT_WALLPAPER_ACTIVITY_CLOSE = 13; /** Screen turned off because of power button */ public final int OFF_BECAUSE_OF_USER = 1; diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java index 0c9d980..9910c37 100644 --- a/core/java/android/widget/MediaController.java +++ b/core/java/android/widget/MediaController.java @@ -250,6 +250,29 @@ public class MediaController extends FrameLayout { } /** + * Disable pause or seek buttons if the stream cannot be paused or seeked. + * This requires the control interface to be a MediaPlayerControlExt + */ + private void disableUnsupportedButtons() { + try { + if (mPauseButton != null && !mPlayer.canPause()) { + mPauseButton.setEnabled(false); + } + if (mRewButton != null && !mPlayer.canSeekBackward()) { + mRewButton.setEnabled(false); + } + if (mFfwdButton != null && !mPlayer.canSeekForward()) { + mFfwdButton.setEnabled(false); + } + } catch (IncompatibleClassChangeError ex) { + // We were given an old version of the interface, that doesn't have + // the canPause/canSeekXYZ methods. This is OK, it just means we + // assume the media can be paused and seeked, and so we don't disable + // the buttons. + } + } + + /** * Show the controller on screen. It will go away * automatically after 'timeout' milliseconds of inactivity. * @param timeout The timeout in milliseconds. Use 0 to show @@ -259,6 +282,7 @@ public class MediaController extends FrameLayout { if (!mShowing && mAnchor != null) { setProgress(); + disableUnsupportedButtons(); int [] anchorpos = new int[2]; mAnchor.getLocationOnScreen(anchorpos); @@ -421,17 +445,13 @@ public class MediaController extends FrameLayout { }; private void updatePausePlay() { - if (mRoot == null) - return; - - ImageButton button = (ImageButton) mRoot.findViewById(com.android.internal.R.id.pause); - if (button == null) + if (mRoot == null || mPauseButton == null) return; if (mPlayer.isPlaying()) { - button.setImageResource(com.android.internal.R.drawable.ic_media_pause); + mPauseButton.setImageResource(com.android.internal.R.drawable.ic_media_pause); } else { - button.setImageResource(com.android.internal.R.drawable.ic_media_play); + mPauseButton.setImageResource(com.android.internal.R.drawable.ic_media_play); } } @@ -516,7 +536,7 @@ public class MediaController extends FrameLayout { if (mProgress != null) { mProgress.setEnabled(enabled); } - + disableUnsupportedButtons(); super.setEnabled(enabled); } @@ -579,5 +599,8 @@ public class MediaController extends FrameLayout { void seekTo(int pos); boolean isPlaying(); int getBufferPercentage(); - }; + boolean canPause(); + boolean canSeekBackward(); + boolean canSeekForward(); + } } diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java index 5bc2507..e60ff25 100644 --- a/core/java/android/widget/VideoView.java +++ b/core/java/android/widget/VideoView.java @@ -23,6 +23,7 @@ import android.content.Intent; import android.content.res.Resources; import android.media.AudioManager; import android.media.MediaPlayer; +import android.media.Metadata; import android.media.MediaPlayer.OnCompletionListener; import android.media.MediaPlayer.OnErrorListener; import android.net.Uri; @@ -34,7 +35,7 @@ import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; -import android.widget.MediaController.MediaPlayerControl; +import android.widget.MediaController.*; import java.io.IOException; @@ -81,6 +82,9 @@ public class VideoView extends SurfaceView implements MediaPlayerControl { private int mCurrentBufferPercentage; private OnErrorListener mOnErrorListener; private int mSeekWhenPrepared; // recording the seek position while preparing + private boolean mCanPause; + private boolean mCanSeekBack; + private boolean mCanSeekForward; public VideoView(Context context) { super(context); @@ -259,6 +263,17 @@ public class VideoView extends SurfaceView implements MediaPlayerControl { MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() { public void onPrepared(MediaPlayer mp) { mCurrentState = STATE_PREPARED; + + // Get the capabilities of the player for this stream + Metadata data = mp.getMetadata(MediaPlayer.METADATA_ALL, + MediaPlayer.BYPASS_METADATA_FILTER); + mCanPause = !data.has(Metadata.PAUSE_AVAILABLE) + || data.getBoolean(Metadata.PAUSE_AVAILABLE); + mCanSeekBack = !data.has(Metadata.SEEK_BACKWARD_AVAILABLE) + || data.getBoolean(Metadata.SEEK_BACKWARD_AVAILABLE); + mCanSeekForward = !data.has(Metadata.SEEK_FORWARD_AVAILABLE) + || data.getBoolean(Metadata.SEEK_FORWARD_AVAILABLE); + if (mOnPreparedListener != null) { mOnPreparedListener.onPrepared(mMediaPlayer); } @@ -267,6 +282,7 @@ public class VideoView extends SurfaceView implements MediaPlayerControl { } mVideoWidth = mp.getVideoWidth(); mVideoHeight = mp.getVideoHeight(); + int seekToPosition = mSeekWhenPrepared; // mSeekWhenPrepared may be changed after seekTo() call if (seekToPosition != 0) { seekTo(seekToPosition); @@ -580,4 +596,16 @@ public class VideoView extends SurfaceView implements MediaPlayerControl { mCurrentState != STATE_IDLE && mCurrentState != STATE_PREPARING); } + + public boolean canPause() { + return mCanPause; + } + + public boolean canSeekBackward() { + return mCanSeekBack; + } + + public boolean canSeekForward() { + return mCanSeekForward; + } } diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 2e73372..f61e247 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -525,6 +525,7 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv) char dexoptFlagsBuf[PROPERTY_VALUE_MAX]; char enableAssertBuf[sizeof("-ea:")-1 + PROPERTY_VALUE_MAX]; char jniOptsBuf[sizeof("-Xjniopts:")-1 + PROPERTY_VALUE_MAX]; + char heapsizeOptsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX]; char* stackTraceFile = NULL; bool checkJni = false; bool checkDexSum = false; @@ -597,16 +598,10 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv) mOptions.add(opt); //options[curOpt++].optionString = "-verbose:class"; -#ifdef CUSTOM_RUNTIME_HEAP_MAX -#define __make_max_heap_opt(val) #val -#define _make_max_heap_opt(val) "-Xmx" __make_max_heap_opt(val) - opt.optionString = _make_max_heap_opt(CUSTOM_RUNTIME_HEAP_MAX); -#undef __make_max_heap_opt -#undef _make_max_heap_opt -#else - /* limit memory use to 16MB */ - opt.optionString = "-Xmx16m"; -#endif + strcpy(heapsizeOptsBuf, "-Xmx"); + property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m"); + //LOGI("Heap size: %s", heapsizeOptsBuf); + opt.optionString = heapsizeOptsBuf; mOptions.add(opt); /* diff --git a/core/res/res/anim/wallpaper_activity_close_enter.xml b/core/res/res/anim/wallpaper_activity_close_enter.xml new file mode 100644 index 0000000..fc6e332 --- /dev/null +++ b/core/res/res/anim/wallpaper_activity_close_enter.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/res/anim/options_panel_exit.xml +** +** Copyright 2007, 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. +*/ +--> + +<set xmlns:android="http://schemas.android.com/apk/res/android" + android:interpolator="@anim/decelerate_interpolator" + android:zAdjustment="top"> + <scale android:fromXScale="2.0" android:toXScale="1.0" + android:fromYScale="2.0" android:toYScale="1.0" + android:pivotX="50%" android:pivotY="50%" + android:duration="@android:integer/config_mediumAnimTime" /> + <translate android:fromXDelta="-150%" android:toXDelta="0" + android:duration="@android:integer/config_mediumAnimTime"/> +</set> diff --git a/core/res/res/anim/wallpaper_activity_close_exit.xml b/core/res/res/anim/wallpaper_activity_close_exit.xml new file mode 100644 index 0000000..edd00fd --- /dev/null +++ b/core/res/res/anim/wallpaper_activity_close_exit.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/res/anim/options_panel_exit.xml +** +** Copyright 2007, 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. +*/ +--> + +<set xmlns:android="http://schemas.android.com/apk/res/android" + android:interpolator="@anim/accelerate_interpolator"> + <scale android:fromXScale="1.0" android:toXScale=".5" + android:fromYScale="1.0" android:toYScale=".5" + android:pivotX="50%" android:pivotY="50%" + android:duration="@android:integer/config_mediumAnimTime" /> + <translate android:fromXDelta="0%" android:toXDelta="100%" + android:duration="@android:integer/config_mediumAnimTime"/> +</set> diff --git a/core/res/res/anim/wallpaper_activity_open_enter.xml b/core/res/res/anim/wallpaper_activity_open_enter.xml new file mode 100644 index 0000000..5b44d97 --- /dev/null +++ b/core/res/res/anim/wallpaper_activity_open_enter.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/res/anim/options_panel_exit.xml +** +** Copyright 2007, 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. +*/ +--> + +<set xmlns:android="http://schemas.android.com/apk/res/android" + android:interpolator="@anim/decelerate_interpolator"> + <scale android:fromXScale=".5" android:toXScale="1.0" + android:fromYScale=".5" android:toYScale="1.0" + android:pivotX="50%" android:pivotY="50%" + android:duration="@android:integer/config_mediumAnimTime" /> + <translate android:fromXDelta="100%" android:toXDelta="0" + android:duration="@android:integer/config_mediumAnimTime"/> +</set> diff --git a/core/res/res/anim/wallpaper_activity_open_exit.xml b/core/res/res/anim/wallpaper_activity_open_exit.xml new file mode 100644 index 0000000..fa39bee --- /dev/null +++ b/core/res/res/anim/wallpaper_activity_open_exit.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/res/anim/options_panel_exit.xml +** +** Copyright 2007, 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. +*/ +--> + +<set xmlns:android="http://schemas.android.com/apk/res/android" + android:interpolator="@anim/accelerate_interpolator" + android:zAdjustment="top"> + <scale android:fromXScale="1.0" android:toXScale="2.0" + android:fromYScale="1.0" android:toYScale="2.0" + android:pivotX="50%" android:pivotY="50%" + android:duration="@android:integer/config_mediumAnimTime" /> + <translate android:fromXDelta="0" android:toXDelta="-150%" + android:duration="@android:integer/config_mediumAnimTime"/> +</set> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index eee87e6..e03211d 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -937,18 +937,68 @@ <attr name="windowShowAnimation" format="reference" /> <!-- The animation used when a window is going from VISIBLE to INVISIBLE. --> <attr name="windowHideAnimation" format="reference" /> + + <!-- When opening a new activity, this is the animation that is + run on the next activity (which is entering the screen). --> <attr name="activityOpenEnterAnimation" format="reference" /> + <!-- When opening a new activity, this is the animation that is + run on the previous activity (which is exiting the screen). --> <attr name="activityOpenExitAnimation" format="reference" /> + <!-- When closing the current activity, this is the animation that is + run on the next activity (which is entering the screen). --> <attr name="activityCloseEnterAnimation" format="reference" /> + <!-- When closing the current activity, this is the animation that is + run on the current activity (which is exiting the screen). --> <attr name="activityCloseExitAnimation" format="reference" /> + <!-- When opening an activity in a new task, this is the animation that is + run on the activity of the new task (which is entering the screen). --> <attr name="taskOpenEnterAnimation" format="reference" /> + <!-- When opening an activity in a new task, this is the animation that is + run on the activity of the old task (which is exiting the screen). --> <attr name="taskOpenExitAnimation" format="reference" /> + <!-- When closing the last activity of a task, this is the animation that is + run on the activity of the next task (which is entering the screen). --> <attr name="taskCloseEnterAnimation" format="reference" /> + <!-- When opening an activity in a new task, this is the animation that is + run on the activity of the old task (which is exiting the screen). --> <attr name="taskCloseExitAnimation" format="reference" /> + <!-- When bringing an existing task to the foreground, this is the + animation that is run on the top activity of the task being brought + to the foreground (which is entering the screen). --> <attr name="taskToFrontEnterAnimation" format="reference" /> + <!-- When bringing an existing task to the foreground, this is the + animation that is run on the current foreground activity + (which is exiting the screen). --> <attr name="taskToFrontExitAnimation" format="reference" /> + <!-- When sending the current task to the background, this is the + animation that is run on the top activity of the task behind + it (which is entering the screen). --> <attr name="taskToBackEnterAnimation" format="reference" /> + <!-- When sending the current task to the background, this is the + animation that is run on the top activity of the current task + (which is exiting the screen). --> <attr name="taskToBackExitAnimation" format="reference" /> + + <!-- When opening a new activity that is on top of the wallpaper + when the current activity is also on top of the wallpaper, + this is the animation that is run on the new activity + (which is entering the screen). --> + <attr name="wallpaperActivityOpenEnterAnimation" format="reference" /> + <!-- When opening a new activity that is on top of the wallpaper + when the current activity is also on top of the wallpaper, + this is the animation that is run on the current activity + (which is exiting the screen). --> + <attr name="wallpaperActivityOpenExitAnimation" format="reference" /> + <!-- When closing a foreround activity that is on top of the wallpaper + when the previous activity is also on top of the wallpaper, + this is the animation that is run on the previous activity + (which is entering the screen). --> + <attr name="wallpaperActivityCloseEnterAnimation" format="reference" /> + <!-- When closing a foreround activity that is on top of the wallpaper + when the previous activity is also on top of the wallpaper, + this is the animation that is run on the current activity + (which is exiting the screen). --> + <attr name="wallpaperActivityCloseExitAnimation" format="reference" /> </declare-styleable> <!-- ============================= --> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 60b492a..bbeb78d 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -1150,6 +1150,10 @@ <public type="attr" name="contentAuthority" /> <public type="attr" name="userVisible" /> <public type="attr" name="windowShowWallpaper" /> + <public type="attr" name="wallpaperActivityOpenEnterAnimation" /> + <public type="attr" name="wallpaperActivityOpenExitAnimation" /> + <public type="attr" name="wallpaperActivityCloseEnterAnimation" /> + <public type="attr" name="wallpaperActivityCloseExitAnimation" /> <public type="style" name="Theme.Wallpaper" /> <public type="style" name="Theme.Wallpaper.NoTitleBar" /> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 22f9136..c14ecc0 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1350,7 +1350,7 @@ <!-- When the battery is low, this is the label of the button to go to the power usage activity to find out what drained the battery. --> - <string name="battery_low_why">Why?</string> + <string name="battery_low_why">Battery use</string> <!-- Title of the alert when something went wrong in the factory test. --> <string name="factorytest_failed">Factory test failed</string> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index 4aa4210..10d2093 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -66,6 +66,10 @@ <item name="taskToFrontExitAnimation">@anim/task_open_exit</item> <item name="taskToBackEnterAnimation">@anim/task_close_enter</item> <item name="taskToBackExitAnimation">@anim/task_close_exit</item> + <item name="wallpaperActivityOpenEnterAnimation">@anim/wallpaper_activity_open_enter</item> + <item name="wallpaperActivityOpenExitAnimation">@anim/wallpaper_activity_open_exit</item> + <item name="wallpaperActivityCloseEnterAnimation">@anim/wallpaper_activity_close_enter</item> + <item name="wallpaperActivityCloseExitAnimation">@anim/wallpaper_activity_close_exit</item> </style> <!-- Standard animations for a non-full-screen window or activity. --> @@ -130,8 +134,7 @@ <item name="windowExitAnimation">@anim/slide_out_down</item> </style> - <!-- Window animations that are applied to input method overlay windows. - {@hide Pending API council approval} --> + <!-- Window animations that are applied to input method overlay windows. --> <style name="Animation.InputMethod"> <item name="windowEnterAnimation">@anim/input_method_enter</item> <item name="windowExitAnimation">@anim/input_method_exit</item> @@ -151,8 +154,7 @@ <item name="windowExitAnimation">@anim/search_bar_exit</item> </style> - <!-- Window animations that are applied to the zoom buttons overlay window. - {@hide Pending API council approval} --> + <!-- Window animations that are applied to the zoom buttons overlay window. --> <style name="Animation.ZoomButtons"> <item name="windowEnterAnimation">@anim/fade_in</item> <item name="windowExitAnimation">@anim/fade_out</item> diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h index 2d5b8d8..6ce2581 100644 --- a/include/media/stagefright/MetaData.h +++ b/include/media/stagefright/MetaData.h @@ -28,23 +28,23 @@ namespace android { enum { - kKeyMIMEType = 'mime', - kKeyWidth = 'widt', - kKeyHeight = 'heig', - kKeyChannelCount = '#chn', - kKeySampleRate = 'srte', - kKeyBitRate = 'brte', - kKeyESDS = 'esds', - kKeyAVCC = 'avcc', - kKeyTimeUnits = '#tim', - kKeyTimeScale = 'scal', - kKeyNeedsNALFraming = 'NALf', - kKeyIsSyncFrame = 'sync', - kKeyDuration = 'dura', - kKeyColorFormat = 'colf', - kKeyPlatformPrivate = 'priv', - kKeyDecoderComponent = 'decC', - kKeyBufferID = 'bfID', + kKeyMIMEType = 'mime', + kKeyWidth = 'widt', + kKeyHeight = 'heig', + kKeyChannelCount = '#chn', + kKeySampleRate = 'srte', + kKeyBitRate = 'brte', + kKeyESDS = 'esds', + kKeyAVCC = 'avcc', + kKeyTimeUnits = '#tim', + kKeyTimeScale = 'scal', + kKeyWantsNALFragments = 'NALf', + kKeyIsSyncFrame = 'sync', + kKeyDuration = 'dura', + kKeyColorFormat = 'colf', + kKeyPlatformPrivate = 'priv', + kKeyDecoderComponent = 'decC', + kKeyBufferID = 'bfID', }; enum { diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h index d4ae349..c8ee255 100644 --- a/include/media/stagefright/OMXCodec.h +++ b/include/media/stagefright/OMXCodec.h @@ -79,7 +79,7 @@ private: enum Quirks { kNeedsFlushBeforeDisable = 1, - kWantsRawNALFrames = 2, + kWantsNALFragments = 2, kRequiresLoadedToIdleAfterAllocation = 4, kRequiresAllocateBufferOnInputPorts = 8, }; diff --git a/include/media/stagefright/OMXDecoder.h b/include/media/stagefright/OMXDecoder.h index 0abc5a6..99d803a 100644 --- a/include/media/stagefright/OMXDecoder.h +++ b/include/media/stagefright/OMXDecoder.h @@ -76,7 +76,7 @@ private: }; enum Quirks { - kWantsRawNALFrames = 1, + kWantsNALFragments = 1, kDoesntReturnBuffersOnDisable = 2, kDoesntFlushOnExecutingToIdle = 4, kDoesntProperlyFlushAllPortsAtOnce = 8, diff --git a/include/ui/ISurfaceFlingerClient.h b/include/ui/ISurfaceFlingerClient.h index 932a70a..5d231e6 100644 --- a/include/ui/ISurfaceFlingerClient.h +++ b/include/ui/ISurfaceFlingerClient.h @@ -52,6 +52,9 @@ public: struct surface_data_t { int32_t token; int32_t identity; + uint32_t width; + uint32_t height; + uint32_t format; status_t readFromParcel(const Parcel& parcel); status_t writeToParcel(Parcel* parcel) const; }; diff --git a/libs/rs/java/Fall/res/raw/fall.c b/libs/rs/java/Fall/res/raw/fall.c index a67764e..f348a62 100644 --- a/libs/rs/java/Fall/res/raw/fall.c +++ b/libs/rs/java/Fall/res/raw/fall.c @@ -68,17 +68,18 @@ void dropWithStrength(int x, int y, int r, int s) { int* current = loadArrayI32(RSID_RIPPLE_MAP, index * rippleMapSize + origin); int sqr = r * r; + float invs = 1.0f / s; int h = 0; - for ( ; h < r; h++) { + for ( ; h < r; h += 1) { int sqv = h * h; int yn = origin + (y - h) * (width + 2); int yp = origin + (y + h) * (width + 2); int w = 0; - for ( ; w < r; w++) { + for ( ; w < r; w += 1) { int squ = w * w; if (squ + sqv < sqr) { - int v = -sqrtf((sqr - (squ + sqv)) << 16) / s; + int v = -sqrtf((sqr - (squ + sqv)) << 16) * invs; current[yn + x + w] = v; current[yp + x + w] = v; current[yn + x - w] = v; @@ -110,16 +111,16 @@ void updateRipples() { while (h) { int w = width; while (w) { - int droplet = ((current[-b] + current[b] + current[-a] + current[a]) >> 1) - next[0]; + int droplet = ((current[-b] + current[b] + current[-a] + current[a]) >> 1) - *next; droplet -= (droplet >> DAMP); - next[0] = droplet; - current++; - next++; - w--; + *next = droplet; + current += 1; + next += 1; + w -= 1; } current += 2; next += 2; - h--; + h -= 1; } } @@ -149,10 +150,14 @@ void generateRipples() { int *map = loadArrayI32(RSID_REFRACTION_MAP, 0); float *vertices = loadTriangleMeshVerticesF(NAMED_WaterMesh); + float fw = (float) width; + float fh = (float) height; + float fy = (1.0f / 512.0f) * (1.0f / RIPPLE_HEIGHT); + int h = height - 1; while (h >= 0) { int w = width - 1; - int wave = current[0]; + int wave = *current; int offset = h * width; while (w >= 0) { int nextWave = current[1]; @@ -169,40 +174,47 @@ void generateRipples() { v &= ~(v >> 31); if (v >= height) v = height - 1; - vertices[(offset + w) * 8 + 3] = u / (float) width; - vertices[(offset + w) * 8 + 4] = v / (float) height; + int index = (offset + w) << 3; + vertices[index + 3] = u / fw; + vertices[index + 4] = v / fh; // Update Z coordinate of the vertex - vertices[(offset + w) * 8 + 7] = (dy / 512.0f) / RIPPLE_HEIGHT; + vertices[index + 7] = dy * fy; - w--; - current++; + w -= 1; + current += 1; wave = nextWave; } - h--; + h -= 1; current += 2; } // Compute the normals for lighting int y = 0; - for ( ; y < height; y++) { + int w8 = width << 3; + for ( ; y < height; y += 1) { int x = 0; int yOffset = y * width; - for ( ; x < width; x++) { + for ( ; x < width; x += 1) { + int o = (yOffset + x) << 3; + int o1 = o + 8; + int ow = o + w8; + int ow1 = ow + 8; + // V1 - float v1x = vertices[(yOffset + x) * 8 + 5]; - float v1y = vertices[(yOffset + x) * 8 + 6]; - float v1z = vertices[(yOffset + x) * 8 + 7]; + float v1x = vertices[o + 5]; + float v1y = vertices[o + 6]; + float v1z = vertices[o + 7]; // V2 - float v2x = vertices[(yOffset + x + 1) * 8 + 5]; - float v2y = vertices[(yOffset + x + 1) * 8 + 6]; - float v2z = vertices[(yOffset + x + 1) * 8 + 7]; + float v2x = vertices[o1 + 5]; + float v2y = vertices[o1 + 6]; + float v2z = vertices[o1 + 7]; // V3 - float v3x = vertices[(yOffset + width + x) * 8 + 5]; - float v3y = vertices[(yOffset + width + x) * 8 + 6]; - float v3z = vertices[(yOffset + width + x) * 8 + 7]; + float v3x = vertices[ow + 5]; + float v3y = vertices[ow + 6]; + float v3z = vertices[ow + 7]; // N1 float n1x = v2x - v1x; @@ -220,15 +232,15 @@ void generateRipples() { float n3z = n1x * n2y - n1y * n2x; // Normalize - float len = magf3(n3x, n3y, n3z); - n3x /= len; - n3y /= len; - n3z /= len; + float len = 1.0f / magf3(n3x, n3y, n3z); + n3x *= len; + n3y *= len; + n3z *= len; // V2 - v2x = vertices[(yOffset + width + x + 1) * 8 + 5]; - v2y = vertices[(yOffset + width + x + 1) * 8 + 6]; - v2z = vertices[(yOffset + width + x + 1) * 8 + 7]; + v2x = vertices[ow1 + 5]; + v2y = vertices[ow1 + 6]; + v2z = vertices[ow1 + 7]; // N1 n1x = v2x - v1x; @@ -240,23 +252,23 @@ void generateRipples() { n2y = v3y - v1y; n2z = v3z - v1z; - // Avegare of previous normal and N1 x N2 - n3x = n3x / 2.0f + (n1y * n2z - n1z * n2y) / 2.0f; - n3y = n3y / 2.0f + (n1z * n2x - n1x * n2z) / 2.0f; - n3z = n3z / 2.0f + (n1x * n2y - n1y * n2x) / 2.0f; + // Average of previous normal and N1 x N2 + n3x = n3x * 0.5f + (n1y * n2z - n1z * n2y) * 0.5f; + n3y = n3y * 0.5f + (n1z * n2x - n1x * n2z) * 0.5f; + n3z = n3z * 0.5f + (n1x * n2y - n1y * n2x) * 0.5f; // Normalize - len = magf3(n3x, n3y, n3z); - n3x /= len; - n3y /= len; - n3z /= len; - - vertices[(yOffset + x) * 8 + 0] = n3x; - vertices[(yOffset + x) * 8 + 1] = n3y; - vertices[(yOffset + x) * 8 + 2] = -n3z; + len = 1.0f / magf3(n3x, n3y, n3z); + n3x *= len; + n3y *= len; + n3z *= len; + + vertices[o + 0] = n3x; + vertices[o + 1] = n3y; + vertices[o + 2] = -n3z; // reset Z - //vertices[(yOffset + x) * 8 + 7] = 0.0f; + //vertices[(yOffset + x) << 3 + 7] = 0.0f; } } } @@ -264,10 +276,10 @@ void generateRipples() { float averageZ(float x1, float x2, float y1, float y2, float* vertices, int meshWidth, int meshHeight, float glWidth, float glHeight) { - x1 = ((x1 + glWidth / 2.0f) / glWidth) * meshWidth; - x2 = ((x2 + glWidth / 2.0f) / glWidth) * meshWidth; - y1 = ((y1 + glHeight / 2.0f) / glHeight) * meshHeight; - y2 = ((y2 + glHeight / 2.0f) / glHeight) * meshHeight; + x1 = ((x1 + glWidth * 0.5f) / glWidth) * meshWidth; + x2 = ((x2 + glWidth * 0.5f) / glWidth) * meshWidth; + y1 = ((y1 + glHeight * 0.5f) / glHeight) * meshHeight; + y2 = ((y2 + glHeight * 0.5f) / glHeight) * meshHeight; int quadX1 = clamp(x1, 0, meshWidth); int quadX2 = clamp(x2, 0, meshWidth); @@ -278,12 +290,12 @@ float averageZ(float x1, float x2, float y1, float y2, float* vertices, int vertexCount = 0; int y = quadY1; - for ( ; y < quadY2; y++) { + for ( ; y < quadY2; y += 1) { int x = quadX1; int yOffset = y * meshWidth; - for ( ; x < quadX2; x++) { - z += vertices[(yOffset + x) * 8 + 7]; - vertexCount++; + for ( ; x < quadX2; x += 1) { + z += vertices[(yOffset + x) << 3 + 7]; + vertexCount += 1; } } @@ -319,10 +331,10 @@ void drawLeaf(int index, float* vertices, int meshWidth, int meshHeight, if (a > 0.0f) { tz = -a; } else { - z1 = averageZ(x1, x, y1, y, vertices, meshWidth, meshHeight, glWidth, glHeight); - z2 = averageZ(x, x2, y1, y, vertices, meshWidth, meshHeight, glWidth, glHeight); - z3 = averageZ(x, x2, y, y2, vertices, meshWidth, meshHeight, glWidth, glHeight); - z4 = averageZ(x1, x, y, y2, vertices, meshWidth, meshHeight, glWidth, glHeight); +// z1 = averageZ(x1, x, y1, y, vertices, meshWidth, meshHeight, glWidth, glHeight); +// z2 = averageZ(x, x2, y1, y, vertices, meshWidth, meshHeight, glWidth, glHeight); +// z3 = averageZ(x, x2, y, y2, vertices, meshWidth, meshHeight, glWidth, glHeight); +// z4 = averageZ(x1, x, y, y2, vertices, meshWidth, meshHeight, glWidth, glHeight); } x1 -= x; @@ -346,8 +358,8 @@ void drawLeaf(int index, float* vertices, int meshWidth, int meshHeight, if (a <= 0.0f) { float rippled = leafStruct[LEAF_STRUCT_RIPPLED]; if (rippled < 0.0f) { - drop(((x + glWidth / 2.0f) / glWidth) * meshWidth, - meshHeight - ((y + glHeight / 2.0f) / glHeight) * meshHeight, + drop(((x + glWidth * 0.5f) / glWidth) * meshWidth, + meshHeight - ((y + glHeight * 0.5f) / glHeight) * meshHeight, DROP_RADIUS); spin /= 4.0f; leafStruct[LEAF_STRUCT_SPIN] = spin; @@ -454,6 +466,35 @@ void drawLighting() { drawTriangleMesh(NAMED_WaterMesh); } +void drawNormals() { + int width = State_meshWidth; + int height = State_meshHeight; + + float *vertices = loadTriangleMeshVerticesF(NAMED_WaterMesh); + + bindProgramVertex(NAMED_PVSky); + bindProgramFragment(NAMED_PFLighting); + + color(1.0f, 0.0f, 0.0f, 1.0f); + + float scale = 1.0f / 10.0f; + int y = 0; + for ( ; y < height; y += 1) { + int yOffset = y * width; + int x = 0; + for ( ; x < width; x += 1) { + int offset = (yOffset + x) << 3; + float vx = vertices[offset + 5]; + float vy = vertices[offset + 6]; + float vz = vertices[offset + 7]; + float nx = vertices[offset + 0]; + float ny = vertices[offset + 1]; + float nz = vertices[offset + 2]; + drawLine(vx, vy, vz, vx + nx * scale, vy + ny * scale, vz + nz * scale); + } + } +} + int main(int index) { int dropX = Drop_dropX; if (dropX != -1) { @@ -471,6 +512,7 @@ int main(int index) { drawSky(); drawLighting(); drawLeaves(); + //drawNormals(); return 1; } diff --git a/libs/rs/java/Fall/src/com/android/fall/rs/FallRS.java b/libs/rs/java/Fall/src/com/android/fall/rs/FallRS.java index 02d4737..3b13bed 100644 --- a/libs/rs/java/Fall/src/com/android/fall/rs/FallRS.java +++ b/libs/rs/java/Fall/src/com/android/fall/rs/FallRS.java @@ -177,22 +177,37 @@ class FallRS { hResolution += 2; for (int y = 0; y <= hResolution; y++) { + final boolean shift = (y & 0x1) == 0; final float yOffset = y * quadHeight - glHeight / 2.0f - quadHeight; final float t = 1.0f - y / (float) hResolution; for (int x = 0; x <= wResolution; x++) { - rs.triangleMeshAddVertex_XYZ_ST_NORM( - -1.0f + x * quadWidth - quadWidth, yOffset, 0.0f, - x / (float) wResolution, t, - 0.0f, 0.0f, -1.0f); + if (shift) { + rs.triangleMeshAddVertex_XYZ_ST_NORM( + -1.0f + x * quadWidth - quadWidth, yOffset, 0.0f, + x / (float) wResolution, t, + 0.0f, 0.0f, -1.0f); + } else { + rs.triangleMeshAddVertex_XYZ_ST_NORM( + -1.0f + x * quadWidth - quadWidth * 0.5f, yOffset, 0.0f, + x / (float) wResolution, t, + 0.0f, 0.0f, -1.0f); + } } } for (int y = 0; y < hResolution; y++) { + final boolean shift = (y & 0x1) == 0; + final int yOffset = y * (wResolution + 1); for (int x = 0; x < wResolution; x++) { - final int index = y * (wResolution + 1) + x; + final int index = yOffset + x; final int iWR1 = index + wResolution + 1; - rs.triangleMeshAddTriangle(index, index + 1, iWR1); - rs.triangleMeshAddTriangle(index + 1, iWR1, iWR1 + 1); + if (shift) { + rs.triangleMeshAddTriangle(index, index + 1, iWR1); + rs.triangleMeshAddTriangle(index + 1, iWR1 + 1, iWR1); + } else { + rs.triangleMeshAddTriangle(index, iWR1 + 1, iWR1); + rs.triangleMeshAddTriangle(index, index + 1, iWR1 + 1); + } } } diff --git a/libs/rs/java/Galaxy/res/raw/galaxy.c b/libs/rs/java/Galaxy/res/raw/galaxy.c index 59c31a1..9ff449f 100644 --- a/libs/rs/java/Galaxy/res/raw/galaxy.c +++ b/libs/rs/java/Galaxy/res/raw/galaxy.c @@ -19,11 +19,13 @@ #define RSID_PARTICLES 1 -#define PARTICLE_STRUCT_FIELDS_COUNT 4 +#define PARTICLE_STRUCT_FIELDS_COUNT 6 #define PARTICLE_STRUCT_ANGLE 0 #define PARTICLE_STRUCT_DISTANCE 1 #define PARTICLE_STRUCT_SPEED 2 #define PARTICLE_STRUCT_RADIUS 3 +#define PARTICLE_STRUCT_S 4 +#define PARTICLE_STRUCT_T 5 #define RSID_PARTICLES_BUFFER 2 #define PARTICLE_BUFFER_COMPONENTS_COUNT 5 @@ -31,19 +33,14 @@ #define PARTICLES_TEXTURES_COUNT 2 #define ELLIPSE_RATIO 0.892f -#define ELLIPSE_TWIST 0.02333333333f void drawSpace(int width, int height) { bindTexture(NAMED_PFBackground, 0, NAMED_TSpace); drawQuadTexCoords( - 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, - width, 0.0f, 0.0f, - 2.0f, 1.0f, - width, height, 0.0f, - 2.0f, 0.0f, - 0.0f, height, 0.0f, - 0.0f, 0.0f); + 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, + width, 0.0f, 0.0f, 2.0f, 1.0f, + width, height, 0.0f, 2.0f, 0.0f, + 0.0f, height, 0.0f, 0.0f, 0.0f); } void drawLights(int width, int height) { @@ -61,39 +58,34 @@ void drawLights(int width, int height) { x + 512.0f * 1.1f, y + 512.0f, 0.0f); } -void drawParticle(float *particle, int index, float *particleBuffer, int bufferIndex, - float w, float h) { - - float distance = particle[index + PARTICLE_STRUCT_DISTANCE]; - float angle = particle[index + PARTICLE_STRUCT_ANGLE]; - float speed = particle[index + PARTICLE_STRUCT_SPEED]; - float r = particle[index + PARTICLE_STRUCT_RADIUS]; +void drawParticle(float *particle, float *particleBuffer, float w, float h) { + float distance = particle[PARTICLE_STRUCT_DISTANCE]; + float angle = particle[PARTICLE_STRUCT_ANGLE]; + float speed = particle[PARTICLE_STRUCT_SPEED]; + float r = particle[PARTICLE_STRUCT_RADIUS]; float a = angle + speed; float x = distance * sinf_fast(a); float y = distance * cosf_fast(a) * ELLIPSE_RATIO; - float z = distance * ELLIPSE_TWIST; - float s = cosf_fast(z); - float t = sinf_fast(z); + float s = particle[PARTICLE_STRUCT_S]; + float t = particle[PARTICLE_STRUCT_T]; float sX = t * x + s * y + w; float sY = s * x - t * y + h; // lower left vertex of the particle's triangle - particleBuffer[bufferIndex + 1] = sX - r; // X - particleBuffer[bufferIndex + 2] = sY + r; // Y + particleBuffer[1] = sX - r; // X + particleBuffer[2] = sY + r; // Y // lower right vertex of the particle's triangle - bufferIndex += PARTICLE_BUFFER_COMPONENTS_COUNT; - particleBuffer[bufferIndex + 1] = sX + r; // X - particleBuffer[bufferIndex + 2] = sY + r; // Y + particleBuffer[6] = sX + r; // X + particleBuffer[7] = sY + r; // Y // upper middle vertex of the particle's triangle - bufferIndex += PARTICLE_BUFFER_COMPONENTS_COUNT; - particleBuffer[bufferIndex + 1] = sX; // X - particleBuffer[bufferIndex + 2] = sY - r; // Y + particleBuffer[11] = sX; // X + particleBuffer[12] = sY - r; // Y - particle[index + PARTICLE_STRUCT_ANGLE] = a; + particle[PARTICLE_STRUCT_ANGLE] = a; } void drawParticles(int width, int height) { @@ -103,7 +95,6 @@ void drawParticles(int width, int height) { int radius = State_galaxyRadius; int particlesCount = State_particlesCount; - int count = particlesCount * PARTICLE_STRUCT_FIELDS_COUNT; float *particle = loadArrayF(RSID_PARTICLES, 0); float *particleBuffer = loadArrayF(RSID_PARTICLES_BUFFER, 0); @@ -112,11 +103,11 @@ void drawParticles(int width, int height) { float h = height * 0.5f; int i = 0; - int bufferIndex = 0; - for ( ; i < count; i += PARTICLE_STRUCT_FIELDS_COUNT) { - drawParticle(particle, i, particleBuffer, bufferIndex, w, h); - // each particle is a triangle (3 vertices) of 6 properties (ABGR, X, Y, Z, S, T) - bufferIndex += 3 * PARTICLE_BUFFER_COMPONENTS_COUNT; + for ( ; i < particlesCount; i++) { + drawParticle(particle, particleBuffer, w, h); + particle += PARTICLE_STRUCT_FIELDS_COUNT; + // each particle is a triangle (3 vertices) of 5 properties (ABGR, X, Y, S, T) + particleBuffer += 3 * PARTICLE_BUFFER_COMPONENTS_COUNT; } uploadToBufferObject(NAMED_ParticlesBuffer); diff --git a/libs/rs/java/Galaxy/src/com/android/galaxy/rs/GalaxyRS.java b/libs/rs/java/Galaxy/src/com/android/galaxy/rs/GalaxyRS.java index 717100d..c6f5816 100644 --- a/libs/rs/java/Galaxy/src/com/android/galaxy/rs/GalaxyRS.java +++ b/libs/rs/java/Galaxy/src/com/android/galaxy/rs/GalaxyRS.java @@ -42,9 +42,11 @@ import static android.util.MathUtils.*; import java.util.TimeZone; +@SuppressWarnings({"FieldCanBeLocal"}) class GalaxyRS { private static final int GALAXY_RADIUS = 300; private static final int PARTICLES_COUNT = 12000; + private static final float ELLIPSE_TWIST = 0.023333333f; private static final int RSID_STATE = 0; @@ -54,11 +56,13 @@ class GalaxyRS { private static final int RSID_TEXTURE_FLARES = 2; private static final int RSID_PARTICLES = 1; - private static final int PARTICLE_STRUCT_FIELDS_COUNT = 4; + private static final int PARTICLE_STRUCT_FIELDS_COUNT = 6; private static final int PARTICLE_STRUCT_ANGLE = 0; private static final int PARTICLE_STRUCT_DISTANCE = 1; private static final int PARTICLE_STRUCT_SPEED = 2; private static final int PARTICLE_STRUCT_RADIUS = 3; + private static final int PARTICLE_STRUCT_S = 4; + private static final int PARTICLE_STRUCT_T = 5; private static final int RSID_PARTICLES_BUFFER = 2; @@ -103,35 +107,6 @@ class GalaxyRS { initRS(); } - public void destroy() { - mScript.destroy(); - mSampler.destroy(); - mLightSampler.destroy(); - mPfBackground.destroy(); - mPfsBackground.destroy(); - mPvBackground.destroy(); - mPvOrthoAlloc.mAlloc.destroy(); - for (Allocation a : mTextures) { - a.destroy(); - } - mState.destroy(); - mPfLighting.destroy(); - mParticles.destroy(); - mPfsLights.destroy(); - mParticlesMesh.destroy(); - mParticlesBuffer.destroy(); - mStateType.destroy(); - } - - @Override - protected void finalize() throws Throwable { - try { - destroy(); - } finally { - super.finalize(); - } - } - private void initRS() { createProgramVertex(); createProgramFragmentStore(); @@ -218,13 +193,16 @@ class GalaxyRS { float d = abs(randomGauss()) * GALAXY_RADIUS / 2.0f + random(-4.0f, 4.0f); float z = randomGauss() * 0.5f * 0.8f * ((GALAXY_RADIUS - d) / (float) GALAXY_RADIUS); z += 1.0f; + float p = d * ELLIPSE_TWIST; particles[index + PARTICLE_STRUCT_ANGLE] = random(0.0f, (float) (Math.PI * 2.0)); particles[index + PARTICLE_STRUCT_DISTANCE] = d; particles[index + PARTICLE_STRUCT_SPEED] = random(0.0015f, 0.0025f) * (0.5f + (0.5f * (float) GALAXY_RADIUS / d)) * 0.7f; particles[index + PARTICLE_STRUCT_RADIUS] = z * random(1.2f, 2.1f); - + particles[index + PARTICLE_STRUCT_S] = (float) Math.cos(p); + particles[index + PARTICLE_STRUCT_T] = (float) Math.sin(p); + int red, green, blue; if (d < GALAXY_RADIUS / 3.0f) { red = (int) (220 + (d / (float) GALAXY_RADIUS) * 35); diff --git a/libs/rs/java/Galaxy/src/com/android/galaxy/rs/GalaxyView.java b/libs/rs/java/Galaxy/src/com/android/galaxy/rs/GalaxyView.java index 341293b..4f6d3f0 100644 --- a/libs/rs/java/Galaxy/src/com/android/galaxy/rs/GalaxyView.java +++ b/libs/rs/java/Galaxy/src/com/android/galaxy/rs/GalaxyView.java @@ -22,8 +22,6 @@ import android.renderscript.RenderScript; import android.renderscript.RSSurfaceView; class GalaxyView extends RSSurfaceView { - private GalaxyRS mRender; - public GalaxyView(Context context) { super(context); setFocusable(true); @@ -34,12 +32,7 @@ class GalaxyView extends RSSurfaceView { super.surfaceChanged(holder, format, w, h); RenderScript RS = createRenderScript(); - mRender = new GalaxyRS(w, h); - mRender.init(RS, getResources()); - } - - @Override - public void surfaceDestroyed(SurfaceHolder holder) { - if (mRender != null) mRender.destroy(); + GalaxyRS render = new GalaxyRS(w, h); + render.init(RS, getResources()); } } diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp index 7bfa81e..413caab 100644 --- a/libs/rs/rsContext.cpp +++ b/libs/rs/rsContext.cpp @@ -25,7 +25,6 @@ using namespace android; using namespace android::renderscript; -Context * Context::gCon = NULL; pthread_key_t Context::gThreadTLSKey = 0; void Context::initEGL() @@ -84,6 +83,9 @@ bool Context::runScript(Script *s, uint32_t launchID) bool Context::runRootScript() { +#if RS_LOG_TIMES + timerSet(RS_TIMER_CLEAR_SWAP); +#endif rsAssert(mRootScript->mEnviroment.mIsRoot); //glColor4f(1,1,1,1); @@ -102,22 +104,53 @@ bool Context::runRootScript() glClear(GL_DEPTH_BUFFER_BIT); #if RS_LOG_TIMES - struct timespec startTime; - clock_gettime(CLOCK_MONOTONIC, &startTime); + timerSet(RS_TIMER_SCRIPT); #endif bool ret = runScript(mRootScript.get(), 0); + return ret; +} -#if RS_LOG_TIMES - struct timespec endTime; - clock_gettime(CLOCK_MONOTONIC, &endTime); +uint64_t Context::getTime() const +{ + struct timespec t; + clock_gettime(CLOCK_MONOTONIC, &t); + return t.tv_nsec + ((uint64_t)t.tv_sec * 1000 * 1000 * 1000); +} - uint64_t t1 = endTime.tv_nsec + ((uint64_t)endTime.tv_sec * 1000 * 1000 * 1000); - uint64_t t2 = startTime.tv_nsec + ((uint64_t)startTime.tv_sec * 1000 * 1000 * 1000); - int t3 = (int)((t1 - t2) / 1000 / 1000); - LOGE("times %i", t3); -#endif +void Context::timerReset() +{ + for (int ct=0; ct < _RS_TIMER_TOTAL; ct++) { + mTimers[ct] = 0; + } +} - return ret; +void Context::timerInit() +{ + mTimeLast = getTime(); + mTimerActive = RS_TIMER_INTERNAL; + timerReset(); +} + +void Context::timerSet(Timers tm) +{ + uint64_t last = mTimeLast; + mTimeLast = getTime(); + mTimers[mTimerActive] += mTimeLast - last; + mTimerActive = tm; +} + +void Context::timerPrint() +{ + double total = 0; + for (int ct = 0; ct < _RS_TIMER_TOTAL; ct++) { + total += mTimers[ct]; + } + + LOGV("RS Time Data: Idle %2.1f (%lli), Internal %2.1f (%lli), Script %2.1f (%lli), Clear & Swap %2.1f (%lli)", + 100.0 * mTimers[RS_TIMER_IDLE] / total, mTimers[RS_TIMER_IDLE] / 1000000, + 100.0 * mTimers[RS_TIMER_INTERNAL] / total, mTimers[RS_TIMER_INTERNAL] / 1000000, + 100.0 * mTimers[RS_TIMER_SCRIPT] / total, mTimers[RS_TIMER_SCRIPT] / 1000000, + 100.0 * mTimers[RS_TIMER_CLEAR_SWAP] / total, mTimers[RS_TIMER_CLEAR_SWAP] / 1000000); } void Context::setupCheck() @@ -168,9 +201,19 @@ void * Context::threadProc(void *vrsc) if (mDraw) { mDraw = rsc->runRootScript(); +#if RS_LOG_TIMES + rsc->timerSet(RS_TIMER_CLEAR_SWAP); +#endif eglSwapBuffers(rsc->mDisplay, rsc->mSurface); +#if RS_LOG_TIMES + rsc->timerSet(RS_TIMER_INTERNAL); + rsc->timerPrint(); + rsc->timerReset(); +#endif + } + if (rsc->mObjDestroy.mNeedToEmpty) { + rsc->objDestroyOOBRun(); } - rsc->objDestroyOOBRun(); } glClearColor(0,0,0,0); @@ -188,9 +231,6 @@ Context::Context(Device *dev, Surface *sur) mRunning = false; mExit = false; - // see comment in header - gCon = this; - int status; pthread_attr_t threadAttr; @@ -213,6 +253,7 @@ Context::Context(Device *dev, Surface *sur) mWndSurface = sur; objDestroyOOBInit(); + timerInit(); LOGV("RS Launching thread"); status = pthread_create(&mThreadId, &threadAttr, threadProc, this); diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h index 52901b2..ca67e40 100644 --- a/libs/rs/rsContext.h +++ b/libs/rs/rsContext.h @@ -72,8 +72,6 @@ public: ScriptCState mScriptC; - static Context * getContext() {return gCon;} - void swapBuffers(); void setRootScript(Script *); void setVertex(ProgramVertex *); @@ -120,6 +118,20 @@ public: ThreadIO mIO; void objDestroyAdd(ObjectBase *); + // Timers + enum Timers { + RS_TIMER_IDLE, + RS_TIMER_INTERNAL, + RS_TIMER_SCRIPT, + RS_TIMER_CLEAR_SWAP, + _RS_TIMER_TOTAL + }; + uint64_t getTime() const; + void timerInit(); + void timerReset(); + void timerSet(Timers); + void timerPrint(); + protected: Device *mDev; @@ -164,13 +176,15 @@ private: static void * threadProc(void *); - // todo: put in TLS - static Context *gCon; Surface *mWndSurface; Vector<ObjectBase *> mNames; KeyedVector<String8,int> mInt32Defines; KeyedVector<String8,float> mFloatDefines; + + uint64_t mTimers[_RS_TIMER_TOTAL]; + Timers mTimerActive; + uint64_t mTimeLast; }; diff --git a/libs/rs/rsThreadIO.cpp b/libs/rs/rsThreadIO.cpp index 20b0a94..4a1dbbb 100644 --- a/libs/rs/rsThreadIO.cpp +++ b/libs/rs/rsThreadIO.cpp @@ -32,12 +32,18 @@ ThreadIO::~ThreadIO() bool ThreadIO::playCoreCommands(Context *con, bool waitForCommand) { - uint32_t cmdID = 0; - uint32_t cmdSize = 0; bool ret = false; while(!mToCore.isEmpty() || waitForCommand) { + uint32_t cmdID = 0; + uint32_t cmdSize = 0; ret = true; +#if RS_LOG_TIMES + con->timerSet(Context::RS_TIMER_IDLE); +#endif const void * data = mToCore.get(&cmdID, &cmdSize); +#if RS_LOG_TIMES + con->timerSet(Context::RS_TIMER_INTERNAL); +#endif waitForCommand = false; //LOGV("playCoreCommands 3 %i %i", cmdID, cmdSize); diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp index 419574c..fd54e35 100644 --- a/libs/surfaceflinger/LayerBase.cpp +++ b/libs/surfaceflinger/LayerBase.cpp @@ -730,14 +730,6 @@ sp<LayerBaseClient> LayerBaseClient::Surface::getOwner() const { return owner; } - -void LayerBaseClient::Surface::getSurfaceData( - ISurfaceFlingerClient::surface_data_t* params) const -{ - params->token = mToken; - params->identity = mIdentity; -} - status_t LayerBaseClient::Surface::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h index 65bf55b..7791941 100644 --- a/libs/surfaceflinger/LayerBase.h +++ b/libs/surfaceflinger/LayerBase.h @@ -321,10 +321,9 @@ public: class Surface : public BnSurface { public: + int32_t getToken() const { return mToken; } + int32_t getIdentity() const { return mIdentity; } - virtual void getSurfaceData( - ISurfaceFlingerClient::surface_data_t* params) const; - protected: Surface(const sp<SurfaceFlinger>& flinger, SurfaceID id, int identity, diff --git a/libs/surfaceflinger/LayerBitmap.cpp b/libs/surfaceflinger/LayerBitmap.cpp index 5e74451..dd61e1a 100644 --- a/libs/surfaceflinger/LayerBitmap.cpp +++ b/libs/surfaceflinger/LayerBitmap.cpp @@ -97,11 +97,9 @@ status_t Buffer::initSize(uint32_t w, uint32_t h, uint32_t reqUsage) err = allocator.alloc(w, h, format, usage, &handle, &stride); if (err == NO_ERROR) { - if (err == NO_ERROR) { - width = w; - height = h; - mVStride = 0; - } + width = w; + height = h; + mVStride = 0; } return err; diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp index 102899c..3824024 100644 --- a/libs/surfaceflinger/SurfaceFlinger.cpp +++ b/libs/surfaceflinger/SurfaceFlinger.cpp @@ -1239,9 +1239,11 @@ sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid, switch (flags & eFXSurfaceMask) { case eFXSurfaceNormal: if (UNLIKELY(flags & ePushBuffers)) { - layer = createPushBuffersSurfaceLocked(client, d, id, w, h, flags); + layer = createPushBuffersSurfaceLocked(client, d, id, + w, h, flags); } else { - layer = createNormalSurfaceLocked(client, d, id, w, h, format, flags); + layer = createNormalSurfaceLocked(client, d, id, + w, h, flags, format); } break; case eFXSurfaceBlur: @@ -1255,8 +1257,13 @@ sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid, if (layer != 0) { setTransactionFlags(eTransactionNeeded); surfaceHandle = layer->getSurface(); - if (surfaceHandle != 0) - surfaceHandle->getSurfaceData(params); + if (surfaceHandle != 0) { + params->token = surfaceHandle->getToken(); + params->identity = surfaceHandle->getIdentity(); + params->width = w; + params->height = h; + params->format = format; + } } return surfaceHandle; @@ -1264,7 +1271,8 @@ sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid, sp<LayerBaseClient> SurfaceFlinger::createNormalSurfaceLocked( const sp<Client>& client, DisplayID display, - int32_t id, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) + int32_t id, uint32_t w, uint32_t h, uint32_t flags, + PixelFormat& format) { // initialize the surfaces switch (format) { // TODO: take h/w into account diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h index 2569a0f..56ea97a 100644 --- a/libs/surfaceflinger/SurfaceFlinger.h +++ b/libs/surfaceflinger/SurfaceFlinger.h @@ -195,8 +195,8 @@ private: sp<LayerBaseClient> createNormalSurfaceLocked( const sp<Client>& client, DisplayID display, - int32_t id, uint32_t w, uint32_t h, - PixelFormat format, uint32_t flags); + int32_t id, uint32_t w, uint32_t h, uint32_t flags, + PixelFormat& format); sp<LayerBaseClient> createBlurSurfaceLocked( const sp<Client>& client, DisplayID display, diff --git a/libs/ui/ISurfaceFlingerClient.cpp b/libs/ui/ISurfaceFlingerClient.cpp index 51e8422..4a6a1d7 100644 --- a/libs/ui/ISurfaceFlingerClient.cpp +++ b/libs/ui/ISurfaceFlingerClient.cpp @@ -189,8 +189,11 @@ status_t BnSurfaceFlingerClient::onTransact( status_t ISurfaceFlingerClient::surface_data_t::readFromParcel(const Parcel& parcel) { - token = parcel.readInt32(); - identity = parcel.readInt32(); + token = parcel.readInt32(); + identity = parcel.readInt32(); + width = parcel.readInt32(); + height = parcel.readInt32(); + format = parcel.readInt32(); return NO_ERROR; } @@ -198,6 +201,9 @@ status_t ISurfaceFlingerClient::surface_data_t::writeToParcel(Parcel* parcel) co { parcel->writeInt32(token); parcel->writeInt32(identity); + parcel->writeInt32(width); + parcel->writeInt32(height); + parcel->writeInt32(format); return NO_ERROR; } diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp index f6792c4..36a10cf 100644 --- a/libs/ui/Surface.cpp +++ b/libs/ui/Surface.cpp @@ -64,11 +64,16 @@ SurfaceBuffer::SurfaceBuffer(const Parcel& data) { // we own the handle in this case width = data.readInt32(); - height = data.readInt32(); - stride = data.readInt32(); - format = data.readInt32(); - usage = data.readInt32(); - handle = data.readNativeHandle(); + if (width < 0) { + width = height = stride = format = usage = 0; + handle = 0; + } else { + height = data.readInt32(); + stride = data.readInt32(); + format = data.readInt32(); + usage = data.readInt32(); + handle = data.readNativeHandle(); + } } SurfaceBuffer::~SurfaceBuffer() @@ -108,16 +113,25 @@ status_t SurfaceBuffer::unlock() status_t SurfaceBuffer::writeToParcel(Parcel* reply, android_native_buffer_t const* buffer) { - if (buffer == NULL) { + if (buffer == NULL) + return BAD_VALUE; + + if (buffer->width < 0 || buffer->height < 0) return BAD_VALUE; + + status_t err = NO_ERROR; + if (buffer->handle == NULL) { + // this buffer doesn't have a handle + reply->writeInt32(NO_MEMORY); + } else { + reply->writeInt32(buffer->width); + reply->writeInt32(buffer->height); + reply->writeInt32(buffer->stride); + reply->writeInt32(buffer->format); + reply->writeInt32(buffer->usage); + err = reply->writeNativeHandle(buffer->handle); } - reply->writeInt32(buffer->width); - reply->writeInt32(buffer->height); - reply->writeInt32(buffer->stride); - reply->writeInt32(buffer->format); - reply->writeInt32(buffer->usage); - reply->writeNativeHandle(buffer->handle); - return NO_ERROR; + return err; } // ---------------------------------------------------------------------- @@ -183,7 +197,8 @@ SurfaceControl::SurfaceControl( uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) : mClient(client), mSurface(surface), mToken(data.token), mIdentity(data.identity), - mWidth(w), mHeight(h), mFormat(format), mFlags(flags) + mWidth(data.width), mHeight(data.height), mFormat(data.format), + mFlags(flags) { } @@ -434,7 +449,7 @@ Surface::~Surface() // this is a client-side operation, the surface is destroyed, unmap // its buffers in this process. for (int i=0 ; i<2 ; i++) { - if (mBuffers[i] != 0) { + if (mBuffers[i] != 0 && mBuffers[i]->handle != 0) { getBufferMapper().unregisterBuffer(mBuffers[i]->handle); } } @@ -590,17 +605,24 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer) if ((back->flags & surface_info_t::eNeedNewBuffer) || mUsageChanged) { mUsageChanged = false; err = getBufferLocked(backIdx, mUsage); + if (err == NO_ERROR) { + // reset the width/height with the what we get from the buffer + const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]); + mWidth = uint32_t(backBuffer->width); + mHeight = uint32_t(backBuffer->height); + } } if (err == NO_ERROR) { const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]); - // reset the width/height with the what we get from the buffer - mWidth = uint32_t(backBuffer->width); - mHeight = uint32_t(backBuffer->height); - mDirtyRegion.set(backBuffer->width, backBuffer->height); - *buffer = backBuffer.get(); + if (backBuffer != 0) { + mDirtyRegion.set(backBuffer->width, backBuffer->height); + *buffer = backBuffer.get(); + } else { + err = NO_MEMORY; + } } - + return err; } @@ -716,7 +738,8 @@ status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) } else { newDirtyRegion.andSelf(bounds); const sp<SurfaceBuffer>& frontBuffer(mBuffers[1-mBackbufferIndex]); - if (backBuffer->width == frontBuffer->width && + if (frontBuffer !=0 && + backBuffer->width == frontBuffer->width && backBuffer->height == frontBuffer->height && !(lcblk->flags & eNoCopyBack)) { @@ -788,18 +811,24 @@ status_t Surface::getBufferLocked(int index, int usage) if (s == 0) return NO_INIT; status_t err = NO_MEMORY; + + // free the current buffer + sp<SurfaceBuffer>& currentBuffer(mBuffers[index]); + if (currentBuffer != 0) { + getBufferMapper().unregisterBuffer(currentBuffer->handle); + currentBuffer.clear(); + } + sp<SurfaceBuffer> buffer = s->getBuffer(usage); LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL"); - if (buffer != 0) { - sp<SurfaceBuffer>& currentBuffer(mBuffers[index]); - if (currentBuffer != 0) { - getBufferMapper().unregisterBuffer(currentBuffer->handle); - currentBuffer.clear(); - } - err = getBufferMapper().registerBuffer(buffer->handle); - LOGW_IF(err, "registerBuffer(...) failed %d (%s)", err, strerror(-err)); - if (err == NO_ERROR) { - currentBuffer = buffer; + if (buffer != 0) { // this should never happen by construction + if (buffer->handle != NULL) { + err = getBufferMapper().registerBuffer(buffer->handle); + LOGW_IF(err, "registerBuffer(...) failed %d (%s)", + err, strerror(-err)); + if (err == NO_ERROR) { + currentBuffer = buffer; + } } } return err; diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index 05b68d4..0a1b142 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -1391,21 +1391,26 @@ public class AudioService extends IAudioService.Stub { } else if (action.equals(BluetoothIntent.HEADSET_STATE_CHANGED_ACTION)) { int state = intent.getIntExtra(BluetoothIntent.HEADSET_STATE, BluetoothHeadset.STATE_ERROR); - BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothIntent.DEVICE); - String address = btDevice.getAddress(); int device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO; - int btClass = btDevice.getBluetoothClass(); - if (BluetoothClass.Device.Major.getDeviceMajor(btClass) == BluetoothClass.Device.Major.AUDIO_VIDEO) { - switch (BluetoothClass.Device.getDevice(btClass)) { - case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET: - case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE: - device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET; - break; - case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO: - device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT; - break; - default: - break; + BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothIntent.DEVICE); + String address = null; + int btClass = BluetoothClass.ERROR; + if (btDevice != null) { + address = btDevice.getAddress(); + btClass = btDevice.getBluetoothClass(); + if (BluetoothClass.Device.Major.getDeviceMajor(btClass) == + BluetoothClass.Device.Major.AUDIO_VIDEO) { + switch (BluetoothClass.Device.getDevice(btClass)) { + case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET: + case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE: + device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET; + break; + case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO: + device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT; + break; + default: + break; + } } } diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp index 662d5fb..894d46c 100644 --- a/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/MPEG4Extractor.cpp @@ -19,9 +19,6 @@ #include <arpa/inet.h> -#undef NDEBUG -#include <assert.h> - #include <ctype.h> #include <stdint.h> #include <stdlib.h> @@ -31,6 +28,7 @@ #include <media/stagefright/MPEG4Extractor.h> #include <media/stagefright/MediaBuffer.h> #include <media/stagefright/MediaBufferGroup.h> +#include <media/stagefright/MediaDebug.h> #include <media/stagefright/MediaSource.h> #include <media/stagefright/MetaData.h> #include <media/stagefright/SampleTable.h> @@ -70,10 +68,8 @@ private: MediaBufferGroup *mGroup; MediaBuffer *mBuffer; - size_t mBufferOffset; - size_t mBufferSizeRemaining; - bool mNeedsNALFraming; + bool mWantsNALFragments; uint8_t *mSrcBuffer; @@ -138,7 +134,7 @@ static const char *const FourCC2MIME(uint32_t fourcc) { return "video/avc"; default: - assert(!"should not be here."); + CHECK(!"should not be here."); return NULL; } } @@ -279,7 +275,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) { return err; } } - assert(*offset == stop_offset); + CHECK_EQ(*offset, stop_offset); if (chunk_type == FOURCC('m', 'o', 'o', 'v')) { mHaveMetadata = true; @@ -291,7 +287,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) { case FOURCC('t', 'k', 'h', 'd'): { - assert(chunk_data_size >= 4); + CHECK(chunk_data_size >= 4); uint8_t version; if (mDataSource->read_at(data_offset, &version, 1) < 1) { @@ -444,7 +440,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) { } uint8_t buffer[8]; - assert(chunk_data_size >= (off_t)sizeof(buffer)); + CHECK(chunk_data_size >= (off_t)sizeof(buffer)); if (mDataSource->read_at( data_offset, buffer, 8) < 8) { return ERROR_IO; @@ -470,7 +466,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) { return err; } } - assert(*offset == stop_offset); + CHECK_EQ(*offset, stop_offset); break; } @@ -518,7 +514,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) { return err; } } - assert(*offset == stop_offset); + CHECK_EQ(*offset, stop_offset); break; } @@ -560,7 +556,7 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) { return err; } } - assert(*offset == stop_offset); + CHECK_EQ(*offset, stop_offset); break; } @@ -728,16 +724,14 @@ MPEG4Source::MPEG4Source( mStarted(false), mGroup(NULL), mBuffer(NULL), - mBufferOffset(0), - mBufferSizeRemaining(0), - mNeedsNALFraming(false), + mWantsNALFragments(false), mSrcBuffer(NULL) { const char *mime; bool success = mFormat->findCString(kKeyMIMEType, &mime); - assert(success); + CHECK(success); success = mFormat->findInt32(kKeyTimeScale, &mTimescale); - assert(success); + CHECK(success); mIsAVC = !strcasecmp(mime, "video/avc"); } @@ -749,21 +743,21 @@ MPEG4Source::~MPEG4Source() { } status_t MPEG4Source::start(MetaData *params) { - assert(!mStarted); + CHECK(!mStarted); int32_t val; - if (mIsAVC && params && params->findInt32(kKeyNeedsNALFraming, &val) + if (params && params->findInt32(kKeyWantsNALFragments, &val) && val != 0) { - mNeedsNALFraming = true; + mWantsNALFragments = true; } else { - mNeedsNALFraming = false; + mWantsNALFragments = false; } mGroup = new MediaBufferGroup; size_t max_size; status_t err = mSampleTable->getMaxSampleSize(&max_size); - assert(err == OK); + CHECK_EQ(err, OK); // Assume that a given buffer only contains at most 10 fragments, // each fragment originally prefixed with a 2 byte length will @@ -779,7 +773,7 @@ status_t MPEG4Source::start(MetaData *params) { } status_t MPEG4Source::stop() { - assert(mStarted); + CHECK(mStarted); if (mBuffer != NULL) { mBuffer->release(); @@ -804,7 +798,7 @@ sp<MetaData> MPEG4Source::getFormat() { status_t MPEG4Source::read( MediaBuffer **out, const ReadOptions *options) { - assert(mStarted); + CHECK(mStarted); *out = NULL; @@ -830,38 +824,124 @@ status_t MPEG4Source::read( off_t offset; size_t size; - status_t err = mSampleTable->getSampleOffsetAndSize( - mCurrentSampleIndex, &offset, &size); + uint32_t dts; + bool newBuffer = false; + if (mBuffer == NULL) { + newBuffer = true; - if (err != OK) { - return err; - } + status_t err = mSampleTable->getSampleOffsetAndSize( + mCurrentSampleIndex, &offset, &size); - uint32_t dts; - err = mSampleTable->getDecodingTime(mCurrentSampleIndex, &dts); + if (err != OK) { + return err; + } - if (err != OK) { - return err; - } + err = mSampleTable->getDecodingTime(mCurrentSampleIndex, &dts); - err = mGroup->acquire_buffer(&mBuffer); - if (err != OK) { - assert(mBuffer == NULL); - return err; + if (err != OK) { + return err; + } + + err = mGroup->acquire_buffer(&mBuffer); + if (err != OK) { + CHECK_EQ(mBuffer, NULL); + return err; + } } - if (!mIsAVC || !mNeedsNALFraming) { + if (!mIsAVC || mWantsNALFragments) { + if (newBuffer) { + ssize_t num_bytes_read = + mDataSource->read_at(offset, (uint8_t *)mBuffer->data(), size); + + if (num_bytes_read < (ssize_t)size) { + mBuffer->release(); + mBuffer = NULL; + + return ERROR_IO; + } + + mBuffer->set_range(0, size); + mBuffer->meta_data()->clear(); + mBuffer->meta_data()->setInt32(kKeyTimeUnits, dts); + mBuffer->meta_data()->setInt32(kKeyTimeScale, mTimescale); + ++mCurrentSampleIndex; + } + + if (!mIsAVC) { + *out = mBuffer; + mBuffer = NULL; + + return OK; + } + + // Each NAL unit is split up into its constituent fragments and + // each one of them returned in its own buffer. + + CHECK(mBuffer->range_length() >= 2); + + const uint8_t *src = + (const uint8_t *)mBuffer->data() + mBuffer->range_offset(); + + size_t nal_size = U16_AT(src); + + CHECK(mBuffer->range_length() >= 2 + nal_size); + + MediaBuffer *clone = mBuffer->clone(); + clone->set_range(mBuffer->range_offset() + 2, nal_size); + + mBuffer->set_range( + mBuffer->range_offset() + 2 + nal_size, + mBuffer->range_length() - 2 - nal_size); + + if (mBuffer->range_length() == 0) { + mBuffer->release(); + mBuffer = NULL; + } + + *out = clone; + + return OK; + } else { + // Whole NAL units are returned but each fragment is prefixed by + // the start code (0x00 00 00 01). + ssize_t num_bytes_read = - mDataSource->read_at(offset, (uint8_t *)mBuffer->data(), size); + mDataSource->read_at(offset, mSrcBuffer, size); if (num_bytes_read < (ssize_t)size) { mBuffer->release(); mBuffer = NULL; - return err; + return ERROR_IO; } - mBuffer->set_range(0, size); + uint8_t *dstData = (uint8_t *)mBuffer->data(); + size_t srcOffset = 0; + size_t dstOffset = 0; + while (srcOffset < size) { + CHECK(srcOffset + 1 < size); + size_t nalLength = + (mSrcBuffer[srcOffset] << 8) | mSrcBuffer[srcOffset + 1]; + CHECK(srcOffset + 1 + nalLength < size); + srcOffset += 2; + + if (nalLength == 0) { + continue; + } + + CHECK(dstOffset + 4 <= mBuffer->size()); + + dstData[dstOffset++] = 0; + dstData[dstOffset++] = 0; + dstData[dstOffset++] = 0; + dstData[dstOffset++] = 1; + memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength); + srcOffset += nalLength; + dstOffset += nalLength; + } + + mBuffer->set_range(0, dstOffset); mBuffer->meta_data()->clear(); mBuffer->meta_data()->setInt32(kKeyTimeUnits, dts); mBuffer->meta_data()->setInt32(kKeyTimeScale, mTimescale); @@ -872,52 +952,6 @@ status_t MPEG4Source::read( return OK; } - - ssize_t num_bytes_read = - mDataSource->read_at(offset, mSrcBuffer, size); - - if (num_bytes_read < (ssize_t)size) { - mBuffer->release(); - mBuffer = NULL; - - return err; - } - - uint8_t *dstData = (uint8_t *)mBuffer->data(); - size_t srcOffset = 0; - size_t dstOffset = 0; - while (srcOffset < size) { - assert(srcOffset + 1 < size); - size_t nalLength = - (mSrcBuffer[srcOffset] << 8) | mSrcBuffer[srcOffset + 1]; - assert(srcOffset + 1 + nalLength < size); - srcOffset += 2; - - if (nalLength == 0) { - continue; - } - - assert(dstOffset + 4 <= mBuffer->size()); - - dstData[dstOffset++] = 0; - dstData[dstOffset++] = 0; - dstData[dstOffset++] = 0; - dstData[dstOffset++] = 1; - memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength); - srcOffset += nalLength; - dstOffset += nalLength; - } - - mBuffer->set_range(0, dstOffset); - mBuffer->meta_data()->clear(); - mBuffer->meta_data()->setInt32(kKeyTimeUnits, dts); - mBuffer->meta_data()->setInt32(kKeyTimeScale, mTimescale); - ++mCurrentSampleIndex; - - *out = mBuffer; - mBuffer = NULL; - - return OK; } bool SniffMPEG4( diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp index 35d599c..1774eaf 100644 --- a/media/libstagefright/OMXCodec.cpp +++ b/media/libstagefright/OMXCodec.cpp @@ -30,6 +30,7 @@ #include <media/stagefright/MetaData.h> #include <media/stagefright/MmapSource.h> #include <media/stagefright/OMXCodec.h> +#include <media/stagefright/Utils.h> #include <utils/Vector.h> #include <OMX_Audio.h> @@ -116,6 +117,39 @@ static const char *GetCodec(const CodecInfo *info, size_t numInfos, return NULL; } +enum { + kAVCProfileBaseline = 0x42, + kAVCProfileMain = 0x4d, + kAVCProfileExtended = 0x58, + kAVCProfileHigh = 0x64, + kAVCProfileHigh10 = 0x6e, + kAVCProfileHigh422 = 0x7a, + kAVCProfileHigh444 = 0xf4, + kAVCProfileCAVLC444Intra = 0x2c +}; + +static const char *AVCProfileToString(uint8_t profile) { + switch (profile) { + case kAVCProfileBaseline: + return "Baseline"; + case kAVCProfileMain: + return "Main"; + case kAVCProfileExtended: + return "Extended"; + case kAVCProfileHigh: + return "High"; + case kAVCProfileHigh10: + return "High 10"; + case kAVCProfileHigh422: + return "High 422"; + case kAVCProfileHigh444: + return "High 444"; + case kAVCProfileCAVLC444Intra: + return "CAVLC 444 Intra"; + default: return "Unknown"; + } +} + // static sp<OMXCodec> OMXCodec::Create( const sp<IOMX> &omx, @@ -152,7 +186,7 @@ sp<OMXCodec> OMXCodec::Create( uint32_t quirks = 0; if (!strcmp(componentName, "OMX.PV.avcdec")) { - quirks |= kWantsRawNALFrames; + quirks |= kWantsNALFragments; } if (!strcmp(componentName, "OMX.TI.MP3.decode")) { quirks |= kNeedsFlushBeforeDisable; @@ -189,15 +223,54 @@ sp<OMXCodec> OMXCodec::Create( } else if (meta->findData(kKeyAVCC, &type, &data, &size)) { printf("found avcc of size %d\n", size); - const uint8_t *ptr = (const uint8_t *)data + 6; + // Parse the AVCDecoderConfigurationRecord + + const uint8_t *ptr = (const uint8_t *)data; + + CHECK(size >= 7); + CHECK_EQ(ptr[0], 1); // configurationVersion == 1 + uint8_t profile = ptr[1]; + uint8_t level = ptr[3]; + + CHECK((ptr[4] >> 2) == 0x3f); // reserved + + size_t lengthSize = 1 + (ptr[4] & 3); + + // commented out check below as H264_QVGA_500_NO_AUDIO.3gp + // violates it... + // CHECK((ptr[5] >> 5) == 7); // reserved + + size_t numSeqParameterSets = ptr[5] & 31; + + ptr += 6; size -= 6; - while (size >= 2) { - size_t length = ptr[0] << 8 | ptr[1]; + + for (size_t i = 0; i < numSeqParameterSets; ++i) { + CHECK(size >= 2); + size_t length = U16_AT(ptr); ptr += 2; size -= 2; - // printf("length = %d, size = %d\n", length, size); + CHECK(size >= length); + + codec->addCodecSpecificData(ptr, length); + + ptr += length; + size -= length; + } + + CHECK(size >= 1); + size_t numPictureParameterSets = *ptr; + ++ptr; + --size; + + for (size_t i = 0; i < numPictureParameterSets; ++i) { + CHECK(size >= 2); + size_t length = U16_AT(ptr); + + ptr += 2; + size -= 2; CHECK(size >= length); @@ -205,13 +278,17 @@ sp<OMXCodec> OMXCodec::Create( ptr += length; size -= length; + } - if (size <= 1) { - break; - } + LOGI("AVC profile = %d (%s), level = %d", + (int)profile, AVCProfileToString(profile), (int)level / 10); + + if (!strcmp(componentName, "OMX.TI.Video.Decoder") + && (profile != kAVCProfileBaseline || level > 39)) { + // This stream exceeds the decoder's capabilities. - ptr++; // XXX skip trailing 0x01 byte??? - --size; + LOGE("Profile and/or level exceed the decoder's capabilities."); + return NULL; } } @@ -529,7 +606,7 @@ void OMXCodec::setVideoOutputFormat( OMXCodec::OMXCodec( const sp<IOMX> &omx, IOMX::node_id node, uint32_t quirks, - bool isEncoder, + bool isEncoder, const char *mime, const char *componentName, const sp<MediaSource> &source) @@ -554,7 +631,7 @@ OMXCodec::OMXCodec( } OMXCodec::~OMXCodec() { - CHECK_EQ(mState, LOADED); + CHECK(mState == LOADED || mState == ERROR); status_t err = mOMX->observe_node(mNode, NULL); CHECK_EQ(err, OK); @@ -569,7 +646,7 @@ OMXCodec::~OMXCodec() { free(mComponentName); mComponentName = NULL; - + free(mMIME); mMIME = NULL; } @@ -772,7 +849,7 @@ void OMXCodec::on_message(const omx_message &msg) { mBufferFilled.signal(); } else if (mPortStatus[kPortIndexOutput] != SHUTTING_DOWN) { CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED); - + MediaBuffer *buffer = info->mMediaBuffer; buffer->set_range( @@ -1149,8 +1226,8 @@ void OMXCodec::drainInputBuffer(BufferInfo *info) { size_t size = specific->mSize; - if (!strcasecmp(mMIME, "video/avc") - && !(mQuirks & kWantsRawNALFrames)) { + if (!strcasecmp("video/avc", mMIME) + && !(mQuirks & kWantsNALFragments)) { static const uint8_t kNALStartCode[4] = { 0x00, 0x00, 0x00, 0x01 }; @@ -1383,7 +1460,7 @@ void OMXCodec::setImageOutputFormat( CHECK_EQ(def.eDomain, OMX_PortDomainImage); OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image; - + CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingUnused); imageDef->eColorFormat = format; imageDef->nFrameWidth = width; @@ -1460,10 +1537,10 @@ status_t OMXCodec::start(MetaData *) { if (mState != LOADED) { return UNKNOWN_ERROR; } - + sp<MetaData> params = new MetaData; - if (!strcasecmp(mMIME, "video/avc") && !(mQuirks & kWantsRawNALFrames)) { - params->setInt32(kKeyNeedsNALFraming, true); + if (mQuirks & kWantsNALFragments) { + params->setInt32(kKeyWantsNALFragments, true); } status_t err = mSource->start(params.get()); @@ -1630,7 +1707,7 @@ static const char *colorFormatString(OMX_COLOR_FORMATTYPE type) { "OMX_COLOR_Format16bitBGR565", "OMX_COLOR_Format18bitRGB666", "OMX_COLOR_Format18bitARGB1665", - "OMX_COLOR_Format19bitARGB1666", + "OMX_COLOR_Format19bitARGB1666", "OMX_COLOR_Format24bitRGB888", "OMX_COLOR_Format24bitBGR888", "OMX_COLOR_Format24bitARGB1887", @@ -1653,11 +1730,11 @@ static const char *colorFormatString(OMX_COLOR_FORMATTYPE type) { "OMX_COLOR_FormatRawBayer8bit", "OMX_COLOR_FormatRawBayer10bit", "OMX_COLOR_FormatRawBayer8bitcompressed", - "OMX_COLOR_FormatL2", - "OMX_COLOR_FormatL4", - "OMX_COLOR_FormatL8", - "OMX_COLOR_FormatL16", - "OMX_COLOR_FormatL24", + "OMX_COLOR_FormatL2", + "OMX_COLOR_FormatL4", + "OMX_COLOR_FormatL8", + "OMX_COLOR_FormatL16", + "OMX_COLOR_FormatL24", "OMX_COLOR_FormatL32", "OMX_COLOR_FormatYUV420PackedSemiPlanar", "OMX_COLOR_FormatYUV422PackedSemiPlanar", diff --git a/media/libstagefright/OMXDecoder.cpp b/media/libstagefright/OMXDecoder.cpp index 94cca43..cf08fa5 100644 --- a/media/libstagefright/OMXDecoder.cpp +++ b/media/libstagefright/OMXDecoder.cpp @@ -139,7 +139,7 @@ sp<OMXDecoder> OMXDecoder::Create( uint32_t quirks = 0; if (!strcmp(codec, "OMX.PV.avcdec")) { - quirks |= kWantsRawNALFrames; + quirks |= kWantsNALFragments; } if (!strcmp(codec, "OMX.TI.AAC.decode") || !strcmp(codec, "OMX.TI.MP3.decode")) { @@ -274,8 +274,8 @@ status_t OMXDecoder::start(MetaData *) { // mDealer->dump("Decoder Dealer"); sp<MetaData> params = new MetaData; - if (mIsAVC && !(mQuirks & kWantsRawNALFrames)) { - params->setInt32(kKeyNeedsNALFraming, true); + if (mQuirks & kWantsNALFragments) { + params->setInt32(kKeyWantsNALFragments, true); } status_t err = mSource->start(params.get()); @@ -1331,7 +1331,7 @@ void OMXDecoder::onRealEmptyBufferDone(IOMX::buffer_id buffer) { size_t range_length = 0; - if (mIsAVC && !(mQuirks & kWantsRawNALFrames)) { + if (mIsAVC && !(mQuirks & kWantsNALFragments)) { assert((*mCodecSpecificDataIterator).size + 4 <= mem->size()); memcpy(mem->pointer(), kNALStartCode, 4); diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index a00a756..7ca8b52 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -405,6 +405,7 @@ public class WindowManagerService extends IWindowManager.Stub // If non-null, this is the currently visible window that is associated // with the wallpaper. WindowState mWallpaperTarget = null; + WindowState mUpcomingWallpaperTarget = null; int mWallpaperAnimLayerAdjustment; AppWindowToken mFocusedApp = null; @@ -1178,60 +1179,136 @@ public class WindowManagerService extends IWindowManager.Stub boolean adjustWallpaperWindowsLocked() { boolean changed = false; + mUpcomingWallpaperTarget = null; + // First find top-most window that has asked to be on top of the // wallpaper; all wallpapers go behind it. final ArrayList localmWindows = mWindows; int N = localmWindows.size(); WindowState w = null; + WindowState foundW = null; + int foundI = 0; + AppWindowToken topToken = null; + AppWindowToken behindToken = null; int i = N; - boolean visible = false; while (i > 0) { i--; w = (WindowState)localmWindows.get(i); + if (topToken != null) { + if (w.mAppToken == topToken) { + continue; + } + if (w.mAppToken != null) { + if (behindToken == null) { + // We need to look through for what is behind the + // potential new wallpaper target... skip all tokens + // that are hidden and not animating, since they can't + // be involved with the transition. + if (w.mAppToken.hidden && w.mAppToken.animation == null) { + continue; + } + behindToken = w.mAppToken; + } + if (w.mAppToken != behindToken) { + break; + } + } + } if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 && w.isReadyForDisplay() && !w.mDrawPending && !w.mCommitDrawPending) { - visible = true; + if (behindToken != null && w.mAppToken == behindToken) { + // We had previously found a wallpaper window that was + // animating, and now we found one behind it. We could + // be doing an animation between two windows on top of + // the wallpaper! + if (mWallpaperTarget == w || mWallpaperTarget == foundW) { + // Retain the current wallpaper target (don't move + // the wallpaper yet), but note the window that is + // going to become the wallpaper target so that + // others know about this special state. + if (DEBUG_WALLPAPER) Log.v(TAG, + "Switching wallpaper activities: cur#" + i + "=" + + w + " upcoming#" + foundI + "=" + foundW); + mUpcomingWallpaperTarget = foundW; + foundW = w; + foundI = i; + break; + } + } + foundW = w; + foundI = i; + if (w.mAppToken != null && w.mAppToken.animation != null) { + // If this app token is animating, we want to keep the + // wallpaper below it if it is animating on top of another + // app with a wallpaper. + topToken = w.mAppToken; + continue; + } break; } } - if (!visible) w = null; - if (DEBUG_WALLPAPER && mWallpaperTarget != w) { - Log.v(TAG, "New wallpaper target: " + w); + if (mNextAppTransition != WindowManagerPolicy.TRANSIT_NONE) { + // If we are currently waiting for an app transition, and either + // the current target or the next target are involved with it, + // then hold off on doing anything with the wallpaper. + // Note that we are checking here for just whether the target + // is part of an app token... which is potentially overly aggressive + // (the app token may not be involved in the transition), but good + // enough (we'll just wait until whatever transition is pending + // executes). + if (mWallpaperTarget != null && mWallpaperTarget.mAppToken != null) { + return false; + } + if (foundW != null && foundW.mAppToken != null) { + return false; + } + if (mUpcomingWallpaperTarget != null && mUpcomingWallpaperTarget.mAppToken != null) { + return false; + } + } + + if (mWallpaperTarget != foundW) { + mWallpaperTarget = foundW; + if (DEBUG_WALLPAPER) { + Log.v(TAG, "New wallpaper target: " + foundW); + } } - mWallpaperTarget = w; + boolean visible = foundW != null; if (visible) { // The window is visible to the compositor... but is it visible // to the user? That is what the wallpaper cares about. - visible = !w.mObscured; + visible = !foundW.mObscured; if (DEBUG_WALLPAPER) Log.v(TAG, "Wallpaper visibility: " + visible); // If the wallpaper target is animating, we may need to copy - // its layer adjustment. - mWallpaperAnimLayerAdjustment = w.mAppToken != null - ? w.mAppToken.animLayerAdjustment : 0; + // its layer adjustment. Only do this if we are not transfering + // between two wallpaper targets. + mWallpaperAnimLayerAdjustment = + (mUpcomingWallpaperTarget == null && foundW.mAppToken != null) + ? foundW.mAppToken.animLayerAdjustment : 0; // Now w is the window we are supposed to be behind... but we // need to be sure to also be behind any of its attached windows, // AND any starting window associated with it. - while (i > 0) { - WindowState wb = (WindowState)localmWindows.get(i-1); - if (wb.mAttachedWindow != w && + while (foundI > 0) { + WindowState wb = (WindowState)localmWindows.get(foundI-1); + if (wb.mAttachedWindow != foundW && (wb.mAttrs.type != TYPE_APPLICATION_STARTING || - wb.mToken != w.mToken)) { + wb.mToken != foundW.mToken)) { // This window is not related to the previous one in any // interesting way, so stop here. break; } - w = wb; - i--; + foundW = wb; + foundI--; } } // Okay i is the position immediately above the wallpaper. Look at // what is below it for later. - w = i > 0 ? (WindowState)localmWindows.get(i-1) : null; + foundW = foundI > 0 ? (WindowState)localmWindows.get(foundI-1) : null; final int dw = mDisplay.getWidth(); final int dh = mDisplay.getHeight(); @@ -1271,9 +1348,10 @@ public class WindowManagerService extends IWindowManager.Stub // First, if this window is at the current index, then all // is well. - if (wallpaper == w) { - i--; - w = i > 0 ? (WindowState)localmWindows.get(i-1) : null; + if (wallpaper == foundW) { + foundI--; + foundW = foundI > 0 + ? (WindowState)localmWindows.get(foundI-1) : null; continue; } @@ -1283,16 +1361,16 @@ public class WindowManagerService extends IWindowManager.Stub int oldIndex = localmWindows.indexOf(wallpaper); if (oldIndex >= 0) { localmWindows.remove(oldIndex); - if (oldIndex < i) { - i--; + if (oldIndex < foundI) { + foundI--; } } // Now stick it in. if (DEBUG_WALLPAPER) Log.v(TAG, "Moving wallpaper " + wallpaper - + " from " + oldIndex + " to " + i); + + " from " + oldIndex + " to " + foundI); - localmWindows.add(i, wallpaper); + localmWindows.add(foundI, wallpaper); changed = true; } } @@ -2246,6 +2324,16 @@ public class WindowManagerService extends IWindowManager.Stub ? com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation : com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation; break; + case WindowManagerPolicy.TRANSIT_WALLPAPER_ACTIVITY_OPEN: + animAttr = enter + ? com.android.internal.R.styleable.WindowAnimation_wallpaperActivityOpenEnterAnimation + : com.android.internal.R.styleable.WindowAnimation_wallpaperActivityOpenExitAnimation; + break; + case WindowManagerPolicy.TRANSIT_WALLPAPER_ACTIVITY_CLOSE: + animAttr = enter + ? com.android.internal.R.styleable.WindowAnimation_wallpaperActivityCloseEnterAnimation + : com.android.internal.R.styleable.WindowAnimation_wallpaperActivityCloseExitAnimation; + break; } a = loadAnimation(lp, animAttr); if (DEBUG_ANIM) Log.v(TAG, "applyAnimation: wtoken=" + wtoken @@ -6874,7 +6962,8 @@ public class WindowManagerService extends IWindowManager.Stub // Wallpapers are animated based on the "real" window they // are currently targeting. - if (mAttrs.type == TYPE_WALLPAPER && mWallpaperTarget != null) { + if (mAttrs.type == TYPE_WALLPAPER && mUpcomingWallpaperTarget == null + && mWallpaperTarget != null) { if (mWallpaperTarget.mHasLocalTransformation) { attachedTransformation = mWallpaperTarget.mTransformation; } @@ -7511,7 +7600,7 @@ public class WindowManagerService extends IWindowManager.Stub if (w == mInputMethodTarget) { setInputMethodAnimLayerAdjustment(adj); } - if (w == mWallpaperTarget) { + if (w == mWallpaperTarget && mUpcomingWallpaperTarget == null) { setWallpaperAnimLayerAdjustmentLocked(adj); } } @@ -8636,6 +8725,60 @@ public class WindowManagerService extends IWindowManager.Stub mH.removeMessages(H.APP_TRANSITION_TIMEOUT); + boolean wallpaperMoved = adjustWallpaperWindowsLocked(); + if (DEBUG_APP_TRANSITIONS) Log.v(TAG, + "Old wallpaper target=" + mWallpaperTarget + + ", upcoming target=" + mUpcomingWallpaperTarget); + if (mUpcomingWallpaperTarget != mWallpaperTarget && + mUpcomingWallpaperTarget != null && + mWallpaperTarget != null) { + // Need to determine if both the closing and + // opening app token sets are wallpaper targets, + // in which case special animations are needed + // (since the wallpaper needs to stay static + // behind them). + int found = 0; + NN = mOpeningApps.size(); + for (i=0; i<NN; i++) { + AppWindowToken wtoken = mOpeningApps.get(i); + if (mUpcomingWallpaperTarget.mAppToken == wtoken) { + found |= 1; + } + if (mWallpaperTarget.mAppToken == wtoken) { + found |= 1; + } + } + NN = mClosingApps.size(); + for (i=0; i<NN; i++) { + AppWindowToken wtoken = mClosingApps.get(i); + if (mUpcomingWallpaperTarget.mAppToken == wtoken) { + found |= 2; + } + if (mWallpaperTarget.mAppToken == wtoken) { + found |= 2; + } + } + + if (found == 3) { + if (DEBUG_APP_TRANSITIONS) Log.v(TAG, + "Wallpaper animation!"); + switch (transit) { + case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN: + case WindowManagerPolicy.TRANSIT_TASK_OPEN: + case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT: + transit = WindowManagerPolicy.TRANSIT_WALLPAPER_ACTIVITY_OPEN; + break; + case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE: + case WindowManagerPolicy.TRANSIT_TASK_CLOSE: + case WindowManagerPolicy.TRANSIT_TASK_TO_BACK: + transit = WindowManagerPolicy.TRANSIT_WALLPAPER_ACTIVITY_CLOSE; + break; + } + if (DEBUG_APP_TRANSITIONS) Log.v(TAG, + "New transit: " + transit); + } + } + // We need to figure out which animation to use... WindowManager.LayoutParams lp = findAnimations(mAppTokens, mOpeningApps, mClosingApps); @@ -8671,7 +8814,6 @@ public class WindowManagerService extends IWindowManager.Stub // This has changed the visibility of windows, so perform // a new layout to get them all up-to-date. mLayoutNeeded = true; - adjustWallpaperWindowsLocked(); if (!moveInputMethodWindowsIfNeededLocked(true)) { assignLayersLocked(); } diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java index afc8b62..bda2d22 100644 --- a/telephony/java/com/android/internal/telephony/CallerInfo.java +++ b/telephony/java/com/android/internal/telephony/CallerInfo.java @@ -20,9 +20,8 @@ import android.content.Context; import android.database.Cursor; import android.graphics.drawable.Drawable; import android.net.Uri; -import android.provider.Contacts; -import android.provider.Contacts.People; -import android.provider.Contacts.Phones; +import android.provider.ContactsContract.PhoneLookup; +import android.provider.ContactsContract.CommonDataKinds.Phone; import android.text.TextUtils; import android.telephony.TelephonyManager; import android.telephony.PhoneNumberUtils; @@ -134,44 +133,39 @@ public class CallerInfo { int columnIndex; // Look for the name - columnIndex = cursor.getColumnIndex(People.NAME); + columnIndex = cursor.getColumnIndex(PhoneLookup.DISPLAY_NAME); if (columnIndex != -1) { info.name = cursor.getString(columnIndex); } // Look for the number - columnIndex = cursor.getColumnIndex(Phones.NUMBER); + columnIndex = cursor.getColumnIndex(PhoneLookup.NUMBER); if (columnIndex != -1) { info.phoneNumber = cursor.getString(columnIndex); } // Look for the label/type combo - columnIndex = cursor.getColumnIndex(Phones.LABEL); + columnIndex = cursor.getColumnIndex(PhoneLookup.LABEL); if (columnIndex != -1) { - int typeColumnIndex = cursor.getColumnIndex(Phones.TYPE); + int typeColumnIndex = cursor.getColumnIndex(PhoneLookup.TYPE); if (typeColumnIndex != -1) { info.numberType = cursor.getInt(typeColumnIndex); info.numberLabel = cursor.getString(columnIndex); - info.phoneLabel = Contacts.Phones.getDisplayLabel(context, + info.phoneLabel = Phone.getDisplayLabel(context, info.numberType, info.numberLabel) .toString(); } } // Look for the person ID - columnIndex = cursor.getColumnIndex(Phones.PERSON_ID); + columnIndex = cursor.getColumnIndex(PhoneLookup._ID); if (columnIndex != -1) { info.person_id = cursor.getLong(columnIndex); - } else { - columnIndex = cursor.getColumnIndex(People._ID); - if (columnIndex != -1) { - info.person_id = cursor.getLong(columnIndex); - } } // look for the custom ringtone, create from the string stored // in the database. - columnIndex = cursor.getColumnIndex(People.CUSTOM_RINGTONE); + columnIndex = cursor.getColumnIndex(PhoneLookup.CUSTOM_RINGTONE); if ((columnIndex != -1) && (cursor.getString(columnIndex) != null)) { info.contactRingtoneUri = Uri.parse(cursor.getString(columnIndex)); } else { @@ -180,7 +174,7 @@ public class CallerInfo { // look for the send to voicemail flag, set it to true only // under certain circumstances. - columnIndex = cursor.getColumnIndex(People.SEND_TO_VOICEMAIL); + columnIndex = cursor.getColumnIndex(PhoneLookup.SEND_TO_VOICEMAIL); info.shouldSendToVoicemail = (columnIndex != -1) && ((cursor.getInt(columnIndex)) == 1); info.contactExists = true; @@ -256,8 +250,7 @@ public class CallerInfo { } } - Uri contactUri = Uri.withAppendedPath(Contacts.Phones.CONTENT_FILTER_URL, - Uri.encode(number)); + Uri contactUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, number); CallerInfo info = getCallerInfo(context, contactUri); diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java index f81f42a..ef456f0 100644 --- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java +++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java @@ -24,7 +24,7 @@ import android.net.Uri; import android.os.Handler; import android.os.Looper; import android.os.Message; -import android.provider.Contacts; +import android.provider.ContactsContract.PhoneLookup; import android.telephony.PhoneNumberUtils; import android.telephony.TelephonyManager; import android.text.TextUtils; @@ -303,7 +303,7 @@ public class CallerInfoAsyncQuery { public static CallerInfoAsyncQuery startQuery(int token, Context context, String number, OnQueryCompleteListener listener, Object cookie) { //contruct the URI object and start Query. - Uri contactRef = Uri.withAppendedPath(Contacts.Phones.CONTENT_FILTER_URL, number); + Uri contactRef = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, number); CallerInfoAsyncQuery c = new CallerInfoAsyncQuery(); c.allocate(context, contactRef); diff --git a/telephony/java/com/android/internal/telephony/IccCard.java b/telephony/java/com/android/internal/telephony/IccCard.java index c2bed88..6657060 100644 --- a/telephony/java/com/android/internal/telephony/IccCard.java +++ b/telephony/java/com/android/internal/telephony/IccCard.java @@ -595,7 +595,7 @@ public abstract class IccCard { // this is common for all radio technologies if (!mIccCardStatus.getCardState().isCardPresent()) { - return IccCard.State.NOT_READY; + return IccCard.State.ABSENT; } RadioState currentRadioState = mPhone.mCM.getRadioState(); |
