diff options
44 files changed, 765 insertions, 1680 deletions
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c index ba79c9fec149..aa95b354ad07 100644 --- a/cmds/dumpstate/dumpstate.c +++ b/cmds/dumpstate/dumpstate.c @@ -124,6 +124,24 @@ static void dumpstate() { dump_file("VM TRACES AT LAST ANR", anr_traces_path); } + /* slow traces for slow operations */ + if (anr_traces_path[0] != 0) { + int tail = strlen(anr_traces_path)-1; + while (tail > 0 && anr_traces_path[tail] != '/') { + tail--; + } + int i = 0; + while (1) { + sprintf(anr_traces_path+tail+1, "slow%02d.txt", i); + if (stat(anr_traces_path, &st)) { + // No traces file at this index, done with the files. + break; + } + dump_file("VM TRACES WHEN SLOW", anr_traces_path); + i++; + } + } + dump_file("NETWORK DEV INFO", "/proc/net/dev"); dump_file("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all"); dump_file("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl"); diff --git a/cmds/stagefright/sf2.cpp b/cmds/stagefright/sf2.cpp index 1d28793474bd..e47cdc05ac72 100644 --- a/cmds/stagefright/sf2.cpp +++ b/cmds/stagefright/sf2.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +//#define LOG_NDEBUG 0 +#define LOG_TAG "sf2" +#include <utils/Log.h> + #include <binder/ProcessState.h> #include <media/stagefright/foundation/hexdump.h> @@ -205,6 +209,12 @@ protected: } looper()->stop(); + } else if (what == ACodec::kWhatError) { + ALOGE("something went wrong, codec reported an error."); + + printf("E\n"); + + (new AMessage(kWhatStop, id()))->post(); } break; } diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java index f69120a7934c..e2b8ce4c0581 100755 --- a/core/java/android/animation/ValueAnimator.java +++ b/core/java/android/animation/ValueAnimator.java @@ -557,12 +557,22 @@ public class ValueAnimator extends Animator { public void handleMessage(Message msg) { switch (msg.what) { case ANIMATION_START: - doAnimationStart(); + // If there are already active animations, or if another ANIMATION_START + // message was processed during this frame, then the pending list may already + // have been cleared. If that's the case, we've already processed the + // active animations for this frame - don't do it again. + if (mPendingAnimations.size() > 0) { + doAnimationFrame(); + } break; } } - private void doAnimationStart() { + private void doAnimationFrame() { + // currentTime holds the common time for all animations processed + // during this frame + long currentTime = AnimationUtils.currentAnimationTimeMillis(); + // mPendingAnimations holds any animations that have requested to be started // We're going to clear mPendingAnimations, but starting animation may // cause more to be added to the pending list (for example, if one animation @@ -583,15 +593,7 @@ public class ValueAnimator extends Animator { } } } - doAnimationFrame(); - } - - private void doAnimationFrame() { - // currentTime holds the common time for all animations processed - // during this frame - long currentTime = AnimationUtils.currentAnimationTimeMillis(); - - // First, process animations currently sitting on the delayed queue, adding + // Next, process animations currently sitting on the delayed queue, adding // them to the active animations if they are ready int numDelayedAnims = mDelayedAnims.size(); for (int i = 0; i < numDelayedAnims; ++i) { diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index 1a74abf26c45..ee12989a0075 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -31,6 +31,14 @@ import com.android.internal.util.Objects; * @hide */ public class NetworkIdentity { + /** + * When enabled, combine all {@link #mSubType} together under + * {@link #SUBTYPE_COMBINED}. + */ + public static final boolean COMBINE_SUBTYPE_ENABLED = true; + + public static final int SUBTYPE_COMBINED = -1; + final int mType; final int mSubType; final String mSubscriberId; @@ -38,7 +46,7 @@ public class NetworkIdentity { public NetworkIdentity(int type, int subType, String subscriberId, boolean roaming) { this.mType = type; - this.mSubType = subType; + this.mSubType = COMBINE_SUBTYPE_ENABLED ? SUBTYPE_COMBINED : subType; this.mSubscriberId = subscriberId; this.mRoaming = roaming; } @@ -52,9 +60,8 @@ public class NetworkIdentity { public boolean equals(Object obj) { if (obj instanceof NetworkIdentity) { final NetworkIdentity ident = (NetworkIdentity) obj; - return mType == ident.mType && mSubType == ident.mSubType - && Objects.equal(mSubscriberId, ident.mSubscriberId) - && mRoaming == ident.mRoaming; + return mType == ident.mType && mSubType == ident.mSubType && mRoaming == ident.mRoaming + && Objects.equal(mSubscriberId, ident.mSubscriberId); } return false; } @@ -63,7 +70,9 @@ public class NetworkIdentity { public String toString() { final String typeName = ConnectivityManager.getNetworkTypeName(mType); final String subTypeName; - if (ConnectivityManager.isNetworkTypeMobile(mType)) { + if (COMBINE_SUBTYPE_ENABLED) { + subTypeName = "COMBINED"; + } else if (ConnectivityManager.isNetworkTypeMobile(mType)) { subTypeName = TelephonyManager.getNetworkTypeName(mSubType); } else { subTypeName = Integer.toString(mSubType); @@ -130,5 +139,4 @@ public class NetworkIdentity { } return new NetworkIdentity(type, subType, subscriberId, roaming); } - } diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 8ebfd8d0aaf9..e1fbdcc705a1 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -20,6 +20,7 @@ import static android.net.ConnectivityManager.TYPE_ETHERNET; import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.ConnectivityManager.TYPE_WIFI_P2P; import static android.net.ConnectivityManager.TYPE_WIMAX; +import static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED; import static android.net.NetworkIdentity.scrubSubscriberId; import static android.telephony.TelephonyManager.NETWORK_CLASS_2_G; import static android.telephony.TelephonyManager.NETWORK_CLASS_3_G; @@ -199,6 +200,7 @@ public class NetworkTemplate implements Parcelable { * Check if mobile network classified 3G or lower with matching IMSI. */ private boolean matchesMobile3gLower(NetworkIdentity ident) { + ensureSubtypeAvailable(); if (ident.mType == TYPE_WIMAX) { return false; } else if (matchesMobile(ident)) { @@ -216,6 +218,7 @@ public class NetworkTemplate implements Parcelable { * Check if mobile network classified 4G with matching IMSI. */ private boolean matchesMobile4g(NetworkIdentity ident) { + ensureSubtypeAvailable(); if (ident.mType == TYPE_WIMAX) { // TODO: consider matching against WiMAX subscriber identity return true; @@ -268,6 +271,13 @@ public class NetworkTemplate implements Parcelable { } } + private static void ensureSubtypeAvailable() { + if (COMBINE_SUBTYPE_ENABLED) { + throw new IllegalArgumentException( + "Unable to enforce 3G_LOWER template on combined data."); + } + } + public static final Creator<NetworkTemplate> CREATOR = new Creator<NetworkTemplate>() { public NetworkTemplate createFromParcel(Parcel in) { return new NetworkTemplate(in); diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java index 759be91cdf7c..ce213fb0ef07 100644 --- a/core/java/android/os/StrictMode.java +++ b/core/java/android/os/StrictMode.java @@ -1201,7 +1201,7 @@ public final class StrictMode { // throttled back to 60fps via SurfaceFlinger/View // invalidates, _not_ by posting frame updates every 16 // milliseconds. - threadHandler.get().post(new Runnable() { + threadHandler.get().postAtFrontOfQueue(new Runnable() { public void run() { long loopFinishTime = SystemClock.uptimeMillis(); diff --git a/core/java/android/webkit/FindActionModeCallback.java b/core/java/android/webkit/FindActionModeCallback.java index 964cf3ecc316..6c331ac87aa6 100644 --- a/core/java/android/webkit/FindActionModeCallback.java +++ b/core/java/android/webkit/FindActionModeCallback.java @@ -45,7 +45,6 @@ class FindActionModeCallback implements ActionMode.Callback, TextWatcher, private int mNumberOfMatches; private int mActiveMatchIndex; private ActionMode mActionMode; - private String mLastFind; FindActionModeCallback(Context context) { mCustomView = LayoutInflater.from(context).inflate( @@ -134,13 +133,12 @@ class FindActionModeCallback implements ActionMode.Callback, TextWatcher, mWebView.clearMatches(); mMatches.setVisibility(View.GONE); mMatchesFound = false; - mLastFind = null; + mWebView.findAll(null); } else { mMatchesFound = true; mMatches.setVisibility(View.INVISIBLE); mNumberOfMatches = 0; - mLastFind = find.toString(); - mWebView.findAllAsync(mLastFind); + mWebView.findAllAsync(find.toString()); } } @@ -150,9 +148,8 @@ class FindActionModeCallback implements ActionMode.Callback, TextWatcher, mInput.showSoftInput(mEditText, 0); } - public void updateMatchCount(int matchIndex, int matchCount, - String findText) { - if (mLastFind != null && mLastFind.equals(findText)) { + public void updateMatchCount(int matchIndex, int matchCount, boolean isNewFind) { + if (!isNewFind) { mNumberOfMatches = matchCount; mActiveMatchIndex = matchIndex; updateMatchesString(); diff --git a/core/java/android/webkit/FindListener.java b/core/java/android/webkit/FindListener.java new file mode 100644 index 000000000000..124f73719a0a --- /dev/null +++ b/core/java/android/webkit/FindListener.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.webkit; + +/** + * @hide + */ +public interface FindListener { + /** + * Notify the host application that a find result is available. + * + * @param numberOfMatches How many matches have been found + * @param activeMatchOrdinal The ordinal of the currently selected match + * @param isDoneCounting Whether we have finished counting matches + */ + public void onFindResultReceived(int numberOfMatches, + int activeMatchOrdinal, boolean isDoneCounting); +} diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index a561577f576e..5e094161a848 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -1226,7 +1226,19 @@ public class WebView extends AbsoluteLayout } - /* + /** + * Register the interface to be used when a find-on-page result has become + * available. This will replace the current handler. + * + * @param listener An implementation of FindListener + * @hide + */ + public void setFindListener(FindListener listener) { + checkThread(); + mProvider.setFindListener(listener); + } + + /** * Highlight and scroll to the next occurance of String in findAll. * Wraps the page infinitely, and scrolls. Must be called after * calling findAll. @@ -1238,8 +1250,9 @@ public class WebView extends AbsoluteLayout mProvider.findNext(forward); } - /* + /** * Find all instances of find on the page and highlight them. + * * @param find String to find. * @return int The number of occurances of the String "find" * that were found. @@ -1250,6 +1263,18 @@ public class WebView extends AbsoluteLayout } /** + * Find all instances of find on the page and highlight them, + * asynchronously. + * + * @param find String to find. + * @hide + */ + public void findAllAsync(String find) { + checkThread(); + mProvider.findAllAsync(find); + } + + /** * Start an ActionMode for finding text in this WebView. Only works if this * WebView is attached to the view system. * @param text If non-null, will be the initial text to search for. diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java index ed43043ff8f0..e5434cec3356 100644 --- a/core/java/android/webkit/WebViewClassic.java +++ b/core/java/android/webkit/WebViewClassic.java @@ -1440,6 +1440,9 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc // Used to notify listeners of a new picture. private PictureListener mPictureListener; + // Used to notify listeners about find-on-page results. + private FindListener mFindListener; + /** * Refer to {@link WebView#requestFocusNodeHref(Message)} for more information */ @@ -3695,6 +3698,17 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc } /** + * Register the interface to be used when a find-on-page result has become + * available. This will replace the current handler. + * + * @param listener An implementation of FindListener + */ + public void setFindListener(FindListener listener) { + checkThread(); + mFindListener = listener; + } + + /** * See {@link WebView#findNext(boolean)} */ @Override @@ -3723,6 +3737,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc checkThread(); if (0 == mNativeClass) return 0; // client isn't initialized mLastFind = find; + if (find == null) return 0; mWebViewCore.removeMessages(EventHub.FIND_ALL); WebViewCore.FindAllRequest request = new WebViewCore.FindAllRequest(find); @@ -4909,11 +4924,9 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc */ private void getSelectionHandles(int[] handles) { handles[0] = mSelectCursorBase.right; - handles[1] = mSelectCursorBase.bottom - - (mSelectCursorBase.height() / 4); + handles[1] = mSelectCursorBase.bottom; handles[2] = mSelectCursorExtent.left; - handles[3] = mSelectCursorExtent.bottom - - (mSelectCursorExtent.height() / 4); + handles[3] = mSelectCursorExtent.bottom; if (!nativeIsBaseFirst(mNativeClass)) { int swap = handles[0]; handles[0] = handles[2]; @@ -8478,10 +8491,11 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc } case UPDATE_MATCH_COUNT: { - if (mFindCallback != null) { - mFindCallback.updateMatchCount(msg.arg1, msg.arg2, - (String) msg.obj); - } + boolean isNewFind = mLastFind == null || !mLastFind.equals(msg.obj); + if (mFindCallback != null) + mFindCallback.updateMatchCount(msg.arg1, msg.arg2, isNewFind); + if (mFindListener != null) + mFindListener.onFindResultReceived(msg.arg1, msg.arg2, true); break; } case CLEAR_CARET_HANDLE: diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java index 2e8ad6d41db5..9016fbceeac2 100644 --- a/core/java/android/webkit/WebViewProvider.java +++ b/core/java/android/webkit/WebViewProvider.java @@ -191,10 +191,14 @@ public interface WebViewProvider { public WebBackForwardList copyBackForwardList(); + public void setFindListener(FindListener listener); + public void findNext(boolean forward); public int findAll(String find); + public void findAllAsync(String find); + public boolean showFindDialog(String text, boolean showIme); public void clearMatches(); diff --git a/core/res/res/anim/screen_rotate_finish_exit.xml b/core/res/res/anim/screen_rotate_finish_exit.xml index 3d9c569b644d..003940e9df4f 100644 --- a/core/res/res/anim/screen_rotate_finish_exit.xml +++ b/core/res/res/anim/screen_rotate_finish_exit.xml @@ -24,12 +24,14 @@ android:pivotX="50%" android:pivotY="50%" android:interpolator="@interpolator/accelerate_decelerate" android:fillEnabled="true" - android:fillBefore="false" android:fillAfter="true" + android:fillBefore="true" android:fillAfter="true" android:duration="@android:integer/config_shortAnimTime"/> <scale android:fromXScale="100%" android:toXScale="100%p" android:fromYScale="100%" android:toYScale="100%p" android:pivotX="50%" android:pivotY="50%" android:interpolator="@interpolator/accelerate_decelerate" + android:fillEnabled="true" + android:fillBefore="true" android:fillAfter="true" android:duration="@android:integer/config_mediumAnimTime" /> <alpha android:fromAlpha="1.0" android:toAlpha="0" android:interpolator="@interpolator/accelerate_decelerate" diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index 09e4e451dced..e5ad4b78db3a 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -746,6 +746,10 @@ status_t ACodec::setComponentRole( "audio_decoder.aac", "audio_encoder.aac" }, { MEDIA_MIMETYPE_AUDIO_VORBIS, "audio_decoder.vorbis", "audio_encoder.vorbis" }, + { MEDIA_MIMETYPE_AUDIO_G711_MLAW, + "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" }, + { MEDIA_MIMETYPE_AUDIO_G711_ALAW, + "audio_decoder.g711alaw", "audio_encoder.g711alaw" }, { MEDIA_MIMETYPE_VIDEO_AVC, "video_decoder.avc", "video_encoder.avc" }, { MEDIA_MIMETYPE_VIDEO_MPEG4, @@ -855,10 +859,6 @@ status_t ACodec::configureCodec( } } - if (err != OK) { - return err; - } - int32_t maxInputSize; if (msg->findInt32("max-input-size", &maxInputSize)) { err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize); @@ -2770,6 +2770,9 @@ bool ACodec::LoadedState::onConfigureComponent( status_t err = mCodec->configureCodec(mime.c_str(), msg); if (err != OK) { + ALOGE("[%s] configureCodec returning error %d", + mCodec->mComponentName.c_str(), err); + mCodec->signalError(OMX_ErrorUndefined, err); return false; } diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp index 278e3a222839..d5e6bec78a2e 100755 --- a/media/libstagefright/OMXCodec.cpp +++ b/media/libstagefright/OMXCodec.cpp @@ -1332,8 +1332,6 @@ void OMXCodec::setComponentRole( "audio_decoder.mp1", "audio_encoder.mp1" }, { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II, "audio_decoder.mp2", "audio_encoder.mp2" }, - { MEDIA_MIMETYPE_AUDIO_MPEG, - "audio_decoder.mp3", "audio_encoder.mp3" }, { MEDIA_MIMETYPE_AUDIO_AMR_NB, "audio_decoder.amrnb", "audio_encoder.amrnb" }, { MEDIA_MIMETYPE_AUDIO_AMR_WB, @@ -1342,6 +1340,10 @@ void OMXCodec::setComponentRole( "audio_decoder.aac", "audio_encoder.aac" }, { MEDIA_MIMETYPE_AUDIO_VORBIS, "audio_decoder.vorbis", "audio_encoder.vorbis" }, + { MEDIA_MIMETYPE_AUDIO_G711_MLAW, + "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" }, + { MEDIA_MIMETYPE_AUDIO_G711_ALAW, + "audio_decoder.g711alaw", "audio_encoder.g711alaw" }, { MEDIA_MIMETYPE_VIDEO_AVC, "video_decoder.avc", "video_encoder.avc" }, { MEDIA_MIMETYPE_VIDEO_MPEG4, diff --git a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp index 7602f2dcbf16..796caa4185b1 100644 --- a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp +++ b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp @@ -236,6 +236,18 @@ OMX_ERRORTYPE SoftAMR::internalSetParameter( return OMX_ErrorNone; } + case OMX_IndexParamAudioPcm: + { + const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = + (OMX_AUDIO_PARAM_PCMMODETYPE *)params; + + if (pcmParams->nPortIndex != 1) { + return OMX_ErrorUndefined; + } + + return OMX_ErrorNone; + } + default: return SimpleSoftOMXComponent::internalSetParameter(index, params); } diff --git a/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp b/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp deleted file mode 100644 index 27d7e4d74a06..000000000000 --- a/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright (C) 2009 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. - */ - -#include "AMRNBEncoder.h" - -#include "gsmamr_enc.h" - -#include <media/stagefright/foundation/ADebug.h> -#include <media/stagefright/MediaBufferGroup.h> -#include <media/stagefright/MediaDefs.h> -#include <media/stagefright/MediaErrors.h> -#include <media/stagefright/MetaData.h> - -namespace android { - -static const int32_t kNumSamplesPerFrame = 160; -static const int32_t kSampleRate = 8000; - -AMRNBEncoder::AMRNBEncoder(const sp<MediaSource> &source, const sp<MetaData> &meta) - : mSource(source), - mMeta(meta), - mStarted(false), - mBufferGroup(NULL), - mEncState(NULL), - mSidState(NULL), - mAnchorTimeUs(0), - mNumFramesOutput(0), - mInputBuffer(NULL), - mMode(MR475), - mNumInputSamples(0) { -} - -AMRNBEncoder::~AMRNBEncoder() { - if (mStarted) { - stop(); - } -} - -static Mode PickModeFromBitrate(int32_t bps) { - if (bps <= 4750) { - return MR475; - } else if (bps <= 5150) { - return MR515; - } else if (bps <= 5900) { - return MR59; - } else if (bps <= 6700) { - return MR67; - } else if (bps <= 7400) { - return MR74; - } else if (bps <= 7950) { - return MR795; - } else if (bps <= 10200) { - return MR102; - } else { - return MR122; - } -} - -status_t AMRNBEncoder::start(MetaData *params) { - if (mStarted) { - ALOGW("Call start() when encoder already started"); - return OK; - } - - mBufferGroup = new MediaBufferGroup; - mBufferGroup->add_buffer(new MediaBuffer(32)); - - CHECK_EQ(AMREncodeInit( - &mEncState, &mSidState, false /* dtx_enable */), - 0); - - status_t err = mSource->start(params); - if (err != OK) { - ALOGE("AudioSource is not available"); - return err; - } - - mAnchorTimeUs = 0; - mNumFramesOutput = 0; - mStarted = true; - mNumInputSamples = 0; - - int32_t bitrate; - if (params && params->findInt32(kKeyBitRate, &bitrate)) { - mMode = PickModeFromBitrate(bitrate); - } else { - mMode = MR475; - } - - return OK; -} - -status_t AMRNBEncoder::stop() { - if (!mStarted) { - ALOGW("Call stop() when encoder has not started."); - return OK; - } - - if (mInputBuffer) { - mInputBuffer->release(); - mInputBuffer = NULL; - } - - delete mBufferGroup; - mBufferGroup = NULL; - - mSource->stop(); - - AMREncodeExit(&mEncState, &mSidState); - mEncState = mSidState = NULL; - - mStarted = false; - - return OK; -} - -sp<MetaData> AMRNBEncoder::getFormat() { - sp<MetaData> srcFormat = mSource->getFormat(); - - mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB); - - int64_t durationUs; - if (srcFormat->findInt64(kKeyDuration, &durationUs)) { - mMeta->setInt64(kKeyDuration, durationUs); - } - - mMeta->setCString(kKeyDecoderComponent, "AMRNBEncoder"); - - return mMeta; -} - -status_t AMRNBEncoder::read( - MediaBuffer **out, const ReadOptions *options) { - status_t err; - - *out = NULL; - - int64_t seekTimeUs; - ReadOptions::SeekMode mode; - CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &mode)); - bool readFromSource = false; - int64_t wallClockTimeUs = -1; - - while (mNumInputSamples < kNumSamplesPerFrame) { - if (mInputBuffer == NULL) { - err = mSource->read(&mInputBuffer, options); - - if (err != OK) { - if (mNumInputSamples == 0) { - return ERROR_END_OF_STREAM; - } - memset(&mInputFrame[mNumInputSamples], - 0, - sizeof(int16_t) - * (kNumSamplesPerFrame - mNumInputSamples)); - mNumInputSamples = kNumSamplesPerFrame; - break; - } - - size_t align = mInputBuffer->range_length() % sizeof(int16_t); - CHECK_EQ(align, 0); - readFromSource = true; - - int64_t timeUs; - if (mInputBuffer->meta_data()->findInt64(kKeyDriftTime, &timeUs)) { - wallClockTimeUs = timeUs; - } - if (mInputBuffer->meta_data()->findInt64(kKeyAnchorTime, &timeUs)) { - mAnchorTimeUs = timeUs; - } - } else { - readFromSource = false; - } - - size_t copy = - (kNumSamplesPerFrame - mNumInputSamples) * sizeof(int16_t); - - if (copy > mInputBuffer->range_length()) { - copy = mInputBuffer->range_length(); - } - - memcpy(&mInputFrame[mNumInputSamples], - (const uint8_t *)mInputBuffer->data() - + mInputBuffer->range_offset(), - copy); - - mNumInputSamples += copy / sizeof(int16_t); - - mInputBuffer->set_range( - mInputBuffer->range_offset() + copy, - mInputBuffer->range_length() - copy); - - if (mInputBuffer->range_length() == 0) { - mInputBuffer->release(); - mInputBuffer = NULL; - } - } - - MediaBuffer *buffer; - CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), (status_t)OK); - - uint8_t *outPtr = (uint8_t *)buffer->data(); - - Frame_Type_3GPP frameType; - int res = AMREncode( - mEncState, mSidState, (Mode)mMode, - mInputFrame, outPtr, &frameType, AMR_TX_WMF); - - CHECK(res >= 0); - CHECK((size_t)res < buffer->size()); - - // Convert header byte from WMF to IETF format. - outPtr[0] = ((outPtr[0] << 3) | 4) & 0x7c; - - buffer->set_range(0, res); - - // Each frame of 160 samples is 20ms long. - int64_t mediaTimeUs = mNumFramesOutput * 20000LL; - buffer->meta_data()->setInt64( - kKeyTime, mAnchorTimeUs + mediaTimeUs); - - if (readFromSource && wallClockTimeUs != -1) { - buffer->meta_data()->setInt64(kKeyDriftTime, - mediaTimeUs - wallClockTimeUs); - } - - ++mNumFramesOutput; - - *out = buffer; - - mNumInputSamples = 0; - - return OK; -} - -} // namespace android diff --git a/media/libstagefright/codecs/amrnb/enc/Android.mk b/media/libstagefright/codecs/amrnb/enc/Android.mk index 21937bfcbc10..28246ae16122 100644 --- a/media/libstagefright/codecs/amrnb/enc/Android.mk +++ b/media/libstagefright/codecs/amrnb/enc/Android.mk @@ -2,7 +2,6 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := \ - AMRNBEncoder.cpp \ src/amrencode.cpp \ src/autocorr.cpp \ src/c1035pf.cpp \ diff --git a/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp b/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp deleted file mode 100644 index 7fd3a9505e10..000000000000 --- a/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Copyright (C) 2010 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. - */ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "AMRWBEncoder" -#include <utils/Log.h> - -#include "AMRWBEncoder.h" -#include "voAMRWB.h" -#include "cmnMemory.h" - -#include <media/stagefright/foundation/ADebug.h> -#include <media/stagefright/MediaBufferGroup.h> -#include <media/stagefright/MediaDefs.h> -#include <media/stagefright/MediaErrors.h> -#include <media/stagefright/MetaData.h> - -namespace android { - -static const int32_t kNumSamplesPerFrame = 320; -static const int32_t kBitsPerSample = 16; -static const int32_t kInputBufferSize = (kBitsPerSample / 8) * kNumSamplesPerFrame; -static const int32_t kSampleRate = 16000; -static const int32_t kNumChannels = 1; - -AMRWBEncoder::AMRWBEncoder(const sp<MediaSource> &source, const sp<MetaData> &meta) - : mSource(source), - mMeta(meta), - mStarted(false), - mBufferGroup(NULL), - mInputBuffer(NULL), - mEncoderHandle(NULL), - mApiHandle(NULL), - mMemOperator(NULL), - mAnchorTimeUs(0), - mNumFramesOutput(0), - mNumInputSamples(0) { -} - -static VOAMRWBMODE pickModeFromBitRate(int32_t bps) { - CHECK(bps >= 0); - if (bps <= 6600) { - return VOAMRWB_MD66; - } else if (bps <= 8850) { - return VOAMRWB_MD885; - } else if (bps <= 12650) { - return VOAMRWB_MD1265; - } else if (bps <= 14250) { - return VOAMRWB_MD1425; - } else if (bps <= 15850) { - return VOAMRWB_MD1585; - } else if (bps <= 18250) { - return VOAMRWB_MD1825; - } else if (bps <= 19850) { - return VOAMRWB_MD1985; - } else if (bps <= 23050) { - return VOAMRWB_MD2305; - } - return VOAMRWB_MD2385; -} - -status_t AMRWBEncoder::initCheck() { - CHECK(mApiHandle == NULL && mEncoderHandle == NULL); - CHECK(mMeta->findInt32(kKeyBitRate, &mBitRate)); - - mApiHandle = new VO_AUDIO_CODECAPI; - CHECK(mApiHandle); - - if (VO_ERR_NONE != voGetAMRWBEncAPI(mApiHandle)) { - ALOGE("Failed to get api handle"); - return UNKNOWN_ERROR; - } - - mMemOperator = new VO_MEM_OPERATOR; - CHECK(mMemOperator != NULL); - mMemOperator->Alloc = cmnMemAlloc; - mMemOperator->Copy = cmnMemCopy; - mMemOperator->Free = cmnMemFree; - mMemOperator->Set = cmnMemSet; - mMemOperator->Check = cmnMemCheck; - - VO_CODEC_INIT_USERDATA userData; - memset(&userData, 0, sizeof(userData)); - userData.memflag = VO_IMF_USERMEMOPERATOR; - userData.memData = (VO_PTR) mMemOperator; - if (VO_ERR_NONE != mApiHandle->Init(&mEncoderHandle, VO_AUDIO_CodingAMRWB, &userData)) { - ALOGE("Failed to init AMRWB encoder"); - return UNKNOWN_ERROR; - } - - // Configure AMRWB encoder$ - VOAMRWBMODE mode = pickModeFromBitRate(mBitRate); - if (VO_ERR_NONE != mApiHandle->SetParam(mEncoderHandle, VO_PID_AMRWB_MODE, &mode)) { - ALOGE("Failed to set AMRWB encoder mode to %d", mode); - return UNKNOWN_ERROR; - } - - VOAMRWBFRAMETYPE type = VOAMRWB_RFC3267; - if (VO_ERR_NONE != mApiHandle->SetParam(mEncoderHandle, VO_PID_AMRWB_FRAMETYPE, &type)) { - ALOGE("Failed to set AMRWB encoder frame type to %d", type); - return UNKNOWN_ERROR; - } - - return OK; -} - -AMRWBEncoder::~AMRWBEncoder() { - if (mStarted) { - stop(); - } -} - -status_t AMRWBEncoder::start(MetaData *params) { - if (mStarted) { - ALOGW("Call start() when encoder already started"); - return OK; - } - - mBufferGroup = new MediaBufferGroup; - - // The largest buffer size is header + 477 bits - mBufferGroup->add_buffer(new MediaBuffer(1024)); - - CHECK_EQ((status_t)OK, initCheck()); - - mNumFramesOutput = 0; - - status_t err = mSource->start(params); - if (err != OK) { - ALOGE("AudioSource is not available"); - return err; - } - mStarted = true; - - return OK; -} - -status_t AMRWBEncoder::stop() { - if (!mStarted) { - ALOGW("Call stop() when encoder has not started"); - return OK; - } - - if (mInputBuffer) { - mInputBuffer->release(); - mInputBuffer = NULL; - } - - delete mBufferGroup; - mBufferGroup = NULL; - - - CHECK_EQ((VO_U32)VO_ERR_NONE, mApiHandle->Uninit(mEncoderHandle)); - mEncoderHandle = NULL; - - delete mApiHandle; - mApiHandle = NULL; - - delete mMemOperator; - mMemOperator; - - mStarted = false; - - mSource->stop(); - return OK; -} - -sp<MetaData> AMRWBEncoder::getFormat() { - sp<MetaData> srcFormat = mSource->getFormat(); - - mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB); - - int64_t durationUs; - if (srcFormat->findInt64(kKeyDuration, &durationUs)) { - mMeta->setInt64(kKeyDuration, durationUs); - } - - mMeta->setCString(kKeyDecoderComponent, "AMRWBEncoder"); - - return mMeta; -} - -status_t AMRWBEncoder::read( - MediaBuffer **out, const ReadOptions *options) { - status_t err; - - *out = NULL; - - int64_t seekTimeUs; - ReadOptions::SeekMode mode; - CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &mode)); - bool readFromSource = false; - int64_t wallClockTimeUs = -1; - - while (mNumInputSamples < kNumSamplesPerFrame) { - if (mInputBuffer == NULL) { - err = mSource->read(&mInputBuffer, options); - - if (err != OK) { - if (mNumInputSamples == 0) { - return ERROR_END_OF_STREAM; - } - memset(&mInputFrame[mNumInputSamples], - 0, - sizeof(int16_t) - * (kNumSamplesPerFrame - mNumInputSamples)); - mNumInputSamples = 0; - break; - } - - size_t align = mInputBuffer->range_length() % sizeof(int16_t); - CHECK_EQ(align, (size_t)0); - - int64_t timeUs; - if (mInputBuffer->meta_data()->findInt64(kKeyDriftTime, &timeUs)) { - wallClockTimeUs = timeUs; - } - if (mInputBuffer->meta_data()->findInt64(kKeyAnchorTime, &timeUs)) { - mAnchorTimeUs = timeUs; - } - readFromSource = true; - } else { - readFromSource = false; - } - - size_t copy = - (kNumSamplesPerFrame - mNumInputSamples) * sizeof(int16_t); - - if (copy > mInputBuffer->range_length()) { - copy = mInputBuffer->range_length(); - } - - memcpy(&mInputFrame[mNumInputSamples], - (const uint8_t *)mInputBuffer->data() - + mInputBuffer->range_offset(), - copy); - - mInputBuffer->set_range( - mInputBuffer->range_offset() + copy, - mInputBuffer->range_length() - copy); - - if (mInputBuffer->range_length() == 0) { - mInputBuffer->release(); - mInputBuffer = NULL; - } - - mNumInputSamples += copy / sizeof(int16_t); - if (mNumInputSamples >= kNumSamplesPerFrame) { - mNumInputSamples %= kNumSamplesPerFrame; - break; // Get a whole input frame 640 bytes - } - } - - VO_CODECBUFFER inputData; - memset(&inputData, 0, sizeof(inputData)); - inputData.Buffer = (unsigned char*) mInputFrame; - inputData.Length = kInputBufferSize; - CHECK(VO_ERR_NONE == mApiHandle->SetInputData(mEncoderHandle,&inputData)); - - MediaBuffer *buffer; - CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), (status_t)OK); - uint8_t *outPtr = (uint8_t *)buffer->data(); - - VO_CODECBUFFER outputData; - memset(&outputData, 0, sizeof(outputData)); - VO_AUDIO_OUTPUTINFO outputInfo; - memset(&outputInfo, 0, sizeof(outputInfo)); - - VO_U32 ret = VO_ERR_NONE; - outputData.Buffer = outPtr; - outputData.Length = buffer->size(); - ret = mApiHandle->GetOutputData(mEncoderHandle, &outputData, &outputInfo); - CHECK(ret == VO_ERR_NONE || ret == VO_ERR_INPUT_BUFFER_SMALL); - - buffer->set_range(0, outputData.Length); - ++mNumFramesOutput; - - int64_t mediaTimeUs = mNumFramesOutput * 20000LL; - buffer->meta_data()->setInt64(kKeyTime, mAnchorTimeUs + mediaTimeUs); - if (readFromSource && wallClockTimeUs != -1) { - buffer->meta_data()->setInt64(kKeyDriftTime, mediaTimeUs - wallClockTimeUs); - } - - *out = buffer; - return OK; -} - -} // namespace android diff --git a/media/libstagefright/codecs/amrwbenc/Android.mk b/media/libstagefright/codecs/amrwbenc/Android.mk index 3a46ec84f16a..d3c3041a0d0d 100644 --- a/media/libstagefright/codecs/amrwbenc/Android.mk +++ b/media/libstagefright/codecs/amrwbenc/Android.mk @@ -5,7 +5,6 @@ include frameworks/base/media/libstagefright/codecs/common/Config.mk LOCAL_SRC_FILES := \ - AMRWBEncoder.cpp \ src/autocorr.c \ src/az_isp.c \ src/bits.c \ diff --git a/media/libstagefright/codecs/g711/dec/SoftG711.cpp b/media/libstagefright/codecs/g711/dec/SoftG711.cpp index 32ef0031f43c..bcdd3c736335 100644 --- a/media/libstagefright/codecs/g711/dec/SoftG711.cpp +++ b/media/libstagefright/codecs/g711/dec/SoftG711.cpp @@ -140,7 +140,7 @@ OMX_ERRORTYPE SoftG711::internalSetParameter( OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = (OMX_AUDIO_PARAM_PCMMODETYPE *)params; - if (pcmParams->nPortIndex != 0) { + if (pcmParams->nPortIndex != 0 && pcmParams->nPortIndex != 1) { return OMX_ErrorUndefined; } @@ -148,7 +148,9 @@ OMX_ERRORTYPE SoftG711::internalSetParameter( return OMX_ErrorUndefined; } - mNumChannels = pcmParams->nChannels; + if(pcmParams->nPortIndex == 0) { + mNumChannels = pcmParams->nChannels; + } return OMX_ErrorNone; } diff --git a/media/libstagefright/include/AACDecoder.h b/media/libstagefright/include/AACDecoder.h deleted file mode 100644 index 886a3b723ebd..000000000000 --- a/media/libstagefright/include/AACDecoder.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2009 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. - */ - -#ifndef AAC_DECODER_H_ - -#define AAC_DECODER_H_ - -#include <media/stagefright/MediaSource.h> - -struct tPVMP4AudioDecoderExternal; - -namespace android { - -struct MediaBufferGroup; -struct MetaData; - -struct AACDecoder : public MediaSource { - AACDecoder(const sp<MediaSource> &source); - - virtual status_t start(MetaData *params); - virtual status_t stop(); - - virtual sp<MetaData> getFormat(); - - virtual status_t read( - MediaBuffer **buffer, const ReadOptions *options); - -protected: - virtual ~AACDecoder(); - -private: - sp<MetaData> mMeta; - sp<MediaSource> mSource; - bool mStarted; - - MediaBufferGroup *mBufferGroup; - - tPVMP4AudioDecoderExternal *mConfig; - void *mDecoderBuf; - int64_t mAnchorTimeUs; - int64_t mNumSamplesOutput; - status_t mInitCheck; - int64_t mNumDecodedBuffers; - int32_t mUpsamplingFactor; - - MediaBuffer *mInputBuffer; - - status_t initCheck(); - AACDecoder(const AACDecoder &); - AACDecoder &operator=(const AACDecoder &); -}; - -} // namespace android - -#endif // AAC_DECODER_H_ diff --git a/media/libstagefright/include/AMRNBDecoder.h b/media/libstagefright/include/AMRNBDecoder.h deleted file mode 100644 index cf24eda779c9..000000000000 --- a/media/libstagefright/include/AMRNBDecoder.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2009 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. - */ - -#ifndef AMR_NB_DECODER_H_ - -#define AMR_NB_DECODER_H_ - -#include <media/stagefright/MediaSource.h> - -namespace android { - -struct MediaBufferGroup; - -struct AMRNBDecoder : public MediaSource { - AMRNBDecoder(const sp<MediaSource> &source); - - virtual status_t start(MetaData *params); - virtual status_t stop(); - - virtual sp<MetaData> getFormat(); - - virtual status_t read( - MediaBuffer **buffer, const ReadOptions *options); - -protected: - virtual ~AMRNBDecoder(); - -private: - sp<MediaSource> mSource; - bool mStarted; - - MediaBufferGroup *mBufferGroup; - - void *mState; - int64_t mAnchorTimeUs; - int64_t mNumSamplesOutput; - - MediaBuffer *mInputBuffer; - - AMRNBDecoder(const AMRNBDecoder &); - AMRNBDecoder &operator=(const AMRNBDecoder &); -}; - -} // namespace android - -#endif // AMR_NB_DECODER_H_ diff --git a/media/libstagefright/include/AMRNBEncoder.h b/media/libstagefright/include/AMRNBEncoder.h deleted file mode 100644 index 71160e67ebbb..000000000000 --- a/media/libstagefright/include/AMRNBEncoder.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2009 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. - */ - -#ifndef AMR_NB_ENCODER_H_ - -#define AMR_NB_ENCODER_H_ - -#include <media/stagefright/MediaSource.h> -#include <media/stagefright/MetaData.h> - -namespace android { - -struct MediaBufferGroup; - -struct AMRNBEncoder : public MediaSource { - AMRNBEncoder(const sp<MediaSource> &source, const sp<MetaData> &meta); - - virtual status_t start(MetaData *params); - virtual status_t stop(); - - virtual sp<MetaData> getFormat(); - - virtual status_t read( - MediaBuffer **buffer, const ReadOptions *options); - -protected: - virtual ~AMRNBEncoder(); - -private: - sp<MediaSource> mSource; - sp<MetaData> mMeta; - bool mStarted; - - MediaBufferGroup *mBufferGroup; - - void *mEncState; - void *mSidState; - int64_t mAnchorTimeUs; - int64_t mNumFramesOutput; - - MediaBuffer *mInputBuffer; - int mMode; - - int16_t mInputFrame[160]; - int32_t mNumInputSamples; - - AMRNBEncoder(const AMRNBEncoder &); - AMRNBEncoder &operator=(const AMRNBEncoder &); -}; - -} // namespace android - -#endif // AMR_NB_ENCODER_H_ diff --git a/media/libstagefright/include/AMRWBDecoder.h b/media/libstagefright/include/AMRWBDecoder.h deleted file mode 100644 index 927c51c0a5f6..000000000000 --- a/media/libstagefright/include/AMRWBDecoder.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2009 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. - */ - -#ifndef AMR_WB_DECODER_H_ - -#define AMR_WB_DECODER_H_ - -#include <media/stagefright/MediaSource.h> - -namespace android { - -struct MediaBufferGroup; - -struct AMRWBDecoder : public MediaSource { - AMRWBDecoder(const sp<MediaSource> &source); - - virtual status_t start(MetaData *params); - virtual status_t stop(); - - virtual sp<MetaData> getFormat(); - - virtual status_t read( - MediaBuffer **buffer, const ReadOptions *options); - -protected: - virtual ~AMRWBDecoder(); - -private: - sp<MediaSource> mSource; - bool mStarted; - - MediaBufferGroup *mBufferGroup; - - void *mState; - void *mDecoderBuf; - int16_t *mDecoderCookie; - int64_t mAnchorTimeUs; - int64_t mNumSamplesOutput; - int16_t mInputSampleBuffer[477]; - - MediaBuffer *mInputBuffer; - - AMRWBDecoder(const AMRWBDecoder &); - AMRWBDecoder &operator=(const AMRWBDecoder &); -}; - -} // namespace android - -#endif // AMR_WB_DECODER_H_ diff --git a/media/libstagefright/include/AMRWBEncoder.h b/media/libstagefright/include/AMRWBEncoder.h deleted file mode 100644 index f2d155fa13b8..000000000000 --- a/media/libstagefright/include/AMRWBEncoder.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2010 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. - */ - -#ifndef AMR_WB_ENCODER_H -#define AMR_WB_ENCODER_H - -#include <media/stagefright/MediaSource.h> -#include <media/stagefright/MetaData.h> - -struct VO_AUDIO_CODECAPI; -struct VO_MEM_OPERATOR; - -namespace android { - -struct MediaBufferGroup; - -class AMRWBEncoder: public MediaSource { - public: - AMRWBEncoder(const sp<MediaSource> &source, const sp<MetaData> &meta); - - virtual status_t start(MetaData *params); - virtual status_t stop(); - virtual sp<MetaData> getFormat(); - virtual status_t read( - MediaBuffer **buffer, const ReadOptions *options); - - - protected: - virtual ~AMRWBEncoder(); - - private: - sp<MediaSource> mSource; - sp<MetaData> mMeta; - bool mStarted; - MediaBufferGroup *mBufferGroup; - MediaBuffer *mInputBuffer; - status_t mInitCheck; - int32_t mBitRate; - void *mEncoderHandle; - VO_AUDIO_CODECAPI *mApiHandle; - VO_MEM_OPERATOR *mMemOperator; - - int64_t mAnchorTimeUs; - int64_t mNumFramesOutput; - - int16_t mInputFrame[320]; - int32_t mNumInputSamples; - - status_t initCheck(); - - AMRWBEncoder& operator=(const AMRWBEncoder &rhs); - AMRWBEncoder(const AMRWBEncoder& copy); - -}; - -} - -#endif //#ifndef AMR_WB_ENCODER_H - diff --git a/media/libstagefright/include/AVCDecoder.h b/media/libstagefright/include/AVCDecoder.h deleted file mode 100644 index eb3b14250cea..000000000000 --- a/media/libstagefright/include/AVCDecoder.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2009 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. - */ - -#ifndef AVC_DECODER_H_ - -#define AVC_DECODER_H_ - -#include <media/stagefright/MediaBuffer.h> -#include <media/stagefright/MediaSource.h> -#include <utils/Vector.h> - -struct tagAVCHandle; - -namespace android { - -struct AVCDecoder : public MediaSource, - public MediaBufferObserver { - AVCDecoder(const sp<MediaSource> &source); - - virtual status_t start(MetaData *params); - virtual status_t stop(); - - virtual sp<MetaData> getFormat(); - - virtual status_t read( - MediaBuffer **buffer, const ReadOptions *options); - - virtual void signalBufferReturned(MediaBuffer *buffer); - -protected: - virtual ~AVCDecoder(); - -private: - sp<MediaSource> mSource; - bool mStarted; - - sp<MetaData> mFormat; - - Vector<MediaBuffer *> mCodecSpecificData; - - tagAVCHandle *mHandle; - Vector<MediaBuffer *> mFrames; - MediaBuffer *mInputBuffer; - - int64_t mAnchorTimeUs; - int64_t mNumSamplesOutput; - int64_t mPendingSeekTimeUs; - MediaSource::ReadOptions::SeekMode mPendingSeekMode; - - int64_t mTargetTimeUs; - - bool mSPSSeen; - bool mPPSSeen; - - void addCodecSpecificData(const uint8_t *data, size_t size); - - static int32_t ActivateSPSWrapper( - void *userData, unsigned int sizeInMbs, unsigned int numBuffers); - - static int32_t BindFrameWrapper( - void *userData, int32_t index, uint8_t **yuv); - - static void UnbindFrame(void *userData, int32_t index); - - int32_t activateSPS( - unsigned int sizeInMbs, unsigned int numBuffers); - - int32_t bindFrame(int32_t index, uint8_t **yuv); - - void releaseFrames(); - - MediaBuffer *drainOutputBuffer(); - - AVCDecoder(const AVCDecoder &); - AVCDecoder &operator=(const AVCDecoder &); -}; - -} // namespace android - -#endif // AVC_DECODER_H_ diff --git a/media/libstagefright/include/G711Decoder.h b/media/libstagefright/include/G711Decoder.h deleted file mode 100644 index 8b5143ac896b..000000000000 --- a/media/libstagefright/include/G711Decoder.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2010 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. - */ - -#ifndef G711_DECODER_H_ - -#define G711_DECODER_H_ - -#include <media/stagefright/MediaSource.h> - -namespace android { - -struct MediaBufferGroup; - -struct G711Decoder : public MediaSource { - G711Decoder(const sp<MediaSource> &source); - - virtual status_t start(MetaData *params); - virtual status_t stop(); - - virtual sp<MetaData> getFormat(); - - virtual status_t read( - MediaBuffer **buffer, const ReadOptions *options); - -protected: - virtual ~G711Decoder(); - -private: - sp<MediaSource> mSource; - bool mStarted; - bool mIsMLaw; - - MediaBufferGroup *mBufferGroup; - - static void DecodeALaw(int16_t *out, const uint8_t *in, size_t inSize); - static void DecodeMLaw(int16_t *out, const uint8_t *in, size_t inSize); - - G711Decoder(const G711Decoder &); - G711Decoder &operator=(const G711Decoder &); -}; - -} // namespace android - -#endif // G711_DECODER_H_ diff --git a/media/libstagefright/include/M4vH263Decoder.h b/media/libstagefright/include/M4vH263Decoder.h deleted file mode 100644 index 7d73e306cd64..000000000000 --- a/media/libstagefright/include/M4vH263Decoder.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2009 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. - */ - -#ifndef M4V_H263_DECODER_H_ - -#define M4V_H263_DECODER_H_ - -#include <media/stagefright/MediaBuffer.h> -#include <media/stagefright/MediaSource.h> - -struct tagvideoDecControls; - -namespace android { - -struct M4vH263Decoder : public MediaSource, - public MediaBufferObserver { - M4vH263Decoder(const sp<MediaSource> &source); - - virtual status_t start(MetaData *params); - virtual status_t stop(); - - virtual sp<MetaData> getFormat(); - - virtual status_t read( - MediaBuffer **buffer, const ReadOptions *options); - - virtual void signalBufferReturned(MediaBuffer *buffer); - -protected: - virtual ~M4vH263Decoder(); - -private: - sp<MediaSource> mSource; - bool mStarted; - int32_t mWidth, mHeight; - - sp<MetaData> mFormat; - - tagvideoDecControls *mHandle; - MediaBuffer *mFrames[2]; - MediaBuffer *mInputBuffer; - - int64_t mNumSamplesOutput; - int64_t mTargetTimeUs; - - void allocateFrames(int32_t width, int32_t height); - void releaseFrames(); - - M4vH263Decoder(const M4vH263Decoder &); - M4vH263Decoder &operator=(const M4vH263Decoder &); -}; - -} // namespace android - -#endif // M4V_H263_DECODER_H_ diff --git a/media/libstagefright/include/MP3Decoder.h b/media/libstagefright/include/MP3Decoder.h deleted file mode 100644 index 4086fb603b53..000000000000 --- a/media/libstagefright/include/MP3Decoder.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2009 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. - */ - -#ifndef MP3_DECODER_H_ - -#define MP3_DECODER_H_ - -#include <media/stagefright/MediaSource.h> - -struct tPVMP3DecoderExternal; - -namespace android { - -struct MediaBufferGroup; - -struct MP3Decoder : public MediaSource { - MP3Decoder(const sp<MediaSource> &source); - - virtual status_t start(MetaData *params); - virtual status_t stop(); - - virtual sp<MetaData> getFormat(); - - virtual status_t read( - MediaBuffer **buffer, const ReadOptions *options); - -protected: - virtual ~MP3Decoder(); - -private: - sp<MediaSource> mSource; - sp<MetaData> mMeta; - int32_t mNumChannels; - - bool mStarted; - - MediaBufferGroup *mBufferGroup; - - tPVMP3DecoderExternal *mConfig; - void *mDecoderBuf; - int64_t mAnchorTimeUs; - int64_t mNumFramesOutput; - - MediaBuffer *mInputBuffer; - - void init(); - - MP3Decoder(const MP3Decoder &); - MP3Decoder &operator=(const MP3Decoder &); -}; - -} // namespace android - -#endif // MP3_DECODER_H_ diff --git a/media/libstagefright/include/VPXDecoder.h b/media/libstagefright/include/VPXDecoder.h deleted file mode 100644 index 3b8362d6d3cb..000000000000 --- a/media/libstagefright/include/VPXDecoder.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2010 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. - */ - -#ifndef VPX_DECODER_H_ - -#define VPX_DECODER_H_ - -#include <media/stagefright/MediaSource.h> -#include <utils/Vector.h> - -namespace android { - -struct MediaBufferGroup; - -struct VPXDecoder : public MediaSource { - VPXDecoder(const sp<MediaSource> &source); - - virtual status_t start(MetaData *params); - virtual status_t stop(); - - virtual sp<MetaData> getFormat(); - - virtual status_t read( - MediaBuffer **buffer, const ReadOptions *options); - -protected: - virtual ~VPXDecoder(); - -private: - sp<MediaSource> mSource; - bool mStarted; - int32_t mWidth, mHeight; - size_t mBufferSize; - - void *mCtx; - MediaBufferGroup *mBufferGroup; - - int64_t mTargetTimeUs; - - sp<MetaData> mFormat; - - VPXDecoder(const VPXDecoder &); - VPXDecoder &operator=(const VPXDecoder &); -}; - -} // namespace android - -#endif // VPX_DECODER_H_ - diff --git a/media/libstagefright/include/VorbisDecoder.h b/media/libstagefright/include/VorbisDecoder.h deleted file mode 100644 index 13e8b77f58c6..000000000000 --- a/media/libstagefright/include/VorbisDecoder.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2010 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. - */ - -#ifndef VORBIS_DECODER_H_ - -#define VORBIS_DECODER_H_ - -#include <media/stagefright/MediaSource.h> - -struct vorbis_dsp_state; -struct vorbis_info; - -namespace android { - -struct MediaBufferGroup; - -struct VorbisDecoder : public MediaSource { - VorbisDecoder(const sp<MediaSource> &source); - - virtual status_t start(MetaData *params); - virtual status_t stop(); - - virtual sp<MetaData> getFormat(); - - virtual status_t read( - MediaBuffer **buffer, const ReadOptions *options); - -protected: - virtual ~VorbisDecoder(); - -private: - enum { - kMaxNumSamplesPerBuffer = 8192 * 2 - }; - - sp<MediaSource> mSource; - bool mStarted; - - MediaBufferGroup *mBufferGroup; - - int32_t mNumChannels; - int32_t mSampleRate; - int64_t mAnchorTimeUs; - int64_t mNumFramesOutput; - int32_t mNumFramesLeftOnPage; - - vorbis_dsp_state *mState; - vorbis_info *mVi; - - int decodePacket(MediaBuffer *packet, MediaBuffer *out); - - VorbisDecoder(const VorbisDecoder &); - VorbisDecoder &operator=(const VorbisDecoder &); -}; - -} // namespace android - -#endif // VORBIS_DECODER_H_ - diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 0c5a8278c581..caee1ab658e1 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -110,6 +110,7 @@ import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserId; import android.provider.Settings; +import android.text.format.Time; import android.util.EventLog; import android.util.Pair; import android.util.Slog; @@ -197,6 +198,8 @@ public final class ActivityManagerService extends ActivityManagerNative private static final String SYSTEM_DEBUGGABLE = "ro.debuggable"; + static final boolean IS_USER_BUILD = "user".equals(Build.TYPE); + // Maximum number of recent tasks that we can remember. static final int MAX_RECENT_TASKS = 20; @@ -2962,6 +2965,12 @@ public final class ActivityManagerService extends ActivityManagerNative return null; } + dumpStackTraces(tracesPath, firstPids, processStats, lastPids); + return tracesFile; + } + + private static void dumpStackTraces(String tracesPath, ArrayList<Integer> firstPids, + ProcessStats processStats, SparseArray<Boolean> lastPids) { // Use a FileObserver to detect when traces finish writing. // The order of traces is considered important to maintain for legibility. FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) { @@ -2972,16 +2981,18 @@ public final class ActivityManagerService extends ActivityManagerNative observer.startWatching(); // First collect all of the stacks of the most important pids. - try { - int num = firstPids.size(); - for (int i = 0; i < num; i++) { - synchronized (observer) { - Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT); - observer.wait(200); // Wait for write-close, give up after 200msec + if (firstPids != null) { + try { + int num = firstPids.size(); + for (int i = 0; i < num; i++) { + synchronized (observer) { + Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT); + observer.wait(200); // Wait for write-close, give up after 200msec + } } + } catch (InterruptedException e) { + Log.wtf(TAG, e); } - } catch (InterruptedException e) { - Log.wtf(TAG, e); } // Next measure CPU usage. @@ -3017,13 +3028,83 @@ public final class ActivityManagerService extends ActivityManagerNative } } - return tracesFile; - } finally { observer.stopWatching(); } } + final void logAppTooSlow(ProcessRecord app, long startTime, String msg) { + if (IS_USER_BUILD) { + return; + } + String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null); + if (tracesPath == null || tracesPath.length() == 0) { + return; + } + + StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); + StrictMode.allowThreadDiskWrites(); + try { + final File tracesFile = new File(tracesPath); + final File tracesDir = tracesFile.getParentFile(); + final File tracesTmp = new File(tracesDir, "__tmp__"); + try { + if (!tracesDir.exists()) tracesFile.mkdirs(); + FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x + + if (tracesFile.exists()) { + tracesTmp.delete(); + tracesFile.renameTo(tracesTmp); + } + StringBuilder sb = new StringBuilder(); + Time tobj = new Time(); + tobj.set(System.currentTimeMillis()); + sb.append(tobj.format("%Y-%m-%d %H:%M:%S")); + sb.append(": "); + TimeUtils.formatDuration(SystemClock.uptimeMillis()-startTime, sb); + sb.append(" since "); + sb.append(msg); + FileOutputStream fos = new FileOutputStream(tracesFile); + fos.write(sb.toString().getBytes()); + if (app == null) { + fos.write("\n*** No application process!".getBytes()); + } + fos.close(); + FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw- + } catch (IOException e) { + Slog.w(TAG, "Unable to prepare slow app traces file: " + tracesPath, e); + return; + } + + if (app != null) { + ArrayList<Integer> firstPids = new ArrayList<Integer>(); + firstPids.add(app.pid); + dumpStackTraces(tracesPath, firstPids, null, null); + } + + File lastTracesFile = null; + File curTracesFile = null; + for (int i=9; i>=0; i--) { + String name = String.format("slow%02d.txt", i); + curTracesFile = new File(tracesDir, name); + if (curTracesFile.exists()) { + if (lastTracesFile != null) { + curTracesFile.renameTo(lastTracesFile); + } else { + curTracesFile.delete(); + } + } + lastTracesFile = curTracesFile; + } + tracesFile.renameTo(curTracesFile); + if (tracesTmp.exists()) { + tracesTmp.renameTo(tracesFile); + } + } finally { + StrictMode.setThreadPolicy(oldPolicy); + } + } + final void appNotResponding(ProcessRecord app, ActivityRecord activity, ActivityRecord parent, final String annotation) { ArrayList<Integer> firstPids = new ArrayList<Integer>(5); diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java index a337b400288a..b42d98ea844d 100644 --- a/services/java/com/android/server/am/ActivityRecord.java +++ b/services/java/com/android/server/am/ActivityRecord.java @@ -85,6 +85,8 @@ final class ActivityRecord { long startTime; // last time this activity was started long lastVisibleTime; // last time this activity became visible long cpuTimeAtResume; // the cpu time of host process at the time of resuming activity + long pauseTime; // last time we started pausing the activity + long launchTickTime; // base time for launch tick messages Configuration configuration; // configuration activity was last running in CompatibilityInfo compat;// last used compatibility mode ActivityRecord resultTo; // who started this entry, so will get our reply @@ -576,6 +578,32 @@ final class ActivityRecord { } } + void startLaunchTickingLocked() { + if (ActivityManagerService.IS_USER_BUILD) { + return; + } + if (launchTickTime == 0) { + launchTickTime = SystemClock.uptimeMillis(); + continueLaunchTickingLocked(); + } + } + + boolean continueLaunchTickingLocked() { + if (launchTickTime != 0) { + Message msg = stack.mHandler.obtainMessage(ActivityStack.LAUNCH_TICK_MSG); + msg.obj = this; + stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG); + stack.mHandler.sendMessageDelayed(msg, ActivityStack.LAUNCH_TICK); + return true; + } + return false; + } + + void finishLaunchTickingLocked() { + launchTickTime = 0; + stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG); + } + // IApplicationToken public boolean mayFreezeScreenLocked(ProcessRecord app) { @@ -631,6 +659,7 @@ final class ActivityRecord { stack.mInitialStartTime = 0; } startTime = 0; + finishLaunchTickingLocked(); } } diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index a375d307fe48..13ee008a6008 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -87,7 +87,10 @@ final class ActivityStack { // How long we wait until giving up on the last activity telling us it // is idle. static final int IDLE_TIMEOUT = 10*1000; - + + // Ticks during which we check progress while waiting for an app to launch. + static final int LAUNCH_TICK = 500; + // How long we wait until giving up on the last activity to pause. This // is short because it directly impacts the responsiveness of starting the // next activity. @@ -275,6 +278,7 @@ final class ActivityStack { static final int LAUNCH_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 4; static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 5; static final int RESUME_TOP_ACTIVITY_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 6; + static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 7; final Handler mHandler = new Handler() { //public Handler() { @@ -297,6 +301,13 @@ final class ActivityStack { // We don't at this point know if the activity is fullscreen, // so we need to be conservative and assume it isn't. Slog.w(TAG, "Activity pause timeout for " + r); + synchronized (mService) { + if (r.app != null) { + mService.logAppTooSlow(r.app, r.pauseTime, + "pausing " + r); + } + } + activityPaused(r != null ? r.appToken : null, true); } break; case IDLE_TIMEOUT_MSG: { @@ -313,6 +324,15 @@ final class ActivityStack { Slog.w(TAG, "Activity idle timeout for " + r); activityIdleInternal(r != null ? r.appToken : null, true, null); } break; + case LAUNCH_TICK_MSG: { + ActivityRecord r = (ActivityRecord)msg.obj; + synchronized (mService) { + if (r.continueLaunchTickingLocked()) { + mService.logAppTooSlow(r.app, r.launchTickTime, + "launching " + r); + } + } + } break; case DESTROY_TIMEOUT_MSG: { ActivityRecord r = (ActivityRecord)msg.obj; // We don't at this point know if the activity is fullscreen, @@ -554,6 +574,9 @@ final class ActivityStack { r.startFreezingScreenLocked(app, 0); mService.mWindowManager.setAppVisibility(r.appToken, true); + // schedule launch ticks to collect information about slow apps. + r.startLaunchTickingLocked(); + // Have the window manager re-evaluate the orientation of // the screen based on the new activity order. Note that // as a result of this, it can call back into the activity @@ -936,6 +959,7 @@ final class ActivityStack { // responsiveness seen by the user. Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG); msg.obj = prev; + prev.pauseTime = SystemClock.uptimeMillis(); mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT); if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete..."); } else { @@ -1480,6 +1504,9 @@ final class ActivityStack { // This activity is now becoming visible. mService.mWindowManager.setAppVisibility(next.appToken, true); + // schedule launch ticks to collect information about slow apps. + next.startLaunchTickingLocked(); + ActivityRecord lastResumedActivity = mResumedActivity; ActivityState lastState = next.state; @@ -3257,6 +3284,7 @@ final class ActivityStack { ActivityRecord r = ActivityRecord.forToken(token); if (r != null) { mHandler.removeMessages(IDLE_TIMEOUT_MSG, r); + r.finishLaunchTickingLocked(); } // Get the activity record. @@ -3627,6 +3655,7 @@ final class ActivityStack { mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r); mHandler.removeMessages(IDLE_TIMEOUT_MSG, r); mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r); + r.finishLaunchTickingLocked(); } final void removeActivityFromHistoryLocked(ActivityRecord r) { diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java index fd8d411842cb..8796afc06ae5 100644 --- a/services/java/com/android/server/net/NetworkStatsService.java +++ b/services/java/com/android/server/net/NetworkStatsService.java @@ -26,6 +26,7 @@ import static android.content.Intent.ACTION_UID_REMOVED; import static android.content.Intent.EXTRA_UID; import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE; +import static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED; import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.SET_DEFAULT; @@ -304,7 +305,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // watch for networkType changes that aren't broadcast through // CONNECTIVITY_ACTION_IMMEDIATE above. - mTeleManager.listen(mPhoneListener, LISTEN_DATA_CONNECTION_STATE); + if (!COMBINE_SUBTYPE_ENABLED) { + mTeleManager.listen(mPhoneListener, LISTEN_DATA_CONNECTION_STATE); + } registerPollAlarmLocked(); registerGlobalAlert(); @@ -325,7 +328,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mContext.unregisterReceiver(mRemovedReceiver); mContext.unregisterReceiver(mShutdownReceiver); - mTeleManager.listen(mPhoneListener, LISTEN_NONE); + if (!COMBINE_SUBTYPE_ENABLED) { + mTeleManager.listen(mPhoneListener, LISTEN_NONE); + } final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis() : System.currentTimeMillis(); diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java index 5ca09e78bb8a..67b667ad1557 100644 --- a/services/java/com/android/server/wm/AppWindowToken.java +++ b/services/java/com/android/server/wm/AppWindowToken.java @@ -240,8 +240,10 @@ class AppWindowToken extends WindowToken { animation.setStartTime(currentTime); animating = true; } - // we're done! - return stepAnimation(currentTime); + if (stepAnimation(currentTime)) { + // we're done! + return true; + } } } else if (animation != null) { // If the display is frozen, and there is a pending animation, diff --git a/services/java/com/android/server/wm/BlackFrame.java b/services/java/com/android/server/wm/BlackFrame.java index 26289c9554da..40e452a96a5e 100644 --- a/services/java/com/android/server/wm/BlackFrame.java +++ b/services/java/com/android/server/wm/BlackFrame.java @@ -157,6 +157,14 @@ public class BlackFrame { } } + public void setAlpha(float alpha) { + for (int i=0; i<mBlackSurfaces.length; i++) { + if (mBlackSurfaces[i] != null) { + mBlackSurfaces[i].surface.setAlpha(alpha); + } + } + } + public void clearMatrix() { for (int i=0; i<mBlackSurfaces.length; i++) { if (mBlackSurfaces[i] != null) { diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java index ab084f9aa48f..e460f7fd4cd8 100644 --- a/services/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java @@ -33,12 +33,15 @@ class ScreenRotationAnimation { static final String TAG = "ScreenRotationAnimation"; static final boolean DEBUG_STATE = false; static final boolean DEBUG_TRANSFORMS = false; + static final boolean USE_CUSTOM_BLACK_FRAME = false; static final int FREEZE_LAYER = WindowManagerService.TYPE_LAYER_MULTIPLIER * 200; final Context mContext; Surface mSurface; - BlackFrame mBlackFrame; + BlackFrame mCustomBlackFrame; + BlackFrame mExitingBlackFrame; + BlackFrame mEnteringBlackFrame; int mWidth, mHeight; int mSnapshotDeltaRotation; @@ -104,6 +107,7 @@ class ScreenRotationAnimation { final Matrix mFrameInitialMatrix = new Matrix(); final Matrix mSnapshotInitialMatrix = new Matrix(); final Matrix mSnapshotFinalMatrix = new Matrix(); + final Matrix mExitFrameFinalMatrix = new Matrix(); final Matrix mTmpMatrix = new Matrix(); final float[] mTmpFloats = new float[9]; private boolean mMoreRotateEnter; @@ -120,9 +124,19 @@ class ScreenRotationAnimation { pw.print(prefix); pw.print("mSurface="); pw.print(mSurface); pw.print(" mWidth="); pw.print(mWidth); pw.print(" mHeight="); pw.println(mHeight); - pw.print(prefix); pw.print("mBlackFrame="); pw.println(mBlackFrame); - if (mBlackFrame != null) { - mBlackFrame.printTo(prefix + " ", pw); + if (USE_CUSTOM_BLACK_FRAME) { + pw.print(prefix); pw.print("mCustomBlackFrame="); pw.println(mCustomBlackFrame); + if (mCustomBlackFrame != null) { + mCustomBlackFrame.printTo(prefix + " ", pw); + } + } + pw.print(prefix); pw.print("mExitingBlackFrame="); pw.println(mExitingBlackFrame); + if (mExitingBlackFrame != null) { + mExitingBlackFrame.printTo(prefix + " ", pw); + } + pw.print(prefix); pw.print("mEnteringBlackFrame="); pw.println(mEnteringBlackFrame); + if (mEnteringBlackFrame != null) { + mEnteringBlackFrame.printTo(prefix + " ", pw); } pw.print(prefix); pw.print(" mSnapshotDeltaRotation="); pw.print(mSnapshotDeltaRotation); pw.print(" mCurRotation="); pw.println(mCurRotation); @@ -164,6 +178,9 @@ class ScreenRotationAnimation { mSnapshotInitialMatrix.printShortString(pw); pw.print(" mSnapshotFinalMatrix="); mSnapshotFinalMatrix.printShortString(pw); pw.println(); + pw.print(prefix); pw.print("mExitFrameFinalMatrix="); + mExitFrameFinalMatrix.printShortString(pw); + pw.println(); } public ScreenRotationAnimation(Context context, SurfaceSession session, @@ -199,7 +216,7 @@ class ScreenRotationAnimation { mSurface = null; return; } - mSurface.setLayer(FREEZE_LAYER); + mSurface.setLayer(FREEZE_LAYER + 1); mSurface.show(); } catch (Surface.OutOfResourcesException e) { Slog.w(TAG, "Unable to allocate freeze surface", e); @@ -320,14 +337,18 @@ class ScreenRotationAnimation { com.android.internal.R.anim.screen_rotate_start_exit); mStartEnterAnimation = AnimationUtils.loadAnimation(mContext, com.android.internal.R.anim.screen_rotate_start_enter); - mStartFrameAnimation = AnimationUtils.loadAnimation(mContext, - com.android.internal.R.anim.screen_rotate_start_frame); + if (USE_CUSTOM_BLACK_FRAME) { + mStartFrameAnimation = AnimationUtils.loadAnimation(mContext, + com.android.internal.R.anim.screen_rotate_start_frame); + } mFinishExitAnimation = AnimationUtils.loadAnimation(mContext, com.android.internal.R.anim.screen_rotate_finish_exit); mFinishEnterAnimation = AnimationUtils.loadAnimation(mContext, com.android.internal.R.anim.screen_rotate_finish_enter); - mFinishFrameAnimation = AnimationUtils.loadAnimation(mContext, - com.android.internal.R.anim.screen_rotate_finish_frame); + if (USE_CUSTOM_BLACK_FRAME) { + mFinishFrameAnimation = AnimationUtils.loadAnimation(mContext, + com.android.internal.R.anim.screen_rotate_finish_frame); + } } if (DEBUG_STATE) Slog.v(TAG, "Rotation delta: " + delta + " finalWidth=" @@ -340,16 +361,20 @@ class ScreenRotationAnimation { com.android.internal.R.anim.screen_rotate_0_exit); mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext, com.android.internal.R.anim.screen_rotate_0_enter); - mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext, - com.android.internal.R.anim.screen_rotate_0_frame); + if (USE_CUSTOM_BLACK_FRAME) { + mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext, + com.android.internal.R.anim.screen_rotate_0_frame); + } break; case Surface.ROTATION_90: mRotateExitAnimation = AnimationUtils.loadAnimation(mContext, com.android.internal.R.anim.screen_rotate_plus_90_exit); mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext, com.android.internal.R.anim.screen_rotate_plus_90_enter); - mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext, - com.android.internal.R.anim.screen_rotate_plus_90_frame); + if (USE_CUSTOM_BLACK_FRAME) { + mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext, + com.android.internal.R.anim.screen_rotate_plus_90_frame); + } break; case Surface.ROTATION_180: mRotateExitAnimation = AnimationUtils.loadAnimation(mContext, @@ -364,8 +389,10 @@ class ScreenRotationAnimation { com.android.internal.R.anim.screen_rotate_minus_90_exit); mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext, com.android.internal.R.anim.screen_rotate_minus_90_enter); - mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext, - com.android.internal.R.anim.screen_rotate_minus_90_frame); + if (USE_CUSTOM_BLACK_FRAME) { + mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext, + com.android.internal.R.anim.screen_rotate_minus_90_frame); + } break; } @@ -385,18 +412,23 @@ class ScreenRotationAnimation { halfWidth, halfHeight); mStartExitAnimation.initialize(halfWidth, halfHeight, mOriginalWidth, mOriginalHeight); - mStartFrameAnimation.initialize(finalWidth, finalHeight, - mOriginalWidth, mOriginalHeight); mFinishEnterAnimation.initialize(finalWidth, finalHeight, halfWidth, halfHeight); mFinishExitAnimation.initialize(halfWidth, halfHeight, mOriginalWidth, mOriginalHeight); - mFinishFrameAnimation.initialize(finalWidth, finalHeight, - mOriginalWidth, mOriginalHeight); + if (USE_CUSTOM_BLACK_FRAME) { + mStartFrameAnimation.initialize(finalWidth, finalHeight, + mOriginalWidth, mOriginalHeight); + mFinishFrameAnimation.initialize(finalWidth, finalHeight, + mOriginalWidth, mOriginalHeight); + } } mRotateEnterAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight); mRotateExitAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight); - mRotateFrameAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight); + if (USE_CUSTOM_BLACK_FRAME) { + mRotateFrameAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, + mOriginalHeight); + } mAnimRunning = false; mFinishAnimReady = false; mFinishAnimStartTime = -1; @@ -406,23 +438,57 @@ class ScreenRotationAnimation { mStartExitAnimation.scaleCurrentDuration(animationScale); mStartEnterAnimation.restrictDuration(maxAnimationDuration); mStartEnterAnimation.scaleCurrentDuration(animationScale); - mStartFrameAnimation.restrictDuration(maxAnimationDuration); - mStartFrameAnimation.scaleCurrentDuration(animationScale); mFinishExitAnimation.restrictDuration(maxAnimationDuration); mFinishExitAnimation.scaleCurrentDuration(animationScale); mFinishEnterAnimation.restrictDuration(maxAnimationDuration); mFinishEnterAnimation.scaleCurrentDuration(animationScale); - mFinishFrameAnimation.restrictDuration(maxAnimationDuration); - mFinishFrameAnimation.scaleCurrentDuration(animationScale); + if (USE_CUSTOM_BLACK_FRAME) { + mStartFrameAnimation.restrictDuration(maxAnimationDuration); + mStartFrameAnimation.scaleCurrentDuration(animationScale); + mFinishFrameAnimation.restrictDuration(maxAnimationDuration); + mFinishFrameAnimation.scaleCurrentDuration(animationScale); + } } mRotateExitAnimation.restrictDuration(maxAnimationDuration); mRotateExitAnimation.scaleCurrentDuration(animationScale); mRotateEnterAnimation.restrictDuration(maxAnimationDuration); mRotateEnterAnimation.scaleCurrentDuration(animationScale); - mRotateFrameAnimation.restrictDuration(maxAnimationDuration); - mRotateFrameAnimation.scaleCurrentDuration(animationScale); + if (USE_CUSTOM_BLACK_FRAME) { + mRotateFrameAnimation.restrictDuration(maxAnimationDuration); + mRotateFrameAnimation.scaleCurrentDuration(animationScale); + } + + if (USE_CUSTOM_BLACK_FRAME && mCustomBlackFrame == null) { + if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i( + WindowManagerService.TAG, + ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation"); + Surface.openTransaction(); + + // Compute the transformation matrix that must be applied + // the the black frame to make it stay in the initial position + // before the new screen rotation. This is different than the + // snapshot transformation because the snapshot is always based + // of the native orientation of the screen, not the orientation + // we were last in. + createRotationMatrix(delta, mOriginalWidth, mOriginalHeight, mFrameInitialMatrix); + + try { + Rect outer = new Rect(-mOriginalWidth*1, -mOriginalHeight*1, + mOriginalWidth*2, mOriginalHeight*2); + Rect inner = new Rect(0, 0, mOriginalWidth, mOriginalHeight); + mCustomBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER + 3); + mCustomBlackFrame.setMatrix(mFrameInitialMatrix); + } catch (Surface.OutOfResourcesException e) { + Slog.w(TAG, "Unable to allocate black surface", e); + } finally { + Surface.closeTransaction(); + if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i( + WindowManagerService.TAG, + "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation"); + } + } - if (mBlackFrame == null) { + if (mExitingBlackFrame == null) { if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i( WindowManagerService.TAG, ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation"); @@ -440,8 +506,29 @@ class ScreenRotationAnimation { Rect outer = new Rect(-mOriginalWidth*1, -mOriginalHeight*1, mOriginalWidth*2, mOriginalHeight*2); Rect inner = new Rect(0, 0, mOriginalWidth, mOriginalHeight); - mBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER + 1); - mBlackFrame.setMatrix(mFrameInitialMatrix); + mExitingBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER + 2); + mExitingBlackFrame.setMatrix(mFrameInitialMatrix); + } catch (Surface.OutOfResourcesException e) { + Slog.w(TAG, "Unable to allocate black surface", e); + } finally { + Surface.closeTransaction(); + if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i( + WindowManagerService.TAG, + "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation"); + } + } + + if (false && mEnteringBlackFrame == null) { + if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i( + WindowManagerService.TAG, + ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation"); + Surface.openTransaction(); + + try { + Rect outer = new Rect(-finalWidth*1, -finalHeight*1, + finalWidth*2, finalHeight*2); + Rect inner = new Rect(0, 0, finalWidth, finalHeight); + mEnteringBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER); } catch (Surface.OutOfResourcesException e) { Slog.w(TAG, "Unable to allocate black surface", e); } finally { @@ -486,9 +573,17 @@ class ScreenRotationAnimation { mSurface.destroy(); mSurface = null; } - if (mBlackFrame != null) { - mBlackFrame.kill(); - mBlackFrame = null; + if (mCustomBlackFrame != null) { + mCustomBlackFrame.kill(); + mCustomBlackFrame = null; + } + if (mExitingBlackFrame != null) { + mExitingBlackFrame.kill(); + mExitingBlackFrame = null; + } + if (mEnteringBlackFrame != null) { + mEnteringBlackFrame.kill(); + mEnteringBlackFrame = null; } if (mStartExitAnimation != null) { mStartExitAnimation.cancel(); @@ -544,123 +639,120 @@ class ScreenRotationAnimation { mFinishAnimStartTime = now; } - // If the start animation is no longer running, we want to keep its - // transformation intact until the finish animation also completes. - mMoreStartExit = false; if (mStartExitAnimation != null) { - mStartExitTransformation.clear(); mMoreStartExit = mStartExitAnimation.getTransformation(now, mStartExitTransformation); if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start exit: " + mStartExitTransformation); - if (!mMoreStartExit) { - if (DEBUG_STATE) Slog.v(TAG, "Start exit animation done!"); - mStartExitAnimation.cancel(); - mStartExitAnimation = null; - } } mMoreStartEnter = false; if (mStartEnterAnimation != null) { - mStartEnterTransformation.clear(); mMoreStartEnter = mStartEnterAnimation.getTransformation(now, mStartEnterTransformation); if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start enter: " + mStartEnterTransformation); - if (!mMoreStartEnter) { - if (DEBUG_STATE) Slog.v(TAG, "Start enter animation done!"); - mStartEnterAnimation.cancel(); - mStartEnterAnimation = null; - } } mMoreStartFrame = false; if (mStartFrameAnimation != null) { - mStartFrameTransformation.clear(); mMoreStartFrame = mStartFrameAnimation.getTransformation(now, mStartFrameTransformation); if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start frame: " + mStartFrameTransformation); - if (!mMoreStartFrame) { - if (DEBUG_STATE) Slog.v(TAG, "Start frame animation done!"); - mStartFrameAnimation.cancel(); - mStartFrameAnimation = null; - } } long finishNow = mFinishAnimReady ? (now - mFinishAnimStartTime) : 0; if (DEBUG_STATE) Slog.v(TAG, "Step: finishNow=" + finishNow); - mFinishExitTransformation.clear(); mMoreFinishExit = false; if (mFinishExitAnimation != null) { mMoreFinishExit = mFinishExitAnimation.getTransformation(finishNow, mFinishExitTransformation); if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish exit: " + mFinishExitTransformation); - if (!mMoreStartExit && !mMoreFinishExit) { - if (DEBUG_STATE) Slog.v(TAG, "Finish exit animation done, clearing start/finish anims!"); - mStartExitTransformation.clear(); - mFinishExitAnimation.cancel(); - mFinishExitAnimation = null; - mFinishExitTransformation.clear(); - } } - mFinishEnterTransformation.clear(); mMoreFinishEnter = false; if (mFinishEnterAnimation != null) { mMoreFinishEnter = mFinishEnterAnimation.getTransformation(finishNow, mFinishEnterTransformation); if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish enter: " + mFinishEnterTransformation); - if (!mMoreStartEnter && !mMoreFinishEnter) { - if (DEBUG_STATE) Slog.v(TAG, "Finish enter animation done, clearing start/finish anims!"); - mStartEnterTransformation.clear(); - mFinishEnterAnimation.cancel(); - mFinishEnterAnimation = null; - mFinishEnterTransformation.clear(); - } } - mFinishFrameTransformation.clear(); mMoreFinishFrame = false; if (mFinishFrameAnimation != null) { mMoreFinishFrame = mFinishFrameAnimation.getTransformation(finishNow, mFinishFrameTransformation); if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish frame: " + mFinishFrameTransformation); - if (!mMoreStartFrame && !mMoreFinishFrame) { - if (DEBUG_STATE) Slog.v(TAG, "Finish frame animation done, clearing start/finish anims!"); - mStartFrameTransformation.clear(); - mFinishFrameAnimation.cancel(); - mFinishFrameAnimation = null; - mFinishFrameTransformation.clear(); - } } - mRotateExitTransformation.clear(); mMoreRotateExit = false; if (mRotateExitAnimation != null) { mMoreRotateExit = mRotateExitAnimation.getTransformation(now, mRotateExitTransformation); if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate exit: " + mRotateExitTransformation); - if (!mMoreFinishExit && !mMoreRotateExit) { - if (DEBUG_STATE) Slog.v(TAG, "Rotate exit animation done!"); - mRotateExitAnimation.cancel(); - mRotateExitAnimation = null; - mRotateExitTransformation.clear(); - } } - mRotateEnterTransformation.clear(); mMoreRotateEnter = false; if (mRotateEnterAnimation != null) { mMoreRotateEnter = mRotateEnterAnimation.getTransformation(now, mRotateEnterTransformation); if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate enter: " + mRotateEnterTransformation); - if (!mMoreFinishEnter && !mMoreRotateEnter) { - if (DEBUG_STATE) Slog.v(TAG, "Rotate enter animation done!"); - mRotateEnterAnimation.cancel(); - mRotateEnterAnimation = null; - mRotateEnterTransformation.clear(); - } } - mRotateFrameTransformation.clear(); mMoreRotateFrame = false; if (mRotateFrameAnimation != null) { mMoreRotateFrame = mRotateFrameAnimation.getTransformation(now, mRotateFrameTransformation); if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate frame: " + mRotateFrameTransformation); - if (!mMoreFinishFrame && !mMoreRotateFrame) { - if (DEBUG_STATE) Slog.v(TAG, "Rotate frame animation done!"); + } + + if (!mMoreStartExit && !mMoreRotateExit && !mMoreFinishExit) { + if (mStartExitAnimation != null) { + if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, clearing start exit anim!"); + mStartExitAnimation.cancel(); + mStartExitAnimation = null; + mStartExitTransformation.clear(); + } + if (mFinishExitAnimation != null) { + if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, clearing finish exit anim!"); + mFinishExitAnimation.cancel(); + mFinishExitAnimation = null; + mFinishExitTransformation.clear(); + } + if (mRotateExitAnimation != null) { + if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, clearing rotate exit anim!"); + mRotateExitAnimation.cancel(); + mRotateExitAnimation = null; + mRotateExitTransformation.clear(); + } + } + + if (!mMoreStartEnter && !mMoreRotateEnter && !mMoreFinishEnter) { + if (mStartEnterAnimation != null) { + if (DEBUG_STATE) Slog.v(TAG, "Enter animations done, clearing start enter anim!"); + mStartEnterAnimation.cancel(); + mStartEnterAnimation = null; + mStartEnterTransformation.clear(); + } + if (mFinishEnterAnimation != null) { + if (DEBUG_STATE) Slog.v(TAG, "Enter animations done, clearing finish enter anim!"); + mFinishEnterAnimation.cancel(); + mFinishEnterAnimation = null; + mFinishEnterTransformation.clear(); + } + if (mRotateEnterAnimation != null) { + if (DEBUG_STATE) Slog.v(TAG, "Enter animations done, clearing rotate enter anim!"); + mRotateEnterAnimation.cancel(); + mRotateEnterAnimation = null; + mRotateEnterTransformation.clear(); + } + } + + if (USE_CUSTOM_BLACK_FRAME && !mMoreStartFrame && !mMoreRotateFrame && !mMoreFinishFrame) { + if (mStartFrameAnimation != null) { + if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, clearing start frame anim!"); + mStartFrameAnimation.cancel(); + mStartFrameAnimation = null; + mStartFrameTransformation.clear(); + } + if (mFinishFrameAnimation != null) { + if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, clearing finish frame anim!"); + mFinishFrameAnimation.cancel(); + mFinishFrameAnimation = null; + mFinishFrameTransformation.clear(); + } + if (mRotateFrameAnimation != null) { + if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, clearing rotate frame anim!"); mRotateFrameAnimation.cancel(); mRotateFrameAnimation = null; mRotateFrameTransformation.clear(); @@ -675,17 +767,19 @@ class ScreenRotationAnimation { mEnterTransformation.compose(mStartEnterTransformation); mEnterTransformation.compose(mFinishEnterTransformation); - //mFrameTransformation.set(mRotateExitTransformation); - //mFrameTransformation.compose(mStartExitTransformation); - //mFrameTransformation.compose(mFinishExitTransformation); - mFrameTransformation.set(mRotateFrameTransformation); - mFrameTransformation.compose(mStartFrameTransformation); - mFrameTransformation.compose(mFinishFrameTransformation); - mFrameTransformation.getMatrix().preConcat(mFrameInitialMatrix); - if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final exit: " + mExitTransformation); if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final enter: " + mEnterTransformation); - if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final frame: " + mFrameTransformation); + + if (USE_CUSTOM_BLACK_FRAME) { + //mFrameTransformation.set(mRotateExitTransformation); + //mFrameTransformation.compose(mStartExitTransformation); + //mFrameTransformation.compose(mFinishExitTransformation); + mFrameTransformation.set(mRotateFrameTransformation); + mFrameTransformation.compose(mStartFrameTransformation); + mFrameTransformation.compose(mFinishFrameTransformation); + mFrameTransformation.getMatrix().preConcat(mFrameInitialMatrix); + if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final frame: " + mFrameTransformation); + } final boolean more = mMoreStartEnter || mMoreStartExit || mMoreStartFrame || mMoreFinishEnter || mMoreFinishExit || mMoreFinishFrame @@ -707,12 +801,32 @@ class ScreenRotationAnimation { } } - if (mBlackFrame != null) { + if (mCustomBlackFrame != null) { if (!mMoreStartFrame && !mMoreFinishFrame && !mMoreRotateFrame) { if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding black frame"); - mBlackFrame.hide(); + mCustomBlackFrame.hide(); + } else { + mCustomBlackFrame.setMatrix(mFrameTransformation.getMatrix()); + } + } + + if (mExitingBlackFrame != null) { + if (!mMoreStartExit && !mMoreFinishExit && !mMoreRotateExit) { + if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding exiting frame"); + mExitingBlackFrame.hide(); + } else { + mExitFrameFinalMatrix.setConcat(mExitTransformation.getMatrix(), mFrameInitialMatrix); + mExitingBlackFrame.setMatrix(mExitFrameFinalMatrix); + mExitingBlackFrame.setAlpha(mExitTransformation.getAlpha()); + } + } + + if (mEnteringBlackFrame != null) { + if (!mMoreStartEnter && !mMoreFinishEnter && !mMoreRotateEnter) { + if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding entering frame"); + mEnteringBlackFrame.hide(); } else { - mBlackFrame.setMatrix(mFrameTransformation.getMatrix()); + mEnteringBlackFrame.setMatrix(mEnterTransformation.getMatrix()); } } diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index f4c4069e3c33..69936577e57b 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -7688,9 +7688,9 @@ public class WindowManagerService extends IWindowManager.Stub Surface.openTransaction(); try { + updateWindowsAppsAndRotationAnimationsLocked(currentTime, innerDw, innerDh); mPendingLayoutChanges = performAnimationsLocked(currentTime, dw, dh, innerDw, innerDh); - updateWindowsAppsAndRotationAnimationsLocked(currentTime, innerDw, innerDh); // THIRD LOOP: Update the surfaces of all windows. diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java index 42ce291801cd..57d03741309a 100644 --- a/services/java/com/android/server/wm/WindowState.java +++ b/services/java/com/android/server/wm/WindowState.java @@ -305,11 +305,6 @@ final class WindowState implements WindowManagerPolicy.WindowState { int mAnimDw; int mAnimDh; - static final int ANIM_STATE_IDLE = 0; - static final int ANIM_STATE_RUNNING = 1; - static final int ANIM_STATE_STOPPING = 2; - int mAnimState = ANIM_STATE_IDLE; - WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token, WindowState attachedWindow, int seq, WindowManager.LayoutParams a, int viewVisibility) { @@ -653,7 +648,6 @@ final class WindowState implements WindowManagerPolicy.WindowState { mLocalAnimating = false; mAnimation.cancel(); mAnimation = null; - mAnimState = ANIM_STATE_IDLE; } } @@ -665,7 +659,6 @@ final class WindowState implements WindowManagerPolicy.WindowState { mAnimation.cancel(); mAnimation = null; destroySurfaceLocked(); - mAnimState = ANIM_STATE_IDLE; } mExiting = false; } @@ -971,7 +964,8 @@ final class WindowState implements WindowManagerPolicy.WindowState { mAppToken.firstWindowDrawn = true; if (mAppToken.startingData != null) { - if (WindowManagerService.DEBUG_STARTING_WINDOW || WindowManagerService.DEBUG_ANIM) Slog.v(WindowManagerService.TAG, + if (WindowManagerService.DEBUG_STARTING_WINDOW || + WindowManagerService.DEBUG_ANIM) Slog.v(WindowManagerService.TAG, "Finish starting " + mToken + ": first real window is shown, no animation"); // If this initial window is animating, stop it -- we @@ -983,7 +977,6 @@ final class WindowState implements WindowManagerPolicy.WindowState { mAnimation = null; // Make sure we clean up the animation. mAnimating = true; - mAnimState = ANIM_STATE_IDLE; } mService.mFinishedStarting.add(mAppToken); mService.mH.sendEmptyMessage(H.FINISHED_STARTING); @@ -995,7 +988,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { } private boolean stepAnimation(long currentTime) { - if ((mAnimation == null) || !mLocalAnimating || (mAnimState != ANIM_STATE_RUNNING)) { + if ((mAnimation == null) || !mLocalAnimating) { return false; } mTransformation.clear(); @@ -1003,9 +996,6 @@ final class WindowState implements WindowManagerPolicy.WindowState { if (WindowManagerService.DEBUG_ANIM) Slog.v( WindowManagerService.TAG, "Stepped animation in " + this + ": more=" + more + ", xform=" + mTransformation); - if (!more) { - mAnimState = ANIM_STATE_STOPPING; - } return more; } @@ -1032,11 +1022,11 @@ final class WindowState implements WindowManagerPolicy.WindowState { mAnimation.setStartTime(currentTime); mLocalAnimating = true; mAnimating = true; - mAnimState = ANIM_STATE_RUNNING; } - if ((mAnimation != null) && mLocalAnimating && - (mAnimState != ANIM_STATE_STOPPING)) { - return stepAnimation(currentTime); + if ((mAnimation != null) && mLocalAnimating) { + if (stepAnimation(currentTime)) { + return true; + } } if (WindowManagerService.DEBUG_ANIM) Slog.v( WindowManagerService.TAG, "Finished animation in " + this + @@ -1137,7 +1127,6 @@ final class WindowState implements WindowManagerPolicy.WindowState { mAppToken.updateReportedVisibilityLocked(); } - mAnimState = ANIM_STATE_IDLE; return false; } diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java b/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java index 7b672da0c45e..879445297ed4 100644 --- a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java +++ b/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java @@ -120,10 +120,8 @@ public final class BridgeResources extends Resources { mProjectCallback = projectCallback; } - public BridgeTypedArray newTypeArray(int numEntries, boolean platformFile, - boolean platformStyleable, String styleableName) { - return new BridgeTypedArray(this, mContext, numEntries, platformFile, - platformStyleable, styleableName); + public BridgeTypedArray newTypeArray(int numEntries, boolean platformFile) { + return new BridgeTypedArray(this, mContext, numEntries, platformFile); } private Pair<String, ResourceValue> getResourceValue(int id, boolean[] platformResFlag_out) { diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java index 8fdac02738ab..cbc199adece4 100644 --- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java +++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java @@ -16,7 +16,7 @@ package android.content.res; -import com.android.ide.common.rendering.api.DeclareStyleableResourceValue; +import com.android.ide.common.rendering.api.AttrResourceValue; import com.android.ide.common.rendering.api.LayoutLog; import com.android.ide.common.rendering.api.RenderResources; import com.android.ide.common.rendering.api.ResourceValue; @@ -51,28 +51,33 @@ public final class BridgeTypedArray extends TypedArray { private final BridgeResources mBridgeResources; private final BridgeContext mContext; private final boolean mPlatformFile; - private final boolean mPlatformStyleable; - private final String mStyleableName; private ResourceValue[] mResourceData; private String[] mNames; + private boolean[] mIsFramework; public BridgeTypedArray(BridgeResources resources, BridgeContext context, int len, - boolean platformFile, boolean platformStyleable, String styleableName) { + boolean platformFile) { super(null, null, null, 0); mBridgeResources = resources; mContext = context; mPlatformFile = platformFile; - mPlatformStyleable = platformStyleable; - mStyleableName = styleableName; mResourceData = new ResourceValue[len]; mNames = new String[len]; + mIsFramework = new boolean[len]; } - /** A bridge-specific method that sets a value in the type array */ - public void bridgeSetValue(int index, String name, ResourceValue value) { + /** + * A bridge-specific method that sets a value in the type array + * @param index the index of the value in the TypedArray + * @param name the name of the attribute + * @param isFramework whether the attribute is in the android namespace. + * @param value the value of the attribute + */ + public void bridgeSetValue(int index, String name, boolean isFramework, ResourceValue value) { mResourceData[index] = value; mNames[index] = name; + mIsFramework[index] = isFramework; } /** @@ -213,8 +218,12 @@ public final class BridgeTypedArray extends TypedArray { return defValue; } + if (s == null) { + return defValue; + } + try { - return (s == null) ? defValue : XmlUtils.convertValueToInt(s, defValue); + return XmlUtils.convertValueToInt(s, defValue); } catch (NumberFormatException e) { // pass } @@ -223,15 +232,14 @@ public final class BridgeTypedArray extends TypedArray { // Check for possible constants and try to find them. // Get the map of attribute-constant -> IntegerValue Map<String, Integer> map = null; - if (mPlatformStyleable) { + if (mIsFramework[index]) { map = Bridge.getEnumValues(mNames[index]); - } else if (mStyleableName != null) { + } else { // get the styleable matching the resolved name RenderResources res = mContext.getRenderResources(); - ResourceValue styleable = res.getProjectResource(ResourceType.DECLARE_STYLEABLE, - mStyleableName); - if (styleable instanceof DeclareStyleableResourceValue) { - map = ((DeclareStyleableResourceValue) styleable).getAttributeValues(mNames[index]); + ResourceValue attr = res.getProjectResource(ResourceType.ATTR, mNames[index]); + if (attr instanceof AttrResourceValue) { + map = ((AttrResourceValue) attr).getAttributeValues(); } } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java index 529be97c17eb..f9f4b3a86b3e 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java @@ -70,13 +70,13 @@ public class BridgeRenderSession extends RenderSession { @Override public Result getProperty(Object objectView, String propertyName) { - // TODO Auto-generated method stub + // pass return super.getProperty(objectView, propertyName); } @Override public Result setProperty(Object objectView, String propertyName, String propertyValue) { - // TODO Auto-generated method stub + // pass return super.setProperty(objectView, propertyName, propertyValue); } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java index 1555d6124951..f9e48e2b8a68 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java @@ -76,13 +76,11 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; import java.util.HashMap; import java.util.IdentityHashMap; +import java.util.List; import java.util.Map; -import java.util.Map.Entry; -import java.util.TreeMap; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; /** * Custom implementation of Context/Activity to handle non compiled resources. @@ -247,15 +245,18 @@ public final class BridgeContext extends Context { public boolean resolveThemeAttribute(int resid, TypedValue outValue, boolean resolveRefs) { Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(resid); + boolean isFrameworkRes = true; if (resourceInfo == null) { resourceInfo = mProjectCallback.resolveResourceId(resid); + isFrameworkRes = false; } if (resourceInfo == null) { return false; } - ResourceValue value = mRenderResources.findItemInTheme(resourceInfo.getSecond()); + ResourceValue value = mRenderResources.findItemInTheme(resourceInfo.getSecond(), + isFrameworkRes); if (resolveRefs) { value = mRenderResources.resolveResValue(value); } @@ -315,12 +316,7 @@ public final class BridgeContext extends Context { if (isPlatformLayout == false && skipCallbackParser == false) { // check if the project callback can provide us with a custom parser. - ILayoutPullParser parser; - if (resource instanceof ResourceValue) { - parser = mProjectCallback.getParser((ResourceValue) resource); - } else { - parser = mProjectCallback.getParser(resource.getName()); - } + ILayoutPullParser parser = getParser(resource); if (parser != null) { BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(parser, @@ -393,6 +389,17 @@ public final class BridgeContext extends Context { return Pair.of(null, false); } + @SuppressWarnings("deprecation") + private ILayoutPullParser getParser(ResourceReference resource) { + ILayoutPullParser parser; + if (resource instanceof ResourceValue) { + parser = mProjectCallback.getParser((ResourceValue) resource); + } else { + parser = mProjectCallback.getParser(resource.getName()); + } + return parser; + } + // ------------ Context methods @Override @@ -524,12 +531,10 @@ public final class BridgeContext extends Context { return null; } - AtomicBoolean frameworkAttributes = new AtomicBoolean(); - AtomicReference<String> attrName = new AtomicReference<String>(); - TreeMap<Integer, String> styleNameMap = searchAttrs(attrs, frameworkAttributes, attrName); + List<Pair<String, Boolean>> attributeList = searchAttrs(attrs); BridgeTypedArray ta = ((BridgeResources) mSystemResources).newTypeArray(attrs.length, - isPlatformFile, frameworkAttributes.get(), attrName.get()); + isPlatformFile); // look for a custom style. String customStyle = null; @@ -555,14 +560,19 @@ public final class BridgeContext extends Context { if (defStyleAttr != 0) { // get the name from the int. - String defStyleName = searchAttr(defStyleAttr); + Pair<String, Boolean> defStyleAttribute = searchAttr(defStyleAttr); if (defaultPropMap != null) { + String defStyleName = defStyleAttribute.getFirst(); + if (defStyleAttribute.getSecond()) { + defStyleName = "android:" + defStyleName; + } defaultPropMap.put("style", defStyleName); } // look for the style in the current theme, and its parent: - ResourceValue item = mRenderResources.findItemInTheme(defStyleName); + ResourceValue item = mRenderResources.findItemInTheme(defStyleAttribute.getFirst(), + defStyleAttribute.getSecond()); if (item != null) { // item is a reference to a style entry. Search for it. @@ -575,19 +585,23 @@ public final class BridgeContext extends Context { } else { Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR, String.format( - "Failed to find style '%s' in current theme", defStyleName), + "Failed to find style '%s' in current theme", + defStyleAttribute.getFirst()), null /*data*/); } } else if (defStyleRes != 0) { + boolean isFrameworkRes = true; Pair<ResourceType, String> value = Bridge.resolveResourceId(defStyleRes); if (value == null) { value = mProjectCallback.resolveResourceId(defStyleRes); + isFrameworkRes = false; } if (value != null) { if (value.getFirst() == ResourceType.STYLE) { // look for the style in the current theme, and its parent: - ResourceValue item = mRenderResources.findItemInTheme(value.getSecond()); + ResourceValue item = mRenderResources.findItemInTheme(value.getSecond(), + isFrameworkRes); if (item != null) { if (item instanceof StyleResourceValue) { if (defaultPropMap != null) { @@ -619,26 +633,28 @@ public final class BridgeContext extends Context { } } - String namespace = BridgeConstants.NS_RESOURCES; - boolean useFrameworkNS = frameworkAttributes.get(); - if (useFrameworkNS == false) { - // need to use the application namespace - namespace = mProjectCallback.getNamespace(); - } + String appNamespace = mProjectCallback.getNamespace(); - if (styleNameMap != null) { - for (Entry<Integer, String> styleAttribute : styleNameMap.entrySet()) { - int index = styleAttribute.getKey().intValue(); + if (attributeList != null) { + for (int index = 0 ; index < attributeList.size() ; index++) { + Pair<String, Boolean> attribute = attributeList.get(index); - String name = styleAttribute.getValue(); + if (attribute == null) { + continue; + } + + String attrName = attribute.getFirst(); + boolean frameworkAttr = attribute.getSecond().booleanValue(); String value = null; if (set != null) { - value = set.getAttributeValue(namespace, name); + value = set.getAttributeValue( + frameworkAttr ? BridgeConstants.NS_RESOURCES : appNamespace, + attrName); // if this is an app attribute, and the first get fails, try with the // new res-auto namespace as well - if (useFrameworkNS == false && value == null) { - value = set.getAttributeValue(BridgeConstants.NS_APP_RES_AUTO, name); + if (frameworkAttr == false && value == null) { + value = set.getAttributeValue(BridgeConstants.NS_APP_RES_AUTO, attrName); } } @@ -649,18 +665,20 @@ public final class BridgeContext extends Context { // look for the value in the custom style first (and its parent if needed) if (customStyleValues != null) { - resValue = mRenderResources.findItemInStyle(customStyleValues, name); + resValue = mRenderResources.findItemInStyle(customStyleValues, + attrName, frameworkAttr); } // then look for the value in the default Style (and its parent if needed) if (resValue == null && defStyleValues != null) { - resValue = mRenderResources.findItemInStyle(defStyleValues, name); + resValue = mRenderResources.findItemInStyle(defStyleValues, + attrName, frameworkAttr); } // if the item is not present in the defStyle, we look in the main theme (and // its parent themes) if (resValue == null) { - resValue = mRenderResources.findItemInTheme(name); + resValue = mRenderResources.findItemInTheme(attrName, frameworkAttr); } // if we found a value, we make sure this doesn't reference another value. @@ -668,18 +686,18 @@ public final class BridgeContext extends Context { if (resValue != null) { // put the first default value, before the resolution. if (defaultPropMap != null) { - defaultPropMap.put(name, resValue.getValue()); + defaultPropMap.put(attrName, resValue.getValue()); } resValue = mRenderResources.resolveResValue(resValue); } - ta.bridgeSetValue(index, name, resValue); + ta.bridgeSetValue(index, attrName, frameworkAttr, resValue); } else { // there is a value in the XML, but we need to resolve it in case it's // referencing another resource or a theme value. - ta.bridgeSetValue(index, name, - mRenderResources.resolveValue(null, name, value, isPlatformFile)); + ta.bridgeSetValue(index, attrName, frameworkAttr, + mRenderResources.resolveValue(null, attrName, value, isPlatformFile)); } } } @@ -705,23 +723,23 @@ public final class BridgeContext extends Context { private BridgeTypedArray createStyleBasedTypedArray(StyleResourceValue style, int[] attrs) throws Resources.NotFoundException { + List<Pair<String, Boolean>> attributes = searchAttrs(attrs); + BridgeTypedArray ta = ((BridgeResources) mSystemResources).newTypeArray(attrs.length, - false, true, null); + false); // for each attribute, get its name so that we can search it in the style for (int i = 0 ; i < attrs.length ; i++) { - Pair<ResourceType, String> resolvedResource = Bridge.resolveResourceId(attrs[i]); - if (resolvedResource != null) { - String attrName = resolvedResource.getSecond(); - // look for the value in the given style - ResourceValue resValue = mRenderResources.findItemInStyle(style, attrName); + Pair<String, Boolean> attribute = attributes.get(i); - if (resValue != null) { - // resolve it to make sure there are no references left. - ta.bridgeSetValue(i, attrName, mRenderResources.resolveResValue(resValue)); + // look for the value in the given style + ResourceValue resValue = mRenderResources.findItemInStyle(style, attribute.getFirst(), + attribute.getSecond()); - resValue = mRenderResources.resolveResValue(resValue); - } + if (resValue != null) { + // resolve it to make sure there are no references left. + ta.bridgeSetValue(i, attribute.getFirst(), attribute.getSecond(), + mRenderResources.resolveResValue(resValue)); } } @@ -732,91 +750,52 @@ public final class BridgeContext extends Context { /** - * The input int[] attrs is one of com.android.internal.R.styleable fields where the name - * of the field is the style being referenced and the array contains one index per attribute. + * The input int[] attrs is a list of attributes. The returns a list of information about + * each attributes. The information is (name, isFramework) * <p/> - * searchAttrs() finds all the names of the attributes referenced so for example if - * attrs == com.android.internal.R.styleable.View, this returns the list of the "xyz" where - * there's a field com.android.internal.R.styleable.View_xyz and the field value is the index - * that is used to reference the attribute later in the TypedArray. * * @param attrs An attribute array reference given to obtainStyledAttributes. - * @param outFrameworkFlag out value indicating if the attr array is a framework value - * @param outAttrName out value for the resolved attr name. - * @return A sorted map Attribute-Value to Attribute-Name for all attributes declared by the - * attribute array. Returns null if nothing is found. + * @return List of attribute information. */ - private TreeMap<Integer,String> searchAttrs(int[] attrs, AtomicBoolean outFrameworkFlag, - AtomicReference<String> outAttrName) { - // get the name of the array from the framework resources - String arrayName = Bridge.resolveResourceId(attrs); - if (arrayName != null) { - // if we found it, get the name of each of the int in the array. - TreeMap<Integer,String> attributes = new TreeMap<Integer, String>(); - for (int i = 0 ; i < attrs.length ; i++) { - Pair<ResourceType, String> info = Bridge.resolveResourceId(attrs[i]); - if (info != null) { - attributes.put(i, info.getSecond()); - } else { - // FIXME Not sure what we should be doing here... - attributes.put(i, null); - } - } + private List<Pair<String, Boolean>> searchAttrs(int[] attrs) { + List<Pair<String, Boolean>> results = new ArrayList<Pair<String, Boolean>>(attrs.length); - if (outFrameworkFlag != null) { - outFrameworkFlag.set(true); - } - if (outAttrName != null) { - outAttrName.set(arrayName); - } - - return attributes; - } - - // if the name was not found in the framework resources, look in the project - // resources - arrayName = mProjectCallback.resolveResourceId(attrs); - if (arrayName != null) { - TreeMap<Integer,String> attributes = new TreeMap<Integer, String>(); - for (int i = 0 ; i < attrs.length ; i++) { - Pair<ResourceType, String> info = mProjectCallback.resolveResourceId(attrs[i]); - if (info != null) { - attributes.put(i, info.getSecond()); - } else { - // FIXME Not sure what we should be doing here... - attributes.put(i, null); - } + // for each attribute, get its name so that we can search it in the style + for (int i = 0 ; i < attrs.length ; i++) { + Pair<ResourceType, String> resolvedResource = Bridge.resolveResourceId(attrs[i]); + boolean isFramework = false; + if (resolvedResource != null) { + isFramework = true; + } else { + resolvedResource = mProjectCallback.resolveResourceId(attrs[i]); } - if (outFrameworkFlag != null) { - outFrameworkFlag.set(false); - } - if (outAttrName != null) { - outAttrName.set(arrayName); + if (resolvedResource != null) { + results.add(Pair.of(resolvedResource.getSecond(), isFramework)); + } else { + results.add(null); } - - return attributes; } - return null; + return results; } /** * Searches for the attribute referenced by its internal id. * * @param attr An attribute reference given to obtainStyledAttributes such as defStyle. - * @return The unique name of the attribute, if found, e.g. "buttonStyle". Returns null + * @return A (name, isFramework) pair describing the attribute if found. Returns null * if nothing is found. */ - public String searchAttr(int attr) { + public Pair<String, Boolean> searchAttr(int attr) { Pair<ResourceType, String> info = Bridge.resolveResourceId(attr); if (info != null) { - return info.getSecond(); + return Pair.of(info.getSecond(), Boolean.TRUE); } info = mProjectCallback.resolveResourceId(attr); if (info != null) { - return info.getSecond(); + return Pair.of(info.getSecond(), Boolean.FALSE); } return null; @@ -876,149 +855,149 @@ public final class BridgeContext extends Context { @Override public boolean bindService(Intent arg0, ServiceConnection arg1, int arg2) { - // TODO Auto-generated method stub + // pass return false; } @Override public int checkCallingOrSelfPermission(String arg0) { - // TODO Auto-generated method stub + // pass return 0; } @Override public int checkCallingOrSelfUriPermission(Uri arg0, int arg1) { - // TODO Auto-generated method stub + // pass return 0; } @Override public int checkCallingPermission(String arg0) { - // TODO Auto-generated method stub + // pass return 0; } @Override public int checkCallingUriPermission(Uri arg0, int arg1) { - // TODO Auto-generated method stub + // pass return 0; } @Override public int checkPermission(String arg0, int arg1, int arg2) { - // TODO Auto-generated method stub + // pass return 0; } @Override public int checkUriPermission(Uri arg0, int arg1, int arg2, int arg3) { - // TODO Auto-generated method stub + // pass return 0; } @Override public int checkUriPermission(Uri arg0, String arg1, String arg2, int arg3, int arg4, int arg5) { - // TODO Auto-generated method stub + // pass return 0; } @Override public void clearWallpaper() { - // TODO Auto-generated method stub + // pass } @Override public Context createPackageContext(String arg0, int arg1) { - // TODO Auto-generated method stub + // pass return null; } @Override public String[] databaseList() { - // TODO Auto-generated method stub + // pass return null; } @Override public boolean deleteDatabase(String arg0) { - // TODO Auto-generated method stub + // pass return false; } @Override public boolean deleteFile(String arg0) { - // TODO Auto-generated method stub + // pass return false; } @Override public void enforceCallingOrSelfPermission(String arg0, String arg1) { - // TODO Auto-generated method stub + // pass } @Override public void enforceCallingOrSelfUriPermission(Uri arg0, int arg1, String arg2) { - // TODO Auto-generated method stub + // pass } @Override public void enforceCallingPermission(String arg0, String arg1) { - // TODO Auto-generated method stub + // pass } @Override public void enforceCallingUriPermission(Uri arg0, int arg1, String arg2) { - // TODO Auto-generated method stub + // pass } @Override public void enforcePermission(String arg0, int arg1, int arg2, String arg3) { - // TODO Auto-generated method stub + // pass } @Override public void enforceUriPermission(Uri arg0, int arg1, int arg2, int arg3, String arg4) { - // TODO Auto-generated method stub + // pass } @Override public void enforceUriPermission(Uri arg0, String arg1, String arg2, int arg3, int arg4, int arg5, String arg6) { - // TODO Auto-generated method stub + // pass } @Override public String[] fileList() { - // TODO Auto-generated method stub + // pass return null; } @Override public AssetManager getAssets() { - // TODO Auto-generated method stub + // pass return null; } @Override public File getCacheDir() { - // TODO Auto-generated method stub + // pass return null; } @Override public File getExternalCacheDir() { - // TODO Auto-generated method stub + // pass return null; } @@ -1032,49 +1011,49 @@ public final class BridgeContext extends Context { @Override public File getDatabasePath(String arg0) { - // TODO Auto-generated method stub + // pass return null; } @Override public File getDir(String arg0, int arg1) { - // TODO Auto-generated method stub + // pass return null; } @Override public File getFileStreamPath(String arg0) { - // TODO Auto-generated method stub + // pass return null; } @Override public File getFilesDir() { - // TODO Auto-generated method stub + // pass return null; } @Override public File getExternalFilesDir(String type) { - // TODO Auto-generated method stub + // pass return null; } @Override public String getPackageCodePath() { - // TODO Auto-generated method stub + // pass return null; } @Override public PackageManager getPackageManager() { - // TODO Auto-generated method stub + // pass return null; } @Override public String getPackageName() { - // TODO Auto-generated method stub + // pass return null; } @@ -1085,25 +1064,25 @@ public final class BridgeContext extends Context { @Override public String getPackageResourcePath() { - // TODO Auto-generated method stub + // pass return null; } @Override public File getSharedPrefsFile(String name) { - // TODO Auto-generated method stub + // pass return null; } @Override public SharedPreferences getSharedPreferences(String arg0, int arg1) { - // TODO Auto-generated method stub + // pass return null; } @Override public Drawable getWallpaper() { - // TODO Auto-generated method stub + // pass return null; } @@ -1119,81 +1098,81 @@ public final class BridgeContext extends Context { @Override public void grantUriPermission(String arg0, Uri arg1, int arg2) { - // TODO Auto-generated method stub + // pass } @Override public FileInputStream openFileInput(String arg0) throws FileNotFoundException { - // TODO Auto-generated method stub + // pass return null; } @Override public FileOutputStream openFileOutput(String arg0, int arg1) throws FileNotFoundException { - // TODO Auto-generated method stub + // pass return null; } @Override public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1, CursorFactory arg2) { - // TODO Auto-generated method stub + // pass return null; } @Override public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1, CursorFactory arg2, DatabaseErrorHandler arg3) { - // TODO Auto-generated method stub + // pass return null; } @Override public Drawable peekWallpaper() { - // TODO Auto-generated method stub + // pass return null; } @Override public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1) { - // TODO Auto-generated method stub + // pass return null; } @Override public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, String arg2, Handler arg3) { - // TODO Auto-generated method stub + // pass return null; } @Override public void removeStickyBroadcast(Intent arg0) { - // TODO Auto-generated method stub + // pass } @Override public void revokeUriPermission(Uri arg0, int arg1) { - // TODO Auto-generated method stub + // pass } @Override public void sendBroadcast(Intent arg0) { - // TODO Auto-generated method stub + // pass } @Override public void sendBroadcast(Intent arg0, String arg1) { - // TODO Auto-generated method stub + // pass } @Override public void sendOrderedBroadcast(Intent arg0, String arg1) { - // TODO Auto-generated method stub + // pass } @@ -1201,13 +1180,13 @@ public final class BridgeContext extends Context { public void sendOrderedBroadcast(Intent arg0, String arg1, BroadcastReceiver arg2, Handler arg3, int arg4, String arg5, Bundle arg6) { - // TODO Auto-generated method stub + // pass } @Override public void sendStickyBroadcast(Intent arg0) { - // TODO Auto-generated method stub + // pass } @@ -1215,79 +1194,79 @@ public final class BridgeContext extends Context { public void sendStickyOrderedBroadcast(Intent intent, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { - // TODO Auto-generated method stub + // pass } @Override public void setTheme(int arg0) { - // TODO Auto-generated method stub + // pass } @Override public void setWallpaper(Bitmap arg0) throws IOException { - // TODO Auto-generated method stub + // pass } @Override public void setWallpaper(InputStream arg0) throws IOException { - // TODO Auto-generated method stub + // pass } @Override public void startActivity(Intent arg0) { - // TODO Auto-generated method stub + // pass } @Override public void startActivity(Intent arg0, Bundle arg1) { - // TODO Auto-generated method stub + // pass } @Override public void startIntentSender(IntentSender intent, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags) throws IntentSender.SendIntentException { - // TODO Auto-generated method stub + // pass } @Override public void startIntentSender(IntentSender intent, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, Bundle options) throws IntentSender.SendIntentException { - // TODO Auto-generated method stub + // pass } @Override public boolean startInstrumentation(ComponentName arg0, String arg1, Bundle arg2) { - // TODO Auto-generated method stub + // pass return false; } @Override public ComponentName startService(Intent arg0) { - // TODO Auto-generated method stub + // pass return null; } @Override public boolean stopService(Intent arg0) { - // TODO Auto-generated method stub + // pass return false; } @Override public void unbindService(ServiceConnection arg0) { - // TODO Auto-generated method stub + // pass } @Override public void unregisterReceiver(BroadcastReceiver arg0) { - // TODO Auto-generated method stub + // pass } @@ -1298,13 +1277,13 @@ public final class BridgeContext extends Context { @Override public void startActivities(Intent[] arg0) { - // TODO Auto-generated method stub + // pass } @Override public void startActivities(Intent[] arg0, Bundle arg1) { - // TODO Auto-generated method stub + // pass } |