diff options
67 files changed, 852 insertions, 3644 deletions
diff --git a/api/current.txt b/api/current.txt index 712b342..86339f2 100644 --- a/api/current.txt +++ b/api/current.txt @@ -16019,6 +16019,8 @@ package android.provider { } protected static abstract interface ContactsContract.GroupsColumns { + field public static final java.lang.String ACTION = "action"; + field public static final java.lang.String ACTION_URI = "action_uri"; field public static final java.lang.String AUTO_ADD = "auto_add"; field public static final java.lang.String DATA_SET = "data_set"; field public static final java.lang.String DELETED = "deleted"; @@ -26097,7 +26099,7 @@ package android.widget { ctor public ShareActionProvider(android.content.Context); method public android.view.View onCreateActionView(); method public void setShareHistoryFileName(java.lang.String); - method public void setShareIntent(android.view.View, android.content.Intent); + method public void setShareIntent(android.content.Intent); field public static final java.lang.String DEFAULT_SHARE_HISTORY_FILE_NAME = "share_history.xml"; } diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java index dce0a97..436fdf8 100644 --- a/core/java/android/app/backup/BackupAgent.java +++ b/core/java/android/app/backup/BackupAgent.java @@ -28,6 +28,7 @@ import android.os.RemoteException; import android.util.Log; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.util.HashSet; import java.util.LinkedList; @@ -533,6 +534,16 @@ public abstract class BackupAgent extends ContextWrapper { Log.d(TAG, "onBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex); throw ex; } finally { + // Send the EOD marker indicating that there is no more data + // forthcoming from this agent. + try { + FileOutputStream out = new FileOutputStream(data.getFileDescriptor()); + byte[] buf = new byte[4]; + out.write(buf); + } catch (IOException e) { + Log.e(TAG, "Unable to finalize backup stream!"); + } + Binder.restoreCallingIdentity(ident); try { callbackBinder.opComplete(token); diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java index 60900e1..2c4b863 100644 --- a/core/java/android/os/storage/StorageVolume.java +++ b/core/java/android/os/storage/StorageVolume.java @@ -172,7 +172,10 @@ public class StorageVolume implements Parcelable { @Override public String toString() { - return mPath; + return "StorageVolume [mAllowMassStorage=" + mAllowMassStorage + ", mDescription=" + + mDescription + ", mEmulated=" + mEmulated + ", mMaxFileSize=" + mMaxFileSize + + ", mMtpReserveSpace=" + mMtpReserveSpace + ", mPath=" + mPath + ", mRemovable=" + + mRemovable + ", mStorageId=" + mStorageId + "]"; } public static final Parcelable.Creator<StorageVolume> CREATOR = diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index 62c8231..0dd9a4d 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -17,6 +17,7 @@ package android.provider; import android.accounts.Account; +import android.app.Activity; import android.content.ContentProviderClient; import android.content.ContentProviderOperation; import android.content.ContentResolver; @@ -6411,6 +6412,28 @@ public final class ContactsContract { public static final String NOTES = "notes"; /** + * The Activity action to open the group in the source app (e.g. + * {@link Intent#ACTION_VIEW}). Can be NULL if the group does not have a dedicated viewer. + * This is used in conjunction with {@link #ACTION_URI}: In order to show an "Open in + * (sourceapp)"-button, both of these fields must be set + * <p> + * Type: TEXT + */ + public static final String ACTION = "action"; + + + /** + * Uri to open the group in the source app. + * Can be NULL if the group does not have a dedicated viewer. + * This is used in conjunction with {@link #ACTION}: In order to show an "Open in + * (sourceapp)"-button, both of these fields must be set + * <p> + * Type: TEXT + */ + public static final String ACTION_URI = "action_uri"; + + + /** * The ID of this group if it is a System Group, i.e. a group that has a special meaning * to the sync adapter, null otherwise. * <P>Type: TEXT</P> diff --git a/core/java/android/view/ActionProvider.java b/core/java/android/view/ActionProvider.java index 47f7358..5601dc5 100644 --- a/core/java/android/view/ActionProvider.java +++ b/core/java/android/view/ActionProvider.java @@ -28,7 +28,9 @@ import android.content.Context; * {@link android.app.ActionBar} as a substitute for the menu item when the item is * displayed as an action item. Also the provider is responsible for performing a * default action if a menu item placed on the overflow menu of the ActionBar is - * selected and none of the menu item callbacks has handled the selection. + * selected and none of the menu item callbacks has handled the selection. For this + * case the provider can also optionally provide a sub-menu for accomplishing the + * task at hand. * </p> * <p> * There are two ways for using an action provider for creating and handling of action views: diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 7ba86a5..3ae10fe 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -9089,6 +9089,52 @@ public class WebView extends AbsoluteLayout } } + /** + * Begin collecting per-tile profiling data + * + * @hide only used by profiling tests + */ + public void tileProfilingStart() { + nativeTileProfilingStart(); + } + /** + * Return per-tile profiling data + * + * @hide only used by profiling tests + */ + public float tileProfilingStop() { + return nativeTileProfilingStop(); + } + + /** @hide only used by profiling tests */ + public void tileProfilingClear() { + nativeTileProfilingClear(); + } + /** @hide only used by profiling tests */ + public int tileProfilingNumFrames() { + return nativeTileProfilingNumFrames(); + } + /** @hide only used by profiling tests */ + public int tileProfilingNumTilesInFrame(int frame) { + return nativeTileProfilingNumTilesInFrame(frame); + } + /** @hide only used by profiling tests */ + public int tileProfilingGetX(int frame, int tile) { + return nativeTileProfilingGetX(frame, tile); + } + /** @hide only used by profiling tests */ + public int tileProfilingGetY(int frame, int tile) { + return nativeTileProfilingGetY(frame, tile); + } + /** @hide only used by profiling tests */ + public boolean tileProfilingGetReady(int frame, int tile) { + return nativeTileProfilingGetReady(frame, tile); + } + /** @hide only used by profiling tests */ + public int tileProfilingGetLevel(int frame, int tile) { + return nativeTileProfilingGetLevel(frame, tile); + } + private native int nativeCacheHitFramePointer(); private native boolean nativeCacheHitIsPlugin(); private native Rect nativeCacheHitNodeBounds(); @@ -9211,6 +9257,15 @@ public class WebView extends AbsoluteLayout private native void nativeStopGL(); private native Rect nativeSubtractLayers(Rect content); private native int nativeTextGeneration(); + private native void nativeTileProfilingStart(); + private native float nativeTileProfilingStop(); + private native void nativeTileProfilingClear(); + private native int nativeTileProfilingNumFrames(); + private native int nativeTileProfilingNumTilesInFrame(int frame); + private native int nativeTileProfilingGetX(int frame, int tile); + private native int nativeTileProfilingGetY(int frame, int tile); + private native boolean nativeTileProfilingGetReady(int frame, int tile); + private native int nativeTileProfilingGetLevel(int frame, int tile); // Never call this version except by updateCachedTextfield(String) - // we always want to pass in our generation number. private native void nativeUpdateCachedTextfield(String updatedText, diff --git a/core/java/android/widget/ActivityChooserModel.java b/core/java/android/widget/ActivityChooserModel.java index 83f80ff..32c44d8 100644 --- a/core/java/android/widget/ActivityChooserModel.java +++ b/core/java/android/widget/ActivityChooserModel.java @@ -126,7 +126,7 @@ public class ActivityChooserModel extends DataSetObservable { */ // This cannot be done by a simple comparator since an Activity weight // is computed from history. Note that Activity implements Comparable. - public void sort(Intent intent, List<Activity> activities, + public void sort(Intent intent, List<ActivityResolveInfo> activities, List<HistoricalRecord> historicalRecords); } @@ -215,7 +215,7 @@ public class ActivityChooserModel extends DataSetObservable { /** * List of activities that can handle the current intent. */ - private final List<Activity> mActivitys = new ArrayList<Activity>(); + private final List<ActivityResolveInfo> mActivites = new ArrayList<ActivityResolveInfo>(); /** * List with historical choice records. @@ -311,9 +311,6 @@ public class ActivityChooserModel extends DataSetObservable { * @return The model. */ public static ActivityChooserModel get(Context context, String historyFileName) { - if (historyFileName == null) { - return new ActivityChooserModel(context, historyFileName); - } synchronized (sRegistryLock) { ActivityChooserModel dataModel = sDataModelRegistry.get(historyFileName); if (dataModel == null) { @@ -380,7 +377,7 @@ public class ActivityChooserModel extends DataSetObservable { */ public int getActivityCount() { synchronized (mInstanceLock) { - return mActivitys.size(); + return mActivites.size(); } } @@ -389,12 +386,12 @@ public class ActivityChooserModel extends DataSetObservable { * * @return The activity. * - * @see Activity + * @see ActivityResolveInfo * @see #setIntent(Intent) */ public ResolveInfo getActivity(int index) { synchronized (mInstanceLock) { - return mActivitys.get(index).resolveInfo; + return mActivites.get(index).resolveInfo; } } @@ -406,10 +403,10 @@ public class ActivityChooserModel extends DataSetObservable { * @return The index if found, -1 otherwise. */ public int getActivityIndex(ResolveInfo activity) { - List<Activity> activities = mActivitys; + List<ActivityResolveInfo> activities = mActivites; final int activityCount = activities.size(); for (int i = 0; i < activityCount; i++) { - Activity currentActivity = activities.get(i); + ActivityResolveInfo currentActivity = activities.get(i); if (currentActivity.resolveInfo == activity) { return i; } @@ -433,8 +430,8 @@ public class ActivityChooserModel extends DataSetObservable { * @see HistoricalRecord */ public Intent chooseActivity(int index) { - Activity chosenActivity = mActivitys.get(index); - Activity defaultActivity = mActivitys.get(0); + ActivityResolveInfo chosenActivity = mActivites.get(index); + ActivityResolveInfo defaultActivity = mActivites.get(0); ComponentName chosenName = new ComponentName( chosenActivity.resolveInfo.activityInfo.packageName, @@ -460,8 +457,8 @@ public class ActivityChooserModel extends DataSetObservable { */ public ResolveInfo getDefaultActivity() { synchronized (mInstanceLock) { - if (!mActivitys.isEmpty()) { - return mActivitys.get(0).resolveInfo; + if (!mActivites.isEmpty()) { + return mActivites.get(0).resolveInfo; } } return null; @@ -478,8 +475,8 @@ public class ActivityChooserModel extends DataSetObservable { * @param index The index of the activity to set as default. */ public void setDefaultActivity(int index) { - Activity newDefaultActivity = mActivitys.get(index); - Activity oldDefaultActivity = mActivitys.get(0); + ActivityResolveInfo newDefaultActivity = mActivites.get(index); + ActivityResolveInfo oldDefaultActivity = mActivites.get(0); final float weight; if (oldDefaultActivity != null) { @@ -572,8 +569,8 @@ public class ActivityChooserModel extends DataSetObservable { */ private void sortActivities() { synchronized (mInstanceLock) { - if (mActivitySorter != null && !mActivitys.isEmpty()) { - mActivitySorter.sort(mIntent, mActivitys, + if (mActivitySorter != null && !mActivites.isEmpty()) { + mActivitySorter.sort(mIntent, mActivites, Collections.unmodifiableList(mHistoricalRecords)); notifyChanged(); } @@ -661,14 +658,14 @@ public class ActivityChooserModel extends DataSetObservable { * Loads the activities. */ private void loadActivitiesLocked() { - mActivitys.clear(); + mActivites.clear(); if (mIntent != null) { List<ResolveInfo> resolveInfos = mContext.getPackageManager().queryIntentActivities(mIntent, 0); final int resolveInfoCount = resolveInfos.size(); for (int i = 0; i < resolveInfoCount; i++) { ResolveInfo resolveInfo = resolveInfos.get(i); - mActivitys.add(new Activity(resolveInfo)); + mActivites.add(new ActivityResolveInfo(resolveInfo)); } sortActivities(); } else { @@ -797,7 +794,7 @@ public class ActivityChooserModel extends DataSetObservable { /** * Represents an activity. */ - public final class Activity implements Comparable<Activity> { + public final class ActivityResolveInfo implements Comparable<ActivityResolveInfo> { /** * The {@link ResolveInfo} of the activity. @@ -814,7 +811,7 @@ public class ActivityChooserModel extends DataSetObservable { * * @param resolveInfo activity {@link ResolveInfo}. */ - public Activity(ResolveInfo resolveInfo) { + public ActivityResolveInfo(ResolveInfo resolveInfo) { this.resolveInfo = resolveInfo; } @@ -834,14 +831,14 @@ public class ActivityChooserModel extends DataSetObservable { if (getClass() != obj.getClass()) { return false; } - Activity other = (Activity) obj; + ActivityResolveInfo other = (ActivityResolveInfo) obj; if (Float.floatToIntBits(weight) != Float.floatToIntBits(other.weight)) { return false; } return true; } - public int compareTo(Activity another) { + public int compareTo(ActivityResolveInfo another) { return Float.floatToIntBits(another.weight) - Float.floatToIntBits(weight); } @@ -862,18 +859,18 @@ public class ActivityChooserModel extends DataSetObservable { private final class DefaultSorter implements ActivitySorter { private static final float WEIGHT_DECAY_COEFFICIENT = 0.95f; - private final Map<String, Activity> mPackageNameToActivityMap = - new HashMap<String, Activity>(); + private final Map<String, ActivityResolveInfo> mPackageNameToActivityMap = + new HashMap<String, ActivityResolveInfo>(); - public void sort(Intent intent, List<Activity> activities, + public void sort(Intent intent, List<ActivityResolveInfo> activities, List<HistoricalRecord> historicalRecords) { - Map<String, Activity> packageNameToActivityMap = + Map<String, ActivityResolveInfo> packageNameToActivityMap = mPackageNameToActivityMap; packageNameToActivityMap.clear(); final int activityCount = activities.size(); for (int i = 0; i < activityCount; i++) { - Activity activity = activities.get(i); + ActivityResolveInfo activity = activities.get(i); activity.weight = 0.0f; String packageName = activity.resolveInfo.activityInfo.packageName; packageNameToActivityMap.put(packageName, activity); @@ -884,9 +881,11 @@ public class ActivityChooserModel extends DataSetObservable { for (int i = lastShareIndex; i >= 0; i--) { HistoricalRecord historicalRecord = historicalRecords.get(i); String packageName = historicalRecord.activity.getPackageName(); - Activity activity = packageNameToActivityMap.get(packageName); - activity.weight += historicalRecord.weight * nextRecordWeight; - nextRecordWeight = nextRecordWeight * WEIGHT_DECAY_COEFFICIENT; + ActivityResolveInfo activity = packageNameToActivityMap.get(packageName); + if (activity != null) { + activity.weight += historicalRecord.weight * nextRecordWeight; + nextRecordWeight = nextRecordWeight * WEIGHT_DECAY_COEFFICIENT; + } } Collections.sort(activities); diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java index 2fe8162..f500b39 100644 --- a/core/java/android/widget/ActivityChooserView.java +++ b/core/java/android/widget/ActivityChooserView.java @@ -16,10 +16,7 @@ package android.widget; -import android.app.AlertDialog; -import android.app.AlertDialog.Builder; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; @@ -27,12 +24,20 @@ import android.content.res.TypedArray; import android.database.DataSetObserver; import android.graphics.Canvas; import android.graphics.drawable.Drawable; -import android.os.Debug; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.ActivityChooserModel; import android.widget.ActivityChooserModel.ActivityChooserModelClient; +import android.widget.AdapterView; +import android.widget.BaseAdapter; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListPopupWindow; +import android.widget.PopupWindow; +import android.widget.TextView; import com.android.internal.R; @@ -56,11 +61,6 @@ import com.android.internal.R; * </li> * </ul> * </p> - * </p> - * This view is backed by a {@link ActivityChooserModel}. Calling {@link #showPopup()} - * while this view is attached to the view hierarchy will show a popup with - * activities while if the view is not attached it will show a dialog. - * </p> * * @hide */ @@ -92,29 +92,21 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod private final ImageButton mDefaultActionButton; /** - * The header for handlers list. + * Observer for the model data. */ - private final View mListHeaderView; + private final DataSetObserver mModelDataSetOberver = new DataSetObserver() { - /** - * The footer for handlers list. - */ - private final View mListFooterView; - - /** - * The title of the header view. - */ - private TextView mListHeaderViewTitle; - - /** - * The title for expanding the activities list. - */ - private final String mListHeaderViewTitleSelectDefault; - - /** - * The title if no activity exist. - */ - private final String mListHeaderViewTitleNoActivities; + @Override + public void onChanged() { + super.onChanged(); + mAdapter.notifyDataSetChanged(); + } + @Override + public void onInvalidated() { + super.onInvalidated(); + mAdapter.notifyDataSetInvalidated(); + } + }; /** * Popup window for showing the activity overflow list. @@ -122,11 +114,6 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod private ListPopupWindow mListPopupWindow; /** - * Alert dialog for showing the activity overflow list. - */ - private AlertDialog mAlertDialog; - - /** * Listener for the dismissal of the popup/alert. */ private PopupWindow.OnDismissListener mOnDismissListener; @@ -147,16 +134,6 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod private boolean mIsAttachedToWindow; /** - * Flag whether this view is showing an alert dialog. - */ - private boolean mIsShowingAlertDialog; - - /** - * Flag whether this view is showing a popup window. - */ - private boolean mIsShowingPopuWindow; - - /** * Create a new instance. * * @param context The application environment. @@ -195,8 +172,7 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod Drawable expandActivityOverflowButtonDrawable = attributesArray.getDrawable( R.styleable.ActivityChooserView_expandActivityOverflowButtonDrawable); - LayoutInflater inflater = (LayoutInflater) context.getSystemService( - Context.LAYOUT_INFLATER_SERVICE); + LayoutInflater inflater = LayoutInflater.from(mContext); inflater.inflate(R.layout.activity_chooser_view, this, true); mCallbacks = new Callbacks(); @@ -211,15 +187,6 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod mExpandActivityOverflowButton.setOnClickListener(mCallbacks); mExpandActivityOverflowButton.setBackgroundDrawable(expandActivityOverflowButtonDrawable); - mListHeaderView = inflater.inflate(R.layout.activity_chooser_list_header, null); - mListFooterView = inflater.inflate(R.layout.activity_chooser_list_footer, null); - - mListHeaderViewTitle = (TextView) mListHeaderView.findViewById(R.id.title); - mListHeaderViewTitleSelectDefault = context.getString( - R.string.activity_chooser_view_select_default); - mListHeaderViewTitleNoActivities = context.getString( - R.string.activity_chooser_view_no_activities); - mAdapter = new ActivityChooserViewAdapter(); mAdapter.registerDataSetObserver(new DataSetObserver() { @Override @@ -262,7 +229,7 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod * @return True if the popup was shown, false if already showing. */ public boolean showPopup() { - if (isShowingPopup()) { + if (isShowingPopup() || !mIsAttachedToWindow) { return false; } mIsSelectingDefaultActivity = false; @@ -276,38 +243,29 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod * @param maxActivityCount The max number of activities to display. */ private void showPopupUnchecked(int maxActivityCount) { - mAdapter.setMaxActivityCount(maxActivityCount); - if (mIsSelectingDefaultActivity) { - if (mAdapter.getActivityCount() > 0) { - mListHeaderViewTitle.setText(mListHeaderViewTitleSelectDefault); - } else { - mListHeaderViewTitle.setText(mListHeaderViewTitleNoActivities); - } - mAdapter.setHeaderView(mListHeaderView); - } else { - mAdapter.setHeaderView(null); + if (mAdapter.getDataModel() == null) { + throw new IllegalStateException("No data model. Did you call #setDataModel?"); } - if (mAdapter.getActivityCount() > maxActivityCount + 1) { - mAdapter.setFooterView(mListFooterView); + mAdapter.setMaxActivityCount(maxActivityCount); + + final int activityCount = mAdapter.getActivityCount(); + if (maxActivityCount != ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_UNLIMITED + && activityCount > maxActivityCount + 1) { + mAdapter.setShowFooterView(true); } else { - mAdapter.setFooterView(null); + mAdapter.setShowFooterView(false); } - if (!mIsAttachedToWindow || mIsShowingAlertDialog) { - AlertDialog alertDialog = getAlertDilalog(); - if (!alertDialog.isShowing()) { - alertDialog.setCustomTitle(this); - alertDialog.show(); - mIsShowingAlertDialog = true; - } - } else { - ListPopupWindow popupWindow = getListPopupWindow(); - if (!popupWindow.isShowing()) { - popupWindow.setContentWidth(mAdapter.measureContentWidth()); - popupWindow.show(); - mIsShowingPopuWindow = true; + ListPopupWindow popupWindow = getListPopupWindow(); + if (!popupWindow.isShowing()) { + if (mIsSelectingDefaultActivity) { + mAdapter.setShowDefaultActivity(true); + } else { + mAdapter.setShowDefaultActivity(false); } + popupWindow.setContentWidth(mAdapter.measureContentWidth()); + popupWindow.show(); } } @@ -317,12 +275,7 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod * @return True if dismissed, false if already dismissed. */ public boolean dismissPopup() { - if (!isShowingPopup()) { - return false; - } - if (mIsShowingAlertDialog) { - getAlertDilalog().dismiss(); - } else if (mIsShowingPopuWindow) { + if (isShowingPopup()) { getListPopupWindow().dismiss(); } return true; @@ -334,12 +287,7 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod * @return True if the popup is shown. */ public boolean isShowingPopup() { - if (mIsShowingAlertDialog) { - return getAlertDilalog().isShowing(); - } else if (mIsShowingPopuWindow) { - return getListPopupWindow().isShowing(); - } - return false; + return getListPopupWindow().isShowing(); } @Override @@ -347,6 +295,7 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod super.onAttachedToWindow(); ActivityChooserModel dataModel = mAdapter.getDataModel(); if (dataModel != null) { + dataModel.registerObserver(mModelDataSetOberver); dataModel.readHistoricalData(); } mIsAttachedToWindow = true; @@ -357,6 +306,7 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod super.onDetachedFromWindow(); ActivityChooserModel dataModel = mAdapter.getDataModel(); if (dataModel != null) { + dataModel.unregisterObserver(mModelDataSetOberver); dataModel.persistHistoricalData(); } mIsAttachedToWindow = false; @@ -371,13 +321,11 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - mActivityChooserContent.layout(left, top, right, bottom); - if (mIsShowingPopuWindow) { - if (isShown()) { - showPopupUnchecked(mAdapter.getMaxActivityCount()); - } else { - dismissPopup(); - } + mActivityChooserContent.layout(0, 0, right - left, bottom - top); + if (getListPopupWindow().isShowing()) { + showPopupUnchecked(mAdapter.getMaxActivityCount()); + } else { + dismissPopup(); } } @@ -429,22 +377,6 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod } /** - * Gets the alert dialog which is lazily initialized. - * - * @return The popup. - */ - private AlertDialog getAlertDilalog() { - if (mAlertDialog == null) { - Builder builder = new Builder(getContext()); - builder.setAdapter(mAdapter, null); - mAlertDialog = builder.create(); - mAlertDialog.getListView().setOnItemClickListener(mCallbacks); - mAlertDialog.setOnDismissListener(mCallbacks); - } - return mAlertDialog; - } - - /** * Updates the buttons state. */ private void updateButtons() { @@ -469,24 +401,23 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod * Interface implementation to avoid publishing them in the APIs. */ private class Callbacks implements AdapterView.OnItemClickListener, - View.OnClickListener, View.OnLongClickListener, PopupWindow.OnDismissListener, - DialogInterface.OnDismissListener { + View.OnClickListener, View.OnLongClickListener, PopupWindow.OnDismissListener { // AdapterView#OnItemClickListener public void onItemClick(AdapterView<?> parent, View view, int position, long id) { ActivityChooserViewAdapter adapter = (ActivityChooserViewAdapter) parent.getAdapter(); final int itemViewType = adapter.getItemViewType(position); switch (itemViewType) { - case ActivityChooserViewAdapter.ITEM_VIEW_TYPE_HEADER: { - /* do nothing */ - } break; case ActivityChooserViewAdapter.ITEM_VIEW_TYPE_FOOTER: { showPopupUnchecked(ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_UNLIMITED); } break; case ActivityChooserViewAdapter.ITEM_VIEW_TYPE_ACTIVITY: { dismissPopup(); if (mIsSelectingDefaultActivity) { - mAdapter.getDataModel().setDefaultActivity(position); + // The item at position zero is the default already. + if (position > 0) { + mAdapter.getDataModel().setDefaultActivity(position); + } } else { // The first item in the model is default action => adjust index Intent launchIntent = mAdapter.getDataModel().chooseActivity(position + 1); @@ -530,16 +461,6 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod // PopUpWindow.OnDismissListener#onDismiss public void onDismiss() { - mIsShowingPopuWindow = false; - notifyOnDismissListener(); - } - - // DialogInterface.OnDismissListener#onDismiss - @Override - public void onDismiss(DialogInterface dialog) { - mIsShowingAlertDialog = false; - AlertDialog alertDialog = (AlertDialog) dialog; - alertDialog.setCustomTitle(null); notifyOnDismissListener(); } @@ -559,59 +480,35 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod public static final int MAX_ACTIVITY_COUNT_DEFAULT = 4; - private static final int ITEM_VIEW_TYPE_HEADER = 0; + private static final int ITEM_VIEW_TYPE_ACTIVITY = 0; - private static final int ITEM_VIEW_TYPE_ACTIVITY = 1; - - private static final int ITEM_VIEW_TYPE_FOOTER = 2; + private static final int ITEM_VIEW_TYPE_FOOTER = 1; private static final int ITEM_VIEW_TYPE_COUNT = 3; - private final DataSetObserver mDataSetOberver = new DataSetObserver() { - - @Override - public void onChanged() { - super.onChanged(); - notifyDataSetChanged(); - } - @Override - public void onInvalidated() { - super.onInvalidated(); - notifyDataSetInvalidated(); - } - }; - private ActivityChooserModel mDataModel; private int mMaxActivityCount = MAX_ACTIVITY_COUNT_DEFAULT; - private ResolveInfo mDefaultActivity; + private boolean mShowDefaultActivity; - private View mHeaderView; - - private View mFooterView; + private boolean mShowFooterView; public void setDataModel(ActivityChooserModel dataModel) { + ActivityChooserModel oldDataModel = mAdapter.getDataModel(); + if (oldDataModel != null && isShown()) { + oldDataModel.unregisterObserver(mModelDataSetOberver); + } mDataModel = dataModel; - mDataModel.registerObserver(mDataSetOberver); - notifyDataSetChanged(); - } - - @Override - public void notifyDataSetChanged() { - if (mDataModel.getActivityCount() > 0) { - mDefaultActivity = mDataModel.getDefaultActivity(); - } else { - mDefaultActivity = null; + if (dataModel != null && isShown()) { + dataModel.registerObserver(mModelDataSetOberver); } - super.notifyDataSetChanged(); + notifyDataSetChanged(); } @Override public int getItemViewType(int position) { - if (mHeaderView != null && position == 0) { - return ITEM_VIEW_TYPE_HEADER; - } else if (mFooterView != null && position == getCount() - 1) { + if (mShowFooterView && position == getCount() - 1) { return ITEM_VIEW_TYPE_FOOTER; } else { return ITEM_VIEW_TYPE_ACTIVITY; @@ -626,14 +523,11 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod public int getCount() { int count = 0; int activityCount = mDataModel.getActivityCount(); - if (activityCount > 0) { + if (!mShowDefaultActivity && mDataModel.getDefaultActivity() != null) { activityCount--; } count = Math.min(activityCount, mMaxActivityCount); - if (mHeaderView != null) { - count++; - } - if (mFooterView != null) { + if (mShowFooterView) { count++; } return count; @@ -642,16 +536,13 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod public Object getItem(int position) { final int itemViewType = getItemViewType(position); switch (itemViewType) { - case ITEM_VIEW_TYPE_HEADER: - return mHeaderView; case ITEM_VIEW_TYPE_FOOTER: - return mFooterView; + return null; case ITEM_VIEW_TYPE_ACTIVITY: - int targetIndex = (mHeaderView == null) ? position : position - 1; - if (mDefaultActivity != null) { - targetIndex++; + if (!mShowDefaultActivity && mDataModel.getDefaultActivity() != null) { + position++; } - return mDataModel.getActivity(targetIndex); + return mDataModel.getActivity(position); default: throw new IllegalArgumentException(); } @@ -661,27 +552,19 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod return position; } - @Override - public boolean isEnabled(int position) { - final int itemViewType = getItemViewType(position); - switch (itemViewType) { - case ITEM_VIEW_TYPE_HEADER: - return false; - case ITEM_VIEW_TYPE_FOOTER: - case ITEM_VIEW_TYPE_ACTIVITY: - return true; - default: - throw new IllegalArgumentException(); - } - } - public View getView(int position, View convertView, ViewGroup parent) { final int itemViewType = getItemViewType(position); switch (itemViewType) { - case ITEM_VIEW_TYPE_HEADER: - return mHeaderView; case ITEM_VIEW_TYPE_FOOTER: - return mFooterView; + if (convertView == null || convertView.getId() != ITEM_VIEW_TYPE_FOOTER) { + convertView = LayoutInflater.from(getContext()).inflate( + R.layout.activity_chooser_view_list_item, parent, false); + convertView.setId(ITEM_VIEW_TYPE_FOOTER); + TextView titleView = (TextView) convertView.findViewById(R.id.title); + titleView.setText(mContext.getString( + R.string.activity_chooser_view_see_all)); + } + return convertView; case ITEM_VIEW_TYPE_ACTIVITY: if (convertView == null || convertView.getId() != R.id.list_item) { convertView = LayoutInflater.from(getContext()).inflate( @@ -695,6 +578,12 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod // Set the title. TextView titleView = (TextView) convertView.findViewById(R.id.title); titleView.setText(activity.loadLabel(packageManager)); + // Highlight the default. + if (mShowDefaultActivity && position == 0) { + convertView.setActivated(true); + } else { + convertView.setActivated(false); + } return convertView; default: throw new IllegalArgumentException(); @@ -702,7 +591,7 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod } public int measureContentWidth() { - // The user may have specified some of the target not to be show but we + // The user may have specified some of the target not to be shown but we // want to measure all of them since after expansion they should fit. final int oldMaxActivityCount = mMaxActivityCount; mMaxActivityCount = MAX_ACTIVITY_COUNT_UNLIMITED; @@ -733,19 +622,12 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod } public ResolveInfo getDefaultActivity() { - return mDefaultActivity; - } - - public void setHeaderView(View headerView) { - if (mHeaderView != headerView) { - mHeaderView = headerView; - notifyDataSetChanged(); - } + return mDataModel.getDefaultActivity(); } - public void setFooterView(View footerView) { - if (mFooterView != footerView) { - mFooterView = footerView; + public void setShowFooterView(boolean showFooterView) { + if (mShowFooterView != showFooterView) { + mShowFooterView = showFooterView; notifyDataSetChanged(); } } @@ -761,5 +643,12 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod public ActivityChooserModel getDataModel() { return mDataModel; } + + public void setShowDefaultActivity(boolean showDefaultActivity) { + if (mShowDefaultActivity != showDefaultActivity) { + mShowDefaultActivity = showDefaultActivity; + notifyDataSetChanged(); + } + } } } diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java index 3b16994..1b713c3 100644 --- a/core/java/android/widget/CalendarView.java +++ b/core/java/android/widget/CalendarView.java @@ -375,6 +375,7 @@ public class CalendarView extends FrameLayout { com.android.internal.R.styleable.TextAppearance); mDateTextSize = dateTextAppearance.getDimensionPixelSize( R.styleable.TextAppearance_textSize, DEFAULT_DATE_TEXT_SIZE); + dateTextAppearance.recycle(); int weekDayTextAppearanceResId = attributesArray.getResourceId( R.styleable.CalendarView_weekDayTextAppearance, diff --git a/core/java/android/widget/ShareActionProvider.java b/core/java/android/widget/ShareActionProvider.java index f48261d..2e0cc62 100644 --- a/core/java/android/widget/ShareActionProvider.java +++ b/core/java/android/widget/ShareActionProvider.java @@ -16,21 +16,25 @@ package android.widget; -import com.android.internal.R; - import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.graphics.drawable.Drawable; import android.util.TypedValue; import android.view.ActionProvider; +import android.view.Menu; import android.view.MenuItem; +import android.view.MenuItem.OnMenuItemClickListener; import android.view.SubMenu; import android.view.View; +import com.android.internal.R; + /** * This is a provider for a share action. It is responsible for creating views - * that enable data sharing and also to perform a default action for showing - * a share dialog. + * that enable data sharing and also to show a sub menu with sharing activities + * if the hosting item is placed on the overflow menu. * <p> * Here is how to use the action provider with custom backing file in a {@link MenuItem}: * </p> @@ -48,15 +52,13 @@ import android.view.View; * // {@link ActionProvider#onCreateActionView()} which uses the backing file name. Omit this * // line if using the default share history file is desired. * mShareActionProvider.setShareHistoryFileName("custom_share_history.xml"); - * // Get the action view and hold onto it to set the share intent. - * mActionView = menuItem.getActionView(); * . . . * } * * // Somewhere in the application. * public void doShare(Intent shareIntent) { * // When you want to share set the share intent. - * mShareActionProvider.setShareIntent(mActionView, shareIntent); + * mShareActionProvider.setShareIntent(shareIntent); * } * </pre> * </code> @@ -71,11 +73,34 @@ import android.view.View; public class ShareActionProvider extends ActionProvider { /** + * The default for the maximal number of activities shown in the sub-menu. + */ + private static final int DEFAULT_INITIAL_ACTIVITY_COUNT = 4; + + /** + * The the maximum number activities shown in the sub-menu. + */ + private int mMaxShownActivityCount = DEFAULT_INITIAL_ACTIVITY_COUNT; + + /** + * Listener for handling menu item clicks. + */ + private final ShareMenuItemOnMenuItemClickListener mOnMenuItemClickListener = + new ShareMenuItemOnMenuItemClickListener(); + + /** * The default name for storing share history. */ public static final String DEFAULT_SHARE_HISTORY_FILE_NAME = "share_history.xml"; + /** + * Context for accessing resources. + */ private final Context mContext; + + /** + * The name of the file with share history data. + */ private String mShareHistoryFileName = DEFAULT_SHARE_HISTORY_FILE_NAME; /** @@ -93,24 +118,59 @@ public class ShareActionProvider extends ActionProvider { */ @Override public View onCreateActionView() { + // Create the view and set its data model. ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName); ActivityChooserView activityChooserView = new ActivityChooserView(mContext); activityChooserView.setActivityChooserModel(dataModel); + + // Lookup and set the expand action icon. TypedValue outTypedValue = new TypedValue(); mContext.getTheme().resolveAttribute(R.attr.actionModeShareDrawable, outTypedValue, true); Drawable drawable = mContext.getResources().getDrawable(outTypedValue.resourceId); activityChooserView.setExpandActivityOverflowButtonDrawable(drawable); + return activityChooserView; } + /** + * {@inheritDoc} + */ @Override public boolean hasSubMenu() { return true; } + /** + * {@inheritDoc} + */ @Override public void onPrepareSubMenu(SubMenu subMenu) { - // TODO Implement me + // Clear since the order of items may change. + subMenu.clear(); + + ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName); + PackageManager packageManager = mContext.getPackageManager(); + + final int expandedActivityCount = dataModel.getActivityCount(); + final int collapsedActivityCount = Math.min(expandedActivityCount, mMaxShownActivityCount); + + // Populate the sub-menu with a sub set of the activities. + for (int i = 0; i < collapsedActivityCount; i++) { + ResolveInfo activity = dataModel.getActivity(i); + subMenu.add(0, i, i, activity.loadLabel(packageManager)) + .setIcon(activity.loadIcon(packageManager)) + .setOnMenuItemClickListener(mOnMenuItemClickListener); + } + + // Add a sub-menu for showing all activities as a list item. + SubMenu expandedSubMenu = subMenu.addSubMenu(Menu.NONE, collapsedActivityCount, + collapsedActivityCount, mContext.getString(R.string.activity_chooser_view_see_all)); + for (int i = 0; i < expandedActivityCount; i++) { + ResolveInfo activity = dataModel.getActivity(i); + expandedSubMenu.add(0, i, i, activity.loadLabel(packageManager)) + .setIcon(activity.loadIcon(packageManager)) + .setOnMenuItemClickListener(mOnMenuItemClickListener); + } } /** @@ -145,18 +205,29 @@ public class ShareActionProvider extends ActionProvider { * </code> * </p> * - * @param actionView An action view created by {@link #onCreateActionView()}. * @param shareIntent The share intent. * * @see Intent#ACTION_SEND * @see Intent#ACTION_SEND_MULTIPLE */ - public void setShareIntent(View actionView, Intent shareIntent) { - if (actionView instanceof ActivityChooserView) { - ActivityChooserView activityChooserView = (ActivityChooserView) actionView; - activityChooserView.getDataModel().setIntent(shareIntent); - } else { - throw new IllegalArgumentException("actionView not instance of ActivityChooserView"); + public void setShareIntent(Intent shareIntent) { + ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, + mShareHistoryFileName); + dataModel.setIntent(shareIntent); + } + + /** + * Reusable listener for handling share item clicks. + */ + private class ShareMenuItemOnMenuItemClickListener implements OnMenuItemClickListener { + @Override + public boolean onMenuItemClick(MenuItem item) { + ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, + mShareHistoryFileName); + final int itemId = item.getItemId(); + Intent launchIntent = dataModel.chooseActivity(itemId); + mContext.startActivity(launchIntent); + return true; } } } diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java index b0b49213..164d581 100644 --- a/core/java/com/android/internal/view/menu/MenuBuilder.java +++ b/core/java/com/android/internal/view/menu/MenuBuilder.java @@ -799,7 +799,7 @@ public class MenuBuilder implements Menu { if (itemImpl == null || !itemImpl.isEnabled()) { return false; } - + boolean invoked = itemImpl.invoke(); if (itemImpl.hasCollapsibleActionView()) { diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java index 0a7313c..541d101 100644 --- a/core/java/com/android/internal/view/menu/MenuItemImpl.java +++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java @@ -320,11 +320,6 @@ public final class MenuItemImpl implements MenuItem { } void setSubMenu(SubMenuBuilder subMenu) { - if ((mMenu != null) && (mMenu instanceof SubMenu)) { - throw new UnsupportedOperationException( - "Attempt to add a sub-menu to a sub-menu."); - } - mSubMenu = subMenu; subMenu.setHeaderTitle(getTitle()); diff --git a/core/java/com/android/server/NetworkManagementSocketTagger.java b/core/java/com/android/server/NetworkManagementSocketTagger.java index 2871073..c446cfb 100644 --- a/core/java/com/android/server/NetworkManagementSocketTagger.java +++ b/core/java/com/android/server/NetworkManagementSocketTagger.java @@ -16,24 +16,37 @@ package com.android.server; +import android.os.SystemProperties; +import android.util.Log; + import dalvik.system.SocketTagger; + import java.io.FileDescriptor; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +import java.math.BigInteger; import java.net.SocketException; import java.nio.charset.Charsets; +import libcore.io.IoUtils; + /** * Assigns tags to sockets for traffic stats. */ public final class NetworkManagementSocketTagger extends SocketTagger { + private static final String TAG = "NetworkManagementSocketTagger"; + private static final boolean LOGD = false; - private static final boolean LOGI = false; - private static final boolean ENABLE_TAGGING = false; + /** + * {@link SystemProperties} key that indicates if {@code qtaguid} bandwidth + * controls have been enabled. + */ + // TODO: remove when always enabled, or once socket tagging silently fails. + public static final String PROP_QTAGUID_ENABLED = "net.qtaguid_enabled"; private static ThreadLocal<SocketTags> threadSocketTags = new ThreadLocal<SocketTags>() { - @Override protected SocketTags initialValue() { + @Override + protected SocketTags initialValue() { return new SocketTags(); } }; @@ -50,11 +63,12 @@ public final class NetworkManagementSocketTagger extends SocketTagger { threadSocketTags.get().statsUid = uid; } - @Override public void tag(FileDescriptor fd) throws SocketException { + @Override + public void tag(FileDescriptor fd) throws SocketException { final SocketTags options = threadSocketTags.get(); - if (LOGI) { - System.logI("tagSocket(" + fd.getInt$() + ") with statsTag=" - + options.statsTag + ", statsUid=" + options.statsUid); + if (LOGD) { + Log.d(TAG, "tagSocket(" + fd.getInt$() + ") with statsTag=" + options.statsTag + + ", statsUid=" + options.statsUid); } try { // TODO: skip tagging when options would be no-op @@ -82,9 +96,10 @@ public final class NetworkManagementSocketTagger extends SocketTagger { internalModuleCtrl(cmd); } - @Override public void untag(FileDescriptor fd) throws SocketException { - if (LOGI) { - System.logI("untagSocket(" + fd.getInt$() + ")"); + @Override + public void untag(FileDescriptor fd) throws SocketException { + if (LOGD) { + Log.i(TAG, "untagSocket(" + fd.getInt$() + ")"); } try { unTagSocketFd(fd); @@ -125,31 +140,22 @@ public final class NetworkManagementSocketTagger extends SocketTagger { * */ private void internalModuleCtrl(String cmd) throws IOException { - if (!ENABLE_TAGGING) return; + if (!SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) return; - final FileOutputStream procOut; - // TODO: Use something like - // android.os.SystemProperties.getInt("persist.bandwidth.enable", 0) - // to see if tagging should happen or not. + // TODO: migrate to native library for tagging commands + FileOutputStream procOut = null; try { procOut = new FileOutputStream("/proc/net/xt_qtaguid/ctrl"); - } catch (FileNotFoundException e) { - if (LOGI) { - System.logI("Can't talk to kernel module:" + e); - } - return; - } - try { procOut.write(cmd.getBytes(Charsets.US_ASCII)); } finally { - procOut.close(); + IoUtils.closeQuietly(procOut); } } /** * Convert {@link Integer} tag to {@code /proc/} format. Assumes unsigned * base-10 format like {@code 2147483647}. Currently strips signed bit to - * avoid using {@link java.math.BigInteger}. + * avoid using {@link BigInteger}. */ public static String tagToKernel(int tag) { // TODO: eventually write in hex, since that's what proc exports diff --git a/core/res/res/layout/activity_chooser_list_footer.xml b/core/res/res/layout/activity_chooser_list_footer.xml deleted file mode 100644 index c05ba1a..0000000 --- a/core/res/res/layout/activity_chooser_list_footer.xml +++ /dev/null @@ -1,42 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2011 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. ---> - -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/list_footer" - android:paddingLeft="16dip" - android:paddingRight="16dip" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:gravity="center" - android:orientation="vertical"> - - <View - android:id="@+id/divider" - android:layout_width="match_parent" - android:layout_height="2dip" - android:background="@android:color/holo_blue_light" /> - - <TextView - android:id="@+id/title" - android:layout_width="wrap_content" - android:layout_height="48dip" - android:gravity="center" - android:textAppearance="?android:attr/textAppearanceLargePopupMenu" - android:duplicateParentState="true" - android:singleLine="true" - android:text="@string/activity_chooser_view_see_all" /> - -</LinearLayout> diff --git a/core/res/res/layout/activity_chooser_list_header.xml b/core/res/res/layout/activity_chooser_list_header.xml deleted file mode 100644 index 0fb256f..0000000 --- a/core/res/res/layout/activity_chooser_list_header.xml +++ /dev/null @@ -1,41 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2011 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. ---> - -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/list_header" - android:paddingLeft="16dip" - android:paddingRight="16dip" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:gravity="center" - android:orientation="vertical"> - - <TextView - android:id="@+id/title" - android:layout_width="wrap_content" - android:layout_height="?android:attr/dropdownListPreferredItemHeight" - android:gravity="center" - android:textAppearance="?android:attr/textAppearanceLargePopupMenu" - android:duplicateParentState="true" - android:singleLine="true" /> - - <View - android:id="@+id/divider" - android:layout_width="match_parent" - android:layout_height="2dip" - android:src="@drawable/divider_strong_holo" /> - -</LinearLayout> diff --git a/core/res/res/layout/activity_chooser_view.xml b/core/res/res/layout/activity_chooser_view.xml index ccf49fc..902b3c0 100644 --- a/core/res/res/layout/activity_chooser_view.xml +++ b/core/res/res/layout/activity_chooser_view.xml @@ -25,11 +25,11 @@ <ImageButton android:id="@+id/default_activity_button" android:layout_width="32dip" android:layout_height="32dip" - android:layout_marginLeft="16dip" /> + android:layout_marginRight="8dip" /> <ImageButton android:id="@+id/expand_activities_button" android:layout_width="32dip" android:layout_height="32dip" - android:layout_marginLeft="16dip" /> + android:layout_marginLeft="8dip" /> </LinearLayout> diff --git a/core/res/res/layout/activity_chooser_view_list_item.xml b/core/res/res/layout/activity_chooser_view_list_item.xml index 61b7e70..f90044e 100644 --- a/core/res/res/layout/activity_chooser_view_list_item.xml +++ b/core/res/res/layout/activity_chooser_view_list_item.xml @@ -18,26 +18,35 @@ android:id="@+id/list_item" android:layout_width="match_parent" android:layout_height="?android:attr/dropdownListPreferredItemHeight" - android:gravity="center_vertical" android:paddingLeft="16dip" - android:paddingRight="16dip"> - - <ImageView - android:id="@+id/icon" - android:layout_width="32dip" - android:layout_height="32dip" - android:layout_gravity="center_vertical" - android:layout_marginRight="8dip" - android:duplicateParentState="true" /> - - <TextView - android:id="@+id/title" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:textAppearance="?android:attr/textAppearanceLargePopupMenu" - android:singleLine="true" - android:duplicateParentState="true" - android:ellipsize="marquee" - android:fadingEdge="horizontal" /> + android:paddingRight="16dip" + android:background="?android:attr/activatedBackgroundIndicator" + android:orientation="vertical" > + + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:duplicateParentState="true" > + + <ImageView + android:id="@+id/icon" + android:layout_width="32dip" + android:layout_height="32dip" + android:layout_gravity="center_vertical" + android:layout_marginRight="8dip" + android:duplicateParentState="true" /> + + <TextView + android:id="@+id/title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:textAppearance="?android:attr/textAppearanceLargePopupMenu" + android:duplicateParentState="true" + android:singleLine="true" + android:ellipsize="marquee" + android:fadingEdge="horizontal" /> + + </LinearLayout> </LinearLayout> diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index a5e5f70..0f6e5cf 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -133,4 +133,7 @@ <!-- Size of right margin on Unsecure unlock LockScreen --> <dimen name="keyguard_lockscreen_status_line_font_right_margin">45dip</dimen> + <!-- Minimum popup width for selecting an activity in ActivityChooserDialog/ActivityChooserView. --> + <dimen name="activity_chooser_popup_min_width">200dip</dimen> + </resources> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 70c204e..d0e3f14 100755 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -3036,9 +3036,10 @@ <!-- Title for a button to expand the list of activities in ActivityChooserView [CHAR LIMIT=25] --> <string name="activity_chooser_view_see_all">See all...</string> - <!-- Title for a message that there are no activities in ActivityChooserView [CHAR LIMIT=25] --> - <string name="activity_chooser_view_no_activities">No activities</string> - <!-- Title for a message that prompts selection of a default share handler in ActivityChooserView [CHAR LIMIT=25] --> - <string name="activity_chooser_view_select_default">Select default</string> + <!-- Title default for a dialog showing possible activities in ActivityChooserView [CHAR LIMIT=25] --> + <string name="activity_chooser_view_dialog_title_default">Select activity</string> + + <!-- Title for a dialog showing possible activities for sharing in ShareActionProvider [CHAR LIMIT=25] --> + <string name="share_action_provider_share_with">Share with...</string> </resources> diff --git a/docs/html/guide/developing/tools/adb.jd b/docs/html/guide/developing/tools/adb.jd index a109dc8..78d12ef 100644 --- a/docs/html/guide/developing/tools/adb.jd +++ b/docs/html/guide/developing/tools/adb.jd @@ -503,7 +503,7 @@ application and send 500 pseudo-random events to it.</p> <ul> <li><code>V</code> — Verbose (lowest priority)</li> <li><code>D</code> — Debug</li> - <li><code>I</code> — Info</li> + <li><code>I</code> — Info (default priority)</li> <li><code>W</code> — Warning</li> <li><code>E</code> — Error</li> <li><code>F</code> — Fatal</li> @@ -520,7 +520,7 @@ of each message, given as <code><priority>/<tag></code>. </p> <p>To reduce the log output to a manageable level, you can restrict log output using <em>filter expressions</em>. Filter expressions let you indicate to the system the tags-priority combinations that you are interested in — the system suppresses other messages for the specified tags. </p> -<p>A filter expression follows this format <code>tag:priority ...</code>, where <code>tag</code> indicates the tag of interest and <code>priority</code> indicates the <em>minimum</em> level of priority to report for that tag. Messages for that tag at or above the specified priority are written to the log. You can supply any number of <code>tag:priority</code> specifications in a single filter expression. The series of specifications is whitespace-delimited. </p> +<p>A filter expression follows this format <code>tag:priority ...</code>, where <code>tag</code> indicates the tag of interest and <code>priority</code> indicates the <em>minimum</em> level of priority to report for that tag. Messages for that tag at or above the specified priority are written to the log. You can supply any number of <code>tag:priority</code> specifications in a single filter expression. The series of specifications is whitespace-delimited. The default output is to show all log messages with the Info priority (*:I).</p> <p>Here's an example of a filter expression that suppresses all log messages except those with the tag "ActivityManager", at priority "Info" or above, and all log messages with tag "MyApp", with priority "Debug" or above:</p> diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs index 3ec174e..f7dbe30 100644 --- a/docs/html/guide/guide_toc.cs +++ b/docs/html/guide/guide_toc.cs @@ -256,8 +256,7 @@ <li class="toggle-list"> <div><a href="<?cs var:toroot ?>guide/topics/renderscript/index.html"> <span class="en">RenderScript</span> - </a> - <span class="new">new!</span></div> + </a></div> <ul> <li><a href="<?cs var:toroot ?>guide/topics/renderscript/graphics.html"> <span class="en">3D Graphics</span> @@ -304,11 +303,9 @@ <!--<li><a style="color:gray;">Localization</a></li> --> <li><a href="<?cs var:toroot ?>guide/topics/appwidgets/index.html"> <span class="en">App Widgets</span></a> - <span class="new">updated</span> </li> <li><a href="<?cs var:toroot?>guide/topics/wireless/bluetooth.html"> <span class="en">Bluetooth</span></a> - <span class="new">updated</span> </li> <li><a href="<?cs var:toroot?>guide/topics/nfc/index.html"> <span class="en">Near Field Communication</span> @@ -316,7 +313,6 @@ <li class="toggle-list"> <div><a href="<?cs var:toroot?>guide/topics/usb/index.html"> <span class="en">USB</span></a> - <span class="new">new!</span> </div> <ul> <li><a href="<?cs var:toroot ?>guide/topics/usb/accessory.html">Accessory</a></li> @@ -341,7 +337,6 @@ </li> <li><a href="<?cs var:toroot?>guide/topics/admin/device-admin.html"> <span class="en">Device Administration</span></a> - <span class="new">updated</span> </li> <li class="toggle-list"> <div> diff --git a/docs/html/resources/dashboard/opengl.jd b/docs/html/resources/dashboard/opengl.jd index 3fcfa89..362ee16 100644 --- a/docs/html/resources/dashboard/opengl.jd +++ b/docs/html/resources/dashboard/opengl.jd @@ -74,6 +74,6 @@ src="http://chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b,6fad0c&chl= </tr> </table> -<p><em>Data collected during a 7-day period ending on May 6, 2011</em></p> +<p><em>Data collected during a 7-day period ending on July 1, 2011</em></p> </div> diff --git a/docs/html/sdk/ndk/index.jd b/docs/html/sdk/ndk/index.jd index e980ca5..97df84f 100644 --- a/docs/html/sdk/ndk/index.jd +++ b/docs/html/sdk/ndk/index.jd @@ -1,16 +1,16 @@ ndk=true -ndk.win_download=android-ndk-r5c-windows.zip -ndk.win_bytes=61627716 -ndk.win_checksum=2c7423842fa0f46871eab118495d4b45 +ndk.win_download=android-ndk-r6-windows.zip +ndk.win_bytes=67642809 +ndk.win_checksum=9c7d5ccc02151a3e5e950c70dc05ac6d -ndk.mac_download=android-ndk-r5c-darwin-x86.tar.bz2 -ndk.mac_bytes=50714712 -ndk.mac_checksum=183bfbbd85cf8e4c0bd7531e8803e75d +ndk.mac_download=android-ndk-r6-darwin-x86.tar.bz2 +ndk.mac_bytes=52682746 +ndk.mac_checksum=a154905e49a6246abd823b75b6eda738 -ndk.linux_download=android-ndk-r5c-linux-x86.tar.bz2 -ndk.linux_bytes=44539890 -ndk.linux_checksum=7659dfdc97026ed1d913e224d0531f61 +ndk.linux_download=android-ndk-r6-linux-x86.tar.bz2 +ndk.linux_bytes=46425290 +ndk.linux_checksum=ff0a43085fe206696d5cdcef3f4f4637 page.title=Android NDK @jd:body @@ -62,6 +62,58 @@ padding: .25em 1em; <div class="toggleable open"> <a href="#" onclick="return toggleDiv(this)"><img src= "{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px" width="9px"> + Android NDK, Revision 6</a> <em>(July 2011)</em> + + <div class="toggleme"> + <p>This release of the NDK includes support for the x86 ABI and other minor changes. + For detailed information describing the changes in this release, read the + <code>CHANGES.HTML</code> document included in the NDK package. + </p> + <dl> + <dt>General notes:</dt> + <dd> + <ul> + <li>Adds support for the x86 ABI, which allows you to generate machine code + that runs on compatible x86-based Android devices. Major features for x86 + include x86-specific toolchains, system headers, libraries and + debugging support. For all of the details regarding x86 support, + see <code>docs/CPU-X86.html</code> in the NDK package. + + <p>By default, code is generated for ARM-based devices, but you can add x86 to your + <code>APP_ABI</code> definition in your <code>Application.mk</code> file to build + for x86 platforms. For example, the following line instructs <code>ndk-build</code> + to build your code for three distinct ABIs:</p> + + <pre>APP_ABI := armeabi armeabi-v7a x86</pre> + + <p>Unless you rely on ARM-based assembly sources, you shouldn't need to touch + your <code>Android.mk</code> files to build x86 machine code.</p> + + </li> + + <li>You can build a standalone x86 toolchain using the <code>--toolchain=x86-4.4.3</code> + option when calling <code>make-standalone-toolchain.sh</code>. See + <code>docs/STANDALONE-TOOLCHAIN.html</code> for more details. + </li> + <li>The new <code>ndk-stack</code> tool lets you translate stack traces in + <code>logcat</code> that are generated by native code. The tool translates + instruction addresses into a readable format that contains things such + as the function, source file, and line number corresponding to each stack frame. + For more information and a usage example, see <code>docs/NDK-STACK.html</code>. + </li> + </ul> + </dd> + <dt>Other changes:</dt> + <dd><code>arm-eabi-4.4.0</code>, which had been deprecated since NDK r5, has been + removed from the NDK distribution.</dd> + + </dl> + </div> + </div> + +<div class="toggleable closed"> + <a href="#" onclick="return toggleDiv(this)"><img src= + "{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px" width="9px"> Android NDK, Revision 5c</a> <em>(June 2011)</em> <div class="toggleme"> diff --git a/docs/html/sdk/ndk/overview.jd b/docs/html/sdk/ndk/overview.jd index 2562a25..93c664d 100644 --- a/docs/html/sdk/ndk/overview.jd +++ b/docs/html/sdk/ndk/overview.jd @@ -53,11 +53,7 @@ page.title=What is the NDK? <li>ARMv7-A (including Thumb-2 and VFPv3-D16 instructions, with optional support for NEON/VFPv3-D32 instructions)</li> - </ul> - - <p>Future releases of the NDK will also support:</p> - <ul> <li>x86 instructions (see CPU-ARCH-ABIS.HTML for more information)</li> </ul> diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs index 0607aad..0539adb 100644 --- a/docs/html/sdk/sdk_toc.cs +++ b/docs/html/sdk/sdk_toc.cs @@ -77,7 +77,7 @@ class="new">new!</span></li> <ul> <li class="toggle-list"> <div><a href="<?cs var:toroot ?>sdk/android-3.1.html"> - <span class="en">Android 3.1 Platform</span></a> <span class="new">new!</span></div> + <span class="en">Android 3.1 Platform</span></a></div> <ul> <li><a href="<?cs var:toroot ?>sdk/android-3.1-highlights.html">Platform Highlights</a></li> <li><a href="<?cs var:toroot ?>sdk/api_diff/12/changes.html">API Differences Report »</a></li> @@ -91,7 +91,7 @@ class="new">new!</span></li> <li><a href="<?cs var:toroot ?>sdk/api_diff/11/changes.html">API Differences Report »</a></li> </ul> </li> - <li><a href="<?cs var:toroot ?>sdk/android-2.3.4.html">Android 2.3.4 Platform</span></a> <span class="new">new!</span></li> + <li><a href="<?cs var:toroot ?>sdk/android-2.3.4.html">Android 2.3.4 Platform</span></a></li> <li class="toggle-list"> <div><a href="<?cs var:toroot ?>sdk/android-2.3.3.html"> <span class="en">Android 2.3.3 Platform</span></a></div> @@ -137,8 +137,8 @@ class="new">new!</span></li> <li><a href="<?cs var:toroot ?>sdk/tools-notes.html">SDK Tools, r12</a> <span class="new">new!</span></li> <li><a href="<?cs var:toroot ?>sdk/win-usb.html">Google USB Driver, r4</a></li> - <li><a href="<?cs var:toroot ?>sdk/compatibility-library.html">Compatibility Library, r2</a> <span -class="new">new!</span></li> + <li><a href="<?cs var:toroot ?>sdk/compatibility-library.html">Compatibility Library, +r2</a></li> </ul> </li> <li> @@ -175,7 +175,7 @@ class="new">new!</span></li> <span style="display:none" class="zh-TW"></span> </h2> <ul> - <li><a href="<?cs var:toroot ?>sdk/ndk/index.html">Android NDK, r5c <span + <li><a href="<?cs var:toroot ?>sdk/ndk/index.html">Android NDK, r6 <span class="new">new!</span></a> </li> <li><a href="<?cs var:toroot ?>sdk/ndk/overview.html">What is the NDK?</a></li> diff --git a/include/media/IStreamSource.h b/include/media/IStreamSource.h index d310cee..cc63356 100644 --- a/include/media/IStreamSource.h +++ b/include/media/IStreamSource.h @@ -51,6 +51,17 @@ struct IStreamListener : public IInterface { // will be suppressed until media time reaches this timestamp. static const char *const kKeyResumeAtPTS; + // When signalling a discontinuity you can optionally + // signal that this is a "hard" discontinuity, i.e. the format + // or configuration of subsequent stream data differs from that + // currently active. To do so, include a non-zero int32_t value + // under the key "kKeyFormatChange" when issuing the DISCONTINUITY + // command. + // The new logical stream must start with proper codec initialization + // information for playback to continue, i.e. SPS and PPS in the case + // of AVC video etc. + static const char *const kKeyFormatChange; + virtual void issueCommand( Command cmd, bool synchronous, const sp<AMessage> &msg = NULL) = 0; }; diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp index 563d7e4..e232ddd 100644 --- a/libs/hwui/Caches.cpp +++ b/libs/hwui/Caches.cpp @@ -73,7 +73,6 @@ void Caches::dumpMemoryUsage() { String8 stringLog; dumpMemoryUsage(stringLog); LOGD("%s", stringLog.string()); - delete stringLog; } void Caches::dumpMemoryUsage(String8 &log) { diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index 7c10518..47049e2 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -43,7 +43,7 @@ enum DebugLevel { kDebugDisabled = 0, kDebugMemory = 1, kDebugCaches = 2, - kDebugMoreCaches = 3 + kDebugMoreCaches = kDebugMemory | kDebugCaches }; // These properties are defined in mega-bytes diff --git a/libs/rs/driver/rsdBcc.cpp b/libs/rs/driver/rsdBcc.cpp index 62eb24e..bbf2836 100644 --- a/libs/rs/driver/rsdBcc.cpp +++ b/libs/rs/driver/rsdBcc.cpp @@ -269,6 +269,7 @@ static void wc_x(void *usr, uint32_t idx) { void rsdScriptInvokeForEach(const Context *rsc, Script *s, + uint32_t slot, const Allocation * ain, Allocation * aout, const void * usr, diff --git a/libs/rs/driver/rsdBcc.h b/libs/rs/driver/rsdBcc.h index 62b50f4..67929bc 100644 --- a/libs/rs/driver/rsdBcc.h +++ b/libs/rs/driver/rsdBcc.h @@ -32,6 +32,7 @@ void rsdScriptInvokeFunction(const android::renderscript::Context *dc, void rsdScriptInvokeForEach(const android::renderscript::Context *rsc, android::renderscript::Script *s, + uint32_t slot, const android::renderscript::Allocation * ain, android::renderscript::Allocation * aout, const void * usr, diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp index b230bb5..e8b1014 100644 --- a/libs/rs/rsScriptC.cpp +++ b/libs/rs/rsScriptC.cpp @@ -121,7 +121,7 @@ void ScriptC::runForEach(Context *rsc, setupGLState(rsc); setupScript(rsc); - rsc->mHal.funcs.script.invokeForEach(rsc, this, ain, aout, usr, usrBytes, sc); + rsc->mHal.funcs.script.invokeForEach(rsc, this, 0, ain, aout, usr, usrBytes, sc); } void ScriptC::Invoke(Context *rsc, uint32_t slot, const void *data, size_t len) { diff --git a/libs/rs/rs_hal.h b/libs/rs/rs_hal.h index 928dca5..6a4537b 100644 --- a/libs/rs/rs_hal.h +++ b/libs/rs/rs_hal.h @@ -70,6 +70,7 @@ typedef struct { int (*invokeRoot)(const Context *rsc, Script *s); void (*invokeForEach)(const Context *rsc, Script *s, + uint32_t slot, const Allocation * ain, Allocation * aout, const void * usr, diff --git a/libs/utils/BackupHelpers.cpp b/libs/utils/BackupHelpers.cpp index 87549fe..7ef30f9 100644 --- a/libs/utils/BackupHelpers.cpp +++ b/libs/utils/BackupHelpers.cpp @@ -481,6 +481,14 @@ static int write_pax_header_entry(char* buf, const char* key, const char* value) return sprintf(buf, "%d %s=%s\n", len, key, value); } +// Wire format to the backup manager service is chunked: each chunk is prefixed by +// a 4-byte count of its size. A chunk size of zero (four zero bytes) indicates EOD. +void send_tarfile_chunk(BackupDataWriter* writer, const char* buffer, size_t size) { + uint32_t chunk_size_no = htonl(size); + writer->WriteEntityData(&chunk_size_no, 4); + if (size != 0) writer->WriteEntityData(buffer, size); +} + int write_tarfile(const String8& packageName, const String8& domain, const String8& rootpath, const String8& filepath, BackupDataWriter* writer) { @@ -660,16 +668,16 @@ int write_tarfile(const String8& packageName, const String8& domain, // Checksum and write the pax block header calc_tar_checksum(paxHeader); - writer->WriteEntityData(paxHeader, 512); + send_tarfile_chunk(writer, paxHeader, 512); // Now write the pax data itself int paxblocks = (paxLen + 511) / 512; - writer->WriteEntityData(paxData, 512 * paxblocks); + send_tarfile_chunk(writer, paxData, 512 * paxblocks); } // Checksum and write the 512-byte ustar file header block to the output calc_tar_checksum(buf); - writer->WriteEntityData(buf, 512); + send_tarfile_chunk(writer, buf, 512); // Now write the file data itself, for real files. We honor tar's convention that // only full 512-byte blocks are sent to write(). @@ -699,7 +707,7 @@ int write_tarfile(const String8& packageName, const String8& domain, memset(buf + nRead, 0, remainder); nRead += remainder; } - writer->WriteEntityData(buf, nRead); + send_tarfile_chunk(writer, buf, nRead); toWrite -= nRead; } } diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java index e8ddd2d..e89be08 100644 --- a/media/java/android/media/MediaScanner.java +++ b/media/java/android/media/MediaScanner.java @@ -835,6 +835,9 @@ public class MediaScanner } } + // For inserts we always use the file URI so we can insert in bulk. + // For updates we compute the URI based on the media type. + Uri tableUri = mFilesUri; Uri result = null; if (rowId == 0) { if (mMtpObjectHandle != 0) { @@ -850,7 +853,7 @@ public class MediaScanner if (mFileInserter != null) { result = mFileInserter.insert(values); } else { - result = mMediaProvider.insert(mFilesUri, values); + result = mMediaProvider.insert(tableUri, values); } if (result != null) { @@ -858,8 +861,18 @@ public class MediaScanner entry.mRowId = rowId; } } else { + if (!mNoMedia) { + if (MediaFile.isVideoFileType(mFileType)) { + tableUri = mVideoUri; + } else if (MediaFile.isImageFileType(mFileType)) { + tableUri = mImagesUri; + } else if (MediaFile.isAudioFileType(mFileType)) { + tableUri = mAudioUri; + } + } + // updated file - result = ContentUris.withAppendedId(mFilesUri, rowId); + result = ContentUris.withAppendedId(tableUri, rowId); // path should never change, and we want to avoid replacing mixed cased paths // with squashed lower case paths values.remove(MediaStore.MediaColumns.DATA); @@ -909,19 +922,19 @@ public class MediaScanner if (notifications && !mDefaultNotificationSet) { if (TextUtils.isEmpty(mDefaultNotificationFilename) || doesPathHaveFilename(entry.mPath, mDefaultNotificationFilename)) { - setSettingIfNotSet(Settings.System.NOTIFICATION_SOUND, mFilesUri, rowId); + setSettingIfNotSet(Settings.System.NOTIFICATION_SOUND, tableUri, rowId); mDefaultNotificationSet = true; } } else if (ringtones && !mDefaultRingtoneSet) { if (TextUtils.isEmpty(mDefaultRingtoneFilename) || doesPathHaveFilename(entry.mPath, mDefaultRingtoneFilename)) { - setSettingIfNotSet(Settings.System.RINGTONE, mFilesUri, rowId); + setSettingIfNotSet(Settings.System.RINGTONE, tableUri, rowId); mDefaultRingtoneSet = true; } } else if (alarms && !mDefaultAlarmSet) { if (TextUtils.isEmpty(mDefaultAlarmAlertFilename) || doesPathHaveFilename(entry.mPath, mDefaultAlarmAlertFilename)) { - setSettingIfNotSet(Settings.System.ALARM_ALERT, mFilesUri, rowId); + setSettingIfNotSet(Settings.System.ALARM_ALERT, tableUri, rowId); mDefaultAlarmSet = true; } } diff --git a/media/libmedia/IStreamSource.cpp b/media/libmedia/IStreamSource.cpp index c14ee82..b311f35 100644 --- a/media/libmedia/IStreamSource.cpp +++ b/media/libmedia/IStreamSource.cpp @@ -29,6 +29,9 @@ namespace android { // static const char *const IStreamListener::kKeyResumeAtPTS = "resume-at-PTS"; +// static +const char *const IStreamListener::kKeyFormatChange = "format-change"; + enum { // IStreamSource SET_LISTENER = IBinder::FIRST_CALL_TRANSACTION, diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp index bbc8a6e..a6a3a18 100644 --- a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp +++ b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp @@ -63,8 +63,17 @@ bool NuPlayer::StreamingSource::feedMoreTSData() { mEOS = true; break; } else if (n == INFO_DISCONTINUITY) { - mTSParser->signalDiscontinuity( - ATSParser::DISCONTINUITY_SEEK, extra); + ATSParser::DiscontinuityType type = ATSParser::DISCONTINUITY_SEEK; + + int32_t formatChange; + if (extra != NULL + && extra->findInt32( + IStreamListener::kKeyFormatChange, &formatChange) + && formatChange != 0) { + type = ATSParser::DISCONTINUITY_FORMATCHANGE; + } + + mTSParser->signalDiscontinuity(type, extra); } else if (n < 0) { CHECK_EQ(n, -EWOULDBLOCK); break; diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk index 7b3b95b..0b998b9 100644 --- a/media/libstagefright/Android.mk +++ b/media/libstagefright/Android.mk @@ -3,8 +3,6 @@ include $(CLEAR_VARS) include frameworks/base/media/libstagefright/codecs/common/Config.mk -BUILD_WITH_SOFTWARE_DECODERS := false - LOCAL_SRC_FILES:= \ ACodec.cpp \ AACExtractor.cpp \ @@ -96,26 +94,6 @@ LOCAL_STATIC_LIBRARIES := \ libstagefright_id3 \ libFLAC \ -ifeq ($(BUILD_WITH_SOFTWARE_DECODERS),true) - -LOCAL_SRC_FILES += \ - ThreadedSource.cpp \ - -LOCAL_STATIC_LIBRARIES += \ - libstagefright_aacdec \ - libstagefright_amrnbdec \ - libstagefright_amrwbdec \ - libstagefright_avcdec \ - libstagefright_g711dec \ - libstagefright_mp3dec \ - libstagefright_m4vh263dec \ - libstagefright_vorbisdec \ - libstagefright_vpxdec \ - libvpx \ - -endif - - ################################################################################ # The following was shamelessly copied from external/webkit/Android.mk and @@ -177,10 +155,6 @@ LOCAL_SHARED_LIBRARIES += \ LOCAL_CFLAGS += -Wno-multichar -ifeq ($(BUILD_WITH_SOFTWARE_DECODERS),true) - LOCAL_CFLAGS += -DHAVE_SOFTWARE_DECODERS -endif - LOCAL_MODULE:= libstagefright include $(BUILD_SHARED_LIBRARY) diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp index 3b05752..b7b0dc0 100755 --- a/media/libstagefright/OMXCodec.cpp +++ b/media/libstagefright/OMXCodec.cpp @@ -18,20 +18,11 @@ #define LOG_TAG "OMXCodec" #include <utils/Log.h> -#include "include/AACDecoder.h" #include "include/AACEncoder.h" -#include "include/AMRNBDecoder.h" #include "include/AMRNBEncoder.h" -#include "include/AMRWBDecoder.h" #include "include/AMRWBEncoder.h" -#include "include/AVCDecoder.h" #include "include/AVCEncoder.h" -#include "include/G711Decoder.h" -#include "include/M4vH263Decoder.h" #include "include/M4vH263Encoder.h" -#include "include/MP3Decoder.h" -#include "include/VorbisDecoder.h" -#include "include/VPXDecoder.h" #include "include/ESDS.h" @@ -53,10 +44,6 @@ #include <OMX_Audio.h> #include <OMX_Component.h> -#if HAVE_SOFTWARE_DECODERS -#include "include/ThreadedSource.h" -#endif - #include "include/avc_utils.h" namespace android { @@ -79,24 +66,6 @@ FACTORY_CREATE_ENCODER(AACEncoder) FACTORY_CREATE_ENCODER(AVCEncoder) FACTORY_CREATE_ENCODER(M4vH263Encoder) -#if HAVE_SOFTWARE_DECODERS - -#define FACTORY_CREATE(name) \ -static sp<MediaSource> Make##name(const sp<MediaSource> &source) { \ - return new name(source); \ -} - -FACTORY_CREATE(AMRNBDecoder) -FACTORY_CREATE(AMRWBDecoder) -FACTORY_CREATE(AACDecoder) -FACTORY_CREATE(AVCDecoder) -FACTORY_CREATE(G711Decoder) -FACTORY_CREATE(MP3Decoder) -FACTORY_CREATE(M4vH263Decoder) -FACTORY_CREATE(VorbisDecoder) -FACTORY_CREATE(VPXDecoder) -#endif - static sp<MediaSource> InstantiateSoftwareEncoder( const char *name, const sp<MediaSource> &source, const sp<MetaData> &meta) { @@ -122,40 +91,6 @@ static sp<MediaSource> InstantiateSoftwareEncoder( return NULL; } -static sp<MediaSource> InstantiateSoftwareCodec( - const char *name, const sp<MediaSource> &source) { -#if HAVE_SOFTWARE_DECODERS - struct FactoryInfo { - const char *name; - sp<MediaSource> (*CreateFunc)(const sp<MediaSource> &); - }; - - static const FactoryInfo kFactoryInfo[] = { - FACTORY_REF(AMRNBDecoder) - FACTORY_REF(AMRWBDecoder) - FACTORY_REF(AACDecoder) - FACTORY_REF(AVCDecoder) - FACTORY_REF(G711Decoder) - FACTORY_REF(MP3Decoder) - FACTORY_REF(M4vH263Decoder) - FACTORY_REF(VorbisDecoder) - FACTORY_REF(VPXDecoder) - }; - for (size_t i = 0; - i < sizeof(kFactoryInfo) / sizeof(kFactoryInfo[0]); ++i) { - if (!strcmp(name, kFactoryInfo[i].name)) { - if (!strcmp(name, "VPXDecoder")) { - return new ThreadedSource( - (*kFactoryInfo[i].CreateFunc)(source)); - } - return (*kFactoryInfo[i].CreateFunc)(source); - } - } -#endif - - return NULL; -} - #undef FACTORY_REF #undef FACTORY_CREATE @@ -163,23 +98,17 @@ static const CodecInfo kDecoderInfo[] = { { MEDIA_MIMETYPE_IMAGE_JPEG, "OMX.TI.JPEG.decode" }, // { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.TI.MP3.decode" }, { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.google.mp3.decoder" }, - { MEDIA_MIMETYPE_AUDIO_MPEG, "MP3Decoder" }, // { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.TI.AMR.decode" }, // { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.Nvidia.amr.decoder" }, { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.google.amrnb.decoder" }, - { MEDIA_MIMETYPE_AUDIO_AMR_NB, "AMRNBDecoder" }, // { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.Nvidia.amrwb.decoder" }, { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.decode" }, { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.google.amrwb.decoder" }, - { MEDIA_MIMETYPE_AUDIO_AMR_WB, "AMRWBDecoder" }, // { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.Nvidia.aac.decoder" }, { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.decode" }, { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.google.aac.decoder" }, - { MEDIA_MIMETYPE_AUDIO_AAC, "AACDecoder" }, { MEDIA_MIMETYPE_AUDIO_G711_ALAW, "OMX.google.g711.alaw.decoder" }, - { MEDIA_MIMETYPE_AUDIO_G711_ALAW, "G711Decoder" }, { MEDIA_MIMETYPE_AUDIO_G711_MLAW, "OMX.google.g711.mlaw.decoder" }, - { MEDIA_MIMETYPE_AUDIO_G711_MLAW, "G711Decoder" }, { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.DUCATI1.VIDEO.DECODER" }, { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.Nvidia.mp4.decode" }, { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.7x30.video.decoder.mpeg4" }, @@ -187,14 +116,12 @@ static const CodecInfo kDecoderInfo[] = { { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.Decoder" }, { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.SEC.MPEG4.Decoder" }, { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.google.mpeg4.decoder" }, - { MEDIA_MIMETYPE_VIDEO_MPEG4, "M4vH263Decoder" }, { MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.DUCATI1.VIDEO.DECODER" }, { MEDIA_MIMETYPE_VIDEO_H263, "OMX.Nvidia.h263.decode" }, { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.7x30.video.decoder.h263" }, { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.decoder.h263" }, { MEDIA_MIMETYPE_VIDEO_H263, "OMX.SEC.H263.Decoder" }, { MEDIA_MIMETYPE_VIDEO_H263, "OMX.google.h263.decoder" }, - { MEDIA_MIMETYPE_VIDEO_H263, "M4vH263Decoder" }, { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.DUCATI1.VIDEO.DECODER" }, { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.Nvidia.h264.decode" }, { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.7x30.video.decoder.avc" }, @@ -203,11 +130,8 @@ static const CodecInfo kDecoderInfo[] = { { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.SEC.AVC.Decoder" }, { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.google.h264.decoder" }, { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.google.avc.decoder" }, - { MEDIA_MIMETYPE_VIDEO_AVC, "AVCDecoder" }, { MEDIA_MIMETYPE_AUDIO_VORBIS, "OMX.google.vorbis.decoder" }, - { MEDIA_MIMETYPE_AUDIO_VORBIS, "VorbisDecoder" }, { MEDIA_MIMETYPE_VIDEO_VPX, "OMX.google.vpx.decoder" }, - { MEDIA_MIMETYPE_VIDEO_VPX, "VPXDecoder" }, { MEDIA_MIMETYPE_VIDEO_MPEG2, "OMX.Nvidia.mpeg2v.decode" }, }; @@ -518,14 +442,15 @@ sp<MediaSource> OMXCodec::Create( for (size_t i = 0; i < matchingCodecs.size(); ++i) { componentName = matchingCodecs[i].string(); - sp<MediaSource> softwareCodec = createEncoder? - InstantiateSoftwareEncoder(componentName, source, meta): - InstantiateSoftwareCodec(componentName, source); + if (createEncoder) { + sp<MediaSource> softwareCodec = + InstantiateSoftwareEncoder(componentName, source, meta); - if (softwareCodec != NULL) { - LOGV("Successfully allocated software codec '%s'", componentName); + if (softwareCodec != NULL) { + LOGV("Successfully allocated software codec '%s'", componentName); - return softwareCodec; + return softwareCodec; + } } LOGV("Attempting to allocate OMX node '%s'", componentName); @@ -4430,12 +4355,9 @@ status_t QueryCodecs( if (strncmp(componentName, "OMX.", 4)) { // Not an OpenMax component but a software codec. -#if HAVE_SOFTWARE_DECODERS results->push(); CodecCapabilities *caps = &results->editItemAt(results->size() - 1); caps->mComponentName = componentName; -#endif - continue; } diff --git a/media/libstagefright/ThreadedSource.cpp b/media/libstagefright/ThreadedSource.cpp deleted file mode 100644 index 38c6e2d..0000000 --- a/media/libstagefright/ThreadedSource.cpp +++ /dev/null @@ -1,213 +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_TAG "ThreadedSource" -//#define LOG_NDEBUG 0 -#include <utils/Log.h> - -#include "include/ThreadedSource.h" - -#include <media/stagefright/foundation/ADebug.h> -#include <media/stagefright/foundation/AMessage.h> -#include <media/stagefright/MediaBuffer.h> -#include <media/stagefright/MetaData.h> - -namespace android { - -static const size_t kMaxQueueSize = 2; - -ThreadedSource::ThreadedSource(const sp<MediaSource> &source) - : mSource(source), - mReflector(new AHandlerReflector<ThreadedSource>(this)), - mLooper(new ALooper), - mStarted(false) { - mLooper->registerHandler(mReflector); -} - -ThreadedSource::~ThreadedSource() { - if (mStarted) { - stop(); - } -} - -status_t ThreadedSource::start(MetaData *params) { - CHECK(!mStarted); - - status_t err = mSource->start(params); - - if (err != OK) { - return err; - } - - mFinalResult = OK; - mSeekTimeUs = -1; - mDecodePending = false; - - Mutex::Autolock autoLock(mLock); - postDecodeMore_l(); - - CHECK_EQ(mLooper->start(), (status_t)OK); - - mStarted = true; - - return OK; -} - -status_t ThreadedSource::stop() { - CHECK(mStarted); - - CHECK_EQ(mLooper->stop(), (status_t)OK); - - Mutex::Autolock autoLock(mLock); - clearQueue_l(); - - status_t err = mSource->stop(); - - mStarted = false; - - return err; -} - -sp<MetaData> ThreadedSource::getFormat() { - return mSource->getFormat(); -} - -status_t ThreadedSource::read( - MediaBuffer **buffer, const ReadOptions *options) { - *buffer = NULL; - - Mutex::Autolock autoLock(mLock); - - int64_t seekTimeUs; - ReadOptions::SeekMode seekMode; - if (options && options->getSeekTo(&seekTimeUs, &seekMode)) { - int32_t seekComplete = 0; - - sp<AMessage> msg = new AMessage(kWhatSeek, mReflector->id()); - msg->setInt64("timeUs", seekTimeUs); - msg->setInt32("mode", seekMode); - msg->setPointer("complete", &seekComplete); - msg->post(); - - while (!seekComplete) { - mCondition.wait(mLock); - } - } - - while (mQueue.empty() && mFinalResult == OK) { - mCondition.wait(mLock); - } - - if (!mQueue.empty()) { - *buffer = *mQueue.begin(); - mQueue.erase(mQueue.begin()); - - if (mFinalResult == OK) { - postDecodeMore_l(); - } - - return OK; - } - - return mFinalResult; -} - -void ThreadedSource::onMessageReceived(const sp<AMessage> &msg) { - switch (msg->what()) { - case kWhatSeek: - { - CHECK(msg->findInt64("timeUs", &mSeekTimeUs)); - CHECK_GE(mSeekTimeUs, 0ll); - - int32_t x; - CHECK(msg->findInt32("mode", &x)); - mSeekMode = (ReadOptions::SeekMode)x; - - int32_t *seekComplete; - CHECK(msg->findPointer("complete", (void **)&seekComplete)); - - Mutex::Autolock autoLock(mLock); - clearQueue_l(); - mFinalResult = OK; - - *seekComplete = 1; - mCondition.signal(); - - postDecodeMore_l(); - break; - } - - case kWhatDecodeMore: - { - { - Mutex::Autolock autoLock(mLock); - mDecodePending = false; - - if (mQueue.size() == kMaxQueueSize) { - break; - } - } - - MediaBuffer *buffer; - ReadOptions options; - if (mSeekTimeUs >= 0) { - options.setSeekTo(mSeekTimeUs, mSeekMode); - mSeekTimeUs = -1ll; - } - status_t err = mSource->read(&buffer, &options); - - Mutex::Autolock autoLock(mLock); - - if (err != OK) { - mFinalResult = err; - } else { - mQueue.push_back(buffer); - - if (mQueue.size() < kMaxQueueSize) { - postDecodeMore_l(); - } - } - - mCondition.signal(); - break; - } - - default: - TRESPASS(); - break; - } -} - -void ThreadedSource::postDecodeMore_l() { - if (mDecodePending) { - return; - } - - mDecodePending = true; - (new AMessage(kWhatDecodeMore, mReflector->id()))->post(); -} - -void ThreadedSource::clearQueue_l() { - while (!mQueue.empty()) { - MediaBuffer *buffer = *mQueue.begin(); - mQueue.erase(mQueue.begin()); - - buffer->release(); - buffer = NULL; - } -} - -} // namespace android diff --git a/media/libstagefright/codecs/aacdec/AACDecoder.cpp b/media/libstagefright/codecs/aacdec/AACDecoder.cpp deleted file mode 100644 index d2e3eaa..0000000 --- a/media/libstagefright/codecs/aacdec/AACDecoder.cpp +++ /dev/null @@ -1,335 +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 "AACDecoder.h" -#define LOG_TAG "AACDecoder" - -#include "../../include/ESDS.h" - -#include "pvmp4audiodecoder_api.h" - -#include <media/stagefright/foundation/ADebug.h> -#include <media/stagefright/MediaBufferGroup.h> -#include <media/stagefright/MediaDefs.h> -#include <media/stagefright/MetaData.h> - -namespace android { - -AACDecoder::AACDecoder(const sp<MediaSource> &source) - : mSource(source), - mStarted(false), - mBufferGroup(NULL), - mConfig(new tPVMP4AudioDecoderExternal), - mDecoderBuf(NULL), - mAnchorTimeUs(0), - mNumSamplesOutput(0), - mInputBuffer(NULL) { - - sp<MetaData> srcFormat = mSource->getFormat(); - - int32_t sampleRate; - CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate)); - - mMeta = new MetaData; - mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); - - // We'll always output stereo, regardless of how many channels are - // present in the input due to decoder limitations. - mMeta->setInt32(kKeyChannelCount, 2); - mMeta->setInt32(kKeySampleRate, sampleRate); - - int64_t durationUs; - if (srcFormat->findInt64(kKeyDuration, &durationUs)) { - mMeta->setInt64(kKeyDuration, durationUs); - } - mMeta->setCString(kKeyDecoderComponent, "AACDecoder"); - - mInitCheck = initCheck(); -} - -status_t AACDecoder::initCheck() { - memset(mConfig, 0, sizeof(tPVMP4AudioDecoderExternal)); - mConfig->outputFormat = OUTPUTFORMAT_16PCM_INTERLEAVED; - mConfig->aacPlusEnabled = 1; - - // The software decoder doesn't properly support mono output on - // AACplus files. Always output stereo. - mConfig->desiredChannels = 2; - - UInt32 memRequirements = PVMP4AudioDecoderGetMemRequirements(); - mDecoderBuf = malloc(memRequirements); - - status_t err = PVMP4AudioDecoderInitLibrary(mConfig, mDecoderBuf); - if (err != MP4AUDEC_SUCCESS) { - LOGE("Failed to initialize MP4 audio decoder"); - return UNKNOWN_ERROR; - } - - uint32_t type; - const void *data; - size_t size; - sp<MetaData> meta = mSource->getFormat(); - if (meta->findData(kKeyESDS, &type, &data, &size)) { - ESDS esds((const char *)data, size); - CHECK_EQ(esds.InitCheck(), (status_t)OK); - - const void *codec_specific_data; - size_t codec_specific_data_size; - esds.getCodecSpecificInfo( - &codec_specific_data, &codec_specific_data_size); - - mConfig->pInputBuffer = (UChar *)codec_specific_data; - mConfig->inputBufferCurrentLength = codec_specific_data_size; - mConfig->inputBufferMaxLength = 0; - - if (PVMP4AudioDecoderConfig(mConfig, mDecoderBuf) - != MP4AUDEC_SUCCESS) { - return ERROR_UNSUPPORTED; - } - } - return OK; -} - -AACDecoder::~AACDecoder() { - if (mStarted) { - stop(); - } - - delete mConfig; - mConfig = NULL; -} - -status_t AACDecoder::start(MetaData *params) { - CHECK(!mStarted); - - mBufferGroup = new MediaBufferGroup; - mBufferGroup->add_buffer(new MediaBuffer(4096 * 2)); - - mSource->start(); - - mAnchorTimeUs = 0; - mNumSamplesOutput = 0; - mStarted = true; - mNumDecodedBuffers = 0; - mUpsamplingFactor = 2; - - return OK; -} - -status_t AACDecoder::stop() { - CHECK(mStarted); - - if (mInputBuffer) { - mInputBuffer->release(); - mInputBuffer = NULL; - } - - free(mDecoderBuf); - mDecoderBuf = NULL; - - delete mBufferGroup; - mBufferGroup = NULL; - - mSource->stop(); - - mStarted = false; - - return OK; -} - -sp<MetaData> AACDecoder::getFormat() { - return mMeta; -} - -status_t AACDecoder::read( - MediaBuffer **out, const ReadOptions *options) { - status_t err; - - *out = NULL; - - int64_t seekTimeUs; - ReadOptions::SeekMode mode; - if (options && options->getSeekTo(&seekTimeUs, &mode)) { - CHECK(seekTimeUs >= 0); - - mNumSamplesOutput = 0; - - if (mInputBuffer) { - mInputBuffer->release(); - mInputBuffer = NULL; - } - - // Make sure that the next buffer output does not still - // depend on fragments from the last one decoded. - PVMP4AudioDecoderResetBuffer(mDecoderBuf); - } else { - seekTimeUs = -1; - } - - if (mInputBuffer == NULL) { - err = mSource->read(&mInputBuffer, options); - - if (err != OK) { - return err; - } - - int64_t timeUs; - if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) { - mAnchorTimeUs = timeUs; - mNumSamplesOutput = 0; - } else { - // We must have a new timestamp after seeking. - CHECK(seekTimeUs < 0); - } - } - - MediaBuffer *buffer; - CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), (status_t)OK); - - mConfig->pInputBuffer = - (UChar *)mInputBuffer->data() + mInputBuffer->range_offset(); - - mConfig->inputBufferCurrentLength = mInputBuffer->range_length(); - mConfig->inputBufferMaxLength = 0; - mConfig->inputBufferUsedLength = 0; - mConfig->remainderBits = 0; - - mConfig->pOutputBuffer = static_cast<Int16 *>(buffer->data()); - mConfig->pOutputBuffer_plus = &mConfig->pOutputBuffer[2048]; - mConfig->repositionFlag = false; - - Int decoderErr = PVMP4AudioDecodeFrame(mConfig, mDecoderBuf); - - /* - * AAC+/eAAC+ streams can be signalled in two ways: either explicitly - * or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual - * rate system and the sampling rate in the final output is actually - * doubled compared with the core AAC decoder sampling rate. - * - * Explicit signalling is done by explicitly defining SBR audio object - * type in the bitstream. Implicit signalling is done by embedding - * SBR content in AAC extension payload specific to SBR, and hence - * requires an AAC decoder to perform pre-checks on actual audio frames. - * - * Thus, we could not say for sure whether a stream is - * AAC+/eAAC+ until the first data frame is decoded. - */ - if (++mNumDecodedBuffers <= 2) { - LOGV("audio/extended audio object type: %d + %d", - mConfig->audioObjectType, mConfig->extendedAudioObjectType); - LOGV("aac+ upsampling factor: %d desired channels: %d", - mConfig->aacPlusUpsamplingFactor, mConfig->desiredChannels); - - CHECK(mNumDecodedBuffers > 0); - - if (decoderErr != MP4AUDEC_SUCCESS) { - // If decoding fails this early, the fields in mConfig may - // not be valid and we cannot recover. - - LOGE("Unable to decode aac content, decoder returned error %d", - decoderErr); - - buffer->release(); - buffer = NULL; - - mInputBuffer->release(); - mInputBuffer = NULL; - - return ERROR_UNSUPPORTED; - } - - if (mNumDecodedBuffers == 1) { - mUpsamplingFactor = mConfig->aacPlusUpsamplingFactor; - // Check on the sampling rate to see whether it is changed. - int32_t sampleRate; - CHECK(mMeta->findInt32(kKeySampleRate, &sampleRate)); - if (mConfig->samplingRate != sampleRate) { - mMeta->setInt32(kKeySampleRate, mConfig->samplingRate); - LOGW("Sample rate was %d Hz, but now is %d Hz", - sampleRate, mConfig->samplingRate); - buffer->release(); - mInputBuffer->release(); - mInputBuffer = NULL; - return INFO_FORMAT_CHANGED; - } - } else { // mNumDecodedBuffers == 2 - if (mConfig->extendedAudioObjectType == MP4AUDIO_AAC_LC || - mConfig->extendedAudioObjectType == MP4AUDIO_LTP) { - if (mUpsamplingFactor == 2) { - // The stream turns out to be not aacPlus mode anyway - LOGW("Disable AAC+/eAAC+ since extended audio object type is %d", - mConfig->extendedAudioObjectType); - mConfig->aacPlusEnabled = 0; - } - } else { - if (mUpsamplingFactor == 1) { - // aacPlus mode does not buy us anything, but to cause - // 1. CPU load to increase, and - // 2. a half speed of decoding - LOGW("Disable AAC+/eAAC+ since upsampling factor is 1"); - mConfig->aacPlusEnabled = 0; - } - } - } - } - - size_t numOutBytes = - mConfig->frameLength * sizeof(int16_t) * mConfig->desiredChannels; - if (mUpsamplingFactor == 2) { - if (mConfig->desiredChannels == 1) { - memcpy(&mConfig->pOutputBuffer[1024], &mConfig->pOutputBuffer[2048], numOutBytes * 2); - } - numOutBytes *= 2; - } - - if (decoderErr != MP4AUDEC_SUCCESS) { - LOGW("AAC decoder returned error %d, substituting silence", decoderErr); - - memset(buffer->data(), 0, numOutBytes); - - // Discard input buffer. - mInputBuffer->release(); - mInputBuffer = NULL; - - // fall through - } - - buffer->set_range(0, numOutBytes); - - if (mInputBuffer != NULL) { - mInputBuffer->set_range( - mInputBuffer->range_offset() + mConfig->inputBufferUsedLength, - mInputBuffer->range_length() - mConfig->inputBufferUsedLength); - - if (mInputBuffer->range_length() == 0) { - mInputBuffer->release(); - mInputBuffer = NULL; - } - } - - buffer->meta_data()->setInt64( - kKeyTime, - mAnchorTimeUs - + (mNumSamplesOutput * 1000000) / mConfig->samplingRate); - - mNumSamplesOutput += mConfig->frameLength * mUpsamplingFactor; - - *out = buffer; - - return OK; -} - -} // namespace android diff --git a/media/libstagefright/codecs/aacdec/Android.mk b/media/libstagefright/codecs/aacdec/Android.mk index 359a2ec..20c7bc0 100644 --- a/media/libstagefright/codecs/aacdec/Android.mk +++ b/media/libstagefright/codecs/aacdec/Android.mk @@ -143,7 +143,6 @@ LOCAL_SRC_FILES := \ unpack_idx.cpp \ window_tables_fxp.cpp \ pvmp4setaudioconfig.cpp \ - AACDecoder.cpp \ LOCAL_CFLAGS := -DAAC_PLUS -DHQ_SBR -DPARAMETRICSTEREO -DOSCL_IMPORT_REF= -DOSCL_EXPORT_REF= -DOSCL_UNUSED_ARG= diff --git a/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp b/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp deleted file mode 100644 index a11d46b..0000000 --- a/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp +++ /dev/null @@ -1,208 +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. - */ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "AMRNBDecoder" -#include <utils/Log.h> - -#include "AMRNBDecoder.h" - -#include "gsmamr_dec.h" - -#include <media/stagefright/MediaBufferGroup.h> -#include <media/stagefright/MediaDebug.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; - -AMRNBDecoder::AMRNBDecoder(const sp<MediaSource> &source) - : mSource(source), - mStarted(false), - mBufferGroup(NULL), - mState(NULL), - mAnchorTimeUs(0), - mNumSamplesOutput(0), - mInputBuffer(NULL) { -} - -AMRNBDecoder::~AMRNBDecoder() { - if (mStarted) { - stop(); - } -} - -status_t AMRNBDecoder::start(MetaData *params) { - CHECK(!mStarted); - - mBufferGroup = new MediaBufferGroup; - mBufferGroup->add_buffer( - new MediaBuffer(kNumSamplesPerFrame * sizeof(int16_t))); - - CHECK_EQ(GSMInitDecode(&mState, (Word8 *)"AMRNBDecoder"), 0); - - mSource->start(); - - mAnchorTimeUs = 0; - mNumSamplesOutput = 0; - mStarted = true; - - return OK; -} - -status_t AMRNBDecoder::stop() { - CHECK(mStarted); - - if (mInputBuffer) { - mInputBuffer->release(); - mInputBuffer = NULL; - } - - delete mBufferGroup; - mBufferGroup = NULL; - - GSMDecodeFrameExit(&mState); - - mSource->stop(); - - mStarted = false; - - return OK; -} - -sp<MetaData> AMRNBDecoder::getFormat() { - sp<MetaData> srcFormat = mSource->getFormat(); - - int32_t numChannels; - int32_t sampleRate; - - CHECK(srcFormat->findInt32(kKeyChannelCount, &numChannels)); - CHECK_EQ(numChannels, 1); - - CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate)); - CHECK_EQ(sampleRate, kSampleRate); - - sp<MetaData> meta = new MetaData; - meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); - meta->setInt32(kKeyChannelCount, numChannels); - meta->setInt32(kKeySampleRate, sampleRate); - - int64_t durationUs; - if (srcFormat->findInt64(kKeyDuration, &durationUs)) { - meta->setInt64(kKeyDuration, durationUs); - } - - meta->setCString(kKeyDecoderComponent, "AMRNBDecoder"); - - return meta; -} - -status_t AMRNBDecoder::read( - MediaBuffer **out, const ReadOptions *options) { - status_t err; - - *out = NULL; - - int64_t seekTimeUs; - ReadOptions::SeekMode mode; - if (options && options->getSeekTo(&seekTimeUs, &mode)) { - CHECK(seekTimeUs >= 0); - - mNumSamplesOutput = 0; - - if (mInputBuffer) { - mInputBuffer->release(); - mInputBuffer = NULL; - } - } else { - seekTimeUs = -1; - } - - if (mInputBuffer == NULL) { - err = mSource->read(&mInputBuffer, options); - - if (err != OK) { - return err; - } - - int64_t timeUs; - if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) { - mAnchorTimeUs = timeUs; - mNumSamplesOutput = 0; - } else { - // We must have a new timestamp after seeking. - CHECK(seekTimeUs < 0); - } - } - - MediaBuffer *buffer; - CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK); - - const uint8_t *inputPtr = - (const uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset(); - - int32_t numBytesRead = - AMRDecode(mState, - (Frame_Type_3GPP)((inputPtr[0] >> 3) & 0x0f), - (UWord8 *)&inputPtr[1], - static_cast<int16_t *>(buffer->data()), - MIME_IETF); - - if (numBytesRead == -1 ) { - LOGE("PV AMR decoder AMRDecode() call failed"); - buffer->release(); - buffer = NULL; - return ERROR_MALFORMED; - } - ++numBytesRead; // Include the frame type header byte. - - buffer->set_range(0, kNumSamplesPerFrame * sizeof(int16_t)); - - if (static_cast<size_t>(numBytesRead) > mInputBuffer->range_length()) { - // This is bad, should never have happened, but did. Abort now. - - buffer->release(); - buffer = NULL; - - return ERROR_MALFORMED; - } - - mInputBuffer->set_range( - mInputBuffer->range_offset() + numBytesRead, - mInputBuffer->range_length() - numBytesRead); - - if (mInputBuffer->range_length() == 0) { - mInputBuffer->release(); - mInputBuffer = NULL; - } - - buffer->meta_data()->setInt64( - kKeyTime, - mAnchorTimeUs - + (mNumSamplesOutput * 1000000) / kSampleRate); - - mNumSamplesOutput += kNumSamplesPerFrame; - - *out = buffer; - - return OK; -} - -} // namespace android diff --git a/media/libstagefright/codecs/amrnb/dec/Android.mk b/media/libstagefright/codecs/amrnb/dec/Android.mk index 5862abc..23a22ef 100644 --- a/media/libstagefright/codecs/amrnb/dec/Android.mk +++ b/media/libstagefright/codecs/amrnb/dec/Android.mk @@ -2,7 +2,6 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := \ - AMRNBDecoder.cpp \ src/a_refl.cpp \ src/agc.cpp \ src/amrdecode.cpp \ diff --git a/media/libstagefright/codecs/amrwb/AMRWBDecoder.cpp b/media/libstagefright/codecs/amrwb/AMRWBDecoder.cpp deleted file mode 100644 index 5b111ef..0000000 --- a/media/libstagefright/codecs/amrwb/AMRWBDecoder.cpp +++ /dev/null @@ -1,225 +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 "AMRWBDecoder.h" - -#include "pvamrwbdecoder.h" - -#include <media/stagefright/MediaBufferGroup.h> -#include <media/stagefright/MediaDebug.h> -#include <media/stagefright/MediaDefs.h> -#include <media/stagefright/MetaData.h> - -namespace android { - -static const int32_t kNumSamplesPerFrame = 320; -static const int32_t kSampleRate = 16000; - -AMRWBDecoder::AMRWBDecoder(const sp<MediaSource> &source) - : mSource(source), - mStarted(false), - mBufferGroup(NULL), - mState(NULL), - mDecoderBuf(NULL), - mDecoderCookie(NULL), - mAnchorTimeUs(0), - mNumSamplesOutput(0), - mInputBuffer(NULL) { -} - -AMRWBDecoder::~AMRWBDecoder() { - if (mStarted) { - stop(); - } -} - -status_t AMRWBDecoder::start(MetaData *params) { - CHECK(!mStarted); - - mBufferGroup = new MediaBufferGroup; - mBufferGroup->add_buffer( - new MediaBuffer(kNumSamplesPerFrame * sizeof(int16_t))); - - int32_t memReq = pvDecoder_AmrWbMemRequirements(); - mDecoderBuf = malloc(memReq); - - pvDecoder_AmrWb_Init(&mState, mDecoderBuf, &mDecoderCookie); - - mSource->start(); - - mAnchorTimeUs = 0; - mNumSamplesOutput = 0; - mStarted = true; - - return OK; -} - -status_t AMRWBDecoder::stop() { - CHECK(mStarted); - - if (mInputBuffer) { - mInputBuffer->release(); - mInputBuffer = NULL; - } - - delete mBufferGroup; - mBufferGroup = NULL; - - free(mDecoderBuf); - mDecoderBuf = NULL; - - mSource->stop(); - - mStarted = false; - - return OK; -} - -sp<MetaData> AMRWBDecoder::getFormat() { - sp<MetaData> srcFormat = mSource->getFormat(); - - int32_t numChannels; - int32_t sampleRate; - - CHECK(srcFormat->findInt32(kKeyChannelCount, &numChannels)); - CHECK_EQ(numChannels, 1); - - CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate)); - CHECK_EQ(sampleRate, kSampleRate); - - sp<MetaData> meta = new MetaData; - meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); - meta->setInt32(kKeyChannelCount, numChannels); - meta->setInt32(kKeySampleRate, sampleRate); - - int64_t durationUs; - if (srcFormat->findInt64(kKeyDuration, &durationUs)) { - meta->setInt64(kKeyDuration, durationUs); - } - - meta->setCString(kKeyDecoderComponent, "AMRWBDecoder"); - - return meta; -} - -static size_t getFrameSize(unsigned FT) { - static const size_t kFrameSizeWB[9] = { - 132, 177, 253, 285, 317, 365, 397, 461, 477 - }; - - size_t frameSize = kFrameSizeWB[FT]; - - // Round up bits to bytes and add 1 for the header byte. - frameSize = (frameSize + 7) / 8 + 1; - - return frameSize; -} - -status_t AMRWBDecoder::read( - MediaBuffer **out, const ReadOptions *options) { - status_t err; - - *out = NULL; - - int64_t seekTimeUs; - ReadOptions::SeekMode seekMode; - if (options && options->getSeekTo(&seekTimeUs, &seekMode)) { - CHECK(seekTimeUs >= 0); - - mNumSamplesOutput = 0; - - if (mInputBuffer) { - mInputBuffer->release(); - mInputBuffer = NULL; - } - } else { - seekTimeUs = -1; - } - - if (mInputBuffer == NULL) { - err = mSource->read(&mInputBuffer, options); - - if (err != OK) { - return err; - } - - int64_t timeUs; - if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) { - mAnchorTimeUs = timeUs; - mNumSamplesOutput = 0; - } else { - // We must have a new timestamp after seeking. - CHECK(seekTimeUs < 0); - } - } - - MediaBuffer *buffer; - CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK); - - const uint8_t *inputPtr = - (const uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset(); - - int16 mode = ((inputPtr[0] >> 3) & 0x0f); - size_t frameSize = getFrameSize(mode); - CHECK(mInputBuffer->range_length() >= frameSize); - - int16 frameType; - RX_State_wb rx_state; - mime_unsorting( - const_cast<uint8_t *>(&inputPtr[1]), - mInputSampleBuffer, - &frameType, &mode, 1, &rx_state); - - int16_t *outPtr = (int16_t *)buffer->data(); - - int16_t numSamplesOutput; - pvDecoder_AmrWb( - mode, mInputSampleBuffer, - outPtr, - &numSamplesOutput, - mDecoderBuf, frameType, mDecoderCookie); - - CHECK_EQ(numSamplesOutput, kNumSamplesPerFrame); - - for (int i = 0; i < kNumSamplesPerFrame; ++i) { - /* Delete the 2 LSBs (14-bit output) */ - outPtr[i] &= 0xfffC; - } - - buffer->set_range(0, numSamplesOutput * sizeof(int16_t)); - - mInputBuffer->set_range( - mInputBuffer->range_offset() + frameSize, - mInputBuffer->range_length() - frameSize); - - if (mInputBuffer->range_length() == 0) { - mInputBuffer->release(); - mInputBuffer = NULL; - } - - buffer->meta_data()->setInt64( - kKeyTime, - mAnchorTimeUs - + (mNumSamplesOutput * 1000000) / kSampleRate); - - mNumSamplesOutput += kNumSamplesPerFrame; - - *out = buffer; - - return OK; -} - -} // namespace android diff --git a/media/libstagefright/codecs/amrwb/Android.mk b/media/libstagefright/codecs/amrwb/Android.mk index ab591d7..c9e1c25 100644 --- a/media/libstagefright/codecs/amrwb/Android.mk +++ b/media/libstagefright/codecs/amrwb/Android.mk @@ -2,7 +2,6 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := \ - AMRWBDecoder.cpp \ src/agc2_amr_wb.cpp \ src/band_pass_6k_7k.cpp \ src/dec_acelp_2p_in_64.cpp \ diff --git a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp deleted file mode 100644 index 490129f..0000000 --- a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp +++ /dev/null @@ -1,622 +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. - */ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "AVCDecoder" -#include <utils/Log.h> - -#include "AVCDecoder.h" - -#include "avcdec_api.h" -#include "avcdec_int.h" - -#include <OMX_Component.h> - -#include <media/stagefright/MediaBufferGroup.h> -#include <media/stagefright/MediaDebug.h> -#include <media/stagefright/MediaDefs.h> -#include <media/stagefright/MediaErrors.h> -#include <media/stagefright/MetaData.h> -#include <media/stagefright/Utils.h> -#include <media/stagefright/foundation/hexdump.h> - -namespace android { - -static const char kStartCode[4] = { 0x00, 0x00, 0x00, 0x01 }; - -static int32_t Malloc(void *userData, int32_t size, int32_t attrs) { - return reinterpret_cast<int32_t>(malloc(size)); -} - -static void Free(void *userData, int32_t ptr) { - free(reinterpret_cast<void *>(ptr)); -} - -AVCDecoder::AVCDecoder(const sp<MediaSource> &source) - : mSource(source), - mStarted(false), - mHandle(new tagAVCHandle), - mInputBuffer(NULL), - mAnchorTimeUs(0), - mNumSamplesOutput(0), - mPendingSeekTimeUs(-1), - mPendingSeekMode(MediaSource::ReadOptions::SEEK_CLOSEST_SYNC), - mTargetTimeUs(-1), - mSPSSeen(false), - mPPSSeen(false) { - memset(mHandle, 0, sizeof(tagAVCHandle)); - mHandle->AVCObject = NULL; - mHandle->userData = this; - mHandle->CBAVC_DPBAlloc = ActivateSPSWrapper; - mHandle->CBAVC_FrameBind = BindFrameWrapper; - mHandle->CBAVC_FrameUnbind = UnbindFrame; - mHandle->CBAVC_Malloc = Malloc; - mHandle->CBAVC_Free = Free; - - mFormat = new MetaData; - mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW); - int32_t width, height; - CHECK(mSource->getFormat()->findInt32(kKeyWidth, &width)); - CHECK(mSource->getFormat()->findInt32(kKeyHeight, &height)); - mFormat->setInt32(kKeyWidth, width); - mFormat->setInt32(kKeyHeight, height); - mFormat->setRect(kKeyCropRect, 0, 0, width - 1, height - 1); - mFormat->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar); - mFormat->setCString(kKeyDecoderComponent, "AVCDecoder"); - - int64_t durationUs; - if (mSource->getFormat()->findInt64(kKeyDuration, &durationUs)) { - mFormat->setInt64(kKeyDuration, durationUs); - } -} - -AVCDecoder::~AVCDecoder() { - if (mStarted) { - stop(); - } - - PVAVCCleanUpDecoder(mHandle); - - delete mHandle; - mHandle = NULL; -} - -status_t AVCDecoder::start(MetaData *) { - CHECK(!mStarted); - - uint32_t type; - const void *data; - size_t size; - sp<MetaData> meta = mSource->getFormat(); - if (meta->findData(kKeyAVCC, &type, &data, &size)) { - // Parse the AVCDecoderConfigurationRecord - - const uint8_t *ptr = (const uint8_t *)data; - - CHECK(size >= 7); - CHECK_EQ(ptr[0], 1); // configurationVersion == 1 - uint8_t profile = ptr[1]; - uint8_t level = ptr[3]; - - // There is decodable content out there that fails the following - // assertion, let's be lenient for now... - // CHECK((ptr[4] >> 2) == 0x3f); // reserved - - size_t lengthSize = 1 + (ptr[4] & 3); - - // commented out check below as H264_QVGA_500_NO_AUDIO.3gp - // violates it... - // CHECK((ptr[5] >> 5) == 7); // reserved - - size_t numSeqParameterSets = ptr[5] & 31; - - ptr += 6; - size -= 6; - - for (size_t i = 0; i < numSeqParameterSets; ++i) { - CHECK(size >= 2); - size_t length = U16_AT(ptr); - - ptr += 2; - size -= 2; - - CHECK(size >= length); - - addCodecSpecificData(ptr, length); - - ptr += length; - size -= length; - } - - CHECK(size >= 1); - size_t numPictureParameterSets = *ptr; - ++ptr; - --size; - - for (size_t i = 0; i < numPictureParameterSets; ++i) { - CHECK(size >= 2); - size_t length = U16_AT(ptr); - - ptr += 2; - size -= 2; - - CHECK(size >= length); - - addCodecSpecificData(ptr, length); - - ptr += length; - size -= length; - } - } - - mSource->start(); - - mAnchorTimeUs = 0; - mNumSamplesOutput = 0; - mPendingSeekTimeUs = -1; - mPendingSeekMode = ReadOptions::SEEK_CLOSEST_SYNC; - mTargetTimeUs = -1; - mSPSSeen = false; - mPPSSeen = false; - mStarted = true; - - return OK; -} - -void AVCDecoder::addCodecSpecificData(const uint8_t *data, size_t size) { - MediaBuffer *buffer = new MediaBuffer(size + 4); - memcpy(buffer->data(), kStartCode, 4); - memcpy((uint8_t *)buffer->data() + 4, data, size); - buffer->set_range(0, size + 4); - - mCodecSpecificData.push(buffer); -} - -status_t AVCDecoder::stop() { - CHECK(mStarted); - - for (size_t i = 0; i < mCodecSpecificData.size(); ++i) { - (*mCodecSpecificData.editItemAt(i)).release(); - } - mCodecSpecificData.clear(); - - if (mInputBuffer) { - mInputBuffer->release(); - mInputBuffer = NULL; - } - - mSource->stop(); - - releaseFrames(); - - mStarted = false; - - return OK; -} - -sp<MetaData> AVCDecoder::getFormat() { - return mFormat; -} - -static void findNALFragment( - const MediaBuffer *buffer, const uint8_t **fragPtr, size_t *fragSize) { - const uint8_t *data = - (const uint8_t *)buffer->data() + buffer->range_offset(); - - size_t size = buffer->range_length(); - - CHECK(size >= 4); - CHECK(!memcmp(kStartCode, data, 4)); - - size_t offset = 4; - while (offset + 3 < size && memcmp(kStartCode, &data[offset], 4)) { - ++offset; - } - - *fragPtr = &data[4]; - if (offset + 3 >= size) { - *fragSize = size - 4; - } else { - *fragSize = offset - 4; - } -} - -MediaBuffer *AVCDecoder::drainOutputBuffer() { - int32_t index; - int32_t Release; - AVCFrameIO Output; - Output.YCbCr[0] = Output.YCbCr[1] = Output.YCbCr[2] = NULL; - AVCDec_Status status = PVAVCDecGetOutput(mHandle, &index, &Release, &Output); - - if (status != AVCDEC_SUCCESS) { - LOGV("PVAVCDecGetOutput returned error %d", status); - return NULL; - } - - CHECK(index >= 0); - CHECK(index < (int32_t)mFrames.size()); - - MediaBuffer *mbuf = mFrames.editItemAt(index); - - bool skipFrame = false; - - if (mTargetTimeUs >= 0) { - int64_t timeUs; - CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs)); - CHECK(timeUs <= mTargetTimeUs); - - if (timeUs < mTargetTimeUs) { - // We're still waiting for the frame with the matching - // timestamp and we won't return the current one. - skipFrame = true; - - LOGV("skipping frame at %lld us", timeUs); - } else { - LOGV("found target frame at %lld us", timeUs); - - mTargetTimeUs = -1; - } - } - - if (!skipFrame) { - mbuf->set_range(0, mbuf->size()); - mbuf->add_ref(); - - return mbuf; - } - - return new MediaBuffer(0); -} - -status_t AVCDecoder::read( - MediaBuffer **out, const ReadOptions *options) { - *out = NULL; - - int64_t seekTimeUs; - ReadOptions::SeekMode mode; - if (options && options->getSeekTo(&seekTimeUs, &mode)) { - LOGV("seek requested to %lld us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6); - - CHECK(seekTimeUs >= 0); - mPendingSeekTimeUs = seekTimeUs; - mPendingSeekMode = mode; - - if (mInputBuffer) { - mInputBuffer->release(); - mInputBuffer = NULL; - } - - PVAVCDecReset(mHandle); - } - - if (mInputBuffer == NULL) { - LOGV("fetching new input buffer."); - - bool seeking = false; - - if (!mCodecSpecificData.isEmpty()) { - mInputBuffer = mCodecSpecificData.editItemAt(0); - mCodecSpecificData.removeAt(0); - } else { - for (;;) { - if (mPendingSeekTimeUs >= 0) { - LOGV("reading data from timestamp %lld (%.2f secs)", - mPendingSeekTimeUs, mPendingSeekTimeUs / 1E6); - } - - ReadOptions seekOptions; - if (mPendingSeekTimeUs >= 0) { - seeking = true; - - seekOptions.setSeekTo(mPendingSeekTimeUs, mPendingSeekMode); - mPendingSeekTimeUs = -1; - } - status_t err = mSource->read(&mInputBuffer, &seekOptions); - seekOptions.clearSeekTo(); - - if (err != OK) { - *out = drainOutputBuffer(); - return (*out == NULL) ? err : (status_t)OK; - } - - if (mInputBuffer->range_length() > 0) { - break; - } - - mInputBuffer->release(); - mInputBuffer = NULL; - } - } - - if (seeking) { - int64_t targetTimeUs; - if (mInputBuffer->meta_data()->findInt64(kKeyTargetTime, &targetTimeUs) - && targetTimeUs >= 0) { - mTargetTimeUs = targetTimeUs; - } else { - mTargetTimeUs = -1; - } - } - } - - const uint8_t *fragPtr; - size_t fragSize; - findNALFragment(mInputBuffer, &fragPtr, &fragSize); - - bool releaseFragment = true; - status_t err = UNKNOWN_ERROR; - - int nalType; - int nalRefIdc; - AVCDec_Status res = - PVAVCDecGetNALType( - const_cast<uint8_t *>(fragPtr), fragSize, - &nalType, &nalRefIdc); - - if (res != AVCDEC_SUCCESS) { - LOGV("cannot determine nal type"); - } else if (nalType == AVC_NALTYPE_SPS || nalType == AVC_NALTYPE_PPS - || (mSPSSeen && mPPSSeen)) { - switch (nalType) { - case AVC_NALTYPE_SPS: - { - mSPSSeen = true; - - res = PVAVCDecSeqParamSet( - mHandle, const_cast<uint8_t *>(fragPtr), - fragSize); - - if (res != AVCDEC_SUCCESS) { - LOGV("PVAVCDecSeqParamSet returned error %d", res); - break; - } - - AVCDecObject *pDecVid = (AVCDecObject *)mHandle->AVCObject; - - int32_t width = - (pDecVid->seqParams[0]->pic_width_in_mbs_minus1 + 1) * 16; - - int32_t height = - (pDecVid->seqParams[0]->pic_height_in_map_units_minus1 + 1) * 16; - - int32_t crop_left, crop_right, crop_top, crop_bottom; - if (pDecVid->seqParams[0]->frame_cropping_flag) - { - crop_left = 2 * pDecVid->seqParams[0]->frame_crop_left_offset; - crop_right = - width - (2 * pDecVid->seqParams[0]->frame_crop_right_offset + 1); - - if (pDecVid->seqParams[0]->frame_mbs_only_flag) - { - crop_top = 2 * pDecVid->seqParams[0]->frame_crop_top_offset; - crop_bottom = - height - - (2 * pDecVid->seqParams[0]->frame_crop_bottom_offset + 1); - } - else - { - crop_top = 4 * pDecVid->seqParams[0]->frame_crop_top_offset; - crop_bottom = - height - - (4 * pDecVid->seqParams[0]->frame_crop_bottom_offset + 1); - } - } else { - crop_bottom = height - 1; - crop_right = width - 1; - crop_top = crop_left = 0; - } - - int32_t prevCropLeft, prevCropTop; - int32_t prevCropRight, prevCropBottom; - if (!mFormat->findRect( - kKeyCropRect, - &prevCropLeft, &prevCropTop, - &prevCropRight, &prevCropBottom)) { - prevCropLeft = prevCropTop = 0; - prevCropRight = width - 1; - prevCropBottom = height - 1; - } - - int32_t oldWidth, oldHeight; - CHECK(mFormat->findInt32(kKeyWidth, &oldWidth)); - CHECK(mFormat->findInt32(kKeyHeight, &oldHeight)); - - if (oldWidth != width || oldHeight != height - || prevCropLeft != crop_left - || prevCropTop != crop_top - || prevCropRight != crop_right - || prevCropBottom != crop_bottom) { - mFormat->setRect( - kKeyCropRect, - crop_left, crop_top, crop_right, crop_bottom); - - mFormat->setInt32(kKeyWidth, width); - mFormat->setInt32(kKeyHeight, height); - - err = INFO_FORMAT_CHANGED; - } else { - *out = new MediaBuffer(0); - err = OK; - } - break; - } - - case AVC_NALTYPE_PPS: - { - mPPSSeen = true; - - res = PVAVCDecPicParamSet( - mHandle, const_cast<uint8_t *>(fragPtr), - fragSize); - - if (res != AVCDEC_SUCCESS) { - LOGV("PVAVCDecPicParamSet returned error %d", res); - break; - } - - *out = new MediaBuffer(0); - - err = OK; - break; - } - - case AVC_NALTYPE_SLICE: - case AVC_NALTYPE_IDR: - { - res = PVAVCDecodeSlice( - mHandle, const_cast<uint8_t *>(fragPtr), - fragSize); - - if (res == AVCDEC_PICTURE_OUTPUT_READY) { - MediaBuffer *mbuf = drainOutputBuffer(); - if (mbuf == NULL) { - break; - } - - *out = mbuf; - - // Do _not_ release input buffer yet. - - releaseFragment = false; - err = OK; - break; - } - - if (res == AVCDEC_PICTURE_READY || res == AVCDEC_SUCCESS) { - *out = new MediaBuffer(0); - - err = OK; - } else { - LOGV("PVAVCDecodeSlice returned error %d", res); - } - break; - } - - case AVC_NALTYPE_SEI: - { - res = PVAVCDecSEI( - mHandle, const_cast<uint8_t *>(fragPtr), - fragSize); - - if (res != AVCDEC_SUCCESS) { - break; - } - - *out = new MediaBuffer(0); - - err = OK; - break; - } - - case AVC_NALTYPE_AUD: - case AVC_NALTYPE_FILL: - case AVC_NALTYPE_EOSEQ: - { - *out = new MediaBuffer(0); - - err = OK; - break; - } - - default: - { - LOGE("Should not be here, unknown nalType %d", nalType); - - err = ERROR_MALFORMED; - break; - } - } - } else { - // We haven't seen SPS or PPS yet. - - *out = new MediaBuffer(0); - err = OK; - } - - if (releaseFragment) { - size_t offset = mInputBuffer->range_offset(); - if (fragSize + 4 == mInputBuffer->range_length()) { - mInputBuffer->release(); - mInputBuffer = NULL; - } else { - mInputBuffer->set_range( - offset + fragSize + 4, - mInputBuffer->range_length() - fragSize - 4); - } - } - - return err; -} - -// static -int32_t AVCDecoder::ActivateSPSWrapper( - void *userData, unsigned int sizeInMbs, unsigned int numBuffers) { - return static_cast<AVCDecoder *>(userData)->activateSPS(sizeInMbs, numBuffers); -} - -// static -int32_t AVCDecoder::BindFrameWrapper( - void *userData, int32_t index, uint8_t **yuv) { - return static_cast<AVCDecoder *>(userData)->bindFrame(index, yuv); -} - -// static -void AVCDecoder::UnbindFrame(void *userData, int32_t index) { -} - -int32_t AVCDecoder::activateSPS( - unsigned int sizeInMbs, unsigned int numBuffers) { - CHECK(mFrames.isEmpty()); - - size_t frameSize = (sizeInMbs << 7) * 3; - for (unsigned int i = 0; i < numBuffers; ++i) { - MediaBuffer *buffer = new MediaBuffer(frameSize); - buffer->setObserver(this); - - mFrames.push(buffer); - } - - return 1; -} - -int32_t AVCDecoder::bindFrame(int32_t index, uint8_t **yuv) { - CHECK(index >= 0); - CHECK(index < (int32_t)mFrames.size()); - - CHECK(mInputBuffer != NULL); - int64_t timeUs; - CHECK(mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)); - mFrames[index]->meta_data()->setInt64(kKeyTime, timeUs); - - *yuv = (uint8_t *)mFrames[index]->data(); - - return 1; -} - -void AVCDecoder::releaseFrames() { - for (size_t i = 0; i < mFrames.size(); ++i) { - MediaBuffer *buffer = mFrames.editItemAt(i); - - buffer->setObserver(NULL); - buffer->release(); - } - mFrames.clear(); -} - -void AVCDecoder::signalBufferReturned(MediaBuffer *buffer) { -} - -} // namespace android diff --git a/media/libstagefright/codecs/avc/dec/Android.mk b/media/libstagefright/codecs/avc/dec/Android.mk index 4d4533b..2949a04 100644 --- a/media/libstagefright/codecs/avc/dec/Android.mk +++ b/media/libstagefright/codecs/avc/dec/Android.mk @@ -2,7 +2,6 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := \ - AVCDecoder.cpp \ src/avcdec_api.cpp \ src/avc_bitstream.cpp \ src/header.cpp \ diff --git a/media/libstagefright/codecs/g711/dec/Android.mk b/media/libstagefright/codecs/g711/dec/Android.mk index 6e98559..6692533 100644 --- a/media/libstagefright/codecs/g711/dec/Android.mk +++ b/media/libstagefright/codecs/g711/dec/Android.mk @@ -2,20 +2,6 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := \ - G711Decoder.cpp - -LOCAL_C_INCLUDES := \ - frameworks/base/media/libstagefright/include \ - -LOCAL_MODULE := libstagefright_g711dec - -include $(BUILD_STATIC_LIBRARY) - -################################################################################ - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ SoftG711.cpp LOCAL_C_INCLUDES := \ diff --git a/media/libstagefright/codecs/g711/dec/G711Decoder.cpp b/media/libstagefright/codecs/g711/dec/G711Decoder.cpp deleted file mode 100644 index 4414e4e..0000000 --- a/media/libstagefright/codecs/g711/dec/G711Decoder.cpp +++ /dev/null @@ -1,213 +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 "G711Decoder" -#include <utils/Log.h> - -#include "G711Decoder.h" - -#include <media/stagefright/MediaBufferGroup.h> -#include <media/stagefright/MediaDebug.h> -#include <media/stagefright/MediaDefs.h> -#include <media/stagefright/MediaErrors.h> -#include <media/stagefright/MetaData.h> - -static const size_t kMaxNumSamplesPerFrame = 16384; - -namespace android { - -G711Decoder::G711Decoder(const sp<MediaSource> &source) - : mSource(source), - mStarted(false), - mBufferGroup(NULL) { -} - -G711Decoder::~G711Decoder() { - if (mStarted) { - stop(); - } -} - -status_t G711Decoder::start(MetaData *params) { - CHECK(!mStarted); - - const char *mime; - CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime)); - - mIsMLaw = false; - if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) { - mIsMLaw = true; - } else if (strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW)) { - return ERROR_UNSUPPORTED; - } - - mBufferGroup = new MediaBufferGroup; - mBufferGroup->add_buffer( - new MediaBuffer(kMaxNumSamplesPerFrame * sizeof(int16_t))); - - mSource->start(); - - mStarted = true; - - return OK; -} - -status_t G711Decoder::stop() { - CHECK(mStarted); - - delete mBufferGroup; - mBufferGroup = NULL; - - mSource->stop(); - - mStarted = false; - - return OK; -} - -sp<MetaData> G711Decoder::getFormat() { - sp<MetaData> srcFormat = mSource->getFormat(); - - int32_t numChannels; - int32_t sampleRate; - - CHECK(srcFormat->findInt32(kKeyChannelCount, &numChannels)); - CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate)); - - sp<MetaData> meta = new MetaData; - meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); - meta->setInt32(kKeyChannelCount, numChannels); - meta->setInt32(kKeySampleRate, sampleRate); - - int64_t durationUs; - if (srcFormat->findInt64(kKeyDuration, &durationUs)) { - meta->setInt64(kKeyDuration, durationUs); - } - - meta->setCString(kKeyDecoderComponent, "G711Decoder"); - - return meta; -} - -status_t G711Decoder::read( - MediaBuffer **out, const ReadOptions *options) { - status_t err; - - *out = NULL; - - int64_t seekTimeUs; - ReadOptions::SeekMode mode; - if (options && options->getSeekTo(&seekTimeUs, &mode)) { - CHECK(seekTimeUs >= 0); - } else { - seekTimeUs = -1; - } - - MediaBuffer *inBuffer; - err = mSource->read(&inBuffer, options); - - if (err != OK) { - return err; - } - - if (inBuffer->range_length() > kMaxNumSamplesPerFrame) { - LOGE("input buffer too large (%d).", inBuffer->range_length()); - - inBuffer->release(); - inBuffer = NULL; - - return ERROR_UNSUPPORTED; - } - - int64_t timeUs; - CHECK(inBuffer->meta_data()->findInt64(kKeyTime, &timeUs)); - - const uint8_t *inputPtr = - (const uint8_t *)inBuffer->data() + inBuffer->range_offset(); - - MediaBuffer *outBuffer; - CHECK_EQ(mBufferGroup->acquire_buffer(&outBuffer), OK); - - if (mIsMLaw) { - DecodeMLaw( - static_cast<int16_t *>(outBuffer->data()), - inputPtr, inBuffer->range_length()); - } else { - DecodeALaw( - static_cast<int16_t *>(outBuffer->data()), - inputPtr, inBuffer->range_length()); - } - - // Each 8-bit byte is converted into a 16-bit sample. - outBuffer->set_range(0, inBuffer->range_length() * 2); - - outBuffer->meta_data()->setInt64(kKeyTime, timeUs); - - inBuffer->release(); - inBuffer = NULL; - - *out = outBuffer; - - return OK; -} - -// static -void G711Decoder::DecodeALaw( - int16_t *out, const uint8_t *in, size_t inSize) { - while (inSize-- > 0) { - int32_t x = *in++; - - int32_t ix = x ^ 0x55; - ix &= 0x7f; - - int32_t iexp = ix >> 4; - int32_t mant = ix & 0x0f; - - if (iexp > 0) { - mant += 16; - } - - mant = (mant << 4) + 8; - - if (iexp > 1) { - mant = mant << (iexp - 1); - } - - *out++ = (x > 127) ? mant : -mant; - } -} - -// static -void G711Decoder::DecodeMLaw( - int16_t *out, const uint8_t *in, size_t inSize) { - while (inSize-- > 0) { - int32_t x = *in++; - - int32_t mantissa = ~x; - int32_t exponent = (mantissa >> 4) & 7; - int32_t segment = exponent + 1; - mantissa &= 0x0f; - - int32_t step = 4 << segment; - - int32_t abs = (0x80l << exponent) + step * mantissa + step / 2 - 4 * 33; - - *out++ = (x < 0x80) ? -abs : abs; - } -} - -} // namespace android diff --git a/media/libstagefright/codecs/m4v_h263/dec/Android.mk b/media/libstagefright/codecs/m4v_h263/dec/Android.mk index f1bec08..2ffa5f2 100644 --- a/media/libstagefright/codecs/m4v_h263/dec/Android.mk +++ b/media/libstagefright/codecs/m4v_h263/dec/Android.mk @@ -2,7 +2,6 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := \ - M4vH263Decoder.cpp \ src/adaptive_smooth_no_mmx.cpp \ src/bitstream.cpp \ src/block_idct.cpp \ diff --git a/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp b/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp deleted file mode 100644 index 2bdb3ef..0000000 --- a/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp +++ /dev/null @@ -1,304 +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. - */ -//#define LOG_NDEBUG 0 -#define LOG_TAG "M4vH263Decoder" -#include <utils/Log.h> -#include <stdlib.h> // for free -#include "ESDS.h" -#include "M4vH263Decoder.h" - -#include "mp4dec_api.h" - -#include <OMX_Component.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> -#include <media/stagefright/Utils.h> - -namespace android { - -M4vH263Decoder::M4vH263Decoder(const sp<MediaSource> &source) - : mSource(source), - mStarted(false), - mHandle(new tagvideoDecControls), - mInputBuffer(NULL), - mNumSamplesOutput(0), - mTargetTimeUs(-1) { - - LOGV("M4vH263Decoder"); - memset(mHandle, 0, sizeof(tagvideoDecControls)); - mFormat = new MetaData; - mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW); - - // CHECK(mSource->getFormat()->findInt32(kKeyWidth, &mWidth)); - // CHECK(mSource->getFormat()->findInt32(kKeyHeight, &mHeight)); - - // We'll ignore the dimension advertised by the source, the decoder - // appears to require us to always start with the default dimensions - // of 352 x 288 to operate correctly and later react to changes in - // the dimensions as needed. - mWidth = 352; - mHeight = 288; - - mFormat->setInt32(kKeyWidth, mWidth); - mFormat->setInt32(kKeyHeight, mHeight); - mFormat->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar); - mFormat->setCString(kKeyDecoderComponent, "M4vH263Decoder"); -} - -M4vH263Decoder::~M4vH263Decoder() { - if (mStarted) { - stop(); - } - - delete mHandle; - mHandle = NULL; -} - -void M4vH263Decoder::allocateFrames(int32_t width, int32_t height) { - size_t frameSize = - (((width + 15) & - 16) * ((height + 15) & - 16) * 3) / 2; - - for (uint32_t i = 0; i < 2; ++i) { - mFrames[i] = new MediaBuffer(frameSize); - mFrames[i]->setObserver(this); - } - - PVSetReferenceYUV( - mHandle, - (uint8_t *)mFrames[1]->data()); -} - -status_t M4vH263Decoder::start(MetaData *) { - CHECK(!mStarted); - - const char *mime = NULL; - sp<MetaData> meta = mSource->getFormat(); - CHECK(meta->findCString(kKeyMIMEType, &mime)); - - MP4DecodingMode mode; - if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { - mode = MPEG4_MODE; - } else { - CHECK(!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)); - mode = H263_MODE; - } - - uint32_t type; - const void *data = NULL; - size_t size = 0; - uint8_t *vol_data[1] = {0}; - int32_t vol_size = 0; - if (meta->findData(kKeyESDS, &type, &data, &size)) { - ESDS esds((const uint8_t *)data, size); - CHECK_EQ(esds.InitCheck(), (status_t)OK); - - const void *codec_specific_data; - size_t codec_specific_data_size; - esds.getCodecSpecificInfo( - &codec_specific_data, &codec_specific_data_size); - - vol_data[0] = (uint8_t *) malloc(codec_specific_data_size); - memcpy(vol_data[0], codec_specific_data, codec_specific_data_size); - vol_size = codec_specific_data_size; - } else { - vol_data[0] = NULL; - vol_size = 0; - - } - - Bool success = PVInitVideoDecoder( - mHandle, vol_data, &vol_size, 1, mWidth, mHeight, mode); - if (vol_data[0]) free(vol_data[0]); - - if (success != PV_TRUE) { - LOGW("PVInitVideoDecoder failed. Unsupported content?"); - return ERROR_UNSUPPORTED; - } - - MP4DecodingMode actualMode = PVGetDecBitstreamMode(mHandle); - if (mode != actualMode) { - PVCleanUpVideoDecoder(mHandle); - return UNKNOWN_ERROR; - } - - PVSetPostProcType((VideoDecControls *) mHandle, 0); - - int32_t width, height; - PVGetVideoDimensions(mHandle, &width, &height); - if (mode == H263_MODE && (width == 0 || height == 0)) { - width = 352; - height = 288; - } - allocateFrames(width, height); - - mSource->start(); - - mNumSamplesOutput = 0; - mTargetTimeUs = -1; - mStarted = true; - - return OK; -} - -status_t M4vH263Decoder::stop() { - CHECK(mStarted); - - if (mInputBuffer) { - mInputBuffer->release(); - mInputBuffer = NULL; - } - - mSource->stop(); - - releaseFrames(); - - mStarted = false; - return (PVCleanUpVideoDecoder(mHandle) == PV_TRUE)? OK: UNKNOWN_ERROR; -} - -sp<MetaData> M4vH263Decoder::getFormat() { - return mFormat; -} - -status_t M4vH263Decoder::read( - MediaBuffer **out, const ReadOptions *options) { - *out = NULL; - - bool seeking = false; - int64_t seekTimeUs; - ReadOptions::SeekMode mode; - if (options && options->getSeekTo(&seekTimeUs, &mode)) { - seeking = true; - CHECK_EQ((int)PVResetVideoDecoder(mHandle), PV_TRUE); - } - - MediaBuffer *inputBuffer = NULL; - status_t err = mSource->read(&inputBuffer, options); - if (err != OK) { - return err; - } - - if (seeking) { - int64_t targetTimeUs; - if (inputBuffer->meta_data()->findInt64(kKeyTargetTime, &targetTimeUs) - && targetTimeUs >= 0) { - mTargetTimeUs = targetTimeUs; - } else { - mTargetTimeUs = -1; - } - } - - uint8_t *bitstream = - (uint8_t *) inputBuffer->data() + inputBuffer->range_offset(); - - uint32_t timestamp = 0xFFFFFFFF; - int32_t bufferSize = inputBuffer->range_length(); - uint32_t useExtTimestamp = 0; - if (PVDecodeVideoFrame( - mHandle, &bitstream, ×tamp, &bufferSize, - &useExtTimestamp, - (uint8_t *)mFrames[mNumSamplesOutput & 0x01]->data()) - != PV_TRUE) { - LOGE("failed to decode video frame."); - - inputBuffer->release(); - inputBuffer = NULL; - - return UNKNOWN_ERROR; - } - - int32_t disp_width, disp_height; - PVGetVideoDimensions(mHandle, &disp_width, &disp_height); - - int32_t buf_width, buf_height; - PVGetBufferDimensions(mHandle, &buf_width, &buf_height); - - if (buf_width != mWidth || buf_height != mHeight) { - ++mNumSamplesOutput; // The client will never get to see this frame. - - inputBuffer->release(); - inputBuffer = NULL; - - mWidth = buf_width; - mHeight = buf_height; - mFormat->setInt32(kKeyWidth, mWidth); - mFormat->setInt32(kKeyHeight, mHeight); - - CHECK_LE(disp_width, buf_width); - CHECK_LE(disp_height, buf_height); - - mFormat->setRect(kKeyCropRect, 0, 0, disp_width - 1, disp_height - 1); - - return INFO_FORMAT_CHANGED; - } - - int64_t timeUs; - CHECK(inputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)); - - inputBuffer->release(); - inputBuffer = NULL; - - bool skipFrame = false; - - if (mTargetTimeUs >= 0) { - CHECK(timeUs <= mTargetTimeUs); - - if (timeUs < mTargetTimeUs) { - // We're still waiting for the frame with the matching - // timestamp and we won't return the current one. - skipFrame = true; - - LOGV("skipping frame at %lld us", timeUs); - } else { - LOGV("found target frame at %lld us", timeUs); - - mTargetTimeUs = -1; - } - } - - if (skipFrame) { - *out = new MediaBuffer(0); - } else { - *out = mFrames[mNumSamplesOutput & 0x01]; - (*out)->add_ref(); - (*out)->meta_data()->setInt64(kKeyTime, timeUs); - } - - ++mNumSamplesOutput; - - return OK; -} - -void M4vH263Decoder::releaseFrames() { - for (size_t i = 0; i < sizeof(mFrames) / sizeof(mFrames[0]); ++i) { - MediaBuffer *buffer = mFrames[i]; - - buffer->setObserver(NULL); - buffer->release(); - - mFrames[i] = NULL; - } -} - -void M4vH263Decoder::signalBufferReturned(MediaBuffer *buffer) { - LOGV("signalBufferReturned"); -} - - -} // namespace android diff --git a/media/libstagefright/codecs/mp3dec/Android.mk b/media/libstagefright/codecs/mp3dec/Android.mk index 229988e..a08c9f0 100644 --- a/media/libstagefright/codecs/mp3dec/Android.mk +++ b/media/libstagefright/codecs/mp3dec/Android.mk @@ -2,7 +2,6 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := \ - MP3Decoder.cpp \ src/pvmp3_normalize.cpp \ src/pvmp3_alias_reduction.cpp \ src/pvmp3_crc.cpp \ diff --git a/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp b/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp deleted file mode 100644 index 0ba42ff..0000000 --- a/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp +++ /dev/null @@ -1,226 +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. - */ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "MP3Decoder" - -#include "MP3Decoder.h" - -#include "include/pvmp3decoder_api.h" - -#include <media/stagefright/MediaBufferGroup.h> -#include <media/stagefright/MediaDebug.h> -#include <media/stagefright/MediaDefs.h> -#include <media/stagefright/MetaData.h> - -namespace android { - -MP3Decoder::MP3Decoder(const sp<MediaSource> &source) - : mSource(source), - mNumChannels(0), - mStarted(false), - mBufferGroup(NULL), - mConfig(new tPVMP3DecoderExternal), - mDecoderBuf(NULL), - mAnchorTimeUs(0), - mNumFramesOutput(0), - mInputBuffer(NULL) { - init(); -} - -void MP3Decoder::init() { - sp<MetaData> srcFormat = mSource->getFormat(); - - int32_t sampleRate; - CHECK(srcFormat->findInt32(kKeyChannelCount, &mNumChannels)); - CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate)); - - mMeta = new MetaData; - mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); - mMeta->setInt32(kKeyChannelCount, mNumChannels); - mMeta->setInt32(kKeySampleRate, sampleRate); - - int64_t durationUs; - if (srcFormat->findInt64(kKeyDuration, &durationUs)) { - mMeta->setInt64(kKeyDuration, durationUs); - } - - mMeta->setCString(kKeyDecoderComponent, "MP3Decoder"); -} - -MP3Decoder::~MP3Decoder() { - if (mStarted) { - stop(); - } - - delete mConfig; - mConfig = NULL; -} - -status_t MP3Decoder::start(MetaData *params) { - CHECK(!mStarted); - - mBufferGroup = new MediaBufferGroup; - mBufferGroup->add_buffer(new MediaBuffer(4608 * 2)); - - mConfig->equalizerType = flat; - mConfig->crcEnabled = false; - - uint32_t memRequirements = pvmp3_decoderMemRequirements(); - mDecoderBuf = malloc(memRequirements); - - pvmp3_InitDecoder(mConfig, mDecoderBuf); - - mSource->start(); - - mAnchorTimeUs = 0; - mNumFramesOutput = 0; - mStarted = true; - - return OK; -} - -status_t MP3Decoder::stop() { - CHECK(mStarted); - - if (mInputBuffer) { - mInputBuffer->release(); - mInputBuffer = NULL; - } - - free(mDecoderBuf); - mDecoderBuf = NULL; - - delete mBufferGroup; - mBufferGroup = NULL; - - mSource->stop(); - - mStarted = false; - - return OK; -} - -sp<MetaData> MP3Decoder::getFormat() { - return mMeta; -} - -status_t MP3Decoder::read( - MediaBuffer **out, const ReadOptions *options) { - status_t err; - - *out = NULL; - - int64_t seekTimeUs; - ReadOptions::SeekMode mode; - if (options && options->getSeekTo(&seekTimeUs, &mode)) { - CHECK(seekTimeUs >= 0); - - mNumFramesOutput = 0; - - if (mInputBuffer) { - mInputBuffer->release(); - mInputBuffer = NULL; - } - - // Make sure that the next buffer output does not still - // depend on fragments from the last one decoded. - pvmp3_InitDecoder(mConfig, mDecoderBuf); - } else { - seekTimeUs = -1; - } - - if (mInputBuffer == NULL) { - err = mSource->read(&mInputBuffer, options); - - if (err != OK) { - return err; - } - - int64_t timeUs; - if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) { - mAnchorTimeUs = timeUs; - mNumFramesOutput = 0; - } else { - // We must have a new timestamp after seeking. - CHECK(seekTimeUs < 0); - } - } - - MediaBuffer *buffer; - CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK); - - mConfig->pInputBuffer = - (uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset(); - - mConfig->inputBufferCurrentLength = mInputBuffer->range_length(); - mConfig->inputBufferMaxLength = 0; - mConfig->inputBufferUsedLength = 0; - - mConfig->outputFrameSize = buffer->size() / sizeof(int16_t); - mConfig->pOutputBuffer = static_cast<int16_t *>(buffer->data()); - - ERROR_CODE decoderErr; - if ((decoderErr = pvmp3_framedecoder(mConfig, mDecoderBuf)) - != NO_DECODING_ERROR) { - LOGV("mp3 decoder returned error %d", decoderErr); - - if (decoderErr != NO_ENOUGH_MAIN_DATA_ERROR || - mConfig->outputFrameSize == 0) { - - if (mConfig->outputFrameSize == 0) { - LOGE("Output frame size is 0"); - } - buffer->release(); - buffer = NULL; - - mInputBuffer->release(); - mInputBuffer = NULL; - - return UNKNOWN_ERROR; - } - - // This is recoverable, just ignore the current frame and - // play silence instead. - memset(buffer->data(), 0, mConfig->outputFrameSize * sizeof(int16_t)); - mConfig->inputBufferUsedLength = mInputBuffer->range_length(); - } - - buffer->set_range( - 0, mConfig->outputFrameSize * sizeof(int16_t)); - - mInputBuffer->set_range( - mInputBuffer->range_offset() + mConfig->inputBufferUsedLength, - mInputBuffer->range_length() - mConfig->inputBufferUsedLength); - - if (mInputBuffer->range_length() == 0) { - mInputBuffer->release(); - mInputBuffer = NULL; - } - - buffer->meta_data()->setInt64( - kKeyTime, - mAnchorTimeUs - + (mNumFramesOutput * 1000000) / mConfig->samplingRate); - - mNumFramesOutput += mConfig->outputFrameSize / mNumChannels; - - *out = buffer; - - return OK; -} - -} // namespace android diff --git a/media/libstagefright/codecs/on2/dec/Android.mk b/media/libstagefright/codecs/on2/dec/Android.mk index 832b885..32bbd6b 100644 --- a/media/libstagefright/codecs/on2/dec/Android.mk +++ b/media/libstagefright/codecs/on2/dec/Android.mk @@ -2,24 +2,6 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := \ - VPXDecoder.cpp \ - -LOCAL_MODULE := libstagefright_vpxdec - -LOCAL_C_INCLUDES := \ - $(TOP)/frameworks/base/media/libstagefright/include \ - frameworks/base/include/media/stagefright/openmax \ - $(TOP)/external/libvpx \ - $(TOP)/external/libvpx/vpx_codec \ - $(TOP)/external/libvpx/vpx_ports - -include $(BUILD_STATIC_LIBRARY) - -################################################################################ - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ SoftVPX.cpp LOCAL_C_INCLUDES := \ @@ -30,7 +12,6 @@ LOCAL_C_INCLUDES := \ frameworks/base/include/media/stagefright/openmax \ LOCAL_STATIC_LIBRARIES := \ - libstagefright_vpxdec \ libvpx LOCAL_SHARED_LIBRARIES := \ diff --git a/media/libstagefright/codecs/on2/dec/VPXDecoder.cpp b/media/libstagefright/codecs/on2/dec/VPXDecoder.cpp deleted file mode 100644 index 489e5ad..0000000 --- a/media/libstagefright/codecs/on2/dec/VPXDecoder.cpp +++ /dev/null @@ -1,277 +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 "VPXDecoder" -#include <utils/Log.h> - -#include "VPXDecoder.h" - -#include <OMX_Component.h> - -#include <media/stagefright/MediaBufferGroup.h> -#include <media/stagefright/MediaDebug.h> -#include <media/stagefright/MediaDefs.h> -#include <media/stagefright/MediaErrors.h> -#include <media/stagefright/MetaData.h> -#include <media/stagefright/Utils.h> - -#include "vpx/vpx_decoder.h" -#include "vpx/vpx_codec.h" -#include "vpx/vp8dx.h" - -namespace android { - -VPXDecoder::VPXDecoder(const sp<MediaSource> &source) - : mSource(source), - mStarted(false), - mBufferSize(0), - mCtx(NULL), - mBufferGroup(NULL), - mTargetTimeUs(-1) { - sp<MetaData> inputFormat = source->getFormat(); - const char *mime; - CHECK(inputFormat->findCString(kKeyMIMEType, &mime)); - CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_VPX)); - - CHECK(inputFormat->findInt32(kKeyWidth, &mWidth)); - CHECK(inputFormat->findInt32(kKeyHeight, &mHeight)); - - mBufferSize = (mWidth * mHeight * 3) / 2; - - mFormat = new MetaData; - mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW); - mFormat->setInt32(kKeyWidth, mWidth); - mFormat->setInt32(kKeyHeight, mHeight); - mFormat->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar); - mFormat->setCString(kKeyDecoderComponent, "VPXDecoder"); - - int64_t durationUs; - if (inputFormat->findInt64(kKeyDuration, &durationUs)) { - mFormat->setInt64(kKeyDuration, durationUs); - } -} - -VPXDecoder::~VPXDecoder() { - if (mStarted) { - stop(); - } -} - -status_t VPXDecoder::start(MetaData *) { - if (mStarted) { - return UNKNOWN_ERROR; - } - - status_t err = mSource->start(); - - if (err != OK) { - return err; - } - - mCtx = new vpx_codec_ctx_t; - vpx_codec_err_t vpx_err; - if ((vpx_err = vpx_codec_dec_init( - (vpx_codec_ctx_t *)mCtx, &vpx_codec_vp8_dx_algo, NULL, 0))) { - LOGE("on2 decoder failed to initialize. (%d)", vpx_err); - - mSource->stop(); - - return UNKNOWN_ERROR; - } - - mBufferGroup = new MediaBufferGroup; - mBufferGroup->add_buffer(new MediaBuffer(mBufferSize)); - mBufferGroup->add_buffer(new MediaBuffer(mBufferSize)); - - mTargetTimeUs = -1; - - mStarted = true; - - return OK; -} - -status_t VPXDecoder::stop() { - if (!mStarted) { - return UNKNOWN_ERROR; - } - - delete mBufferGroup; - mBufferGroup = NULL; - - vpx_codec_destroy((vpx_codec_ctx_t *)mCtx); - delete (vpx_codec_ctx_t *)mCtx; - mCtx = NULL; - - mSource->stop(); - - mStarted = false; - - return OK; -} - -sp<MetaData> VPXDecoder::getFormat() { - return mFormat; -} - -status_t VPXDecoder::read( - MediaBuffer **out, const ReadOptions *options) { - *out = NULL; - - bool seeking = false; - int64_t seekTimeUs; - ReadOptions::SeekMode seekMode; - if (options && options->getSeekTo(&seekTimeUs, &seekMode)) { - seeking = true; - } - - MediaBuffer *input; - status_t err = mSource->read(&input, options); - - if (err != OK) { - return err; - } - - LOGV("read %d bytes from source\n", input->range_length()); - - if (seeking) { - int64_t targetTimeUs; - if (input->meta_data()->findInt64(kKeyTargetTime, &targetTimeUs) - && targetTimeUs >= 0) { - mTargetTimeUs = targetTimeUs; - } else { - mTargetTimeUs = -1; - } - } - - if (vpx_codec_decode( - (vpx_codec_ctx_t *)mCtx, - (uint8_t *)input->data() + input->range_offset(), - input->range_length(), - NULL, - 0)) { - LOGE("on2 decoder failed to decode frame."); - input->release(); - input = NULL; - - return UNKNOWN_ERROR; - } - - LOGV("successfully decoded 1 or more frames."); - - int64_t timeUs; - CHECK(input->meta_data()->findInt64(kKeyTime, &timeUs)); - - input->release(); - input = NULL; - - bool skipFrame = false; - - if (mTargetTimeUs >= 0) { - CHECK(timeUs <= mTargetTimeUs); - - if (timeUs < mTargetTimeUs) { - // We're still waiting for the frame with the matching - // timestamp and we won't return the current one. - skipFrame = true; - - LOGV("skipping frame at %lld us", timeUs); - } else { - LOGV("found target frame at %lld us", timeUs); - - mTargetTimeUs = -1; - } - } - - if (skipFrame) { - *out = new MediaBuffer(0); - return OK; - } - - vpx_codec_iter_t iter = NULL; - vpx_image_t *img = vpx_codec_get_frame((vpx_codec_ctx_t *)mCtx, &iter); - - if (img == NULL) { - // The VPX format supports "internal-only" frames that are - // referenced by future content but never actually displayed, so - // this is a perfectly valid scenario. - - *out = new MediaBuffer(0); - return OK; - } - - CHECK_EQ(img->fmt, IMG_FMT_I420); - - int32_t width = img->d_w; - int32_t height = img->d_h; - - if (width != mWidth || height != mHeight) { - LOGI("Image dimensions changed, width = %d, height = %d", - width, height); - - mWidth = width; - mHeight = height; - mFormat->setInt32(kKeyWidth, width); - mFormat->setInt32(kKeyHeight, height); - - mBufferSize = (mWidth * mHeight * 3) / 2; - delete mBufferGroup; - mBufferGroup = new MediaBufferGroup; - mBufferGroup->add_buffer(new MediaBuffer(mBufferSize)); - mBufferGroup->add_buffer(new MediaBuffer(mBufferSize)); - - return INFO_FORMAT_CHANGED; - } - - MediaBuffer *output; - CHECK_EQ(mBufferGroup->acquire_buffer(&output), OK); - - const uint8_t *srcLine = (const uint8_t *)img->planes[PLANE_Y]; - uint8_t *dst = (uint8_t *)output->data(); - for (size_t i = 0; i < img->d_h; ++i) { - memcpy(dst, srcLine, img->d_w); - - srcLine += img->stride[PLANE_Y]; - dst += img->d_w; - } - - srcLine = (const uint8_t *)img->planes[PLANE_U]; - for (size_t i = 0; i < img->d_h / 2; ++i) { - memcpy(dst, srcLine, img->d_w / 2); - - srcLine += img->stride[PLANE_U]; - dst += img->d_w / 2; - } - - srcLine = (const uint8_t *)img->planes[PLANE_V]; - for (size_t i = 0; i < img->d_h / 2; ++i) { - memcpy(dst, srcLine, img->d_w / 2); - - srcLine += img->stride[PLANE_V]; - dst += img->d_w / 2; - } - - output->set_range(0, (width * height * 3) / 2); - - output->meta_data()->setInt64(kKeyTime, timeUs); - - *out = output; - - return OK; -} - -} // namespace android - diff --git a/media/libstagefright/codecs/vorbis/dec/Android.mk b/media/libstagefright/codecs/vorbis/dec/Android.mk index 9251229..f33f3ac 100644 --- a/media/libstagefright/codecs/vorbis/dec/Android.mk +++ b/media/libstagefright/codecs/vorbis/dec/Android.mk @@ -2,21 +2,6 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := \ - VorbisDecoder.cpp \ - -LOCAL_C_INCLUDES := \ - frameworks/base/media/libstagefright/include \ - external/tremolo \ - -LOCAL_MODULE := libstagefright_vorbisdec - -include $(BUILD_STATIC_LIBRARY) - -################################################################################ - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ SoftVorbis.cpp LOCAL_C_INCLUDES := \ @@ -24,9 +9,6 @@ LOCAL_C_INCLUDES := \ frameworks/base/media/libstagefright/include \ frameworks/base/include/media/stagefright/openmax \ -LOCAL_STATIC_LIBRARIES := \ - libstagefright_vorbisdec - LOCAL_SHARED_LIBRARIES := \ libvorbisidec libstagefright libstagefright_omx \ libstagefright_foundation libutils diff --git a/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp b/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp deleted file mode 100644 index e14fb95..0000000 --- a/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp +++ /dev/null @@ -1,275 +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 "VorbisDecoder" -#include <utils/Log.h> - -#include "VorbisDecoder.h" - -#include <media/stagefright/MediaBufferGroup.h> -#include <media/stagefright/MediaDebug.h> -#include <media/stagefright/MediaDefs.h> -#include <media/stagefright/MediaErrors.h> -#include <media/stagefright/MetaData.h> - -extern "C" { - #include <Tremolo/codec_internal.h> - - int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb); - int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb); - int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb); -} - -namespace android { - -VorbisDecoder::VorbisDecoder(const sp<MediaSource> &source) - : mSource(source), - mStarted(false), - mBufferGroup(NULL), - mAnchorTimeUs(0), - mNumFramesOutput(0), - mState(NULL), - mVi(NULL) { - sp<MetaData> srcFormat = mSource->getFormat(); - CHECK(srcFormat->findInt32(kKeyChannelCount, &mNumChannels)); - CHECK(srcFormat->findInt32(kKeySampleRate, &mSampleRate)); -} - -VorbisDecoder::~VorbisDecoder() { - if (mStarted) { - stop(); - } -} - -static void makeBitReader( - const void *data, size_t size, - ogg_buffer *buf, ogg_reference *ref, oggpack_buffer *bits) { - buf->data = (uint8_t *)data; - buf->size = size; - buf->refcount = 1; - buf->ptr.owner = NULL; - - ref->buffer = buf; - ref->begin = 0; - ref->length = size; - ref->next = NULL; - - oggpack_readinit(bits, ref); -} - -status_t VorbisDecoder::start(MetaData *params) { - CHECK(!mStarted); - - mBufferGroup = new MediaBufferGroup; - mBufferGroup->add_buffer( - new MediaBuffer(kMaxNumSamplesPerBuffer * sizeof(int16_t))); - - mSource->start(); - - sp<MetaData> meta = mSource->getFormat(); - - mVi = new vorbis_info; - vorbis_info_init(mVi); - - /////////////////////////////////////////////////////////////////////////// - - uint32_t type; - const void *data; - size_t size; - CHECK(meta->findData(kKeyVorbisInfo, &type, &data, &size)); - - ogg_buffer buf; - ogg_reference ref; - oggpack_buffer bits; - makeBitReader((const uint8_t *)data + 7, size - 7, &buf, &ref, &bits); - CHECK_EQ(0, _vorbis_unpack_info(mVi, &bits)); - - /////////////////////////////////////////////////////////////////////////// - - CHECK(meta->findData(kKeyVorbisBooks, &type, &data, &size)); - - makeBitReader((const uint8_t *)data + 7, size - 7, &buf, &ref, &bits); - CHECK_EQ(0, _vorbis_unpack_books(mVi, &bits)); - - /////////////////////////////////////////////////////////////////////////// - - mState = new vorbis_dsp_state; - CHECK_EQ(0, vorbis_dsp_init(mState, mVi)); - - mAnchorTimeUs = 0; - mNumFramesOutput = 0; - - // If the source never limits the number of valid frames contained - // in the input data, we'll assume that all of the decoded frames are - // valid. - mNumFramesLeftOnPage = -1; - - mStarted = true; - - return OK; -} - -status_t VorbisDecoder::stop() { - CHECK(mStarted); - - vorbis_dsp_clear(mState); - delete mState; - mState = NULL; - - vorbis_info_clear(mVi); - delete mVi; - mVi = NULL; - - delete mBufferGroup; - mBufferGroup = NULL; - - mSource->stop(); - - mStarted = false; - - return OK; -} - -sp<MetaData> VorbisDecoder::getFormat() { - sp<MetaData> srcFormat = mSource->getFormat(); - - sp<MetaData> meta = new MetaData; - meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); - meta->setInt32(kKeyChannelCount, mNumChannels); - meta->setInt32(kKeySampleRate, mSampleRate); - - int64_t durationUs; - if (srcFormat->findInt64(kKeyDuration, &durationUs)) { - meta->setInt64(kKeyDuration, durationUs); - } - - meta->setCString(kKeyDecoderComponent, "VorbisDecoder"); - - return meta; -} - -int VorbisDecoder::decodePacket(MediaBuffer *packet, MediaBuffer *out) { - ogg_buffer buf; - buf.data = (uint8_t *)packet->data() + packet->range_offset(); - buf.size = packet->range_length(); - buf.refcount = 1; - buf.ptr.owner = NULL; - - ogg_reference ref; - ref.buffer = &buf; - ref.begin = 0; - ref.length = packet->range_length(); - ref.next = NULL; - - ogg_packet pack; - pack.packet = &ref; - pack.bytes = packet->range_length(); - pack.b_o_s = 0; - pack.e_o_s = 0; - pack.granulepos = 0; - pack.packetno = 0; - - int numFrames = 0; - - int err = vorbis_dsp_synthesis(mState, &pack, 1); - if (err != 0) { - LOGW("vorbis_dsp_synthesis returned %d", err); - } else { - numFrames = vorbis_dsp_pcmout( - mState, (int16_t *)out->data(), kMaxNumSamplesPerBuffer); - - if (numFrames < 0) { - LOGE("vorbis_dsp_pcmout returned %d", numFrames); - numFrames = 0; - } - } - - if (mNumFramesLeftOnPage >= 0) { - if (numFrames > mNumFramesLeftOnPage) { - LOGV("discarding %d frames at end of page", - numFrames - mNumFramesLeftOnPage); - numFrames = mNumFramesLeftOnPage; - } - mNumFramesLeftOnPage -= numFrames; - } - - out->set_range(0, numFrames * sizeof(int16_t) * mNumChannels); - - return numFrames; -} - -status_t VorbisDecoder::read( - MediaBuffer **out, const ReadOptions *options) { - status_t err; - - *out = NULL; - - int64_t seekTimeUs; - ReadOptions::SeekMode mode; - if (options && options->getSeekTo(&seekTimeUs, &mode)) { - CHECK(seekTimeUs >= 0); - - mNumFramesOutput = 0; - vorbis_dsp_restart(mState); - } else { - seekTimeUs = -1; - } - - MediaBuffer *inputBuffer; - err = mSource->read(&inputBuffer, options); - - if (err != OK) { - return ERROR_END_OF_STREAM; - } - - int64_t timeUs; - if (inputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) { - mAnchorTimeUs = timeUs; - mNumFramesOutput = 0; - } else { - // We must have a new timestamp after seeking. - CHECK(seekTimeUs < 0); - } - - int32_t numPageSamples; - if (inputBuffer->meta_data()->findInt32( - kKeyValidSamples, &numPageSamples)) { - CHECK(numPageSamples >= 0); - mNumFramesLeftOnPage = numPageSamples; - } - - MediaBuffer *outputBuffer; - CHECK_EQ(mBufferGroup->acquire_buffer(&outputBuffer), OK); - - int numFrames = decodePacket(inputBuffer, outputBuffer); - - inputBuffer->release(); - inputBuffer = NULL; - - outputBuffer->meta_data()->setInt64( - kKeyTime, - mAnchorTimeUs - + (mNumFramesOutput * 1000000ll) / mSampleRate); - - mNumFramesOutput += numFrames; - - *out = outputBuffer; - - return OK; -} - -} // namespace android diff --git a/media/libstagefright/include/ThreadedSource.h b/media/libstagefright/include/ThreadedSource.h deleted file mode 100644 index c67295c..0000000 --- a/media/libstagefright/include/ThreadedSource.h +++ /dev/null @@ -1,73 +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 THREADED_SOURCE_H_ - -#define THREADED_SOURCE_H_ - -#include <media/stagefright/foundation/ABase.h> -#include <media/stagefright/foundation/AHandlerReflector.h> -#include <media/stagefright/foundation/ALooper.h> -#include <media/stagefright/MediaSource.h> -#include <utils/threads.h> - -namespace android { - -struct ThreadedSource : public MediaSource { - ThreadedSource(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 onMessageReceived(const sp<AMessage> &msg); - -protected: - virtual ~ThreadedSource(); - -private: - enum { - kWhatDecodeMore = 'deco', - kWhatSeek = 'seek', - }; - - sp<MediaSource> mSource; - sp<AHandlerReflector<ThreadedSource> > mReflector; - sp<ALooper> mLooper; - - Mutex mLock; - Condition mCondition; - List<MediaBuffer *> mQueue; - status_t mFinalResult; - bool mDecodePending; - bool mStarted; - - int64_t mSeekTimeUs; - ReadOptions::SeekMode mSeekMode; - - void postDecodeMore_l(); - void clearQueue_l(); - - DISALLOW_EVIL_CONSTRUCTORS(ThreadedSource); -}; - -} // namespace android - -#endif // THREADED_SOURCE_H_ diff --git a/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp b/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp index f86ca47..e390ae2 100644 --- a/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp +++ b/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp @@ -29,7 +29,6 @@ #include <camera/ICamera.h> #include <camera/ICameraClient.h> #include <camera/ICameraService.h> -#include <ui/Overlay.h> #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> #include <binder/ProcessState.h> @@ -311,8 +310,6 @@ public: virtual status_t registerBuffers(const BufferHeap& buffers); virtual void postBuffer(ssize_t offset); virtual void unregisterBuffers(); - virtual sp<OverlayRef> createOverlay( - uint32_t w, uint32_t h, int32_t format, int32_t orientation); virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, int usage); virtual status_t setBufferCount(int bufferCount); @@ -381,13 +378,6 @@ void MSurface::waitUntil(int c0, int c1, int c2) { } } -sp<OverlayRef> MSurface::createOverlay(uint32_t w, uint32_t h, int32_t format, - int32_t orientation) { - // Not implemented. - ASSERT(0); - return NULL; -} - // // Utilities to use the Holder service // diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp index da9b55c..10b9083 100644 --- a/services/input/InputDispatcher.cpp +++ b/services/input/InputDispatcher.cpp @@ -3154,9 +3154,11 @@ void InputDispatcher::setInputWindows(const Vector<InputWindow>& inputWindows) { mLastHoverWindow = NULL; } + mWindows.clear(); + // Loop over new windows and rebuild the necessary window pointers for // tracking focus and touch. - mWindows = inputWindows; + mWindows.appendVector(inputWindows); size_t numWindows = mWindows.size(); for (size_t i = 0; i < numWindows; i++) { @@ -4558,7 +4560,8 @@ void InputDispatcher::TouchState::copyFrom(const TouchState& other) { split = other.split; deviceId = other.deviceId; source = other.source; - windows = other.windows; + windows.clear(); + windows.appendVector(other.windows); } void InputDispatcher::TouchState::addOrUpdateWindow(const InputWindow* window, diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java index 786f2fa..168b894 100644 --- a/services/java/com/android/server/BackupManagerService.java +++ b/services/java/com/android/server/BackupManagerService.java @@ -76,6 +76,7 @@ import com.android.internal.backup.IBackupTransport; import com.android.internal.backup.LocalTransport; import com.android.server.PackageManagerBackupAgent.Metadata; +import java.io.DataInputStream; import java.io.EOFException; import java.io.File; import java.io.FileDescriptor; @@ -96,6 +97,10 @@ import java.util.Map; import java.util.Random; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.zip.Deflater; +import java.util.zip.DeflaterOutputStream; +import java.util.zip.Inflater; +import java.util.zip.InflaterInputStream; class BackupManagerService extends IBackupManager.Stub { private static final String TAG = "BackupManagerService"; @@ -1679,6 +1684,7 @@ class BackupManagerService extends IBackupManager.Stub { class PerformFullBackupTask implements Runnable { ParcelFileDescriptor mOutputFile; + DeflaterOutputStream mDeflater; IFullBackupRestoreObserver mObserver; boolean mIncludeApks; boolean mIncludeShared; @@ -1688,6 +1694,55 @@ class BackupManagerService extends IBackupManager.Stub { File mFilesDir; File mManifestFile; + class FullBackupRunner implements Runnable { + PackageInfo mPackage; + IBackupAgent mAgent; + ParcelFileDescriptor mPipe; + int mToken; + boolean mSendApk; + + FullBackupRunner(PackageInfo pack, IBackupAgent agent, ParcelFileDescriptor pipe, + int token, boolean sendApk) throws IOException { + mPackage = pack; + mAgent = agent; + mPipe = ParcelFileDescriptor.dup(pipe.getFileDescriptor()); + mToken = token; + mSendApk = sendApk; + } + + @Override + public void run() { + try { + BackupDataOutput output = new BackupDataOutput( + mPipe.getFileDescriptor()); + + if (DEBUG) Slog.d(TAG, "Writing manifest for " + mPackage.packageName); + writeAppManifest(mPackage, mManifestFile, mSendApk); + FullBackup.backupToTar(mPackage.packageName, null, null, + mFilesDir.getAbsolutePath(), + mManifestFile.getAbsolutePath(), + output); + + if (mSendApk) { + writeApkToBackup(mPackage, output); + } + + if (DEBUG) Slog.d(TAG, "Calling doFullBackup()"); + prepareOperationTimeout(mToken, TIMEOUT_FULL_BACKUP_INTERVAL); + mAgent.doFullBackup(mPipe, mToken, mBackupManagerBinder); + } catch (IOException e) { + Slog.e(TAG, "Error running full backup for " + mPackage.packageName); + } catch (RemoteException e) { + Slog.e(TAG, "Remote agent vanished during full backup of " + + mPackage.packageName); + } finally { + try { + mPipe.close(); + } catch (IOException e) {} + } + } + } + PerformFullBackupTask(ParcelFileDescriptor fd, IFullBackupRestoreObserver observer, boolean includeApks, boolean includeShared, boolean doAllApps, String[] packages, AtomicBoolean latch) { @@ -1736,13 +1791,21 @@ class BackupManagerService extends IBackupManager.Stub { } } + // Set up the compression stage + FileOutputStream ofstream = new FileOutputStream(mOutputFile.getFileDescriptor()); + Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION); + DeflaterOutputStream out = new DeflaterOutputStream(ofstream, deflater, true); + + // !!! TODO: if using encryption, set up the encryption stage + // and emit the tar header stating the password salt. + PackageInfo pkg = null; try { // Now back up the app data via the agent mechanism int N = packagesToBackup.size(); for (int i = 0; i < N; i++) { pkg = packagesToBackup.get(i); - backupOnePackage(pkg); + backupOnePackage(pkg, out); } // Finally, shared storage if requested @@ -1754,6 +1817,7 @@ class BackupManagerService extends IBackupManager.Stub { } finally { tearDown(pkg); try { + out.close(); mOutputFile.close(); } catch (IOException e) { /* nothing we can do about this */ @@ -1771,13 +1835,17 @@ class BackupManagerService extends IBackupManager.Stub { } } - private void backupOnePackage(PackageInfo pkg) throws RemoteException { + private void backupOnePackage(PackageInfo pkg, DeflaterOutputStream out) + throws RemoteException { Slog.d(TAG, "Binding to full backup agent : " + pkg.packageName); IBackupAgent agent = bindToAgentSynchronous(pkg.applicationInfo, IApplicationThread.BACKUP_MODE_FULL); if (agent != null) { + ParcelFileDescriptor[] pipes = null; try { + pipes = ParcelFileDescriptor.createPipe(); + ApplicationInfo app = pkg.applicationInfo; final boolean sendApk = mIncludeApks && ((app.flags & ApplicationInfo.FLAG_FORWARD_LOCK) == 0) @@ -1786,31 +1854,54 @@ class BackupManagerService extends IBackupManager.Stub { sendOnBackupPackage(pkg.packageName); - BackupDataOutput output = new BackupDataOutput( - mOutputFile.getFileDescriptor()); - - if (DEBUG) Slog.d(TAG, "Writing manifest for " + pkg.packageName); - writeAppManifest(pkg, mManifestFile, sendApk); - FullBackup.backupToTar(pkg.packageName, null, null, - mFilesDir.getAbsolutePath(), - mManifestFile.getAbsolutePath(), - output); - - if (sendApk) { - writeApkToBackup(pkg, output); + final int token = generateToken(); + FullBackupRunner runner = new FullBackupRunner(pkg, agent, pipes[1], + token, sendApk); + pipes[1].close(); // the runner has dup'd it + pipes[1] = null; + Thread t = new Thread(runner); + t.start(); + + // Now pull data from the app and stuff it into the compressor + try { + FileInputStream raw = new FileInputStream(pipes[0].getFileDescriptor()); + DataInputStream in = new DataInputStream(raw); + + byte[] buffer = new byte[16 * 1024]; + int chunkTotal; + while ((chunkTotal = in.readInt()) > 0) { + while (chunkTotal > 0) { + int toRead = (chunkTotal > buffer.length) + ? buffer.length : chunkTotal; + int nRead = in.read(buffer, 0, toRead); + out.write(buffer, 0, nRead); + chunkTotal -= nRead; + } + } + } catch (IOException e) { + Slog.i(TAG, "Caught exception reading from agent", e); } - if (DEBUG) Slog.d(TAG, "Calling doFullBackup()"); - final int token = generateToken(); - prepareOperationTimeout(token, TIMEOUT_FULL_BACKUP_INTERVAL); - agent.doFullBackup(mOutputFile, token, mBackupManagerBinder); if (!waitUntilOperationComplete(token)) { Slog.e(TAG, "Full backup failed on package " + pkg.packageName); } else { - if (DEBUG) Slog.d(TAG, "Full backup success: " + pkg.packageName); + if (DEBUG) Slog.d(TAG, "Full package backup success: " + pkg.packageName); } + } catch (IOException e) { Slog.e(TAG, "Error backing up " + pkg.packageName, e); + } finally { + try { + if (pipes != null) { + if (pipes[0] != null) pipes[0].close(); + if (pipes[1] != null) pipes[1].close(); + } + + // Apply a full sync/flush after each application's data + out.flush(); + } catch (IOException e) { + Slog.w(TAG, "Error bringing down backup stack"); + } } } else { Slog.w(TAG, "Unable to bind to full agent for " + pkg.packageName); @@ -2084,11 +2175,12 @@ class BackupManagerService extends IBackupManager.Stub { try { mBytes = 0; byte[] buffer = new byte[32 * 1024]; - FileInputStream instream = new FileInputStream(mInputFile.getFileDescriptor()); + FileInputStream rawInStream = new FileInputStream(mInputFile.getFileDescriptor()); + InflaterInputStream in = new InflaterInputStream(rawInStream); boolean didRestore; do { - didRestore = restoreOneFile(instream, buffer); + didRestore = restoreOneFile(in, buffer); } while (didRestore); if (DEBUG) Slog.v(TAG, "Done consuming input tarfile, total bytes=" + mBytes); diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java index 2e54c99..94465fd 100644 --- a/services/java/com/android/server/MountService.java +++ b/services/java/com/android/server/MountService.java @@ -2361,6 +2361,19 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC pw.print(" -> "); pw.println(e.getValue().toString()); } } + + pw.println(""); + + synchronized (mVolumes) { + pw.println(" mVolumes:"); + + final int N = mVolumes.size(); + for (int i = 0; i < N; i++) { + final StorageVolume v = mVolumes.get(i); + pw.print(" "); + pw.println(v.toString()); + } + } } } diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java index 829df39..41e8a31 100644 --- a/services/java/com/android/server/NetworkManagementService.java +++ b/services/java/com/android/server/NetworkManagementService.java @@ -196,6 +196,9 @@ class NetworkManagementService extends INetworkManagementService.Stub { } else { Slog.d(TAG, "not enabling bandwidth control"); } + + SystemProperties.set(NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED, + mBandwidthControlEnabled ? "1" : "0"); } public void registerObserver(INetworkManagementEventObserver obs) { diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java index 260cdc8..fc2f2f8 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java @@ -131,6 +131,10 @@ public final class BridgeTypedArray extends TypedArray { */ @Override public CharSequence getText(int index) { + if (index < 0 || index >= mResourceData.length) { + return null; + } + if (mResourceData[index] != null) { // FIXME: handle styled strings! return mResourceData[index].getValue(); @@ -149,6 +153,10 @@ public final class BridgeTypedArray extends TypedArray { */ @Override public String getString(int index) { + if (index < 0 || index >= mResourceData.length) { + return null; + } + if (mResourceData[index] != null) { return mResourceData[index].getValue(); } @@ -166,6 +174,10 @@ public final class BridgeTypedArray extends TypedArray { */ @Override public boolean getBoolean(int index, boolean defValue) { + if (index < 0 || index >= mResourceData.length) { + return defValue; + } + if (mResourceData[index] == null) { return defValue; } @@ -188,6 +200,10 @@ public final class BridgeTypedArray extends TypedArray { */ @Override public int getInt(int index, int defValue) { + if (index < 0 || index >= mResourceData.length) { + return defValue; + } + if (mResourceData[index] == null) { return defValue; } @@ -252,6 +268,10 @@ public final class BridgeTypedArray extends TypedArray { */ @Override public float getFloat(int index, float defValue) { + if (index < 0 || index >= mResourceData.length) { + return defValue; + } + if (mResourceData[index] == null) { return defValue; } @@ -287,6 +307,10 @@ public final class BridgeTypedArray extends TypedArray { */ @Override public int getColor(int index, int defValue) { + if (index < 0 || index >= mResourceData.length) { + return defValue; + } + if (mResourceData[index] == null) { return defValue; } @@ -311,6 +335,10 @@ public final class BridgeTypedArray extends TypedArray { */ @Override public ColorStateList getColorStateList(int index) { + if (index < 0 || index >= mResourceData.length) { + return null; + } + if (mResourceData[index] == null) { return null; } @@ -395,6 +423,10 @@ public final class BridgeTypedArray extends TypedArray { */ @Override public float getDimension(int index, float defValue) { + if (index < 0 || index >= mResourceData.length) { + return defValue; + } + if (mResourceData[index] == null) { return defValue; } @@ -568,6 +600,10 @@ public final class BridgeTypedArray extends TypedArray { */ @Override public float getFraction(int index, int base, int pbase, float defValue) { + if (index < 0 || index >= mResourceData.length) { + return defValue; + } + if (mResourceData[index] == null) { return defValue; } @@ -607,6 +643,10 @@ public final class BridgeTypedArray extends TypedArray { */ @Override public int getResourceId(int index, int defValue) { + if (index < 0 || index >= mResourceData.length) { + return defValue; + } + // get the Resource for this index ResourceValue resValue = mResourceData[index]; @@ -718,6 +758,10 @@ public final class BridgeTypedArray extends TypedArray { */ @Override public Drawable getDrawable(int index) { + if (index < 0 || index >= mResourceData.length) { + return null; + } + if (mResourceData[index] == null) { return null; } @@ -744,6 +788,10 @@ public final class BridgeTypedArray extends TypedArray { */ @Override public CharSequence[] getTextArray(int index) { + if (index < 0 || index >= mResourceData.length) { + return null; + } + if (mResourceData[index] == null) { return null; } @@ -776,6 +824,10 @@ public final class BridgeTypedArray extends TypedArray { */ @Override public boolean getValue(int index, TypedValue outValue) { + if (index < 0 || index >= mResourceData.length) { + return false; + } + if (mResourceData[index] == null) { return false; } @@ -795,6 +847,10 @@ public final class BridgeTypedArray extends TypedArray { */ @Override public boolean hasValue(int index) { + if (index < 0 || index >= mResourceData.length) { + return false; + } + return mResourceData[index] != null; } @@ -811,6 +867,10 @@ public final class BridgeTypedArray extends TypedArray { */ @Override public TypedValue peekValue(int index) { + if (index < 0 || index >= mResourceData.length) { + return null; + } + if (getValue(index, mValue)) { return mValue; } diff --git a/voip/java/android/net/sip/SipAudioCall.java b/voip/java/android/net/sip/SipAudioCall.java index c1affa6..fcdbd2c 100644 --- a/voip/java/android/net/sip/SipAudioCall.java +++ b/voip/java/android/net/sip/SipAudioCall.java @@ -57,6 +57,7 @@ public class SipAudioCall { private static final boolean RELEASE_SOCKET = true; private static final boolean DONT_RELEASE_SOCKET = false; private static final int SESSION_TIMEOUT = 5; // in seconds + private static final int TRANSFER_TIMEOUT = 15; // in seconds /** Listener for events relating to a SIP call, such as when a call is being * recieved ("on ringing") or a call is outgoing ("on calling"). @@ -537,10 +538,14 @@ public class SipAudioCall { Log.v(TAG, "onCallTransferring mSipSession:" + mSipSession + " newSession:" + newSession); mTransferringSession = newSession; - // session changing request try { - String answer = createAnswer(sessionDescription).encode(); - newSession.answerCall(answer, SESSION_TIMEOUT); + if (sessionDescription == null) { + newSession.makeCall(newSession.getPeerProfile(), + createOffer().encode(), TRANSFER_TIMEOUT); + } else { + String answer = createAnswer(sessionDescription).encode(); + newSession.answerCall(answer, SESSION_TIMEOUT); + } } catch (Throwable e) { Log.e(TAG, "onCallTransferring()", e); newSession.endCall(); diff --git a/voip/java/com/android/server/sip/SipHelper.java b/voip/java/com/android/server/sip/SipHelper.java index c031bc1..dc628e0 100644 --- a/voip/java/com/android/server/sip/SipHelper.java +++ b/voip/java/com/android/server/sip/SipHelper.java @@ -19,6 +19,9 @@ package com.android.server.sip; import gov.nist.javax.sip.SipStackExt; import gov.nist.javax.sip.clientauthutils.AccountManager; import gov.nist.javax.sip.clientauthutils.AuthenticationHelper; +import gov.nist.javax.sip.header.extensions.ReferencesHeader; +import gov.nist.javax.sip.header.extensions.ReferredByHeader; +import gov.nist.javax.sip.header.extensions.ReplacesHeader; import android.net.sip.SipProfile; import android.util.Log; @@ -284,14 +287,18 @@ class SipHelper { } public ClientTransaction sendInvite(SipProfile caller, SipProfile callee, - String sessionDescription, String tag) - throws SipException { + String sessionDescription, String tag, ReferredByHeader referredBy, + String replaces) throws SipException { try { Request request = createRequest(Request.INVITE, caller, callee, tag); + if (referredBy != null) request.addHeader(referredBy); + if (replaces != null) { + request.addHeader(mHeaderFactory.createHeader( + ReplacesHeader.NAME, replaces)); + } request.setContent(sessionDescription, mHeaderFactory.createContentTypeHeader( "application", "sdp")); - ClientTransaction clientTransaction = mSipProvider.getNewClientTransaction(request); if (DEBUG) Log.d(TAG, "send INVITE: " + request); @@ -455,6 +462,25 @@ class SipHelper { } } + public void sendReferNotify(Dialog dialog, String content) + throws SipException { + try { + Request request = dialog.createRequest(Request.NOTIFY); + request.addHeader(mHeaderFactory.createSubscriptionStateHeader( + "active;expires=60")); + // set content here + request.setContent(content, + mHeaderFactory.createContentTypeHeader( + "message", "sipfrag")); + request.addHeader(mHeaderFactory.createEventHeader( + ReferencesHeader.REFER)); + if (DEBUG) Log.d(TAG, "send NOTIFY: " + request); + dialog.sendRequest(mSipProvider.getNewClientTransaction(request)); + } catch (ParseException e) { + throw new SipException("sendReferNotify()", e); + } + } + public void sendInviteRequestTerminated(Request inviteRequest, ServerTransaction inviteTransaction) throws SipException { try { diff --git a/voip/java/com/android/server/sip/SipSessionGroup.java b/voip/java/com/android/server/sip/SipSessionGroup.java index 4e44402..48d9b17 100644 --- a/voip/java/com/android/server/sip/SipSessionGroup.java +++ b/voip/java/com/android/server/sip/SipSessionGroup.java @@ -18,12 +18,15 @@ package com.android.server.sip; import gov.nist.javax.sip.clientauthutils.AccountManager; import gov.nist.javax.sip.clientauthutils.UserCredentials; -import gov.nist.javax.sip.header.SIPHeaderNames; import gov.nist.javax.sip.header.ProxyAuthenticate; +import gov.nist.javax.sip.header.ReferTo; +import gov.nist.javax.sip.header.SIPHeaderNames; +import gov.nist.javax.sip.header.StatusLine; import gov.nist.javax.sip.header.WWWAuthenticate; import gov.nist.javax.sip.header.extensions.ReferredByHeader; import gov.nist.javax.sip.header.extensions.ReplacesHeader; import gov.nist.javax.sip.message.SIPMessage; +import gov.nist.javax.sip.message.SIPResponse; import android.net.sip.ISipSession; import android.net.sip.ISipSessionListener; @@ -71,12 +74,15 @@ import javax.sip.address.SipURI; import javax.sip.header.CSeqHeader; import javax.sip.header.ExpiresHeader; import javax.sip.header.FromHeader; +import javax.sip.header.HeaderAddress; import javax.sip.header.MinExpiresHeader; +import javax.sip.header.ReferToHeader; import javax.sip.header.ViaHeader; import javax.sip.message.Message; import javax.sip.message.Request; import javax.sip.message.Response; + /** * Manages {@link ISipSession}'s for a SIP account. */ @@ -390,25 +396,26 @@ class SipSessionGroup implements SipListener { } } + private SipSessionImpl createNewSession(RequestEvent event, + ISipSessionListener listener, ServerTransaction transaction, + int newState) throws SipException { + SipSessionImpl newSession = new SipSessionImpl(listener); + newSession.mServerTransaction = transaction; + newSession.mState = newState; + newSession.mDialog = newSession.mServerTransaction.getDialog(); + newSession.mInviteReceived = event; + newSession.mPeerProfile = createPeerProfile((HeaderAddress) + event.getRequest().getHeader(FromHeader.NAME)); + newSession.mPeerSessionDescription = + extractContent(event.getRequest()); + return newSession; + } + private class SipSessionCallReceiverImpl extends SipSessionImpl { public SipSessionCallReceiverImpl(ISipSessionListener listener) { super(listener); } - private SipSessionImpl createNewSession(RequestEvent event, - ISipSessionListener listener, ServerTransaction transaction) - throws SipException { - SipSessionImpl newSession = new SipSessionImpl(listener); - newSession.mServerTransaction = transaction; - newSession.mState = SipSession.State.INCOMING_CALL; - newSession.mDialog = newSession.mServerTransaction.getDialog(); - newSession.mInviteReceived = event; - newSession.mPeerProfile = createPeerProfile(event.getRequest()); - newSession.mPeerSessionDescription = - extractContent(event.getRequest()); - return newSession; - } - private int processInviteWithReplaces(RequestEvent event, ReplacesHeader replaces) { String callId = replaces.getCallId(); @@ -452,7 +459,8 @@ class SipSessionGroup implements SipListener { // got INVITE w/ replaces request. newSession = createNewSession(event, replacedSession.mProxy.getListener(), - mSipHelper.getServerTransaction(event)); + mSipHelper.getServerTransaction(event), + SipSession.State.INCOMING_CALL); newSession.mProxy.onCallTransferring(newSession, newSession.mPeerSessionDescription); } else { @@ -461,7 +469,8 @@ class SipSessionGroup implements SipListener { } else { // New Incoming call. newSession = createNewSession(event, mProxy, - mSipHelper.sendRinging(event, generateTag())); + mSipHelper.sendRinging(event, generateTag()), + SipSession.State.INCOMING_CALL); mProxy.onRinging(newSession, newSession.mPeerProfile, newSession.mPeerSessionDescription); } @@ -507,6 +516,11 @@ class SipSessionGroup implements SipListener { private SipSessionImpl mKeepAliveSession; + // the following three members are used for handling refer request. + SipSessionImpl mReferSession; + ReferredByHeader mReferredBy; + String mReplaces; + // lightweight timer class SessionTimer { private boolean mRunning = true; @@ -556,6 +570,9 @@ class SipSessionGroup implements SipListener { mInviteReceived = null; mPeerSessionDescription = null; mAuthenticationRetryCount = 0; + mReferSession = null; + mReferredBy = null; + mReplaces = null; if (mDialog != null) mDialog.delete(); mDialog = null; @@ -969,15 +986,26 @@ class SipSessionGroup implements SipListener { return (proxyAuth == null) ? null : proxyAuth.getNonce(); } + private String getResponseString(int statusCode) { + StatusLine statusLine = new StatusLine(); + statusLine.setStatusCode(statusCode); + statusLine.setReasonPhrase(SIPResponse.getReasonPhrase(statusCode)); + return statusLine.encode(); + } + private boolean readyForCall(EventObject evt) throws SipException { // expect MakeCallCommand, RegisterCommand, DEREGISTER if (evt instanceof MakeCallCommand) { mState = SipSession.State.OUTGOING_CALL; MakeCallCommand cmd = (MakeCallCommand) evt; mPeerProfile = cmd.getPeerProfile(); - mClientTransaction = mSipHelper.sendInvite(mLocalProfile, - mPeerProfile, cmd.getSessionDescription(), - generateTag()); + if (mReferSession != null) { + mSipHelper.sendReferNotify(mReferSession.mDialog, + getResponseString(Response.TRYING)); + } + mClientTransaction = mSipHelper.sendInvite( + mLocalProfile, mPeerProfile, cmd.getSessionDescription(), + generateTag(), mReferredBy, mReplaces); mDialog = mClientTransaction.getDialog(); addSipSession(this); startSessionTimer(cmd.getTimeout()); @@ -1072,6 +1100,12 @@ class SipSessionGroup implements SipListener { } return true; case Response.OK: + if (mReferSession != null) { + mSipHelper.sendReferNotify(mReferSession.mDialog, + getResponseString(Response.OK)); + // since we don't need to remember the session anymore. + mReferSession = null; + } mSipHelper.sendInviteAck(event, mDialog); mPeerSessionDescription = extractContent(response); establishCall(true); @@ -1087,6 +1121,10 @@ class SipSessionGroup implements SipListener { // rfc3261#section-14.1; re-schedule invite return true; default: + if (mReferSession != null) { + mSipHelper.sendReferNotify(mReferSession.mDialog, + getResponseString(Response.SERVICE_UNAVAILABLE)); + } if (statusCode >= 400) { // error: an ack is sent automatically by the stack onError(response); @@ -1155,6 +1193,38 @@ class SipSessionGroup implements SipListener { return false; } + private boolean processReferRequest(RequestEvent event) + throws SipException { + try { + ReferToHeader referto = (ReferToHeader) event.getRequest() + .getHeader(ReferTo.NAME); + Address address = referto.getAddress(); + SipURI uri = (SipURI) address.getURI(); + String replacesHeader = uri.getHeader(ReplacesHeader.NAME); + String username = uri.getUser(); + if (username == null) { + mSipHelper.sendResponse(event, Response.BAD_REQUEST); + return false; + } + // send notify accepted + mSipHelper.sendResponse(event, Response.ACCEPTED); + SipSessionImpl newSession = createNewSession(event, + this.mProxy.getListener(), + mSipHelper.getServerTransaction(event), + SipSession.State.READY_TO_CALL); + newSession.mReferSession = this; + newSession.mReferredBy = (ReferredByHeader) event.getRequest() + .getHeader(ReferredByHeader.NAME); + newSession.mReplaces = replacesHeader; + newSession.mPeerProfile = createPeerProfile(referto); + newSession.mProxy.onCallTransferring(newSession, + null); + return true; + } catch (IllegalArgumentException e) { + throw new SipException("createPeerProfile()", e); + } + } + private boolean inCall(EventObject evt) throws SipException { // expect END_CALL cmd, BYE request, hold call (MakeCallCommand) // OK retransmission is handled in SipStack @@ -1175,6 +1245,8 @@ class SipSessionGroup implements SipListener { mSipHelper.sendResponse((RequestEvent) evt, Response.OK); endCallNormally(); return true; + } else if (isRequestEvent(Request.REFER, evt)) { + return processReferRequest((RequestEvent) evt); } else if (evt instanceof MakeCallCommand) { // to change call mState = SipSession.State.OUTGOING_CALL; @@ -1182,6 +1254,8 @@ class SipSessionGroup implements SipListener { ((MakeCallCommand) evt).getSessionDescription()); startSessionTimer(((MakeCallCommand) evt).getTimeout()); return true; + } else if (evt instanceof ResponseEvent) { + if (expectResponse(Request.NOTIFY, evt)) return true; } return false; } @@ -1558,12 +1632,10 @@ class SipSessionGroup implements SipListener { return false; } - private static SipProfile createPeerProfile(Request request) + private static SipProfile createPeerProfile(HeaderAddress header) throws SipException { try { - FromHeader fromHeader = - (FromHeader) request.getHeader(FromHeader.NAME); - Address address = fromHeader.getAddress(); + Address address = header.getAddress(); SipURI uri = (SipURI) address.getURI(); String username = uri.getUser(); if (username == null) username = ANONYMOUS; |
