summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt19
-rw-r--r--cmds/system_server/system_main.cpp5
-rw-r--r--core/java/android/app/backup/BackupAgent.java11
-rw-r--r--core/java/android/os/storage/StorageVolume.java5
-rw-r--r--core/java/android/provider/ContactsContract.java261
-rwxr-xr-xcore/java/android/speech/tts/TextToSpeech.java45
-rw-r--r--core/java/android/view/ActionProvider.java4
-rw-r--r--core/java/android/webkit/CallbackProxy.java17
-rw-r--r--core/java/android/webkit/SearchBox.java20
-rw-r--r--core/java/android/webkit/SearchBoxImpl.java80
-rw-r--r--core/java/android/webkit/WebView.java55
-rw-r--r--core/java/android/webkit/WebViewCore.java2
-rw-r--r--core/java/android/widget/ActivityChooserModel.java63
-rw-r--r--core/java/android/widget/ActivityChooserView.java311
-rw-r--r--core/java/android/widget/CalendarView.java1
-rw-r--r--core/java/android/widget/ShareActionProvider.java101
-rw-r--r--core/java/com/android/internal/view/menu/ActionMenuPresenter.java11
-rw-r--r--core/java/com/android/internal/view/menu/IconMenuPresenter.java6
-rw-r--r--core/java/com/android/internal/view/menu/ListMenuItemView.java26
-rw-r--r--core/java/com/android/internal/view/menu/MenuBuilder.java2
-rw-r--r--core/java/com/android/internal/view/menu/MenuItemImpl.java5
-rw-r--r--core/java/com/android/internal/view/menu/MenuPopupHelper.java31
-rw-r--r--core/java/com/android/server/NetworkManagementSocketTagger.java56
-rw-r--r--core/jni/AndroidRuntime.cpp7
-rw-r--r--core/jni/android_net_TrafficStats.cpp8
-rw-r--r--core/jni/android_os_Debug.cpp6
-rw-r--r--core/jni/android_os_FileUtils.cpp15
-rw-r--r--core/jni/android_os_Power.cpp8
-rw-r--r--core/jni/android_server_BluetoothEventLoop.cpp2
-rw-r--r--core/jni/android_util_Log.cpp4
-rw-r--r--core/jni/android_util_Process.cpp8
-rw-r--r--core/jni/com_android_internal_os_ZygoteInit.cpp8
-rw-r--r--core/res/res/layout/activity_chooser_list_footer.xml42
-rw-r--r--core/res/res/layout/activity_chooser_list_header.xml41
-rw-r--r--core/res/res/layout/activity_chooser_view.xml4
-rw-r--r--core/res/res/layout/activity_chooser_view_list_item.xml49
-rw-r--r--core/res/res/layout/list_menu_item_icon.xml4
-rw-r--r--core/res/res/layout/popup_menu_item_layout.xml2
-rw-r--r--core/res/res/values/dimens.xml3
-rwxr-xr-xcore/res/res/values/strings.xml9
-rw-r--r--docs/html/guide/developing/tools/adb.jd4
-rw-r--r--docs/html/guide/guide_toc.cs7
-rw-r--r--docs/html/resources/dashboard/opengl.jd2
-rw-r--r--docs/html/sdk/ndk/index.jd70
-rw-r--r--docs/html/sdk/ndk/overview.jd4
-rw-r--r--docs/html/sdk/sdk_toc.cs10
-rw-r--r--include/media/stagefright/ShoutcastSource.h61
-rw-r--r--include/private/binder/binder_module.h115
-rw-r--r--libs/binder/ProcessState.cpp12
-rw-r--r--libs/hwui/Caches.cpp1
-rw-r--r--libs/hwui/Properties.h2
-rw-r--r--libs/rs/driver/rsdBcc.cpp1
-rw-r--r--libs/rs/driver/rsdBcc.h1
-rw-r--r--libs/rs/rsContext.cpp4
-rw-r--r--libs/rs/rsScriptC.cpp2
-rw-r--r--libs/rs/rs_hal.h1
-rw-r--r--libs/ui/InputTransport.cpp4
-rw-r--r--libs/utils/BackupHelpers.cpp16
-rw-r--r--media/java/android/media/MediaScanner.java23
-rw-r--r--media/jni/android_mtp_MtpDatabase.cpp11
-rw-r--r--media/jni/android_mtp_MtpDevice.cpp45
-rw-r--r--media/libstagefright/Android.mk29
-rw-r--r--media/libstagefright/HTTPBase.cpp19
-rw-r--r--media/libstagefright/HTTPStream.cpp623
-rw-r--r--media/libstagefright/NuHTTPDataSource.cpp560
-rwxr-xr-xmedia/libstagefright/OMXCodec.cpp92
-rw-r--r--media/libstagefright/ShoutcastSource.cpp157
-rw-r--r--media/libstagefright/ThreadedSource.cpp213
-rw-r--r--media/libstagefright/codecs/aacdec/AACDecoder.cpp335
-rw-r--r--media/libstagefright/codecs/aacdec/Android.mk1
-rw-r--r--media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp208
-rw-r--r--media/libstagefright/codecs/amrnb/dec/Android.mk1
-rw-r--r--media/libstagefright/codecs/amrwb/AMRWBDecoder.cpp225
-rw-r--r--media/libstagefright/codecs/amrwb/Android.mk1
-rw-r--r--media/libstagefright/codecs/avc/dec/AVCDecoder.cpp622
-rw-r--r--media/libstagefright/codecs/avc/dec/Android.mk1
-rw-r--r--media/libstagefright/codecs/g711/dec/Android.mk14
-rw-r--r--media/libstagefright/codecs/g711/dec/G711Decoder.cpp213
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/Android.mk1
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp304
-rw-r--r--media/libstagefright/codecs/mp3dec/Android.mk1
-rw-r--r--media/libstagefright/codecs/mp3dec/MP3Decoder.cpp226
-rw-r--r--media/libstagefright/codecs/on2/dec/Android.mk19
-rw-r--r--media/libstagefright/codecs/on2/dec/VPXDecoder.cpp277
-rw-r--r--media/libstagefright/codecs/vorbis/dec/Android.mk18
-rw-r--r--media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp275
-rw-r--r--media/libstagefright/include/HTTPBase.h2
-rw-r--r--media/libstagefright/include/HTTPStream.h91
-rw-r--r--media/libstagefright/include/NuHTTPDataSource.h114
-rw-r--r--media/libstagefright/include/OMX.h1
-rw-r--r--media/libstagefright/include/ThreadedSource.h73
-rw-r--r--media/libstagefright/omx/OMX.cpp63
-rw-r--r--media/libstagefright/rtsp/ARTSPConnection.cpp4
-rw-r--r--media/libstagefright/rtsp/MyHandler.h6
-rw-r--r--services/audioflinger/AudioPolicyService.cpp3
-rw-r--r--services/camera/tests/CameraServiceTest/CameraServiceTest.cpp10
-rw-r--r--services/input/InputApplication.h30
-rw-r--r--services/input/InputDispatcher.cpp533
-rw-r--r--services/input/InputDispatcher.h57
-rw-r--r--services/input/InputWindow.cpp12
-rw-r--r--services/input/InputWindow.h35
-rw-r--r--services/input/tests/InputReader_test.cpp5
-rw-r--r--services/java/com/android/server/BackupManagerService.java134
-rw-r--r--services/java/com/android/server/MountService.java13
-rw-r--r--services/java/com/android/server/NetworkManagementService.java3
-rw-r--r--services/java/com/android/server/accessibility/AccessibilityManagerService.java4
-rw-r--r--services/java/com/android/server/accessibility/TouchExplorer.java2
-rw-r--r--services/java/com/android/server/wm/AppWindowToken.java2
-rw-r--r--services/java/com/android/server/wm/InputApplication.java37
-rw-r--r--services/java/com/android/server/wm/InputApplicationHandle.java6
-rw-r--r--services/java/com/android/server/wm/InputManager.java11
-rw-r--r--services/java/com/android/server/wm/InputMonitor.java173
-rw-r--r--services/java/com/android/server/wm/InputWindow.java85
-rw-r--r--services/java/com/android/server/wm/InputWindowHandle.java53
-rw-r--r--services/java/com/android/server/wm/InputWindowList.java89
-rw-r--r--services/java/com/android/server/wm/WindowState.java3
-rw-r--r--services/jni/Android.mk2
-rw-r--r--services/jni/com_android_server_AlarmManagerService.cpp17
-rw-r--r--services/jni/com_android_server_BatteryService.cpp3
-rw-r--r--services/jni/com_android_server_InputApplication.cpp93
-rw-r--r--services/jni/com_android_server_InputApplication.h32
-rw-r--r--services/jni/com_android_server_InputApplicationHandle.cpp34
-rw-r--r--services/jni/com_android_server_InputApplicationHandle.h2
-rw-r--r--services/jni/com_android_server_InputManager.cpp77
-rw-r--r--services/jni/com_android_server_InputWindow.cpp218
-rw-r--r--services/jni/com_android_server_InputWindow.h32
-rw-r--r--services/jni/com_android_server_InputWindowHandle.cpp159
-rw-r--r--services/jni/com_android_server_InputWindowHandle.h2
-rw-r--r--services/jni/onload.cpp4
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java60
-rw-r--r--voip/java/android/net/sip/SipAudioCall.java11
-rw-r--r--voip/java/com/android/server/sip/SipHelper.java32
-rw-r--r--voip/java/com/android/server/sip/SipSessionGroup.java120
133 files changed, 2067 insertions, 6673 deletions
diff --git a/api/current.txt b/api/current.txt
index d3333f0..86339f2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -15750,6 +15750,7 @@ package android.provider {
public static final class ContactsContract.CommonDataKinds.Photo implements android.provider.ContactsContract.DataColumnsWithJoins {
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/photo";
field public static final java.lang.String PHOTO = "data15";
+ field public static final java.lang.String PHOTO_FILE_ID = "data14";
}
public static final class ContactsContract.CommonDataKinds.Relation implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
@@ -15889,7 +15890,9 @@ package android.provider {
public static final class ContactsContract.Contacts.Photo implements android.provider.BaseColumns android.provider.ContactsContract.DataColumnsWithJoins {
field public static final java.lang.String CONTENT_DIRECTORY = "photo";
+ field public static final java.lang.String DISPLAY_PHOTO = "display_photo";
field public static final java.lang.String PHOTO = "data15";
+ field public static final java.lang.String PHOTO_FILE_ID = "data14";
}
public static final class ContactsContract.Contacts.StreamItems implements android.provider.ContactsContract.StreamItemsColumns {
@@ -15902,6 +15905,7 @@ package android.provider {
field public static final java.lang.String IN_VISIBLE_GROUP = "in_visible_group";
field public static final java.lang.String IS_USER_PROFILE = "is_user_profile";
field public static final java.lang.String LOOKUP_KEY = "lookup";
+ field public static final java.lang.String PHOTO_FILE_ID = "photo_file_id";
field public static final java.lang.String PHOTO_ID = "photo_id";
field public static final java.lang.String PHOTO_THUMBNAIL_URI = "photo_thumb_uri";
field public static final java.lang.String PHOTO_URI = "photo_uri";
@@ -15990,6 +15994,13 @@ package android.provider {
field public static final int UNDEFINED = 0; // 0x0
}
+ public static final class ContactsContract.DisplayPhoto {
+ field public static final android.net.Uri CONTENT_MAX_DIMENSIONS_URI;
+ field public static final android.net.Uri CONTENT_URI;
+ field public static final java.lang.String DISPLAY_MAX_DIM = "display_max_dim";
+ field public static final java.lang.String THUMBNAIL_MAX_DIM = "thumbnail_max_dim";
+ }
+
public static abstract interface ContactsContract.FullNameStyle {
field public static final int CHINESE = 3; // 0x3
field public static final int CJK = 2; // 0x2
@@ -16008,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";
@@ -16125,6 +16138,10 @@ package android.provider {
field public static final java.lang.String CONTENT_DIRECTORY = "data";
}
+ public static final class ContactsContract.RawContacts.DisplayPhoto {
+ field public static final java.lang.String CONTENT_DIRECTORY = "display_photo";
+ }
+
public static final class ContactsContract.RawContacts.Entity implements android.provider.BaseColumns android.provider.ContactsContract.DataColumns {
field public static final java.lang.String CONTENT_DIRECTORY = "entity";
field public static final java.lang.String DATA_ID = "data_id";
@@ -26082,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/cmds/system_server/system_main.cpp b/cmds/system_server/system_main.cpp
index 543f650..d67329d 100644
--- a/cmds/system_server/system_main.cpp
+++ b/cmds/system_server/system_main.cpp
@@ -52,10 +52,5 @@ int main(int argc, const char* const argv[])
LOGW("*** Current priority: %d\n", getpriority(PRIO_PROCESS, 0));
setpriority(PRIO_PROCESS, 0, -1);
- #if HAVE_ANDROID_OS
- //setgid(GID_SYSTEM);
- //setuid(UID_SYSTEM);
- #endif
-
system_init();
}
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 ec67683..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;
@@ -749,11 +750,25 @@ public final class ContactsContract {
public static final String PHOTO_ID = "photo_id";
/**
+ * Photo file ID of the full-size photo. If present, this will be used to populate
+ * {@link #PHOTO_URI}. The ID can also be used with
+ * {@link ContactsContract.DisplayPhoto#CONTENT_URI} to create a URI to the photo.
+ * If this is present, {@link #PHOTO_ID} is also guaranteed to be populated.
+ *
+ * <P>Type: INTEGER</P>
+ */
+ public static final String PHOTO_FILE_ID = "photo_file_id";
+
+ /**
* A URI that can be used to retrieve the contact's full-size photo.
+ * If PHOTO_FILE_ID is not null, this will be populated with a URI based off
+ * {@link ContactsContract.DisplayPhoto#CONTENT_URI}. Otherwise, this will
+ * be populated with the same value as {@link #PHOTO_THUMBNAIL_URI}.
* A photo can be referred to either by a URI (this field) or by ID
- * (see {@link #PHOTO_ID}). If PHOTO_ID is not null, PHOTO_URI and
- * PHOTO_THUMBNAIL_URI shall not be null (but not necessarily vice versa).
- * Thus using PHOTO_URI is a more robust method of retrieving contact photos.
+ * (see {@link #PHOTO_ID}). If either PHOTO_FILE_ID or PHOTO_ID is not null,
+ * PHOTO_URI and PHOTO_THUMBNAIL_URI shall not be null (but not necessarily
+ * vice versa). Thus using PHOTO_URI is a more robust method of retrieving
+ * contact photos.
*
* <P>Type: TEXT</P>
*/
@@ -766,7 +781,7 @@ public final class ContactsContract {
* PHOTO_THUMBNAIL_URI shall not be null (but not necessarily vice versa).
* If the content provider does not differentiate between full-size photos
* and thumbnail photos, PHOTO_THUMBNAIL_URI and {@link #PHOTO_URI} can contain
- * the same value, but either both shell be null or both not null.
+ * the same value, but either both shall be null or both not null.
*
* <P>Type: TEXT</P>
*/
@@ -1690,10 +1705,15 @@ public final class ContactsContract {
/**
* A <i>read-only</i> sub-directory of a single contact that contains
- * the contact's primary photo.
+ * the contact's primary photo. The photo may be stored in up to two ways -
+ * the default "photo" is a thumbnail-sized image stored directly in the data
+ * row, while the "display photo", if present, is a larger version stored as
+ * a file.
* <p>
* Usage example:
- *
+ * <dl>
+ * <dt>Retrieving the thumbnail-sized photo</dt>
+ * <dd>
* <pre>
* public InputStream openPhoto(long contactId) {
* Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
@@ -1716,10 +1736,29 @@ public final class ContactsContract {
* return null;
* }
* </pre>
+ * </dd>
+ * <dt>Retrieving the larger photo version</dt>
+ * <dd>
+ * <pre>
+ * public InputStream openDisplayPhoto(long contactId) {
+ * Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
+ * Uri displayPhotoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.DISPLAY_PHOTO);
+ * try {
+ * AssetFileDescriptor fd =
+ * getContentResolver().openAssetFile(displayPhotoUri, "r");
+ * return fd.createInputStream();
+ * } catch (FileNotFoundException e) {
+ * return null;
+ * }
+ * }
+ * </pre>
+ * </dd>
+ * </dl>
*
* </p>
- * <p>You should also consider using the convenience method
+ * <p>You may also consider using the convenience method
* {@link ContactsContract.Contacts#openContactPhotoInputStream(ContentResolver, Uri)}
+ * to retrieve the raw photo contents of the thumbnail-sized photo.
* </p>
* <p>
* This directory can be used either with a {@link #CONTENT_URI} or
@@ -1738,6 +1777,19 @@ public final class ContactsContract {
public static final String CONTENT_DIRECTORY = "photo";
/**
+ * The directory twig for retrieving the full-size display photo.
+ */
+ public static final String DISPLAY_PHOTO = "display_photo";
+
+ /**
+ * Full-size photo file ID of the raw contact.
+ * See {@link ContactsContract.DisplayPhoto}.
+ * <p>
+ * Type: NUMBER
+ */
+ public static final String PHOTO_FILE_ID = DATA14;
+
+ /**
* Thumbnail photo of the raw contact. This is the raw bytes of an image
* that could be inflated using {@link android.graphics.BitmapFactory}.
* <p>
@@ -2498,6 +2550,56 @@ public final class ContactsContract {
}
/**
+ * <p>
+ * A sub-directory of a single raw contact that represents its primary
+ * display photo. To access this directory append
+ * {@link RawContacts.DisplayPhoto#CONTENT_DIRECTORY} to the raw contact URI.
+ * The resulting URI represents an image file, and should be interacted with
+ * using ContentProvider.openAssetFile.
+ * <p>
+ * <p>
+ * Note that this sub-directory also supports opening the photo as an asset file
+ * in write mode. Callers can create or replace the primary photo associated
+ * with this raw contact by opening the asset file and writing the full-size
+ * photo contents into it. When the file is closed, the image will be parsed,
+ * sized down if necessary for the full-size display photo and thumbnail
+ * dimensions, and stored.
+ * </p>
+ * <p>
+ * Usage example:
+ * <pre>
+ * public void writeDisplayPhoto(long rawContactId, byte[] photo) {
+ * Uri rawContactPhotoUri = Uri.withAppendedPath(
+ * ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId),
+ * RawContacts.DisplayPhoto.CONTENT_DIRECTORY);
+ * try {
+ * AssetFileDescriptor fd =
+ * getContentResolver().openAssetFile(rawContactPhotoUri, "rw");
+ * OutputStream os = fd.createOutputStream();
+ * os.write(photo);
+ * os.close();
+ * fd.close();
+ * } catch (IOException e) {
+ * // Handle error cases.
+ * }
+ * }
+ * </pre>
+ * </p>
+ */
+ public static final class DisplayPhoto {
+ /**
+ * No public constructor since this is a utility class
+ */
+ private DisplayPhoto() {
+ }
+
+ /**
+ * The directory twig for this sub-table
+ */
+ public static final String CONTENT_DIRECTORY = "display_photo";
+ }
+
+ /**
* TODO: javadoc
* @param cursor
* @return
@@ -3192,6 +3294,50 @@ public final class ContactsContract {
}
/**
+ * <p>
+ * Constants for the photo files table, which tracks metadata for hi-res photos
+ * stored in the file system.
+ * </p>
+ *
+ * @hide
+ */
+ public static final class PhotoFiles implements BaseColumns, PhotoFilesColumns {
+ /**
+ * No public constructor since this is a utility class
+ */
+ private PhotoFiles() {
+ }
+ }
+
+ /**
+ * Columns in the PhotoFiles table.
+ *
+ * @see ContactsContract.PhotoFiles
+ *
+ * @hide
+ */
+ protected interface PhotoFilesColumns {
+
+ /**
+ * The height, in pixels, of the photo this entry is associated with.
+ * <P>Type: NUMBER</P>
+ */
+ public static final String HEIGHT = "height";
+
+ /**
+ * The width, in pixels, of the photo this entry is associated with.
+ * <P>Type: NUMBER</P>
+ */
+ public static final String WIDTH = "width";
+
+ /**
+ * The size, in bytes, of the photo stored on disk.
+ * <P>Type: NUMBER</P>
+ */
+ public static final String FILESIZE = "filesize";
+ }
+
+ /**
* Columns in the Data table.
*
* @see ContactsContract.Data
@@ -5891,7 +6037,7 @@ public final class ContactsContract {
/**
* <p>
- * A data kind representing an photo for the contact.
+ * A data kind representing a photo for the contact.
* </p>
* <p>
* Some sync adapters will choose to download photos in a separate
@@ -5911,10 +6057,17 @@ public final class ContactsContract {
* <th>Alias</th><th colspan='2'>Data column</th>
* </tr>
* <tr>
+ * <td>NUMBER</td>
+ * <td>{@link #PHOTO_FILE_ID}</td>
+ * <td>{@link #DATA14}</td>
+ * <td>ID of the hi-res photo file.</td>
+ * </tr>
+ * <tr>
* <td>BLOB</td>
* <td>{@link #PHOTO}</td>
* <td>{@link #DATA15}</td>
- * <td>By convention, binary data is stored in DATA15.</td>
+ * <td>By convention, binary data is stored in DATA15. The thumbnail of the
+ * photo is stored in this column.</td>
* </tr>
* </table>
*/
@@ -5928,6 +6081,14 @@ public final class ContactsContract {
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/photo";
/**
+ * Photo file ID for the display photo of the raw contact.
+ * See {@link ContactsContract.DisplayPhoto}.
+ * <p>
+ * Type: NUMBER
+ */
+ public static final String PHOTO_FILE_ID = DATA14;
+
+ /**
* Thumbnail photo of the raw contact. This is the raw bytes of an image
* that could be inflated using {@link android.graphics.BitmapFactory}.
* <p>
@@ -6251,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>
@@ -7047,6 +7230,66 @@ public final class ContactsContract {
}
/**
+ * Helper class for accessing full-size photos by photo file ID.
+ * <p>
+ * Usage example:
+ * <dl>
+ * <dt>Retrieving a full-size photo by photo file ID (see
+ * {@link ContactsContract.ContactsColumns#PHOTO_FILE_ID})
+ * </dt>
+ * <dd>
+ * <pre>
+ * public InputStream openDisplayPhoto(long photoFileId) {
+ * Uri displayPhotoUri = ContentUris.withAppendedId(DisplayPhoto.CONTENT_URI, photoKey);
+ * try {
+ * AssetFileDescriptor fd = getContentResolver().openAssetFile(displayPhotoUri, "r");
+ * return fd.createInputStream();
+ * } catch (FileNotFoundException e) {
+ * return null;
+ * }
+ * }
+ * </pre>
+ * </dd>
+ * </dl>
+ * </p>
+ */
+ public static final class DisplayPhoto {
+ /**
+ * no public constructor since this is a utility class
+ */
+ private DisplayPhoto() {}
+
+ /**
+ * The content:// style URI for this class, which allows access to full-size photos,
+ * given a key.
+ */
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "display_photo");
+
+ /**
+ * This URI allows the caller to query for the maximum dimensions of a display photo
+ * or thumbnail. Requests to this URI can be performed on the UI thread because
+ * they are always unblocking.
+ */
+ public static final Uri CONTENT_MAX_DIMENSIONS_URI =
+ Uri.withAppendedPath(AUTHORITY_URI, "photo_dimensions");
+
+ /**
+ * Queries to {@link ContactsContract.DisplayPhoto#CONTENT_MAX_DIMENSIONS_URI} will
+ * contain this column, populated with the maximum height and width (in pixels)
+ * that will be stored for a display photo. Larger photos will be down-sized to
+ * fit within a square of this many pixels.
+ */
+ public static final String DISPLAY_MAX_DIM = "display_max_dim";
+
+ /**
+ * Queries to {@link ContactsContract.DisplayPhoto#CONTENT_MAX_DIMENSIONS_URI} will
+ * contain this column, populated with the height and width (in pixels) for photo
+ * thumbnails.
+ */
+ public static final String THUMBNAIL_MAX_DIM = "thumbnail_max_dim";
+ }
+
+ /**
* Contains helper classes used to create or manage {@link android.content.Intent Intents}
* that involve contacts.
*/
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 8e4725f..32ca226 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -181,7 +181,7 @@ public class TextToSpeech {
*
* @hide
* @deprecated No longer in use, the default engine is determined by
- * the sort order defined in {@link EngineInfoComparator}. Note that
+ * the sort order defined in {@link TtsEngines}. Note that
* this doesn't "break" anything because there is no guarantee that
* the engine specified below is installed on a given build, let
* alone be the default.
@@ -504,36 +504,39 @@ public class TextToSpeech {
}
private int initTts() {
- String defaultEngine = getDefaultEngine();
- String engine = defaultEngine;
- if (mEnginesHelper.isEngineInstalled(mRequestedEngine)) {
- engine = mRequestedEngine;
- }
-
- // Try requested engine
- if (connectToEngine(engine)) {
- mCurrentEngine = engine;
- return SUCCESS;
+ // Step 1: Try connecting to the engine that was requested.
+ if (mRequestedEngine != null && mEnginesHelper.isEngineInstalled(mRequestedEngine)) {
+ if (connectToEngine(mRequestedEngine)) {
+ mCurrentEngine = mRequestedEngine;
+ return SUCCESS;
+ }
}
- // Fall back to user's default engine if different from the already tested one
- if (!engine.equals(defaultEngine)) {
+ // Step 2: Try connecting to the user's default engine.
+ final String defaultEngine = getDefaultEngine();
+ if (defaultEngine != null && !defaultEngine.equals(mRequestedEngine)) {
if (connectToEngine(defaultEngine)) {
- mCurrentEngine = engine;
+ mCurrentEngine = defaultEngine;
return SUCCESS;
}
}
+ // Step 3: Try connecting to the highest ranked engine in the
+ // system.
final String highestRanked = mEnginesHelper.getHighestRankedEngineName();
- // Fall back to the hardcoded default if different from the two above
- if (!defaultEngine.equals(highestRanked)
- && !engine.equals(highestRanked)) {
+ if (highestRanked != null && !highestRanked.equals(mRequestedEngine) &&
+ !highestRanked.equals(defaultEngine)) {
if (connectToEngine(highestRanked)) {
- mCurrentEngine = engine;
+ mCurrentEngine = highestRanked;
return SUCCESS;
}
}
+ // NOTE: The API currently does not allow the caller to query whether
+ // they are actually connected to any engine. This might fail for various
+ // reasons like if the user disables all her TTS engines.
+
+ mCurrentEngine = null;
dispatchOnInit(ERROR);
return ERROR;
}
@@ -963,7 +966,7 @@ public class TextToSpeech {
/**
* Synthesizes the given text to a file using the specified parameters.
*
- * @param text Thetext that should be synthesized
+ * @param text The text that should be synthesized
* @param params Parameters for the request. Can be null.
* Supported parameter names:
* {@link Engine#KEY_PARAM_UTTERANCE_ID}.
@@ -1073,7 +1076,9 @@ public class TextToSpeech {
*
* @deprecated This doesn't inform callers when the TTS engine has been
* initialized. {@link #TextToSpeech(Context, OnInitListener, String)}
- * can be used with the appropriate engine name.
+ * can be used with the appropriate engine name. Also, there is no
+ * guarantee that the engine specified will be loaded. If it isn't
+ * installed or disabled, the user / system wide defaults will apply.
*
* @param enginePackageName The package name for the synthesis engine (e.g. "com.svox.pico")
*
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/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index 0294e3f..88583df 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -120,6 +120,7 @@ class CallbackProxy extends Handler {
private static final int AUTO_LOGIN = 140;
private static final int CLIENT_CERT_REQUEST = 141;
private static final int SEARCHBOX_IS_SUPPORTED_CALLBACK = 142;
+ private static final int SEARCHBOX_DISPATCH_COMPLETE_CALLBACK= 143;
// Message triggered by the client to resume execution
private static final int NOTIFY = 200;
@@ -821,6 +822,13 @@ class CallbackProxy extends Handler {
searchBox.handleIsSupportedCallback(supported);
break;
}
+ case SEARCHBOX_DISPATCH_COMPLETE_CALLBACK: {
+ SearchBoxImpl searchBox = (SearchBoxImpl) mWebView.getSearchBox();
+ Boolean success = (Boolean) msg.obj;
+ searchBox.handleDispatchCompleteCallback(msg.getData().getString("function"),
+ msg.getData().getInt("id"), success);
+ break;
+ }
}
}
@@ -1641,4 +1649,13 @@ class CallbackProxy extends Handler {
msg.obj = new Boolean(isSupported);
sendMessage(msg);
}
+
+ void onSearchboxDispatchCompleteCallback(String function, int id, boolean success) {
+ Message msg = obtainMessage(SEARCHBOX_DISPATCH_COMPLETE_CALLBACK);
+ msg.obj = Boolean.valueOf(success);
+ msg.getData().putString("function", function);
+ msg.getData().putInt("id", id);
+
+ sendMessage(msg);
+ }
}
diff --git a/core/java/android/webkit/SearchBox.java b/core/java/android/webkit/SearchBox.java
index 5075302..6512c4b 100644
--- a/core/java/android/webkit/SearchBox.java
+++ b/core/java/android/webkit/SearchBox.java
@@ -68,11 +68,15 @@ public interface SearchBox {
* Notify the search page of any changes to the searchbox. Such as
* a change in the typed query (onchange), the user commiting a given query
* (onsubmit), or a change in size of a suggestions dropdown (onresize).
+ *
+ * @param listener an optional listener to notify of the success of the operation,
+ * indicating if the javascript function existed and could be called or not.
+ * It will be called on the UI thread.
*/
- void onchange();
- void onsubmit();
- void onresize();
- void oncancel();
+ void onchange(SearchBoxListener listener);
+ void onsubmit(SearchBoxListener listener);
+ void onresize(SearchBoxListener listener);
+ void oncancel(SearchBoxListener listener);
/**
* Add and remove listeners to the given Searchbox. Listeners are notified
@@ -91,8 +95,12 @@ public interface SearchBox {
* Listeners (if any) will be called on the thread that created the
* webview.
*/
- interface SearchBoxListener {
- void onSuggestionsReceived(String query, List<String> suggestions);
+ public abstract class SearchBoxListener {
+ public void onSuggestionsReceived(String query, List<String> suggestions) {}
+ public void onChangeComplete(boolean called) {}
+ public void onSubmitComplete(boolean called) {}
+ public void onResizeComplete(boolean called) {}
+ public void onCancelComplete(boolean called) {}
}
interface IsSupportedCallback {
diff --git a/core/java/android/webkit/SearchBoxImpl.java b/core/java/android/webkit/SearchBoxImpl.java
index 61fb2ce..9942d25 100644
--- a/core/java/android/webkit/SearchBoxImpl.java
+++ b/core/java/android/webkit/SearchBoxImpl.java
@@ -16,10 +16,12 @@
package android.webkit;
+import android.text.TextUtils;
import android.util.Log;
import android.webkit.WebViewCore.EventHub;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import org.json.JSONArray;
@@ -69,7 +71,7 @@ final class SearchBoxImpl implements SearchBox {
private static final String SET_VERBATIM_SCRIPT
= "if (window.chrome && window.chrome.searchBox) {"
- + " window.chrome.searchBox.verbatim = %s;"
+ + " window.chrome.searchBox.verbatim = %1$s;"
+ "}";
private static final String SET_SELECTION_SCRIPT
@@ -89,13 +91,21 @@ final class SearchBoxImpl implements SearchBox {
+ "}";
private static final String DISPATCH_EVENT_SCRIPT
- = "if (window.chrome && window.chrome.searchBox &&"
- + " window.chrome.searchBox.on%1$s) { window.chrome.searchBox.on%1$s(); }";
+ = "if (window.chrome && window.chrome.searchBox && window.chrome.searchBox.on%1$s) {"
+ + " window.chrome.searchBox.on%1$s();"
+ + " window.searchBoxJavaBridge_.dispatchCompleteCallback('%1$s', %2$d, true);"
+ + "} else {"
+ + " window.searchBoxJavaBridge_.dispatchCompleteCallback('%1$s', %2$d, false);"
+ + "}";
+
+ private static final String EVENT_CHANGE = "change";
+ private static final String EVENT_SUBMIT = "submit";
+ private static final String EVENT_RESIZE = "resize";
+ private static final String EVENT_CANCEL = "cancel";
private static final String IS_SUPPORTED_SCRIPT
= "if (window.searchBoxJavaBridge_) {"
- + " if (window.chrome && window.chrome.searchBox && "
- + " window.chrome.searchBox.onsubmit) {"
+ + " if (window.chrome && window.chrome.sv) {"
+ " window.searchBoxJavaBridge_.isSupportedCallback(true);"
+ " } else {"
+ " window.searchBoxJavaBridge_.isSupportedCallback(false);"
@@ -105,11 +115,14 @@ final class SearchBoxImpl implements SearchBox {
private final WebViewCore mWebViewCore;
private final CallbackProxy mCallbackProxy;
private IsSupportedCallback mSupportedCallback;
+ private int mNextEventId = 1;
+ private final HashMap<Integer, SearchBoxListener> mEventCallbacks;
SearchBoxImpl(WebViewCore webViewCore, CallbackProxy callbackProxy) {
mListeners = new ArrayList<SearchBoxListener>();
mWebViewCore = webViewCore;
mCallbackProxy = callbackProxy;
+ mEventCallbacks = new HashMap<Integer, SearchBoxListener>();
}
@Override
@@ -141,27 +154,36 @@ final class SearchBoxImpl implements SearchBox {
}
@Override
- public void onchange() {
- dispatchEvent("change");
+ public void onchange(SearchBoxListener callback) {
+ dispatchEvent(EVENT_CHANGE, callback);
}
@Override
- public void onsubmit() {
- dispatchEvent("submit");
+ public void onsubmit(SearchBoxListener callback) {
+ dispatchEvent(EVENT_SUBMIT, callback);
}
@Override
- public void onresize() {
- dispatchEvent("resize");
+ public void onresize(SearchBoxListener callback) {
+ dispatchEvent(EVENT_RESIZE, callback);
}
@Override
- public void oncancel() {
- dispatchEvent("cancel");
+ public void oncancel(SearchBoxListener callback) {
+ dispatchEvent(EVENT_CANCEL, callback);
}
- private void dispatchEvent(String eventName) {
- final String js = String.format(DISPATCH_EVENT_SCRIPT, eventName);
+ private void dispatchEvent(String eventName, SearchBoxListener callback) {
+ int eventId;
+ if (callback != null) {
+ synchronized(this) {
+ eventId = mNextEventId++;
+ mEventCallbacks.put(eventId, callback);
+ }
+ } else {
+ eventId = 0;
+ }
+ final String js = String.format(DISPATCH_EVENT_SCRIPT, eventName, eventId);
dispatchJs(js);
}
@@ -202,9 +224,35 @@ final class SearchBoxImpl implements SearchBox {
}
}
+ // Called by Javascript through the Java bridge.
+ public void dispatchCompleteCallback(String function, int id, boolean successful) {
+ mCallbackProxy.onSearchboxDispatchCompleteCallback(function, id, successful);
+ }
+
+ public void handleDispatchCompleteCallback(String function, int id, boolean successful) {
+ if (id != 0) {
+ SearchBoxListener listener;
+ synchronized(this) {
+ listener = mEventCallbacks.get(id);
+ mEventCallbacks.remove(id);
+ }
+ if (listener != null) {
+ if (TextUtils.equals(EVENT_CHANGE, function)) {
+ listener.onChangeComplete(successful);
+ } else if (TextUtils.equals(EVENT_SUBMIT, function)) {
+ listener.onSubmitComplete(successful);
+ } else if (TextUtils.equals(EVENT_RESIZE, function)) {
+ listener.onResizeComplete(successful);
+ } else if (TextUtils.equals(EVENT_CANCEL, function)) {
+ listener.onCancelComplete(successful);
+ }
+ }
+ }
+ }
+
// This is used as a hackish alternative to javascript escaping.
// There appears to be no such functionality in the core framework.
- private String jsonSerialize(String query) {
+ private static String jsonSerialize(String query) {
JSONStringer stringer = new JSONStringer();
try {
stringer.array().value(query).endArray();
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/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index c652e55..5414b79 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -248,7 +248,7 @@ public final class WebViewCore {
/* Get the BrowserFrame component. This is used for subwindow creation and
* is called only from BrowserFrame in the WebCore thread. */
- /* package */ BrowserFrame getBrowserFrame() {
+ /* package */ synchronized BrowserFrame getBrowserFrame() {
return mBrowserFrame;
}
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/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
index 9c06d69..80f68ac 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
@@ -544,6 +544,17 @@ public class ActionMenuPresenter extends BaseMenuPresenter {
}
setCallback(mPopupPresenterCallback);
+
+ boolean preserveIconSpacing = false;
+ final int count = subMenu.size();
+ for (int i = 0; i < count; i++) {
+ MenuItem childItem = subMenu.getItem(i);
+ if (childItem.isVisible() && childItem.getIcon() != null) {
+ preserveIconSpacing = true;
+ break;
+ }
+ }
+ setForceShowIcon(preserveIconSpacing);
}
@Override
diff --git a/core/java/com/android/internal/view/menu/IconMenuPresenter.java b/core/java/com/android/internal/view/menu/IconMenuPresenter.java
index 56128d4..d1b1dae 100644
--- a/core/java/com/android/internal/view/menu/IconMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/IconMenuPresenter.java
@@ -179,8 +179,10 @@ public class IconMenuPresenter extends BaseMenuPresenter {
@Override
public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
mOpenSubMenuId = 0;
- mOpenSubMenu.dismiss();
- mOpenSubMenu = null;
+ if (mOpenSubMenu != null) {
+ mOpenSubMenu.dismiss();
+ mOpenSubMenu = null;
+ }
}
@Override
diff --git a/core/java/com/android/internal/view/menu/ListMenuItemView.java b/core/java/com/android/internal/view/menu/ListMenuItemView.java
index 0c3c605..a1e16d4 100644
--- a/core/java/com/android/internal/view/menu/ListMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ListMenuItemView.java
@@ -22,6 +22,7 @@ import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ImageView;
@@ -50,6 +51,8 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView
private LayoutInflater mInflater;
+ private boolean mForceShowIcon;
+
public ListMenuItemView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs);
@@ -99,6 +102,10 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView
setEnabled(itemData.isEnabled());
}
+ public void setForceShowIcon(boolean forceShow) {
+ mPreserveIconSpacing = mForceShowIcon = forceShow;
+ }
+
public void setTitle(CharSequence title) {
if (title != null) {
mTitleView.setText(title);
@@ -189,12 +196,12 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView
}
public void setIcon(Drawable icon) {
- final boolean showIcon = mItemData.shouldShowIcon();
+ final boolean showIcon = mItemData.shouldShowIcon() || mForceShowIcon;
if (!showIcon && !mPreserveIconSpacing) {
return;
}
- if (mIconView == null && icon == null) {
+ if (mIconView == null && icon == null && !mPreserveIconSpacing) {
return;
}
@@ -213,6 +220,19 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView
}
}
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ if (mIconView != null && mPreserveIconSpacing) {
+ // Enforce minimum icon spacing
+ ViewGroup.LayoutParams lp = getLayoutParams();
+ LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams();
+ if (lp.height > 0 && iconLp.width <= 0) {
+ iconLp.width = lp.height;
+ }
+ }
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+
private void insertIconView() {
LayoutInflater inflater = getInflater();
mIconView = (ImageView) inflater.inflate(com.android.internal.R.layout.list_menu_item_icon,
@@ -241,7 +261,7 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView
}
public boolean showsIcon() {
- return false;
+ return mForceShowIcon;
}
private LayoutInflater getInflater() {
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/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index 4ecc828..6265618 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -19,15 +19,16 @@ package com.android.internal.view.menu;
import android.content.Context;
import android.content.res.Resources;
import android.os.Parcelable;
-import android.util.DisplayMetrics;
import android.view.KeyEvent;
import android.view.LayoutInflater;
+import android.view.MenuItem;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
+import android.widget.FrameLayout;
import android.widget.ListAdapter;
import android.widget.ListPopupWindow;
import android.widget.PopupWindow;
@@ -58,6 +59,10 @@ public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.On
private Callback mPresenterCallback;
+ boolean mForceShowIcon;
+
+ private ViewGroup mMeasureParent;
+
public MenuPopupHelper(Context context, MenuBuilder menu) {
this(context, menu, null, false);
}
@@ -86,6 +91,10 @@ public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.On
mAnchorView = anchor;
}
+ public void setForceShowIcon(boolean forceShow) {
+ mForceShowIcon = forceShow;
+ }
+
public void show() {
if (!tryShow()) {
throw new IllegalStateException("MenuPopupHelper cannot be used without an anchor");
@@ -170,7 +179,10 @@ public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.On
itemType = positionType;
itemView = null;
}
- itemView = adapter.getView(i, itemView, null);
+ if (mMeasureParent == null) {
+ mMeasureParent = new FrameLayout(mContext);
+ }
+ itemView = adapter.getView(i, itemView, mMeasureParent);
itemView.measure(widthMeasureSpec, heightMeasureSpec);
width = Math.max(width, itemView.getMeasuredWidth());
}
@@ -228,6 +240,18 @@ public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.On
if (subMenu.hasVisibleItems()) {
MenuPopupHelper subPopup = new MenuPopupHelper(mContext, subMenu, mAnchorView, false);
subPopup.setCallback(mPresenterCallback);
+
+ boolean preserveIconSpacing = false;
+ final int count = subMenu.size();
+ for (int i = 0; i < count; i++) {
+ MenuItem childItem = subMenu.getItem(i);
+ if (childItem.isVisible() && childItem.getIcon() != null) {
+ preserveIconSpacing = true;
+ break;
+ }
+ }
+ subPopup.setForceShowIcon(preserveIconSpacing);
+
if (subPopup.tryShow()) {
if (mPresenterCallback != null) {
mPresenterCallback.onOpenSubMenu(subMenu);
@@ -293,6 +317,9 @@ public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.On
}
MenuView.ItemView itemView = (MenuView.ItemView) convertView;
+ if (mForceShowIcon) {
+ ((ListMenuItemView) convertView).setForceShowIcon(true);
+ }
itemView.initialize(getItem(position), 0);
return convertView;
}
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/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index a61217a..23c6da7 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -623,16 +623,9 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
}
/* enable debugging; set suspend=y to pause during VM init */
-#ifdef HAVE_ANDROID_OS
/* use android ADB transport */
opt.optionString =
"-agentlib:jdwp=transport=dt_android_adb,suspend=n,server=y";
-#else
- /* use TCP socket; address=0 means start at port 8000 and probe up */
- LOGI("Using TCP socket for JDWP\n");
- opt.optionString =
- "-agentlib:jdwp=transport=dt_socket,suspend=n,server=y,address=0";
-#endif
mOptions.add(opt);
char enableDPBuf[sizeof("-Xdeadlockpredict:") + PROPERTY_VALUE_MAX];
diff --git a/core/jni/android_net_TrafficStats.cpp b/core/jni/android_net_TrafficStats.cpp
index d54981e..c22b071 100644
--- a/core/jni/android_net_TrafficStats.cpp
+++ b/core/jni/android_net_TrafficStats.cpp
@@ -44,7 +44,6 @@ enum Tcp_Udp {
// Returns an ASCII decimal number read from the specified file, -1 on error.
static jlong readNumber(char const* filename) {
-#ifdef HAVE_ANDROID_OS
char buf[80];
int fd = open(filename, O_RDONLY);
if (fd < 0) {
@@ -62,9 +61,6 @@ static jlong readNumber(char const* filename) {
close(fd);
buf[len] = '\0';
return atoll(buf);
-#else // Simulator
- return -1;
-#endif
}
static const char* mobile_iface_list[] = {
@@ -101,7 +97,6 @@ static jlong getAll(const char** iface_list, const char* what) {
// Returns the sum of numbers from the specified path under /sys/class/net/*,
// -1 if no such file exists.
static jlong readTotal(char const* suffix) {
-#ifdef HAVE_ANDROID_OS
char filename[PATH_MAX] = "/sys/class/net/";
DIR *dir = opendir(filename);
if (dir == NULL) {
@@ -123,9 +118,6 @@ static jlong readTotal(char const* suffix) {
closedir(dir);
return total;
-#else // Simulator
- return -1;
-#endif
}
// Mobile stats get accessed a lot more often than total stats.
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 2297834..a4432c3 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -278,7 +278,6 @@ jint android_os_Debug_getProxyObjectCount(JNIEnv* env, jobject clazz);
jint android_os_Debug_getDeathObjectCount(JNIEnv* env, jobject clazz);
-#ifdef HAVE_ANDROID_OS
/* pulled out of bionic */
extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
@@ -414,7 +413,6 @@ static void dumpNativeHeap(FILE* fp)
fprintf(fp, "END\n");
}
-#endif /*HAVE_ANDROID_OS*/
/*
* Dump the native heap, writing human-readable output to the specified
@@ -449,13 +447,9 @@ static void android_os_Debug_dumpNativeHeap(JNIEnv* env, jobject clazz,
return;
}
-#ifdef HAVE_ANDROID_OS
LOGD("Native heap dump starting...\n");
dumpNativeHeap(fp);
LOGD("Native heap dump complete.\n");
-#else
- fprintf(fp, "Native heap dump not available on this platform\n");
-#endif
fclose(fp);
}
diff --git a/core/jni/android_os_FileUtils.cpp b/core/jni/android_os_FileUtils.cpp
index 89dce89..8d65cbc 100644
--- a/core/jni/android_os_FileUtils.cpp
+++ b/core/jni/android_os_FileUtils.cpp
@@ -28,11 +28,8 @@
#include <sys/types.h>
#include <fcntl.h>
#include <signal.h>
-
-#if HAVE_ANDROID_OS
#include <sys/ioctl.h>
#include <linux/msdos_fs.h>
-#endif
namespace android {
@@ -53,7 +50,6 @@ jint android_os_FileUtils_setPermissions(JNIEnv* env, jobject clazz,
jstring file, jint mode,
jint uid, jint gid)
{
- #if HAVE_ANDROID_OS
const jchar* str = env->GetStringCritical(file, 0);
String8 file8;
if (str) {
@@ -70,15 +66,11 @@ jint android_os_FileUtils_setPermissions(JNIEnv* env, jobject clazz,
}
}
return chmod(file8.string(), mode) == 0 ? 0 : errno;
- #else
- return ENOSYS;
- #endif
}
jint android_os_FileUtils_getPermissions(JNIEnv* env, jobject clazz,
jstring file, jintArray outArray)
{
- #if HAVE_ANDROID_OS
const jchar* str = env->GetStringCritical(file, 0);
String8 file8;
if (str) {
@@ -107,9 +99,6 @@ jint android_os_FileUtils_getPermissions(JNIEnv* env, jobject clazz,
}
env->ReleasePrimitiveArrayCritical(outArray, array, 0);
return 0;
- #else
- return ENOSYS;
- #endif
}
jint android_os_FileUtils_setUMask(JNIEnv* env, jobject clazz, jint mask)
@@ -119,7 +108,6 @@ jint android_os_FileUtils_setUMask(JNIEnv* env, jobject clazz, jint mask)
jint android_os_FileUtils_getFatVolumeId(JNIEnv* env, jobject clazz, jstring path)
{
- #if HAVE_ANDROID_OS
if (path == NULL) {
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
return -1;
@@ -137,9 +125,6 @@ jint android_os_FileUtils_getFatVolumeId(JNIEnv* env, jobject clazz, jstring pat
env->ReleaseStringUTFChars(path, pathStr);
return result;
- #else
- return -1;
- #endif
}
jboolean android_os_FileUtils_getFileStatus(JNIEnv* env, jobject clazz, jstring path, jobject fileStatus) {
diff --git a/core/jni/android_os_Power.cpp b/core/jni/android_os_Power.cpp
index 9ae4a63..dc16990 100644
--- a/core/jni/android_os_Power.cpp
+++ b/core/jni/android_os_Power.cpp
@@ -70,16 +70,11 @@ setScreenState(JNIEnv *env, jobject clazz, jboolean on)
static void android_os_Power_shutdown(JNIEnv *env, jobject clazz)
{
-#ifdef HAVE_ANDROID_OS
android_reboot(ANDROID_RB_POWEROFF, 0, 0);
-#else
- sync();
-#endif
}
static void android_os_Power_reboot(JNIEnv *env, jobject clazz, jstring reason)
{
-#ifdef HAVE_ANDROID_OS
if (reason == NULL) {
android_reboot(ANDROID_RB_RESTART, 0, 0);
} else {
@@ -88,9 +83,6 @@ static void android_os_Power_reboot(JNIEnv *env, jobject clazz, jstring reason)
env->ReleaseStringUTFChars(reason, chars); // In case it fails.
}
jniThrowIOException(env, errno);
-#else
- sync();
-#endif
}
static JNINativeMethod method_table[] = {
diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp
index 2b09442..8f84b81 100644
--- a/core/jni/android_server_BluetoothEventLoop.cpp
+++ b/core/jni/android_server_BluetoothEventLoop.cpp
@@ -1115,7 +1115,7 @@ DBusHandlerResult agent_event_filter(DBusConnection *conn,
LOGV("... uuid = %s", uuid);
dbus_message_ref(msg); // increment refcount because we pass to java
- env->CallBooleanMethod(nat->me, method_onAgentAuthorize,
+ env->CallVoidMethod(nat->me, method_onAgentAuthorize,
env->NewStringUTF(object_path), env->NewStringUTF(uuid),
int(msg));
diff --git a/core/jni/android_util_Log.cpp b/core/jni/android_util_Log.cpp
index 0fbe0e7..2c7bb84 100644
--- a/core/jni/android_util_Log.cpp
+++ b/core/jni/android_util_Log.cpp
@@ -58,9 +58,6 @@ static int toLevel(const char* value)
static jboolean android_util_Log_isLoggable(JNIEnv* env, jobject clazz, jstring tag, jint level)
{
-#ifndef HAVE_ANDROID_OS
- return false;
-#else /* HAVE_ANDROID_OS */
int len;
char key[PROPERTY_KEY_MAX];
char buf[PROPERTY_VALUE_MAX];
@@ -93,7 +90,6 @@ static jboolean android_util_Log_isLoggable(JNIEnv* env, jobject clazz, jstring
len = property_get(key, buf, "");
int logLevel = toLevel(buf);
return (logLevel >= 0 && level >= logLevel) ? true : false;
-#endif /* HAVE_ANDROID_OS */
}
/*
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index d1ba2d1..47d343a 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -352,20 +352,12 @@ void android_os_Process_setArgV0(JNIEnv* env, jobject clazz, jstring name)
jint android_os_Process_setUid(JNIEnv* env, jobject clazz, jint uid)
{
- #if HAVE_ANDROID_OS
return setuid(uid) == 0 ? 0 : errno;
- #else
- return ENOSYS;
- #endif
}
jint android_os_Process_setGid(JNIEnv* env, jobject clazz, jint uid)
{
- #if HAVE_ANDROID_OS
return setgid(uid) == 0 ? 0 : errno;
- #else
- return ENOSYS;
- #endif
}
static int pid_compare(const void* v1, const void* v2)
diff --git a/core/jni/com_android_internal_os_ZygoteInit.cpp b/core/jni/com_android_internal_os_ZygoteInit.cpp
index 86fd9cb..7e5dede 100644
--- a/core/jni/com_android_internal_os_ZygoteInit.cpp
+++ b/core/jni/com_android_internal_os_ZygoteInit.cpp
@@ -27,13 +27,11 @@
#include <JNIHelp.h>
#include "android_runtime/AndroidRuntime.h"
-#ifdef HAVE_ANDROID_OS
#include <linux/capability.h>
#include <linux/prctl.h>
#include <sys/prctl.h>
extern "C" int capget(cap_user_header_t hdrp, cap_user_data_t datap);
extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
-#endif
namespace android {
@@ -168,7 +166,6 @@ static void com_android_internal_os_ZygoteInit_setCloseOnExec (JNIEnv *env,
static void com_android_internal_os_ZygoteInit_setCapabilities (JNIEnv *env,
jobject clazz, jlong permitted, jlong effective)
{
-#ifdef HAVE_ANDROID_OS
struct __user_cap_header_struct capheader;
struct __user_cap_data_struct capdata;
int err;
@@ -190,15 +187,11 @@ static void com_android_internal_os_ZygoteInit_setCapabilities (JNIEnv *env,
jniThrowIOException(env, errno);
return;
}
-#endif /* HAVE_ANDROID_OS */
}
static jlong com_android_internal_os_ZygoteInit_capgetPermitted (JNIEnv *env,
jobject clazz, jint pid)
{
-#ifndef HAVE_ANDROID_OS
- return (jlong)0;
-#else
struct __user_cap_header_struct capheader;
struct __user_cap_data_struct capdata;
int err;
@@ -217,7 +210,6 @@ static jlong com_android_internal_os_ZygoteInit_capgetPermitted (JNIEnv *env,
}
return (jlong) capdata.permitted;
-#endif /* HAVE_ANDROID_OS */
}
static jint com_android_internal_os_ZygoteInit_selectReadable (
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/layout/list_menu_item_icon.xml b/core/res/res/layout/list_menu_item_icon.xml
index 6ff14dd..a885211 100644
--- a/core/res/res/layout/list_menu_item_icon.xml
+++ b/core/res/res/layout/list_menu_item_icon.xml
@@ -19,6 +19,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
- android:layout_marginRight="8dip"
+ android:layout_marginLeft="8dip"
+ android:layout_marginRight="-8dip"
+ android:scaleType="center"
android:duplicateParentState="true" />
diff --git a/core/res/res/layout/popup_menu_item_layout.xml b/core/res/res/layout/popup_menu_item_layout.xml
index fef017d..1a12c01 100644
--- a/core/res/res/layout/popup_menu_item_layout.xml
+++ b/core/res/res/layout/popup_menu_item_layout.xml
@@ -18,7 +18,6 @@
android:layout_width="match_parent"
android:layout_height="?android:attr/dropdownListPreferredItemHeight"
android:minWidth="196dip"
- android:paddingLeft="16dip"
android:paddingRight="16dip">
<!-- Icon will be inserted here. -->
@@ -29,6 +28,7 @@
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
+ android:layout_marginLeft="16dip"
android:duplicateParentState="true">
<TextView
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> &mdash; Verbose (lowest priority)</li>
<li><code>D</code> &mdash; Debug</li>
- <li><code>I</code> &mdash; Info</li>
+ <li><code>I</code> &mdash; Info (default priority)</li>
<li><code>W</code> &mdash; Warning</li>
<li><code>E</code> &mdash; Error</li>
<li><code>F</code> &mdash; Fatal</li>
@@ -520,7 +520,7 @@ of each message, given as <code>&lt;priority&gt;/&lt;tag&gt;</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 &mdash; 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 &raquo;</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 &raquo;</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/stagefright/ShoutcastSource.h b/include/media/stagefright/ShoutcastSource.h
deleted file mode 100644
index bc67156..0000000
--- a/include/media/stagefright/ShoutcastSource.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SHOUTCAST_SOURCE_H_
-
-#define SHOUTCAST_SOURCE_H_
-
-#include <sys/types.h>
-
-#include <media/stagefright/MediaSource.h>
-
-namespace android {
-
-class HTTPStream;
-class MediaBufferGroup;
-
-class ShoutcastSource : public MediaSource {
-public:
- // Assumes ownership of "http".
- ShoutcastSource(HTTPStream *http);
-
- virtual status_t start(MetaData *params = NULL);
- virtual status_t stop();
-
- virtual sp<MetaData> getFormat();
-
- virtual status_t read(
- MediaBuffer **buffer, const ReadOptions *options = NULL);
-
-protected:
- virtual ~ShoutcastSource();
-
-private:
- HTTPStream *mHttp;
- size_t mMetaDataOffset;
- size_t mBytesUntilMetaData;
-
- MediaBufferGroup *mGroup;
- bool mStarted;
-
- ShoutcastSource(const ShoutcastSource &);
- ShoutcastSource &operator= (const ShoutcastSource &);
-};
-
-} // namespace android
-
-#endif // SHOUTCAST_SOURCE_H_
-
diff --git a/include/private/binder/binder_module.h b/include/private/binder/binder_module.h
index fdf327e..a8dd64f 100644
--- a/include/private/binder/binder_module.h
+++ b/include/private/binder/binder_module.h
@@ -21,126 +21,11 @@
namespace android {
#endif
-#if defined(HAVE_ANDROID_OS)
-
/* obtain structures and constants from the kernel header */
#include <sys/ioctl.h>
#include <linux/binder.h>
-#else
-
-/* Some parts of the simulator need fake versions of this
- * stuff in order to compile. Really this should go away
- * entirely...
- */
-
-#define BINDER_CURRENT_PROTOCOL_VERSION 7
-
-#define BINDER_TYPE_BINDER 1
-#define BINDER_TYPE_WEAK_BINDER 2
-#define BINDER_TYPE_HANDLE 3
-#define BINDER_TYPE_WEAK_HANDLE 4
-#define BINDER_TYPE_FD 5
-
-struct flat_binder_object {
- unsigned long type;
- unsigned long flags;
- union {
- void *binder;
- signed long handle;
- };
- void *cookie;
-};
-
-struct binder_write_read {
- signed long write_size;
- signed long write_consumed;
- unsigned long write_buffer;
- signed long read_size;
- signed long read_consumed;
- unsigned long read_buffer;
-};
-
-struct binder_transaction_data {
- union {
- size_t handle;
- void *ptr;
- } target;
- void *cookie;
- unsigned int code;
-
- unsigned int flags;
- pid_t sender_pid;
- uid_t sender_euid;
- size_t data_size;
- size_t offsets_size;
-
- union {
- struct {
- const void *buffer;
- const void *offsets;
- } ptr;
- uint8_t buf[8];
- } data;
-};
-
-enum transaction_flags {
- TF_ONE_WAY = 0x01,
- TF_ROOT_OBJECT = 0x04,
- TF_STATUS_CODE = 0x08,
- TF_ACCEPT_FDS = 0x10,
-};
-
-
-enum {
- FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff,
- FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100,
-};
-
-enum BinderDriverReturnProtocol {
- BR_ERROR,
- BR_OK,
- BR_TRANSACTION,
- BR_REPLY,
- BR_ACQUIRE_RESULT,
- BR_DEAD_REPLY,
- BR_TRANSACTION_COMPLETE,
- BR_INCREFS,
- BR_ACQUIRE,
- BR_RELEASE,
- BR_DECREFS,
- BR_ATTEMPT_ACQUIRE,
- BR_NOOP,
- BR_SPAWN_LOOPER,
- BR_FINISHED,
- BR_DEAD_BINDER,
- BR_CLEAR_DEATH_NOTIFICATION_DONE,
- BR_FAILED_REPLY,
-};
-
-enum BinderDriverCommandProtocol {
- BC_TRANSACTION,
- BC_REPLY,
- BC_ACQUIRE_RESULT,
- BC_FREE_BUFFER,
- BC_INCREFS,
- BC_ACQUIRE,
- BC_RELEASE,
- BC_DECREFS,
- BC_INCREFS_DONE,
- BC_ACQUIRE_DONE,
- BC_ATTEMPT_ACQUIRE,
- BC_REGISTER_LOOPER,
- BC_ENTER_LOOPER,
- BC_EXIT_LOOPER,
- BC_REQUEST_DEATH_NOTIFICATION,
- BC_CLEAR_DEATH_NOTIFICATION,
- BC_DEAD_BINDER_DONE,
-};
-
-#endif
-
#ifdef __cplusplus
} // namespace android
#endif
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 7264ac4..f5288c8 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -154,11 +154,7 @@ bool ProcessState::becomeContextManager(context_check_func checkFunc, void* user
mBinderContextUserData = userData;
int dummy = 0;
-#if defined(HAVE_ANDROID_OS)
status_t result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy);
-#else
- status_t result = INVALID_OPERATION;
-#endif
if (result == 0) {
mManagesContexts = true;
} else if (result == -1) {
@@ -304,12 +300,7 @@ static int open_driver()
if (fd >= 0) {
fcntl(fd, F_SETFD, FD_CLOEXEC);
int vers;
-#if defined(HAVE_ANDROID_OS)
status_t result = ioctl(fd, BINDER_VERSION, &vers);
-#else
- status_t result = -1;
- errno = EPERM;
-#endif
if (result == -1) {
LOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
close(fd);
@@ -320,14 +311,11 @@ static int open_driver()
close(fd);
fd = -1;
}
-#if defined(HAVE_ANDROID_OS)
size_t maxThreads = 15;
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
if (result == -1) {
LOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
}
-#endif
-
} else {
LOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));
}
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/rsContext.cpp b/libs/rs/rsContext.cpp
index 44e9d89..8798612 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -693,7 +693,9 @@ RsContext rsContextCreateGL(RsDevice vdev, uint32_t version,
LOGV("rsContextCreateGL %p", vdev);
Device * dev = static_cast<Device *>(vdev);
Context *rsc = Context::createContext(dev, &sc);
- rsc->setDPI(dpi);
+ if (rsc) {
+ rsc->setDPI(dpi);
+ }
LOGV("rsContextCreateGL ret %p ", rsc);
return rsc;
}
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/ui/InputTransport.cpp b/libs/ui/InputTransport.cpp
index c46d6f4..1e602e9 100644
--- a/libs/ui/InputTransport.cpp
+++ b/libs/ui/InputTransport.cpp
@@ -83,7 +83,9 @@ status_t InputChannel::openInputChannelPair(const String8& name,
sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
status_t result;
- int serverAshmemFd = ashmem_create_region(name.string(), DEFAULT_MESSAGE_BUFFER_SIZE);
+ String8 ashmemName("InputChannel ");
+ ashmemName.append(name);
+ int serverAshmemFd = ashmem_create_region(ashmemName.string(), DEFAULT_MESSAGE_BUFFER_SIZE);
if (serverAshmemFd < 0) {
result = -errno;
LOGE("channel '%s' ~ Could not create shared memory region. errno=%d",
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/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 0f3c063..4dbcb90 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -79,7 +79,6 @@ MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database) {
return (MtpDatabase *)env->GetIntField(database, field_context);
}
-#ifdef HAVE_ANDROID_OS
// ----------------------------------------------------------------------------
class MyMtpDatabase : public MtpDatabase {
@@ -1066,42 +1065,32 @@ void MyMtpDatabase::sessionEnded() {
checkAndClearExceptionFromCallback(env, __FUNCTION__);
}
-#endif // HAVE_ANDROID_OS
-
// ----------------------------------------------------------------------------
static void
android_mtp_MtpDatabase_setup(JNIEnv *env, jobject thiz)
{
-#ifdef HAVE_ANDROID_OS
MyMtpDatabase* database = new MyMtpDatabase(env, thiz);
env->SetIntField(thiz, field_context, (int)database);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
-#endif
}
static void
android_mtp_MtpDatabase_finalize(JNIEnv *env, jobject thiz)
{
-#ifdef HAVE_ANDROID_OS
MyMtpDatabase* database = (MyMtpDatabase *)env->GetIntField(thiz, field_context);
database->cleanup(env);
delete database;
env->SetIntField(thiz, field_context, 0);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
-#endif
}
static jstring
android_mtp_MtpPropertyGroup_format_date_time(JNIEnv *env, jobject thiz, jlong seconds)
{
-#ifdef HAVE_ANDROID_OS
char date[20];
formatDateTime(seconds, date, sizeof(date));
return env->NewStringUTF(date);
-#else
- return NULL;
-#endif
}
// ----------------------------------------------------------------------------
diff --git a/media/jni/android_mtp_MtpDevice.cpp b/media/jni/android_mtp_MtpDevice.cpp
index 40bbaa3..6b73f6c 100644
--- a/media/jni/android_mtp_MtpDevice.cpp
+++ b/media/jni/android_mtp_MtpDevice.cpp
@@ -85,8 +85,6 @@ static jfieldID field_objectInfo_dateCreated;
static jfieldID field_objectInfo_dateModified;
static jfieldID field_objectInfo_keywords;
-#ifdef HAVE_ANDROID_OS
-
MtpDevice* get_device_from_object(JNIEnv* env, jobject javaDevice)
{
return (MtpDevice*)env->GetIntField(javaDevice, field_context);
@@ -100,15 +98,11 @@ static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodNa
}
}
-#endif // HAVE_ANDROID_OS
-
// ----------------------------------------------------------------------------
static jboolean
android_mtp_MtpDevice_open(JNIEnv *env, jobject thiz, jstring deviceName, jint fd)
{
-#ifdef HAVE_ANDROID_OS
- LOGD("open\n");
const char *deviceNameStr = env->GetStringUTFChars(deviceName, NULL);
if (deviceNameStr == NULL) {
return false;
@@ -120,27 +114,22 @@ android_mtp_MtpDevice_open(JNIEnv *env, jobject thiz, jstring deviceName, jint f
if (device)
env->SetIntField(thiz, field_context, (int)device);
return (device != NULL);
-#endif
}
static void
android_mtp_MtpDevice_close(JNIEnv *env, jobject thiz)
{
-#ifdef HAVE_ANDROID_OS
- LOGD("close\n");
MtpDevice* device = get_device_from_object(env, thiz);
if (device) {
device->close();
delete device;
env->SetIntField(thiz, field_context, 0);
}
-#endif
}
static jobject
android_mtp_MtpDevice_get_device_info(JNIEnv *env, jobject thiz)
{
-#ifdef HAVE_ANDROID_OS
MtpDevice* device = get_device_from_object(env, thiz);
if (!device) {
LOGD("android_mtp_MtpDevice_get_device_info device is null");
@@ -173,15 +162,11 @@ android_mtp_MtpDevice_get_device_info(JNIEnv *env, jobject thiz)
delete deviceInfo;
return info;
-#else
- return NULL;
-#endif
}
static jintArray
android_mtp_MtpDevice_get_storage_ids(JNIEnv *env, jobject thiz)
{
-#ifdef HAVE_ANDROID_OS
MtpDevice* device = get_device_from_object(env, thiz);
if (!device)
return NULL;
@@ -196,15 +181,11 @@ android_mtp_MtpDevice_get_storage_ids(JNIEnv *env, jobject thiz)
delete storageIDs;
return array;
-#else
- return NULL;
-#endif
}
static jobject
android_mtp_MtpDevice_get_storage_info(JNIEnv *env, jobject thiz, jint storageID)
{
-#ifdef HAVE_ANDROID_OS
MtpDevice* device = get_device_from_object(env, thiz);
if (!device)
return NULL;
@@ -234,16 +215,12 @@ android_mtp_MtpDevice_get_storage_info(JNIEnv *env, jobject thiz, jint storageID
delete storageInfo;
return info;
-#else
- return NULL;
-#endif
}
static jintArray
android_mtp_MtpDevice_get_object_handles(JNIEnv *env, jobject thiz,
jint storageID, jint format, jint objectID)
{
-#ifdef HAVE_ANDROID_OS
MtpDevice* device = get_device_from_object(env, thiz);
if (!device)
return NULL;
@@ -258,15 +235,11 @@ android_mtp_MtpDevice_get_object_handles(JNIEnv *env, jobject thiz,
delete handles;
return array;
-#else
- return NULL;
-#endif
}
static jobject
android_mtp_MtpDevice_get_object_info(JNIEnv *env, jobject thiz, jint objectID)
{
-#ifdef HAVE_ANDROID_OS
MtpDevice* device = get_device_from_object(env, thiz);
if (!device)
return NULL;
@@ -324,9 +297,6 @@ android_mtp_MtpDevice_get_object_info(JNIEnv *env, jobject thiz, jint objectID)
delete objectInfo;
return info;
-#else
- return NULL;
-#endif
}
struct get_object_callback_data {
@@ -344,7 +314,6 @@ static bool get_object_callback(void* data, int offset, int length, void* client
static jbyteArray
android_mtp_MtpDevice_get_object(JNIEnv *env, jobject thiz, jint objectID, jint objectSize)
{
-#ifdef HAVE_ANDROID_OS
MtpDevice* device = get_device_from_object(env, thiz);
if (!device)
return NULL;
@@ -361,14 +330,12 @@ android_mtp_MtpDevice_get_object(JNIEnv *env, jobject thiz, jint objectID, jint
if (device->readObject(objectID, get_object_callback, objectSize, &data))
return array;
-#endif
return NULL;
}
static jbyteArray
android_mtp_MtpDevice_get_thumbnail(JNIEnv *env, jobject thiz, jint objectID)
{
-#ifdef HAVE_ANDROID_OS
MtpDevice* device = get_device_from_object(env, thiz);
if (!device)
return NULL;
@@ -382,51 +349,41 @@ android_mtp_MtpDevice_get_thumbnail(JNIEnv *env, jobject thiz, jint objectID)
free(thumbnail);
return array;
-#else
- return NULL;
-#endif
}
static jboolean
android_mtp_MtpDevice_delete_object(JNIEnv *env, jobject thiz, jint object_id)
{
-#ifdef HAVE_ANDROID_OS
MtpDevice* device = get_device_from_object(env, thiz);
if (device)
return device->deleteObject(object_id);
else
- #endif
return NULL;
}
static jlong
android_mtp_MtpDevice_get_parent(JNIEnv *env, jobject thiz, jint object_id)
{
-#ifdef HAVE_ANDROID_OS
MtpDevice* device = get_device_from_object(env, thiz);
if (device)
return device->getParent(object_id);
else
-#endif
return -1;
}
static jlong
android_mtp_MtpDevice_get_storage_id(JNIEnv *env, jobject thiz, jint object_id)
{
- #ifdef HAVE_ANDROID_OS
MtpDevice* device = get_device_from_object(env, thiz);
if (device)
return device->getStorageID(object_id);
else
-#endif
return -1;
}
static jboolean
android_mtp_MtpDevice_import_file(JNIEnv *env, jobject thiz, jint object_id, jstring dest_path)
{
-#ifdef HAVE_ANDROID_OS
MtpDevice* device = get_device_from_object(env, thiz);
if (device) {
const char *destPathStr = env->GetStringUTFChars(dest_path, NULL);
@@ -438,7 +395,7 @@ android_mtp_MtpDevice_import_file(JNIEnv *env, jobject thiz, jint object_id, jst
env->ReleaseStringUTFChars(dest_path, destPathStr);
return result;
}
-#endif
+
return false;
}
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 7b3b95b..e17e1e8 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 \
@@ -24,7 +22,6 @@ LOCAL_SRC_FILES:= \
FileSource.cpp \
FLACExtractor.cpp \
HTTPBase.cpp \
- HTTPStream.cpp \
JPEGSource.cpp \
MP3Extractor.cpp \
MPEG2TSWriter.cpp \
@@ -38,13 +35,11 @@ LOCAL_SRC_FILES:= \
MediaSourceSplitter.cpp \
MetaData.cpp \
NuCachedSource2.cpp \
- NuHTTPDataSource.cpp \
OMXClient.cpp \
OMXCodec.cpp \
OggExtractor.cpp \
SampleIterator.cpp \
SampleTable.cpp \
- ShoutcastSource.cpp \
StagefrightMediaScanner.cpp \
StagefrightMetadataRetriever.cpp \
ThrottledSource.cpp \
@@ -96,26 +91,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 +152,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/HTTPBase.cpp b/media/libstagefright/HTTPBase.cpp
index 0d24551..f9d8501 100644
--- a/media/libstagefright/HTTPBase.cpp
+++ b/media/libstagefright/HTTPBase.cpp
@@ -24,10 +24,11 @@
#include "include/ChromiumHTTPDataSource.h"
#endif
-#include "include/NuHTTPDataSource.h"
-
+#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ALooper.h>
+
#include <cutils/properties.h>
+#include <cutils/qtaguid.h>
namespace android {
@@ -44,14 +45,12 @@ HTTPBase::HTTPBase()
// static
sp<HTTPBase> HTTPBase::Create(uint32_t flags) {
#if CHROMIUM_AVAILABLE
- char value[PROPERTY_VALUE_MAX];
- if (!property_get("media.stagefright.use-chromium", value, NULL)
- || (strcasecmp("false", value) && strcmp("0", value))) {
return new ChromiumHTTPDataSource(flags);
- } else
#endif
{
- return new NuHTTPDataSource(flags);
+ TRESPASS();
+
+ return NULL;
}
}
@@ -135,4 +134,10 @@ bool HTTPBase::getUID(uid_t *uid) const {
return true;
}
+// static
+void HTTPBase::RegisterSocketUser(int s, uid_t uid) {
+ static const uint32_t kTag = 0xdeadbeef;
+ set_qtaguid(s, kTag, uid);
+}
+
} // namespace android
diff --git a/media/libstagefright/HTTPStream.cpp b/media/libstagefright/HTTPStream.cpp
deleted file mode 100644
index d526ebd..0000000
--- a/media/libstagefright/HTTPStream.cpp
+++ /dev/null
@@ -1,623 +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 "HTTPStream"
-#include <utils/Log.h>
-
-#include "include/HTTPStream.h"
-
-#include <sys/socket.h>
-
-#include <arpa/inet.h>
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <netdb.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-
-#include <openssl/ssl.h>
-
-namespace android {
-
-// static
-const char *HTTPStream::kStatusKey = ":status:"; // MUST be lowercase.
-
-HTTPStream::HTTPStream()
- : mState(READY),
- mUIDValid(false),
- mSocket(-1),
- mSSLContext(NULL),
- mSSL(NULL) {
-}
-
-HTTPStream::~HTTPStream() {
- disconnect();
-
- if (mSSLContext != NULL) {
- SSL_CTX_free((SSL_CTX *)mSSLContext);
- mSSLContext = NULL;
- }
-}
-
-void HTTPStream::setUID(uid_t uid) {
- mUIDValid = true;
- mUID = uid;
-}
-
-static bool MakeSocketBlocking(int s, bool blocking) {
- // Make socket non-blocking.
- int flags = fcntl(s, F_GETFL, 0);
- if (flags == -1) {
- return false;
- }
-
- if (blocking) {
- flags &= ~O_NONBLOCK;
- } else {
- flags |= O_NONBLOCK;
- }
-
- return fcntl(s, F_SETFL, flags) != -1;
-}
-
-static status_t MyConnect(
- int s, const struct sockaddr *addr, socklen_t addrlen) {
- status_t result = UNKNOWN_ERROR;
-
- MakeSocketBlocking(s, false);
-
- if (connect(s, addr, addrlen) == 0) {
- result = OK;
- } else if (errno != EINPROGRESS) {
- result = -errno;
- } else {
- for (;;) {
- fd_set rs, ws;
- FD_ZERO(&rs);
- FD_ZERO(&ws);
- FD_SET(s, &rs);
- FD_SET(s, &ws);
-
- struct timeval tv;
- tv.tv_sec = 0;
- tv.tv_usec = 100000ll;
-
- int nfds = ::select(s + 1, &rs, &ws, NULL, &tv);
-
- if (nfds < 0) {
- if (errno == EINTR) {
- continue;
- }
-
- result = -errno;
- break;
- }
-
- if (FD_ISSET(s, &ws) && !FD_ISSET(s, &rs)) {
- result = OK;
- break;
- }
-
- if (FD_ISSET(s, &rs) || FD_ISSET(s, &ws)) {
- // Get the pending error.
- int error = 0;
- socklen_t errorLen = sizeof(error);
- if (getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &errorLen) == -1) {
- // Couldn't get the real error, so report why not.
- result = -errno;
- } else {
- result = -error;
- }
- break;
- }
-
- // Timeout expired. Try again.
- }
- }
-
- MakeSocketBlocking(s, true);
-
- return result;
-}
-
-// Apparently under out linux closing a socket descriptor from one thread
-// will not unblock a pending send/recv on that socket on another thread.
-static ssize_t MySendReceive(
- int s, void *data, size_t size, int flags, bool sendData) {
- ssize_t result = 0;
-
- if (s < 0) {
- return -1;
- }
- while (size > 0) {
- fd_set rs, ws, es;
- FD_ZERO(&rs);
- FD_ZERO(&ws);
- FD_ZERO(&es);
- FD_SET(s, sendData ? &ws : &rs);
- FD_SET(s, &es);
-
- struct timeval tv;
- tv.tv_sec = 0;
- tv.tv_usec = 100000ll;
-
- int nfds = ::select(
- s + 1,
- sendData ? NULL : &rs,
- sendData ? &ws : NULL,
- &es,
- &tv);
-
- if (nfds < 0) {
- if (errno == EINTR) {
- continue;
- }
-
- result = -errno;
- break;
- } else if (nfds == 0) {
- // timeout
-
- continue;
- }
-
- CHECK_EQ(nfds, 1);
-
- ssize_t nbytes =
- sendData ? send(s, data, size, flags) : recv(s, data, size, flags);
-
- if (nbytes < 0) {
- if (errno == EINTR) {
- continue;
- }
-
- result = -errno;
- break;
- } else if (nbytes == 0) {
- result = 0;
- break;
- }
-
- data = (uint8_t *)data + nbytes;
- size -= nbytes;
-
- result = nbytes;
- break;
- }
-
- return result;
-}
-
-static ssize_t MySend(int s, const void *data, size_t size, int flags) {
- return MySendReceive(
- s, const_cast<void *>(data), size, flags, true /* sendData */);
-}
-
-static ssize_t MyReceive(int s, void *data, size_t size, int flags) {
- return MySendReceive(s, data, size, flags, false /* sendData */);
-}
-
-status_t HTTPStream::connect(const char *server, int port, bool https) {
- if (port < 0) {
- port = https ? 443 : 80;
- }
-
- Mutex::Autolock autoLock(mLock);
-
- status_t err = OK;
-
- if (mState == CONNECTED) {
- return ERROR_ALREADY_CONNECTED;
- }
-
- if (port < 0 || port > (int) USHRT_MAX) {
- return UNKNOWN_ERROR;
- }
-
- char service[sizeof("65536")];
- sprintf(service, "%d", port);
- struct addrinfo hints, *ai;
- memset(&hints, 0, sizeof(hints));
- hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
- hints.ai_socktype = SOCK_STREAM;
-
- int ret = getaddrinfo(server, service, &hints, &ai);
- if (ret) {
- return ERROR_UNKNOWN_HOST;
- }
-
- CHECK_EQ(mSocket, -1);
-
- mState = CONNECTING;
- status_t res = -1;
- struct addrinfo *tmp;
- for (tmp = ai; tmp; tmp = tmp->ai_next) {
- mSocket = socket(tmp->ai_family, tmp->ai_socktype, tmp->ai_protocol);
- if (mSocket < 0) {
- continue;
- }
-
- if (mUIDValid) {
- RegisterSocketUser(mSocket, mUID);
- }
-
- setReceiveTimeout(30); // Time out reads after 30 secs by default.
-
- int s = mSocket;
-
- mLock.unlock();
-
- res = MyConnect(s, tmp->ai_addr, tmp->ai_addrlen);
-
- mLock.lock();
-
- if (mState != CONNECTING) {
- close(s);
- freeaddrinfo(ai);
- return UNKNOWN_ERROR;
- }
-
- if (res == OK) {
- break;
- }
-
- close(s);
- }
-
- freeaddrinfo(ai);
-
- if (res != OK) {
- close(mSocket);
- mSocket = -1;
-
- mState = READY;
- return res;
- }
-
- if (https) {
- CHECK(mSSL == NULL);
-
- if (mSSLContext == NULL) {
- SSL_library_init();
-
- mSSLContext = SSL_CTX_new(TLSv1_client_method());
-
- if (mSSLContext == NULL) {
- LOGE("failed to create SSL context");
- mState = READY;
- return ERROR_IO;
- }
- }
-
- mSSL = SSL_new((SSL_CTX *)mSSLContext);
-
- if (mSSL == NULL) {
- LOGE("failed to create SSL session");
-
- mState = READY;
- return ERROR_IO;
- }
-
- int res = SSL_set_fd((SSL *)mSSL, mSocket);
-
- if (res == 1) {
- res = SSL_connect((SSL *)mSSL);
- }
-
- if (res != 1) {
- SSL_free((SSL *)mSSL);
- mSSL = NULL;
-
- LOGE("failed to connect over SSL");
- mState = READY;
-
- return ERROR_IO;
- }
- }
-
- mState = CONNECTED;
-
- return OK;
-}
-
-status_t HTTPStream::disconnect() {
- Mutex::Autolock autoLock(mLock);
-
- if (mState != CONNECTED && mState != CONNECTING) {
- return ERROR_NOT_CONNECTED;
- }
-
- if (mSSL != NULL) {
- SSL_shutdown((SSL *)mSSL);
-
- SSL_free((SSL *)mSSL);
- mSSL = NULL;
- }
-
- CHECK(mSocket >= 0);
- close(mSocket);
- mSocket = -1;
-
- mState = READY;
-
- return OK;
-}
-
-status_t HTTPStream::send(const char *data, size_t size) {
- if (mState != CONNECTED) {
- return ERROR_NOT_CONNECTED;
- }
-
- while (size > 0) {
- ssize_t n;
- if (mSSL != NULL) {
- n = SSL_write((SSL *)mSSL, data, size);
-
- if (n < 0) {
- n = -SSL_get_error((SSL *)mSSL, n);
- }
- } else {
- n = MySend(mSocket, data, size, 0);
- }
-
- if (n < 0) {
- disconnect();
-
- return n;
- } else if (n == 0) {
- disconnect();
-
- return ERROR_CONNECTION_LOST;
- }
-
- size -= (size_t)n;
- data += (size_t)n;
- }
-
- return OK;
-}
-
-status_t HTTPStream::send(const char *data) {
- return send(data, strlen(data));
-}
-
-// A certain application spawns a local webserver that sends invalid responses,
-// specifically it terminates header line with only a newline instead of the
-// CRLF (carriage-return followed by newline) required by the HTTP specs.
-// The workaround accepts both behaviours but could potentially break
-// legitimate responses that use a single newline to "fold" headers, which is
-// why it's not yet on by default.
-#define WORKAROUND_FOR_MISSING_CR 1
-
-status_t HTTPStream::receive_line(char *line, size_t size) {
- if (mState != CONNECTED) {
- return ERROR_NOT_CONNECTED;
- }
-
- bool saw_CR = false;
- size_t length = 0;
-
- for (;;) {
- char c;
- ssize_t n;
- if (mSSL != NULL) {
- n = SSL_read((SSL *)mSSL, &c, 1);
-
- if (n < 0) {
- n = -SSL_get_error((SSL *)mSSL, n);
- }
- } else {
- n = MyReceive(mSocket, &c, 1, 0);
- }
-
- if (n < 0) {
- disconnect();
-
- return ERROR_IO;
- } else if (n == 0) {
- disconnect();
-
- return ERROR_CONNECTION_LOST;
- }
-
-#if WORKAROUND_FOR_MISSING_CR
- if (c == '\n') {
- // We have a complete line.
-
- line[saw_CR ? length - 1 : length] = '\0';
- return OK;
- }
-#else
- if (saw_CR && c == '\n') {
- // We have a complete line.
-
- line[length - 1] = '\0';
- return OK;
- }
-#endif
-
- saw_CR = (c == '\r');
-
- if (length + 1 >= size) {
- return ERROR_MALFORMED;
- }
- line[length++] = c;
- }
-}
-
-status_t HTTPStream::receive_header(int *http_status) {
- *http_status = -1;
- mHeaders.clear();
-
- char line[2048];
- status_t err = receive_line(line, sizeof(line));
- if (err != OK) {
- return err;
- }
-
- mHeaders.add(AString(kStatusKey), AString(line));
-
- char *spacePos = strchr(line, ' ');
- if (spacePos == NULL) {
- // Malformed response?
- return UNKNOWN_ERROR;
- }
-
- char *status_start = spacePos + 1;
- char *status_end = status_start;
- while (isdigit(*status_end)) {
- ++status_end;
- }
-
- if (status_end == status_start) {
- // Malformed response, status missing?
- return UNKNOWN_ERROR;
- }
-
- memmove(line, status_start, status_end - status_start);
- line[status_end - status_start] = '\0';
-
- long tmp = strtol(line, NULL, 10);
- if (tmp < 0 || tmp > 999) {
- return UNKNOWN_ERROR;
- }
-
- *http_status = (int)tmp;
-
- for (;;) {
- err = receive_line(line, sizeof(line));
- if (err != OK) {
- return err;
- }
-
- if (*line == '\0') {
- // Empty line signals the end of the header.
- break;
- }
-
- // puts(line);
-
- char *colonPos = strchr(line, ':');
- if (colonPos == NULL) {
- AString key = line;
- key.tolower();
-
- mHeaders.add(key, AString());
- } else {
- char *end_of_key = colonPos;
- while (end_of_key > line && isspace(end_of_key[-1])) {
- --end_of_key;
- }
-
- char *start_of_value = colonPos + 1;
- while (isspace(*start_of_value)) {
- ++start_of_value;
- }
-
- *end_of_key = '\0';
-
- AString key = line;
- key.tolower();
-
- mHeaders.add(key, AString(start_of_value));
- }
- }
-
- return OK;
-}
-
-ssize_t HTTPStream::receive(void *data, size_t size) {
- size_t total = 0;
- while (total < size) {
- ssize_t n;
- if (mSSL != NULL) {
- n = SSL_read((SSL *)mSSL, (char *)data + total, size - total);
-
- if (n < 0) {
- n = -SSL_get_error((SSL *)mSSL, n);
- }
- } else {
- n = MyReceive(mSocket, (char *)data + total, size - total, 0);
- }
-
- if (n < 0) {
- LOGE("recv failed, errno = %d (%s)", (int)n, strerror(-n));
-
- disconnect();
- return (ssize_t)ERROR_IO;
- } else if (n == 0) {
- disconnect();
-
- LOGE("recv failed, server is gone, total received: %d bytes",
- total);
-
- return total == 0 ? (ssize_t)ERROR_CONNECTION_LOST : total;
- }
-
- total += (size_t)n;
- }
-
- return (ssize_t)total;
-}
-
-bool HTTPStream::find_header_value(const AString &key, AString *value) const {
- AString key_lower = key;
- key_lower.tolower();
-
- ssize_t index = mHeaders.indexOfKey(key_lower);
- if (index < 0) {
- value->clear();
- return false;
- }
-
- *value = mHeaders.valueAt(index);
-
- return true;
-}
-
-void HTTPStream::setReceiveTimeout(int seconds) {
- if (seconds < 0) {
- // Disable the timeout.
- seconds = 0;
- }
-
- struct timeval tv;
- tv.tv_usec = 0;
- tv.tv_sec = seconds;
- CHECK_EQ(0, setsockopt(mSocket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)));
-}
-
-// static
-void HTTPStream::RegisterSocketUser(int s, uid_t uid) {
- // Lower bits MUST be 0.
- static const uint64_t kTag = 0xdeadbeef00000000ll;
-
- AString line = StringPrintf("t %d %llu %d", s, kTag, uid);
-
- int fd = open("/proc/net/xt_qtaguid/ctrl", O_WRONLY);
- write(fd, line.c_str(), line.size());
- close(fd);
- fd = -1;
-}
-
-} // namespace android
-
diff --git a/media/libstagefright/NuHTTPDataSource.cpp b/media/libstagefright/NuHTTPDataSource.cpp
deleted file mode 100644
index 2949767..0000000
--- a/media/libstagefright/NuHTTPDataSource.cpp
+++ /dev/null
@@ -1,560 +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 "NuHTTPDataSource"
-#include <utils/Log.h>
-
-#include "include/NuHTTPDataSource.h"
-
-#include <cutils/properties.h>
-#include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/MediaDebug.h>
-#include <media/stagefright/MediaErrors.h>
-
-namespace android {
-
-static bool ParseSingleUnsignedLong(
- const char *from, unsigned long *x) {
- char *end;
- *x = strtoul(from, &end, 10);
-
- if (end == from || *end != '\0') {
- return false;
- }
-
- return true;
-}
-
-static bool ParseURL(
- const char *url, String8 *host, unsigned *port,
- String8 *path, bool *https) {
- host->setTo("");
- *port = 0;
- path->setTo("");
-
- size_t hostStart;
- if (!strncasecmp("http://", url, 7)) {
- hostStart = 7;
- *https = false;
- } else if (!strncasecmp("https://", url, 8)) {
- hostStart = 8;
- *https = true;
- } else {
- return false;
- }
-
- const char *slashPos = strchr(&url[hostStart], '/');
-
- if (slashPos == NULL) {
- host->setTo(&url[hostStart]);
- path->setTo("/");
- } else {
- host->setTo(&url[hostStart], slashPos - &url[hostStart]);
- path->setTo(slashPos);
- }
-
- const char *colonPos = strchr(host->string(), ':');
-
- if (colonPos != NULL) {
- unsigned long x;
- if (!ParseSingleUnsignedLong(colonPos + 1, &x) || x >= 65536) {
- return false;
- }
-
- *port = x;
-
- size_t colonOffset = colonPos - host->string();
- String8 tmp(host->string(), colonOffset);
- *host = tmp;
- } else {
- *port = (*https) ? 443 : 80;
- }
-
- return true;
-}
-
-NuHTTPDataSource::NuHTTPDataSource(uint32_t flags)
- : mFlags(flags),
- mState(DISCONNECTED),
- mPort(0),
- mHTTPS(false),
- mOffset(0),
- mContentLength(0),
- mContentLengthValid(false),
- mHasChunkedTransferEncoding(false),
- mChunkDataBytesLeft(0),
- mDecryptHandle(NULL),
- mDrmManagerClient(NULL) {
-}
-
-NuHTTPDataSource::~NuHTTPDataSource() {
- if (mDecryptHandle != NULL) {
- // To release mDecryptHandle
- CHECK(mDrmManagerClient);
- mDrmManagerClient->closeDecryptSession(mDecryptHandle);
- mDecryptHandle = NULL;
- }
-
- if (mDrmManagerClient != NULL) {
- delete mDrmManagerClient;
- mDrmManagerClient = NULL;
- }
-}
-
-status_t NuHTTPDataSource::connect(
- const char *uri,
- const KeyedVector<String8, String8> *overrides,
- off64_t offset) {
- String8 headers;
- MakeFullHeaders(overrides, &headers);
-
- return connect(uri, headers, offset);
-}
-
-status_t NuHTTPDataSource::connect(
- const char *uri,
- const String8 &headers,
- off64_t offset) {
- String8 host, path;
- unsigned port;
-
- mUri = uri;
- mContentType = String8("application/octet-stream");
-
- bool https;
- if (!ParseURL(uri, &host, &port, &path, &https)) {
- return ERROR_MALFORMED;
- }
-
- uid_t uid;
- if (getUID(&uid)) {
- mHTTP.setUID(uid);
- }
-
- return connect(host, port, path, https, headers, offset);
-}
-
-static bool IsRedirectStatusCode(int httpStatus) {
- return httpStatus == 301 || httpStatus == 302
- || httpStatus == 303 || httpStatus == 307;
-}
-
-status_t NuHTTPDataSource::connect(
- const char *host, unsigned port, const char *path,
- bool https,
- const String8 &headers,
- off64_t offset) {
- if (!(mFlags & kFlagIncognito)) {
- LOGI("connect to %s:%u%s @%lld", host, port, path, offset);
- } else {
- LOGI("connect to <URL suppressed> @%lld", offset);
- }
-
- bool needsToReconnect = true;
-
- if (mState == CONNECTED && host == mHost && port == mPort
- && https == mHTTPS && offset == mOffset) {
- if (mContentLengthValid && mOffset == mContentLength) {
- LOGI("Didn't have to reconnect, old one's still good.");
- needsToReconnect = false;
- }
- }
-
- mHost = host;
- mPort = port;
- mPath = path;
- mHTTPS = https;
- mHeaders = headers;
-
- status_t err = OK;
-
- mState = CONNECTING;
-
- if (needsToReconnect) {
- mHTTP.disconnect();
- err = mHTTP.connect(host, port, https);
- }
-
- if (err != OK) {
- mState = DISCONNECTED;
- } else if (mState != CONNECTING) {
- err = UNKNOWN_ERROR;
- } else {
- mState = CONNECTED;
-
- mOffset = offset;
- mContentLength = 0;
- mContentLengthValid = false;
-
- String8 request("GET ");
- request.append(mPath);
- request.append(" HTTP/1.1\r\n");
- request.append("Host: ");
- request.append(mHost);
- if (mPort != 80) {
- request.append(StringPrintf(":%u", mPort).c_str());
- }
- request.append("\r\n");
-
- if (offset != 0) {
- char rangeHeader[128];
- sprintf(rangeHeader, "Range: bytes=%lld-\r\n", offset);
- request.append(rangeHeader);
- }
-
- request.append(mHeaders);
- request.append("\r\n");
-
- int httpStatus;
- if ((err = mHTTP.send(request.string(), request.size())) != OK
- || (err = mHTTP.receive_header(&httpStatus)) != OK) {
- mHTTP.disconnect();
- mState = DISCONNECTED;
- return err;
- }
-
- if (IsRedirectStatusCode(httpStatus)) {
- AString value;
- CHECK(mHTTP.find_header_value("Location", &value));
-
- mState = DISCONNECTED;
-
- mHTTP.disconnect();
-
- return connect(value.c_str(), headers, offset);
- }
-
- if (httpStatus < 200 || httpStatus >= 300) {
- mState = DISCONNECTED;
- mHTTP.disconnect();
-
- return ERROR_IO;
- }
-
- mHasChunkedTransferEncoding = false;
-
- {
- AString value;
- if (mHTTP.find_header_value("Transfer-Encoding", &value)) {
- // We don't currently support any transfer encodings but
- // chunked.
-
- if (!strcasecmp(value.c_str(), "chunked")) {
- LOGI("Chunked transfer encoding applied.");
- mHasChunkedTransferEncoding = true;
- mChunkDataBytesLeft = 0;
- } else {
- mState = DISCONNECTED;
- mHTTP.disconnect();
-
- LOGE("We don't support '%s' transfer encoding.", value.c_str());
-
- return ERROR_UNSUPPORTED;
- }
- }
- }
-
- {
- AString value;
- if (mHTTP.find_header_value("Content-Type", &value)) {
- mContentType = String8(value.c_str());
- } else {
- mContentType = String8("application/octet-stream");
- }
- }
-
- applyTimeoutResponse();
-
- if (offset == 0) {
- AString value;
- unsigned long x;
- if (mHTTP.find_header_value(AString("Content-Length"), &value)
- && ParseSingleUnsignedLong(value.c_str(), &x)) {
- mContentLength = (off64_t)x;
- mContentLengthValid = true;
- } else {
- LOGW("Server did not give us the content length!");
- }
- } else {
- if (httpStatus != 206 /* Partial Content */) {
- // We requested a range but the server didn't support that.
- LOGE("We requested a range but the server didn't "
- "support that.");
- return ERROR_UNSUPPORTED;
- }
-
- AString value;
- unsigned long x;
- if (mHTTP.find_header_value(AString("Content-Range"), &value)) {
- const char *slashPos = strchr(value.c_str(), '/');
- if (slashPos != NULL
- && ParseSingleUnsignedLong(slashPos + 1, &x)) {
- mContentLength = x;
- mContentLengthValid = true;
- }
- }
- }
- }
-
- return err;
-}
-
-void NuHTTPDataSource::disconnect() {
- if (mState == CONNECTING || mState == CONNECTED) {
- mHTTP.disconnect();
- }
- mState = DISCONNECTED;
-}
-
-status_t NuHTTPDataSource::initCheck() const {
- return mState == CONNECTED ? OK : NO_INIT;
-}
-
-ssize_t NuHTTPDataSource::internalRead(void *data, size_t size) {
- if (!mHasChunkedTransferEncoding) {
- return mHTTP.receive(data, size);
- }
-
- if (mChunkDataBytesLeft < 0) {
- return 0;
- } else if (mChunkDataBytesLeft == 0) {
- char line[1024];
- status_t err = mHTTP.receive_line(line, sizeof(line));
-
- if (err != OK) {
- return err;
- }
-
- LOGV("line = '%s'", line);
-
- char *end;
- unsigned long n = strtoul(line, &end, 16);
-
- if (end == line || (*end != ';' && *end != '\0')) {
- LOGE("malformed HTTP chunk '%s'", line);
- return ERROR_MALFORMED;
- }
-
- mChunkDataBytesLeft = n;
- LOGV("chunk data size = %lu", n);
-
- if (mChunkDataBytesLeft == 0) {
- mChunkDataBytesLeft = -1;
- return 0;
- }
-
- // fall through
- }
-
- if (size > (size_t)mChunkDataBytesLeft) {
- size = mChunkDataBytesLeft;
- }
-
- ssize_t n = mHTTP.receive(data, size);
-
- if (n < 0) {
- return n;
- }
-
- mChunkDataBytesLeft -= (size_t)n;
-
- if (mChunkDataBytesLeft == 0) {
- char line[1024];
- status_t err = mHTTP.receive_line(line, sizeof(line));
-
- if (err != OK) {
- return err;
- }
-
- if (line[0] != '\0') {
- LOGE("missing HTTP chunk terminator.");
- return ERROR_MALFORMED;
- }
- }
-
- return n;
-}
-
-ssize_t NuHTTPDataSource::readAt(off64_t offset, void *data, size_t size) {
- LOGV("readAt offset %ld, size %d", offset, size);
-
- Mutex::Autolock autoLock(mLock);
-
- if (offset != mOffset) {
- String8 host = mHost;
- String8 path = mPath;
- String8 headers = mHeaders;
- status_t err = connect(host, mPort, path, mHTTPS, headers, offset);
-
- if (err != OK) {
- return err;
- }
- }
-
- if (mContentLengthValid) {
- size_t avail =
- (offset >= mContentLength) ? 0 : mContentLength - offset;
-
- if (size > avail) {
- size = avail;
- }
- }
-
- size_t numBytesRead = 0;
- while (numBytesRead < size) {
- int64_t startTimeUs = ALooper::GetNowUs();
-
- ssize_t n =
- internalRead((uint8_t *)data + numBytesRead, size - numBytesRead);
-
- if (n < 0) {
- if (numBytesRead == 0 || mContentLengthValid) {
- return n;
- }
-
- // If there was an error we want to at least return the data
- // we've already successfully read. The next call to read will
- // then return the error.
- n = 0;
- }
-
- int64_t delayUs = ALooper::GetNowUs() - startTimeUs;
- addBandwidthMeasurement(n, delayUs);
-
- numBytesRead += (size_t)n;
-
- if (n == 0) {
- if (mContentLengthValid) {
- // We know the content length and made sure not to read beyond
- // it and yet the server closed the connection on us.
- return ERROR_IO;
- }
-
- break;
- }
- }
-
- mOffset += numBytesRead;
-
- return numBytesRead;
-}
-
-status_t NuHTTPDataSource::getSize(off64_t *size) {
- *size = 0;
-
- if (mState != CONNECTED) {
- return ERROR_IO;
- }
-
- if (mContentLengthValid) {
- *size = mContentLength;
- return OK;
- }
-
- return ERROR_UNSUPPORTED;
-}
-
-uint32_t NuHTTPDataSource::flags() {
- return kWantsPrefetching | kIsHTTPBasedSource;
-}
-
-// static
-void NuHTTPDataSource::MakeFullHeaders(
- const KeyedVector<String8, String8> *overrides, String8 *headers) {
- headers->setTo("");
-
- headers->append("User-Agent: stagefright/1.1 (Linux;Android ");
-
-#if (PROPERTY_VALUE_MAX < 8)
-#error "PROPERTY_VALUE_MAX must be at least 8"
-#endif
-
- char value[PROPERTY_VALUE_MAX];
- property_get("ro.build.version.release", value, "Unknown");
- headers->append(value);
- headers->append(")\r\n");
-
- if (overrides == NULL) {
- return;
- }
-
- for (size_t i = 0; i < overrides->size(); ++i) {
- String8 line;
- line.append(overrides->keyAt(i));
- line.append(": ");
- line.append(overrides->valueAt(i));
- line.append("\r\n");
-
- headers->append(line);
- }
-}
-
-void NuHTTPDataSource::applyTimeoutResponse() {
- AString timeout;
- if (mHTTP.find_header_value("X-SocketTimeout", &timeout)) {
- const char *s = timeout.c_str();
- char *end;
- long tmp = strtol(s, &end, 10);
- if (end == s || *end != '\0') {
- LOGW("Illegal X-SocketTimeout value given.");
- return;
- }
-
- LOGI("overriding default timeout, new timeout is %ld seconds", tmp);
- mHTTP.setReceiveTimeout(tmp);
- }
-}
-
-sp<DecryptHandle> NuHTTPDataSource::DrmInitialization() {
- if (mDrmManagerClient == NULL) {
- mDrmManagerClient = new DrmManagerClient();
- }
-
- if (mDrmManagerClient == NULL) {
- return NULL;
- }
-
- if (mDecryptHandle == NULL) {
- /* Note if redirect occurs, mUri is the redirect uri instead of the
- * original one
- */
- mDecryptHandle = mDrmManagerClient->openDecryptSession(mUri);
- }
-
- if (mDecryptHandle == NULL) {
- delete mDrmManagerClient;
- mDrmManagerClient = NULL;
- }
-
- return mDecryptHandle;
-}
-
-void NuHTTPDataSource::getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client) {
- handle = mDecryptHandle;
-
- *client = mDrmManagerClient;
-}
-
-String8 NuHTTPDataSource::getUri() {
- return mUri;
-}
-
-String8 NuHTTPDataSource::getMIMEType() const {
- return mContentType;
-}
-
-} // namespace android
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/ShoutcastSource.cpp b/media/libstagefright/ShoutcastSource.cpp
deleted file mode 100644
index 783f2d0..0000000
--- a/media/libstagefright/ShoutcastSource.cpp
+++ /dev/null
@@ -1,157 +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 "include/HTTPStream.h"
-
-#include <stdlib.h>
-
-#include <media/stagefright/MediaBuffer.h>
-#include <media/stagefright/MediaBufferGroup.h>
-#include <media/stagefright/MediaDebug.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/ShoutcastSource.h>
-
-namespace android {
-
-ShoutcastSource::ShoutcastSource(HTTPStream *http)
- : mHttp(http),
- mMetaDataOffset(0),
- mBytesUntilMetaData(0),
- mGroup(NULL),
- mStarted(false) {
- AString metaint;
- if (mHttp->find_header_value("icy-metaint", &metaint)) {
- char *end;
- const char *start = metaint.c_str();
- mMetaDataOffset = strtol(start, &end, 10);
- CHECK(end > start && *end == '\0');
- CHECK(mMetaDataOffset > 0);
-
- mBytesUntilMetaData = mMetaDataOffset;
- }
-}
-
-ShoutcastSource::~ShoutcastSource() {
- if (mStarted) {
- stop();
- }
-
- delete mHttp;
- mHttp = NULL;
-}
-
-status_t ShoutcastSource::start(MetaData *) {
- CHECK(!mStarted);
-
- mGroup = new MediaBufferGroup;
- mGroup->add_buffer(new MediaBuffer(4096)); // XXX
-
- mStarted = true;
-
- return OK;
-}
-
-status_t ShoutcastSource::stop() {
- CHECK(mStarted);
-
- delete mGroup;
- mGroup = NULL;
-
- mStarted = false;
-
- return OK;
-}
-
-sp<MetaData> ShoutcastSource::getFormat() {
- sp<MetaData> meta = new MetaData;
- meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
- meta->setInt32(kKeySampleRate, 44100);
- meta->setInt32(kKeyChannelCount, 2); // XXX
-
- return meta;
-}
-
-status_t ShoutcastSource::read(
- MediaBuffer **out, const ReadOptions *options) {
- CHECK(mStarted);
-
- *out = NULL;
-
- int64_t seekTimeUs;
- ReadOptions::SeekMode mode;
- if (options && options->getSeekTo(&seekTimeUs, &mode)) {
- return ERROR_UNSUPPORTED;
- }
-
- MediaBuffer *buffer;
- status_t err = mGroup->acquire_buffer(&buffer);
- if (err != OK) {
- return err;
- }
-
- *out = buffer;
-
- size_t num_bytes = buffer->size();
- if (mMetaDataOffset > 0 && num_bytes > mBytesUntilMetaData) {
- num_bytes = mBytesUntilMetaData;
- }
-
- ssize_t n = mHttp->receive(buffer->data(), num_bytes);
-
- if (n <= 0) {
- return (status_t)n;
- }
-
- buffer->set_range(0, n);
-
- mBytesUntilMetaData -= (size_t)n;
-
- if (mBytesUntilMetaData == 0) {
- unsigned char num_16_byte_blocks = 0;
- n = mHttp->receive((char *)&num_16_byte_blocks, 1);
- CHECK_EQ(n, 1);
-
- char meta[255 * 16];
- size_t meta_size = num_16_byte_blocks * 16;
- size_t meta_length = 0;
- while (meta_length < meta_size) {
- n = mHttp->receive(&meta[meta_length], meta_size - meta_length);
- if (n <= 0) {
- return (status_t)n;
- }
-
- meta_length += (size_t) n;
- }
-
- while (meta_length > 0 && meta[meta_length - 1] == '\0') {
- --meta_length;
- }
-
- if (meta_length > 0) {
- // Technically we should probably attach this meta data to the
- // next buffer. XXX
- buffer->meta_data()->setData('shou', 'shou', meta, meta_length);
- }
-
- mBytesUntilMetaData = mMetaDataOffset;
- }
-
- return OK;
-}
-
-} // namespace android
-
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, &timestamp, &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/HTTPBase.h b/media/libstagefright/include/HTTPBase.h
index 2e25dd9..0e9af69 100644
--- a/media/libstagefright/include/HTTPBase.h
+++ b/media/libstagefright/include/HTTPBase.h
@@ -53,6 +53,8 @@ struct HTTPBase : public DataSource {
static sp<HTTPBase> Create(uint32_t flags = 0);
+ static void RegisterSocketUser(int s, uid_t uid);
+
protected:
void addBandwidthMeasurement(size_t numBytes, int64_t delayUs);
diff --git a/media/libstagefright/include/HTTPStream.h b/media/libstagefright/include/HTTPStream.h
deleted file mode 100644
index 88ba9d6..0000000
--- a/media/libstagefright/include/HTTPStream.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef HTTP_STREAM_H_
-
-#define HTTP_STREAM_H_
-
-#include <sys/types.h>
-
-#include <media/stagefright/foundation/AString.h>
-#include <media/stagefright/MediaErrors.h>
-#include <utils/KeyedVector.h>
-#include <utils/threads.h>
-
-namespace android {
-
-class HTTPStream {
-public:
- HTTPStream();
- ~HTTPStream();
-
- void setUID(uid_t uid);
-
- status_t connect(const char *server, int port = -1, bool https = false);
- status_t disconnect();
-
- status_t send(const char *data, size_t size);
-
- // Assumes data is a '\0' terminated string.
- status_t send(const char *data);
-
- // Receive up to "size" bytes of data.
- ssize_t receive(void *data, size_t size);
-
- status_t receive_header(int *http_status);
-
- // The header key used to retrieve the status line.
- static const char *kStatusKey;
-
- bool find_header_value(
- const AString &key, AString *value) const;
-
- // Pass a negative value to disable the timeout.
- void setReceiveTimeout(int seconds);
-
- // Receive a line of data terminated by CRLF, line will be '\0' terminated
- // _excluding_ the termianting CRLF.
- status_t receive_line(char *line, size_t size);
-
- static void RegisterSocketUser(int s, uid_t uid);
-
-private:
- enum State {
- READY,
- CONNECTING,
- CONNECTED
- };
-
- State mState;
- Mutex mLock;
-
- bool mUIDValid;
- uid_t mUID;
-
- int mSocket;
-
- KeyedVector<AString, AString> mHeaders;
-
- void *mSSLContext;
- void *mSSL;
-
- HTTPStream(const HTTPStream &);
- HTTPStream &operator=(const HTTPStream &);
-};
-
-} // namespace android
-
-#endif // HTTP_STREAM_H_
diff --git a/media/libstagefright/include/NuHTTPDataSource.h b/media/libstagefright/include/NuHTTPDataSource.h
deleted file mode 100644
index c265b3a..0000000
--- a/media/libstagefright/include/NuHTTPDataSource.h
+++ /dev/null
@@ -1,114 +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 NU_HTTP_DATA_SOURCE_H_
-
-#define NU_HTTP_DATA_SOURCE_H_
-
-#include <utils/List.h>
-#include <utils/String8.h>
-#include <utils/threads.h>
-
-#include "HTTPStream.h"
-#include "include/HTTPBase.h"
-
-namespace android {
-
-struct NuHTTPDataSource : public HTTPBase {
- NuHTTPDataSource(uint32_t flags = 0);
-
- virtual status_t connect(
- const char *uri,
- const KeyedVector<String8, String8> *headers = NULL,
- off64_t offset = 0);
-
- virtual void disconnect();
-
- virtual status_t initCheck() const;
-
- virtual ssize_t readAt(off64_t offset, void *data, size_t size);
- virtual status_t getSize(off64_t *size);
- virtual uint32_t flags();
-
- virtual sp<DecryptHandle> DrmInitialization();
- virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client);
- virtual String8 getUri();
-
- virtual String8 getMIMEType() const;
-
-protected:
- virtual ~NuHTTPDataSource();
-
-private:
- enum State {
- DISCONNECTED,
- CONNECTING,
- CONNECTED
- };
-
- Mutex mLock;
-
- uint32_t mFlags;
-
- State mState;
-
- String8 mHost;
- unsigned mPort;
- String8 mPath;
- bool mHTTPS;
- String8 mHeaders;
- String8 mUri;
-
- HTTPStream mHTTP;
- off64_t mOffset;
- off64_t mContentLength;
- bool mContentLengthValid;
- bool mHasChunkedTransferEncoding;
-
- String8 mContentType;
-
- // The number of data bytes in the current chunk before any subsequent
- // chunk header (or -1 if no more chunks).
- ssize_t mChunkDataBytesLeft;
-
- sp<DecryptHandle> mDecryptHandle;
- DrmManagerClient *mDrmManagerClient;
-
- status_t connect(
- const char *uri, const String8 &headers, off64_t offset);
-
- status_t connect(
- const char *host, unsigned port, const char *path,
- bool https,
- const String8 &headers,
- off64_t offset);
-
- // Read up to "size" bytes of data, respect transfer encoding.
- ssize_t internalRead(void *data, size_t size);
-
- void applyTimeoutResponse();
-
- static void MakeFullHeaders(
- const KeyedVector<String8, String8> *overrides,
- String8 *headers);
-
- NuHTTPDataSource(const NuHTTPDataSource &);
- NuHTTPDataSource &operator=(const NuHTTPDataSource &);
-};
-
-} // namespace android
-
-#endif // NU_HTTP_DATA_SOURCE_H_
diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/include/OMX.h
index ec3e5fa..d54b1c1 100644
--- a/media/libstagefright/include/OMX.h
+++ b/media/libstagefright/include/OMX.h
@@ -121,6 +121,7 @@ protected:
virtual ~OMX();
private:
+ struct CallbackDispatcherThread;
struct CallbackDispatcher;
Mutex mLock;
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/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index d23aa3a..25f30d6 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -20,8 +20,6 @@
#include <dlfcn.h>
-#include <sys/prctl.h>
-
#include "../include/OMX.h"
#include "../include/OMXNodeInstance.h"
@@ -38,11 +36,32 @@ namespace android {
////////////////////////////////////////////////////////////////////////////////
+// This provides the underlying Thread used by CallbackDispatcher.
+// Note that deriving CallbackDispatcher from Thread does not work.
+
+struct OMX::CallbackDispatcherThread : public Thread {
+ CallbackDispatcherThread(CallbackDispatcher *dispatcher)
+ : mDispatcher(dispatcher) {
+ }
+
+private:
+ CallbackDispatcher *mDispatcher;
+
+ bool threadLoop();
+
+ CallbackDispatcherThread(const CallbackDispatcherThread &);
+ CallbackDispatcherThread &operator=(const CallbackDispatcherThread &);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
struct OMX::CallbackDispatcher : public RefBase {
CallbackDispatcher(OMXNodeInstance *owner);
void post(const omx_message &msg);
+ bool loop();
+
protected:
virtual ~CallbackDispatcher();
@@ -54,13 +73,10 @@ private:
Condition mQueueChanged;
List<omx_message> mQueue;
- pthread_t mThread;
+ sp<CallbackDispatcherThread> mThread;
void dispatch(const omx_message &msg);
- static void *ThreadWrapper(void *me);
- void threadEntry();
-
CallbackDispatcher(const CallbackDispatcher &);
CallbackDispatcher &operator=(const CallbackDispatcher &);
};
@@ -68,13 +84,8 @@ private:
OMX::CallbackDispatcher::CallbackDispatcher(OMXNodeInstance *owner)
: mOwner(owner),
mDone(false) {
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
-
- pthread_create(&mThread, &attr, ThreadWrapper, this);
-
- pthread_attr_destroy(&attr);
+ mThread = new CallbackDispatcherThread(this);
+ mThread->run("OMXCallbackDisp", ANDROID_PRIORITY_AUDIO);
}
OMX::CallbackDispatcher::~CallbackDispatcher() {
@@ -86,10 +97,8 @@ OMX::CallbackDispatcher::~CallbackDispatcher() {
}
// Don't call join on myself
- CHECK(mThread != pthread_self());
-
- void *dummy;
- pthread_join(mThread, &dummy);
+ status_t status = mThread->join();
+ CHECK(status == NO_ERROR);
}
void OMX::CallbackDispatcher::post(const omx_message &msg) {
@@ -107,17 +116,7 @@ void OMX::CallbackDispatcher::dispatch(const omx_message &msg) {
mOwner->onMessage(msg);
}
-// static
-void *OMX::CallbackDispatcher::ThreadWrapper(void *me) {
- static_cast<CallbackDispatcher *>(me)->threadEntry();
-
- return NULL;
-}
-
-void OMX::CallbackDispatcher::threadEntry() {
- androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
- prctl(PR_SET_NAME, (unsigned long)"OMXCallbackDisp", 0, 0, 0);
-
+bool OMX::CallbackDispatcher::loop() {
for (;;) {
omx_message msg;
@@ -137,6 +136,14 @@ void OMX::CallbackDispatcher::threadEntry() {
dispatch(msg);
}
+
+ return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+bool OMX::CallbackDispatcherThread::threadLoop() {
+ return mDispatcher->loop();
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index 072d6b2..b398c9d 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -34,7 +34,7 @@
#include <openssl/md5.h>
#include <sys/socket.h>
-#include "HTTPStream.h"
+#include "HTTPBase.h"
namespace android {
@@ -251,7 +251,7 @@ void ARTSPConnection::onConnect(const sp<AMessage> &msg) {
mSocket = socket(AF_INET, SOCK_STREAM, 0);
if (mUIDValid) {
- HTTPStream::RegisterSocketUser(mSocket, mUID);
+ HTTPBase::RegisterSocketUser(mSocket, mUID);
}
MakeSocketBlocking(mSocket, false);
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 3188959..71d68f6 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -40,7 +40,7 @@
#include <sys/socket.h>
#include <netdb.h>
-#include "HTTPStream.h"
+#include "HTTPBase.h"
// If no access units are received within 5 secs, assume that the rtp
// stream has ended and signal end of stream.
@@ -1181,8 +1181,8 @@ private:
&info->mRTPSocket, &info->mRTCPSocket, &rtpPort);
if (mUIDValid) {
- HTTPStream::RegisterSocketUser(info->mRTPSocket, mUID);
- HTTPStream::RegisterSocketUser(info->mRTCPSocket, mUID);
+ HTTPBase::RegisterSocketUser(info->mRTPSocket, mUID);
+ HTTPBase::RegisterSocketUser(info->mRTCPSocket, mUID);
}
request.append("Transport: RTP/AVP/UDP;unicast;client_port=");
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index 47ca3a0..8e16d94 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -48,9 +48,6 @@ static const int kDumpLockRetries = 50;
static const int kDumpLockSleep = 20000;
static bool checkPermission() {
-#ifndef HAVE_ANDROID_OS
- return true;
-#endif
if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
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/InputApplication.h b/services/input/InputApplication.h
index cc80062..8902f7a 100644
--- a/services/input/InputApplication.h
+++ b/services/input/InputApplication.h
@@ -26,26 +26,32 @@
namespace android {
/*
- * A handle to an application that can receive input.
- * Used by the native input dispatcher to indirectly refer to the window manager objects
+ * Describes the properties of an application that can receive input.
+ *
+ * Used by the native input dispatcher as a handle for the window manager objects
* that describe an application.
*/
class InputApplicationHandle : public RefBase {
+public:
+ String8 name;
+ nsecs_t dispatchingTimeout;
+
+ /**
+ * Requests that the state of this object be updated to reflect
+ * the most current available information about the application.
+ *
+ * This method should only be called from within the input dispatcher's
+ * critical section.
+ *
+ * Returns true on success, or false if the handle is no longer valid.
+ */
+ virtual bool update() = 0;
+
protected:
InputApplicationHandle() { }
virtual ~InputApplicationHandle() { }
};
-
-/*
- * An input application describes properties of an application that can receive input.
- */
-struct InputApplication {
- sp<InputApplicationHandle> inputApplicationHandle;
- String8 name;
- nsecs_t dispatchingTimeout;
-};
-
} // namespace android
#endif // _UI_INPUT_APPLICATION_H
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index da9b55c..1cac502 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -211,11 +211,8 @@ InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& polic
mPendingEvent(NULL), mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
mNextUnblockedEvent(NULL),
mDispatchEnabled(true), mDispatchFrozen(false), mInputFilterEnabled(false),
- mFocusedWindow(NULL),
- mFocusedApplication(NULL),
mCurrentInputTargetsValid(false),
- mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE),
- mLastHoverWindow(NULL) {
+ mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
mLooper = new Looper(false);
mInboundQueue.headSentinel.refCount = -1;
@@ -501,16 +498,15 @@ bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
if (motionEntry->action == AMOTION_EVENT_ACTION_DOWN
&& (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
&& mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY
- && mInputTargetWaitApplication != NULL) {
+ && mInputTargetWaitApplicationHandle != NULL) {
int32_t x = int32_t(motionEntry->firstSample.pointerCoords[0].
getAxisValue(AMOTION_EVENT_AXIS_X));
int32_t y = int32_t(motionEntry->firstSample.pointerCoords[0].
getAxisValue(AMOTION_EVENT_AXIS_Y));
- const InputWindow* touchedWindow = findTouchedWindowAtLocked(x, y);
- if (touchedWindow
- && touchedWindow->inputWindowHandle != NULL
- && touchedWindow->inputWindowHandle->getInputApplicationHandle()
- != mInputTargetWaitApplication) {
+ sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(x, y);
+ if (touchedWindowHandle != NULL
+ && touchedWindowHandle->inputApplicationHandle
+ != mInputTargetWaitApplicationHandle) {
// User touched a different application than the one we are waiting on.
// Flag the event, and start pruning the input queue.
mNextUnblockedEvent = motionEntry;
@@ -524,25 +520,25 @@ bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
return needWake;
}
-const InputWindow* InputDispatcher::findTouchedWindowAtLocked(int32_t x, int32_t y) {
+sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t x, int32_t y) {
// Traverse windows from front to back to find touched window.
- size_t numWindows = mWindows.size();
+ size_t numWindows = mWindowHandles.size();
for (size_t i = 0; i < numWindows; i++) {
- const InputWindow* window = & mWindows.editItemAt(i);
- int32_t flags = window->layoutParamsFlags;
-
- if (window->visible) {
- if (!(flags & InputWindow::FLAG_NOT_TOUCHABLE)) {
- bool isTouchModal = (flags & (InputWindow::FLAG_NOT_FOCUSABLE
- | InputWindow::FLAG_NOT_TOUCH_MODAL)) == 0;
- if (isTouchModal || window->touchableRegionContainsPoint(x, y)) {
+ sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
+ int32_t flags = windowHandle->layoutParamsFlags;
+
+ if (windowHandle->visible) {
+ if (!(flags & InputWindowHandle::FLAG_NOT_TOUCHABLE)) {
+ bool isTouchModal = (flags & (InputWindowHandle::FLAG_NOT_FOCUSABLE
+ | InputWindowHandle::FLAG_NOT_TOUCH_MODAL)) == 0;
+ if (isTouchModal || windowHandle->touchableRegionContainsPoint(x, y)) {
// Found window.
- return window;
+ return windowHandle;
}
}
}
- if (flags & InputWindow::FLAG_SYSTEM_ERROR) {
+ if (flags & InputWindowHandle::FLAG_SYSTEM_ERROR) {
// Error window is on top but not visible, so touch is dropped.
return NULL;
}
@@ -781,8 +777,8 @@ bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
CommandEntry* commandEntry = postCommandLocked(
& InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
- if (mFocusedWindow) {
- commandEntry->inputWindowHandle = mFocusedWindow->inputWindowHandle;
+ if (mFocusedWindowHandle != NULL) {
+ commandEntry->inputWindowHandle = mFocusedWindowHandle;
}
commandEntry->keyEntry = entry;
entry->refCount += 1;
@@ -1011,7 +1007,7 @@ void InputDispatcher::resetTargetsLocked() {
mCurrentInputTargetsValid = false;
mCurrentInputTargets.clear();
mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
- mInputTargetWaitApplication.clear();
+ mInputTargetWaitApplicationHandle.clear();
}
void InputDispatcher::commitTargetsLocked() {
@@ -1019,9 +1015,11 @@ void InputDispatcher::commitTargetsLocked() {
}
int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
- const EventEntry* entry, const InputApplication* application, const InputWindow* window,
+ const EventEntry* entry,
+ const sp<InputApplicationHandle>& applicationHandle,
+ const sp<InputWindowHandle>& windowHandle,
nsecs_t* nextWakeupTime) {
- if (application == NULL && window == NULL) {
+ if (applicationHandle == NULL && windowHandle == NULL) {
if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) {
#if DEBUG_FOCUS
LOGD("Waiting for system to become ready for input.");
@@ -1030,29 +1028,29 @@ int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
mInputTargetWaitStartTime = currentTime;
mInputTargetWaitTimeoutTime = LONG_LONG_MAX;
mInputTargetWaitTimeoutExpired = false;
- mInputTargetWaitApplication.clear();
+ mInputTargetWaitApplicationHandle.clear();
}
} else {
if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
#if DEBUG_FOCUS
LOGD("Waiting for application to become ready for input: %s",
- getApplicationWindowLabelLocked(application, window).string());
+ getApplicationWindowLabelLocked(applicationHandle, windowHandle).string());
#endif
- nsecs_t timeout = window ? window->dispatchingTimeout :
- application ? application->dispatchingTimeout : DEFAULT_INPUT_DISPATCHING_TIMEOUT;
+ nsecs_t timeout = windowHandle != NULL ? windowHandle->dispatchingTimeout :
+ applicationHandle != NULL ?
+ applicationHandle->dispatchingTimeout : DEFAULT_INPUT_DISPATCHING_TIMEOUT;
mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;
mInputTargetWaitStartTime = currentTime;
mInputTargetWaitTimeoutTime = currentTime + timeout;
mInputTargetWaitTimeoutExpired = false;
- mInputTargetWaitApplication.clear();
+ mInputTargetWaitApplicationHandle.clear();
- if (window && window->inputWindowHandle != NULL) {
- mInputTargetWaitApplication =
- window->inputWindowHandle->getInputApplicationHandle();
+ if (windowHandle != NULL) {
+ mInputTargetWaitApplicationHandle = windowHandle->inputApplicationHandle;
}
- if (mInputTargetWaitApplication == NULL && application) {
- mInputTargetWaitApplication = application->inputApplicationHandle;
+ if (mInputTargetWaitApplicationHandle == NULL && applicationHandle != NULL) {
+ mInputTargetWaitApplicationHandle = applicationHandle;
}
}
}
@@ -1062,7 +1060,8 @@ int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
}
if (currentTime >= mInputTargetWaitTimeoutTime) {
- onANRLocked(currentTime, application, window, entry->eventTime, mInputTargetWaitStartTime);
+ onANRLocked(currentTime, applicationHandle, windowHandle,
+ entry->eventTime, mInputTargetWaitStartTime);
// Force poll loop to wake up immediately on next iteration once we get the
// ANR response back from the policy.
@@ -1129,15 +1128,15 @@ int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
// If there is no currently focused window and no focused application
// then drop the event.
- if (! mFocusedWindow) {
- if (mFocusedApplication) {
+ if (mFocusedWindowHandle == NULL) {
+ if (mFocusedApplicationHandle != NULL) {
#if DEBUG_FOCUS
LOGD("Waiting because there is no focused window but there is a "
"focused application that may eventually add a window: %s.",
- getApplicationWindowLabelLocked(mFocusedApplication, NULL).string());
+ getApplicationWindowLabelLocked(mFocusedApplicationHandle, NULL).string());
#endif
injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- mFocusedApplication, NULL, nextWakeupTime);
+ mFocusedApplicationHandle, NULL, nextWakeupTime);
goto Unresponsive;
}
@@ -1147,34 +1146,34 @@ int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
}
// Check permissions.
- if (! checkInjectionPermission(mFocusedWindow, entry->injectionState)) {
+ if (! checkInjectionPermission(mFocusedWindowHandle, entry->injectionState)) {
injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
goto Failed;
}
// If the currently focused window is paused then keep waiting.
- if (mFocusedWindow->paused) {
+ if (mFocusedWindowHandle->paused) {
#if DEBUG_FOCUS
LOGD("Waiting because focused window is paused.");
#endif
injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- mFocusedApplication, mFocusedWindow, nextWakeupTime);
+ mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime);
goto Unresponsive;
}
// If the currently focused window is still working on previous events then keep waiting.
- if (! isWindowFinishedWithPreviousInputLocked(mFocusedWindow)) {
+ if (! isWindowFinishedWithPreviousInputLocked(mFocusedWindowHandle)) {
#if DEBUG_FOCUS
LOGD("Waiting because focused window still processing previous input.");
#endif
injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- mFocusedApplication, mFocusedWindow, nextWakeupTime);
+ mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime);
goto Unresponsive;
}
// Success! Output targets.
injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
- addWindowTargetLocked(mFocusedWindow,
+ addWindowTargetLocked(mFocusedWindowHandle,
InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS, BitSet32(0));
// Done.
@@ -1236,7 +1235,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
// Update the touch state as needed based on the properties of the touch event.
int32_t injectionResult = INPUT_EVENT_INJECTION_PENDING;
InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN;
- const InputWindow* newHoverWindow = NULL;
+ sp<InputWindowHandle> newHoverWindowHandle;
bool isSplit = mTouchState.split;
bool switchedDevice = mTouchState.deviceId >= 0
@@ -1279,42 +1278,44 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
getAxisValue(AMOTION_EVENT_AXIS_X));
int32_t y = int32_t(sample->pointerCoords[pointerIndex].
getAxisValue(AMOTION_EVENT_AXIS_Y));
- const InputWindow* newTouchedWindow = NULL;
- const InputWindow* topErrorWindow = NULL;
+ sp<InputWindowHandle> newTouchedWindowHandle;
+ sp<InputWindowHandle> topErrorWindowHandle;
bool isTouchModal = false;
// Traverse windows from front to back to find touched window and outside targets.
- size_t numWindows = mWindows.size();
+ size_t numWindows = mWindowHandles.size();
for (size_t i = 0; i < numWindows; i++) {
- const InputWindow* window = & mWindows.editItemAt(i);
- int32_t flags = window->layoutParamsFlags;
+ sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
+ int32_t flags = windowHandle->layoutParamsFlags;
- if (flags & InputWindow::FLAG_SYSTEM_ERROR) {
- if (! topErrorWindow) {
- topErrorWindow = window;
+ if (flags & InputWindowHandle::FLAG_SYSTEM_ERROR) {
+ if (topErrorWindowHandle == NULL) {
+ topErrorWindowHandle = windowHandle;
}
}
- if (window->visible) {
- if (! (flags & InputWindow::FLAG_NOT_TOUCHABLE)) {
- isTouchModal = (flags & (InputWindow::FLAG_NOT_FOCUSABLE
- | InputWindow::FLAG_NOT_TOUCH_MODAL)) == 0;
- if (isTouchModal || window->touchableRegionContainsPoint(x, y)) {
- if (! screenWasOff || flags & InputWindow::FLAG_TOUCHABLE_WHEN_WAKING) {
- newTouchedWindow = window;
+ if (windowHandle->visible) {
+ if (! (flags & InputWindowHandle::FLAG_NOT_TOUCHABLE)) {
+ isTouchModal = (flags & (InputWindowHandle::FLAG_NOT_FOCUSABLE
+ | InputWindowHandle::FLAG_NOT_TOUCH_MODAL)) == 0;
+ if (isTouchModal || windowHandle->touchableRegionContainsPoint(x, y)) {
+ if (! screenWasOff
+ || (flags & InputWindowHandle::FLAG_TOUCHABLE_WHEN_WAKING)) {
+ newTouchedWindowHandle = windowHandle;
}
break; // found touched window, exit window loop
}
}
if (maskedAction == AMOTION_EVENT_ACTION_DOWN
- && (flags & InputWindow::FLAG_WATCH_OUTSIDE_TOUCH)) {
+ && (flags & InputWindowHandle::FLAG_WATCH_OUTSIDE_TOUCH)) {
int32_t outsideTargetFlags = InputTarget::FLAG_DISPATCH_AS_OUTSIDE;
- if (isWindowObscuredAtPointLocked(window, x, y)) {
+ if (isWindowObscuredAtPointLocked(windowHandle, x, y)) {
outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
}
- mTempTouchState.addOrUpdateWindow(window, outsideTargetFlags, BitSet32(0));
+ mTempTouchState.addOrUpdateWindow(
+ windowHandle, outsideTargetFlags, BitSet32(0));
}
}
}
@@ -1322,7 +1323,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
// If there is an error window but it is not taking focus (typically because
// it is invisible) then wait for it. Any other focused window may in
// fact be in ANR state.
- if (topErrorWindow && newTouchedWindow != topErrorWindow) {
+ if (topErrorWindowHandle != NULL && newTouchedWindowHandle != topErrorWindowHandle) {
#if DEBUG_FOCUS
LOGD("Waiting because system error window is pending.");
#endif
@@ -1333,26 +1334,26 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
}
// Figure out whether splitting will be allowed for this window.
- if (newTouchedWindow && newTouchedWindow->supportsSplitTouch()) {
+ if (newTouchedWindowHandle != NULL && newTouchedWindowHandle->supportsSplitTouch()) {
// New window supports splitting.
isSplit = true;
} else if (isSplit) {
// New window does not support splitting but we have already split events.
// Assign the pointer to the first foreground window we find.
// (May be NULL which is why we put this code block before the next check.)
- newTouchedWindow = mTempTouchState.getFirstForegroundWindow();
+ newTouchedWindowHandle = mTempTouchState.getFirstForegroundWindowHandle();
}
// If we did not find a touched window then fail.
- if (! newTouchedWindow) {
- if (mFocusedApplication) {
+ if (newTouchedWindowHandle == NULL) {
+ if (mFocusedApplicationHandle != NULL) {
#if DEBUG_FOCUS
LOGD("Waiting because there is no touched window but there is a "
"focused application that may eventually add a new window: %s.",
- getApplicationWindowLabelLocked(mFocusedApplication, NULL).string());
+ getApplicationWindowLabelLocked(mFocusedApplicationHandle, NULL).string());
#endif
injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- mFocusedApplication, NULL, nextWakeupTime);
+ mFocusedApplicationHandle, NULL, nextWakeupTime);
goto Unresponsive;
}
@@ -1366,20 +1367,20 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
if (isSplit) {
targetFlags |= InputTarget::FLAG_SPLIT;
}
- if (isWindowObscuredAtPointLocked(newTouchedWindow, x, y)) {
+ if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) {
targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
}
// Update hover state.
if (isHoverAction) {
- newHoverWindow = newTouchedWindow;
+ newHoverWindowHandle = newTouchedWindowHandle;
// Ensure all subsequent motion samples are also within the touched window.
// Set *outSplitBatchAfterSample to the sample before the first one that is not
// within the touched window.
if (!isTouchModal) {
while (sample->next) {
- if (!newHoverWindow->touchableRegionContainsPoint(
+ if (!newHoverWindowHandle->touchableRegionContainsPoint(
sample->next->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X),
sample->next->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y))) {
*outSplitBatchAfterSample = sample;
@@ -1389,7 +1390,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
}
}
} else if (maskedAction == AMOTION_EVENT_ACTION_SCROLL) {
- newHoverWindow = mLastHoverWindow;
+ newHoverWindowHandle = mLastHoverWindowHandle;
}
// Update the temporary touch state.
@@ -1398,7 +1399,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
uint32_t pointerId = entry->pointerProperties[pointerIndex].id;
pointerIds.markBit(pointerId);
}
- mTempTouchState.addOrUpdateWindow(newTouchedWindow, targetFlags, pointerIds);
+ mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);
} else {
/* Case 2: Pointer move, up, cancel or non-splittable pointer down. */
@@ -1420,19 +1421,22 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
int32_t x = int32_t(sample->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X));
int32_t y = int32_t(sample->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y));
- const InputWindow* oldTouchedWindow = mTempTouchState.getFirstForegroundWindow();
- const InputWindow* newTouchedWindow = findTouchedWindowAtLocked(x, y);
- if (oldTouchedWindow != newTouchedWindow && newTouchedWindow) {
+ sp<InputWindowHandle> oldTouchedWindowHandle =
+ mTempTouchState.getFirstForegroundWindowHandle();
+ sp<InputWindowHandle> newTouchedWindowHandle = findTouchedWindowAtLocked(x, y);
+ if (oldTouchedWindowHandle != newTouchedWindowHandle
+ && newTouchedWindowHandle != NULL) {
#if DEBUG_FOCUS
LOGD("Touch is slipping out of window %s into window %s.",
- oldTouchedWindow->name.string(), newTouchedWindow->name.string());
+ oldTouchedWindowHandle->name.string(),
+ newTouchedWindowHandle->name.string());
#endif
// Make a slippery exit from the old window.
- mTempTouchState.addOrUpdateWindow(oldTouchedWindow,
+ mTempTouchState.addOrUpdateWindow(oldTouchedWindowHandle,
InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT, BitSet32(0));
// Make a slippery entrance into the new window.
- if (newTouchedWindow->supportsSplitTouch()) {
+ if (newTouchedWindowHandle->supportsSplitTouch()) {
isSplit = true;
}
@@ -1441,7 +1445,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
if (isSplit) {
targetFlags |= InputTarget::FLAG_SPLIT;
}
- if (isWindowObscuredAtPointLocked(newTouchedWindow, x, y)) {
+ if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) {
targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
}
@@ -1449,7 +1453,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
if (isSplit) {
pointerIds.markBit(entry->pointerProperties[0].id);
}
- mTempTouchState.addOrUpdateWindow(newTouchedWindow, targetFlags, pointerIds);
+ mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);
// Split the batch here so we send exactly one sample.
*outSplitBatchAfterSample = &entry->firstSample;
@@ -1457,25 +1461,25 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
}
}
- if (newHoverWindow != mLastHoverWindow) {
+ if (newHoverWindowHandle != mLastHoverWindowHandle) {
// Split the batch here so we send exactly one sample as part of ENTER or EXIT.
*outSplitBatchAfterSample = &entry->firstSample;
// Let the previous window know that the hover sequence is over.
- if (mLastHoverWindow) {
+ if (mLastHoverWindowHandle != NULL) {
#if DEBUG_HOVER
- LOGD("Sending hover exit event to window %s.", mLastHoverWindow->name.string());
+ LOGD("Sending hover exit event to window %s.", mLastHoverWindowHandle->name.string());
#endif
- mTempTouchState.addOrUpdateWindow(mLastHoverWindow,
+ mTempTouchState.addOrUpdateWindow(mLastHoverWindowHandle,
InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT, BitSet32(0));
}
// Let the new window know that the hover sequence is starting.
- if (newHoverWindow) {
+ if (newHoverWindowHandle != NULL) {
#if DEBUG_HOVER
- LOGD("Sending hover enter event to window %s.", newHoverWindow->name.string());
+ LOGD("Sending hover enter event to window %s.", newHoverWindowHandle->name.string());
#endif
- mTempTouchState.addOrUpdateWindow(newHoverWindow,
+ mTempTouchState.addOrUpdateWindow(newHoverWindowHandle,
InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER, BitSet32(0));
}
}
@@ -1488,7 +1492,8 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
haveForegroundWindow = true;
- if (! checkInjectionPermission(touchedWindow.window, entry->injectionState)) {
+ if (! checkInjectionPermission(touchedWindow.windowHandle,
+ entry->injectionState)) {
injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
injectionPermission = INJECTION_PERMISSION_DENIED;
goto Failed;
@@ -1510,14 +1515,15 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
// Check whether windows listening for outside touches are owned by the same UID. If it is
// set the policy flag that we will not reveal coordinate information to this window.
if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
- const InputWindow* foregroundWindow = mTempTouchState.getFirstForegroundWindow();
- const int32_t foregroundWindowUid = foregroundWindow->ownerUid;
+ sp<InputWindowHandle> foregroundWindowHandle =
+ mTempTouchState.getFirstForegroundWindowHandle();
+ const int32_t foregroundWindowUid = foregroundWindowHandle->ownerUid;
for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
if (touchedWindow.targetFlags & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
- const InputWindow* inputWindow = touchedWindow.window;
- if (inputWindow->ownerUid != foregroundWindowUid) {
- mTempTouchState.addOrUpdateWindow(inputWindow,
+ sp<InputWindowHandle> inputWindowHandle = touchedWindow.windowHandle;
+ if (inputWindowHandle->ownerUid != foregroundWindowUid) {
+ mTempTouchState.addOrUpdateWindow(inputWindowHandle,
InputTarget::FLAG_ZERO_COORDS, BitSet32(0));
}
}
@@ -1529,22 +1535,22 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
// If the touched window is paused then keep waiting.
- if (touchedWindow.window->paused) {
+ if (touchedWindow.windowHandle->paused) {
#if DEBUG_FOCUS
LOGD("Waiting because touched window is paused.");
#endif
injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- NULL, touchedWindow.window, nextWakeupTime);
+ NULL, touchedWindow.windowHandle, nextWakeupTime);
goto Unresponsive;
}
// If the touched window is still working on previous events then keep waiting.
- if (! isWindowFinishedWithPreviousInputLocked(touchedWindow.window)) {
+ if (! isWindowFinishedWithPreviousInputLocked(touchedWindow.windowHandle)) {
#if DEBUG_FOCUS
LOGD("Waiting because touched window still processing previous input.");
#endif
injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- NULL, touchedWindow.window, nextWakeupTime);
+ NULL, touchedWindow.windowHandle, nextWakeupTime);
goto Unresponsive;
}
}
@@ -1557,12 +1563,13 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
// engine only supports touch events. We would need to add a mechanism similar
// to View.onGenericMotionEvent to enable wallpapers to handle these events.
if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
- const InputWindow* foregroundWindow = mTempTouchState.getFirstForegroundWindow();
- if (foregroundWindow->hasWallpaper) {
- for (size_t i = 0; i < mWindows.size(); i++) {
- const InputWindow* window = & mWindows[i];
- if (window->layoutParamsType == InputWindow::TYPE_WALLPAPER) {
- mTempTouchState.addOrUpdateWindow(window,
+ sp<InputWindowHandle> foregroundWindowHandle =
+ mTempTouchState.getFirstForegroundWindowHandle();
+ if (foregroundWindowHandle->hasWallpaper) {
+ for (size_t i = 0; i < mWindowHandles.size(); i++) {
+ sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
+ if (windowHandle->layoutParamsType == InputWindowHandle::TYPE_WALLPAPER) {
+ mTempTouchState.addOrUpdateWindow(windowHandle,
InputTarget::FLAG_WINDOW_IS_OBSCURED
| InputTarget::FLAG_DISPATCH_AS_IS,
BitSet32(0));
@@ -1576,7 +1583,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
const TouchedWindow& touchedWindow = mTempTouchState.windows.itemAt(i);
- addWindowTargetLocked(touchedWindow.window, touchedWindow.targetFlags,
+ addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
touchedWindow.pointerIds);
}
@@ -1658,7 +1665,7 @@ Failed:
}
// Update hover state.
- mLastHoverWindow = newHoverWindow;
+ mLastHoverWindowHandle = newHoverWindowHandle;
}
} else {
#if DEBUG_FOCUS
@@ -1681,16 +1688,16 @@ Unresponsive:
return injectionResult;
}
-void InputDispatcher::addWindowTargetLocked(const InputWindow* window, int32_t targetFlags,
- BitSet32 pointerIds) {
+void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
+ int32_t targetFlags, BitSet32 pointerIds) {
mCurrentInputTargets.push();
InputTarget& target = mCurrentInputTargets.editTop();
- target.inputChannel = window->inputChannel;
+ target.inputChannel = windowHandle->inputChannel;
target.flags = targetFlags;
- target.xOffset = - window->frameLeft;
- target.yOffset = - window->frameTop;
- target.scaleFactor = window->scaleFactor;
+ target.xOffset = - windowHandle->frameLeft;
+ target.yOffset = - windowHandle->frameTop;
+ target.scaleFactor = windowHandle->scaleFactor;
target.pointerIds = pointerIds;
}
@@ -1708,17 +1715,17 @@ void InputDispatcher::addMonitoringTargetsLocked() {
}
}
-bool InputDispatcher::checkInjectionPermission(const InputWindow* window,
+bool InputDispatcher::checkInjectionPermission(const sp<InputWindowHandle>& windowHandle,
const InjectionState* injectionState) {
if (injectionState
- && (window == NULL || window->ownerUid != injectionState->injectorUid)
+ && (windowHandle == NULL || windowHandle->ownerUid != injectionState->injectorUid)
&& !hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid)) {
- if (window) {
- LOGW("Permission denied: injecting event from pid %d uid %d to window "
- "with input channel %s owned by uid %d",
+ if (windowHandle != NULL) {
+ LOGW("Permission denied: injecting event from pid %d uid %d to window %s "
+ "owned by uid %d",
injectionState->injectorPid, injectionState->injectorUid,
- window->inputChannel->getName().string(),
- window->ownerUid);
+ windowHandle->name.string(),
+ windowHandle->ownerUid);
} else {
LOGW("Permission denied: injecting event from pid %d uid %d",
injectionState->injectorPid, injectionState->injectorUid);
@@ -1729,22 +1736,24 @@ bool InputDispatcher::checkInjectionPermission(const InputWindow* window,
}
bool InputDispatcher::isWindowObscuredAtPointLocked(
- const InputWindow* window, int32_t x, int32_t y) const {
- size_t numWindows = mWindows.size();
+ const sp<InputWindowHandle>& windowHandle, int32_t x, int32_t y) const {
+ size_t numWindows = mWindowHandles.size();
for (size_t i = 0; i < numWindows; i++) {
- const InputWindow* other = & mWindows.itemAt(i);
- if (other == window) {
+ sp<InputWindowHandle> otherHandle = mWindowHandles.itemAt(i);
+ if (otherHandle == windowHandle) {
break;
}
- if (other->visible && ! other->isTrustedOverlay() && other->frameContainsPoint(x, y)) {
+ if (otherHandle->visible && ! otherHandle->isTrustedOverlay()
+ && otherHandle->frameContainsPoint(x, y)) {
return true;
}
}
return false;
}
-bool InputDispatcher::isWindowFinishedWithPreviousInputLocked(const InputWindow* window) {
- ssize_t connectionIndex = getConnectionIndexLocked(window->inputChannel);
+bool InputDispatcher::isWindowFinishedWithPreviousInputLocked(
+ const sp<InputWindowHandle>& windowHandle) {
+ ssize_t connectionIndex = getConnectionIndexLocked(windowHandle->inputChannel);
if (connectionIndex >= 0) {
sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
return connection->outboundQueue.isEmpty();
@@ -1753,19 +1762,20 @@ bool InputDispatcher::isWindowFinishedWithPreviousInputLocked(const InputWindow*
}
}
-String8 InputDispatcher::getApplicationWindowLabelLocked(const InputApplication* application,
- const InputWindow* window) {
- if (application) {
- if (window) {
- String8 label(application->name);
+String8 InputDispatcher::getApplicationWindowLabelLocked(
+ const sp<InputApplicationHandle>& applicationHandle,
+ const sp<InputWindowHandle>& windowHandle) {
+ if (applicationHandle != NULL) {
+ if (windowHandle != NULL) {
+ String8 label(applicationHandle->name);
label.append(" - ");
- label.append(window->name);
+ label.append(windowHandle->name);
return label;
} else {
- return application->name;
+ return applicationHandle->name;
}
- } else if (window) {
- return window->name;
+ } else if (windowHandle != NULL) {
+ return windowHandle->name;
} else {
return String8("<unknown application or window>");
}
@@ -2422,11 +2432,11 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
}
InputTarget target;
- const InputWindow* window = getWindowLocked(connection->inputChannel);
- if (window) {
- target.xOffset = -window->frameLeft;
- target.yOffset = -window->frameTop;
- target.scaleFactor = window->scaleFactor;
+ sp<InputWindowHandle> windowHandle = getWindowHandleLocked(connection->inputChannel);
+ if (windowHandle != NULL) {
+ target.xOffset = -windowHandle->frameLeft;
+ target.yOffset = -windowHandle->frameTop;
+ target.scaleFactor = windowHandle->scaleFactor;
} else {
target.xOffset = 0;
target.yOffset = 0;
@@ -2809,7 +2819,7 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t
}
if (action == AMOTION_EVENT_ACTION_HOVER_MOVE) {
- if (!mLastHoverWindow) {
+ if (mLastHoverWindowHandle == NULL) {
#if DEBUG_BATCHING
LOGD("Not streaming hover move because there is no "
"last hovered window.");
@@ -2817,15 +2827,16 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t
goto NoBatchingOrStreaming;
}
- const InputWindow* hoverWindow = findTouchedWindowAtLocked(
+ sp<InputWindowHandle> hoverWindowHandle = findTouchedWindowAtLocked(
pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X),
pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y));
- if (mLastHoverWindow != hoverWindow) {
+ if (mLastHoverWindowHandle != hoverWindowHandle) {
#if DEBUG_BATCHING
LOGD("Not streaming hover move because the last hovered window "
"is '%s' but the currently hovered window is '%s'.",
- mLastHoverWindow->name.string(),
- hoverWindow ? hoverWindow->name.string() : "<null>");
+ mLastHoverWindowHandle->name.string(),
+ hoverWindowHandle != NULL
+ ? hoverWindowHandle->name.string() : "<null>");
#endif
goto NoBatchingOrStreaming;
}
@@ -3125,111 +3136,109 @@ void InputDispatcher::decrementPendingForegroundDispatchesLocked(EventEntry* ent
}
}
-const InputWindow* InputDispatcher::getWindowLocked(const sp<InputChannel>& inputChannel) {
- for (size_t i = 0; i < mWindows.size(); i++) {
- const InputWindow* window = & mWindows[i];
- if (window->inputChannel == inputChannel) {
- return window;
+sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked(
+ const sp<InputChannel>& inputChannel) const {
+ size_t numWindows = mWindowHandles.size();
+ for (size_t i = 0; i < numWindows; i++) {
+ const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
+ if (windowHandle->inputChannel == inputChannel) {
+ return windowHandle;
}
}
return NULL;
}
-void InputDispatcher::setInputWindows(const Vector<InputWindow>& inputWindows) {
+bool InputDispatcher::hasWindowHandleLocked(
+ const sp<InputWindowHandle>& windowHandle) const {
+ size_t numWindows = mWindowHandles.size();
+ for (size_t i = 0; i < numWindows; i++) {
+ if (mWindowHandles.itemAt(i) == windowHandle) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) {
#if DEBUG_FOCUS
LOGD("setInputWindows");
#endif
{ // acquire lock
AutoMutex _l(mLock);
- // Clear old window pointers.
- sp<InputChannel> oldFocusedWindowChannel;
- if (mFocusedWindow) {
- oldFocusedWindowChannel = mFocusedWindow->inputChannel;
- mFocusedWindow = NULL;
- }
- sp<InputChannel> oldLastHoverWindowChannel;
- if (mLastHoverWindow) {
- oldLastHoverWindowChannel = mLastHoverWindow->inputChannel;
- mLastHoverWindow = NULL;
- }
-
- // Loop over new windows and rebuild the necessary window pointers for
- // tracking focus and touch.
- mWindows = inputWindows;
+ mWindowHandles = inputWindowHandles;
- size_t numWindows = mWindows.size();
- for (size_t i = 0; i < numWindows; i++) {
- const InputWindow* window = & mWindows.itemAt(i);
- if (window->hasFocus) {
- mFocusedWindow = window;
- break;
+ sp<InputWindowHandle> newFocusedWindowHandle;
+ bool foundHoveredWindow = false;
+ for (size_t i = 0; i < mWindowHandles.size(); i++) {
+ const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
+ if (!windowHandle->update() || windowHandle->inputChannel == NULL) {
+ mWindowHandles.removeAt(i--);
+ continue;
}
+ if (windowHandle->hasFocus) {
+ newFocusedWindowHandle = windowHandle;
+ }
+ if (windowHandle == mLastHoverWindowHandle) {
+ foundHoveredWindow = true;
+ }
+ }
+
+ if (!foundHoveredWindow) {
+ mLastHoverWindowHandle = NULL;
}
- if (oldFocusedWindowChannel != NULL) {
- if (!mFocusedWindow || oldFocusedWindowChannel != mFocusedWindow->inputChannel) {
+ if (mFocusedWindowHandle != newFocusedWindowHandle) {
+ if (mFocusedWindowHandle != NULL) {
#if DEBUG_FOCUS
LOGD("Focus left window: %s",
- oldFocusedWindowChannel->getName().string());
+ mFocusedWindowHandle->name.string());
#endif
CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
"focus left window");
- synthesizeCancelationEventsForInputChannelLocked(oldFocusedWindowChannel, options);
- oldFocusedWindowChannel.clear();
+ synthesizeCancelationEventsForInputChannelLocked(
+ mFocusedWindowHandle->inputChannel, options);
}
- }
- if (mFocusedWindow && oldFocusedWindowChannel == NULL) {
+ if (newFocusedWindowHandle != NULL) {
#if DEBUG_FOCUS
- LOGD("Focus entered window: %s",
- mFocusedWindow->inputChannel->getName().string());
+ LOGD("Focus entered window: %s",
+ newFocusedWindowHandle->name.string());
#endif
+ }
+ mFocusedWindowHandle = newFocusedWindowHandle;
}
- for (size_t i = 0; i < mTouchState.windows.size(); ) {
+ for (size_t i = 0; i < mTouchState.windows.size(); i++) {
TouchedWindow& touchedWindow = mTouchState.windows.editItemAt(i);
- const InputWindow* window = getWindowLocked(touchedWindow.channel);
- if (window) {
- touchedWindow.window = window;
- i += 1;
- } else {
+ if (!hasWindowHandleLocked(touchedWindow.windowHandle)) {
#if DEBUG_FOCUS
- LOGD("Touched window was removed: %s", touchedWindow.channel->getName().string());
+ LOGD("Touched window was removed: %s", touchedWindow.windowHandle->name.string());
#endif
CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
"touched window was removed");
- synthesizeCancelationEventsForInputChannelLocked(touchedWindow.channel, options);
- mTouchState.windows.removeAt(i);
+ synthesizeCancelationEventsForInputChannelLocked(
+ touchedWindow.windowHandle->inputChannel, options);
+ mTouchState.windows.removeAt(i--);
}
}
-
- // Recover the last hovered window.
- if (oldLastHoverWindowChannel != NULL) {
- mLastHoverWindow = getWindowLocked(oldLastHoverWindowChannel);
- oldLastHoverWindowChannel.clear();
- }
-
-#if DEBUG_FOCUS
- //logDispatchStateLocked();
-#endif
} // release lock
// Wake up poll loop since it may need to make new input dispatching choices.
mLooper->wake();
}
-void InputDispatcher::setFocusedApplication(const InputApplication* inputApplication) {
+void InputDispatcher::setFocusedApplication(
+ const sp<InputApplicationHandle>& inputApplicationHandle) {
#if DEBUG_FOCUS
LOGD("setFocusedApplication");
#endif
{ // acquire lock
AutoMutex _l(mLock);
- releaseFocusedApplicationLocked();
-
- if (inputApplication) {
- mFocusedApplicationStorage = *inputApplication;
- mFocusedApplication = & mFocusedApplicationStorage;
+ if (inputApplicationHandle != NULL && inputApplicationHandle->update()) {
+ mFocusedApplicationHandle = inputApplicationHandle;
+ } else {
+ mFocusedApplicationHandle.clear();
}
#if DEBUG_FOCUS
@@ -3241,13 +3250,6 @@ void InputDispatcher::setFocusedApplication(const InputApplication* inputApplica
mLooper->wake();
}
-void InputDispatcher::releaseFocusedApplicationLocked() {
- if (mFocusedApplication) {
- mFocusedApplication = NULL;
- mFocusedApplicationStorage.inputApplicationHandle.clear();
- }
-}
-
void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) {
#if DEBUG_FOCUS
LOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
@@ -3313,15 +3315,15 @@ bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel,
{ // acquire lock
AutoMutex _l(mLock);
- const InputWindow* fromWindow = getWindowLocked(fromChannel);
- const InputWindow* toWindow = getWindowLocked(toChannel);
- if (! fromWindow || ! toWindow) {
+ sp<InputWindowHandle> fromWindowHandle = getWindowHandleLocked(fromChannel);
+ sp<InputWindowHandle> toWindowHandle = getWindowHandleLocked(toChannel);
+ if (fromWindowHandle == NULL || toWindowHandle == NULL) {
#if DEBUG_FOCUS
LOGD("Cannot transfer focus because from or to window not found.");
#endif
return false;
}
- if (fromWindow == toWindow) {
+ if (fromWindowHandle == toWindowHandle) {
#if DEBUG_FOCUS
LOGD("Trivial transfer to same window.");
#endif
@@ -3331,7 +3333,7 @@ bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel,
bool found = false;
for (size_t i = 0; i < mTouchState.windows.size(); i++) {
const TouchedWindow& touchedWindow = mTouchState.windows[i];
- if (touchedWindow.window == fromWindow) {
+ if (touchedWindow.windowHandle == fromWindowHandle) {
int32_t oldTargetFlags = touchedWindow.targetFlags;
BitSet32 pointerIds = touchedWindow.pointerIds;
@@ -3340,7 +3342,7 @@ bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel,
int32_t newTargetFlags = oldTargetFlags
& (InputTarget::FLAG_FOREGROUND
| InputTarget::FLAG_SPLIT | InputTarget::FLAG_DISPATCH_AS_IS);
- mTouchState.addOrUpdateWindow(toWindow, newTargetFlags, pointerIds);
+ mTouchState.addOrUpdateWindow(toWindowHandle, newTargetFlags, pointerIds);
found = true;
break;
@@ -3390,7 +3392,7 @@ void InputDispatcher::resetAndDropEverythingLocked(const char* reason) {
resetTargetsLocked();
mTouchState.reset();
- mLastHoverWindow = NULL;
+ mLastHoverWindowHandle.clear();
}
void InputDispatcher::logDispatchStateLocked() {
@@ -3413,15 +3415,15 @@ void InputDispatcher::dumpDispatchStateLocked(String8& dump) {
dump.appendFormat(INDENT "DispatchEnabled: %d\n", mDispatchEnabled);
dump.appendFormat(INDENT "DispatchFrozen: %d\n", mDispatchFrozen);
- if (mFocusedApplication) {
+ if (mFocusedApplicationHandle != NULL) {
dump.appendFormat(INDENT "FocusedApplication: name='%s', dispatchingTimeout=%0.3fms\n",
- mFocusedApplication->name.string(),
- mFocusedApplication->dispatchingTimeout / 1000000.0);
+ mFocusedApplicationHandle->name.string(),
+ mFocusedApplicationHandle->dispatchingTimeout / 1000000.0);
} else {
dump.append(INDENT "FocusedApplication: <null>\n");
}
dump.appendFormat(INDENT "FocusedWindow: name='%s'\n",
- mFocusedWindow != NULL ? mFocusedWindow->name.string() : "<null>");
+ mFocusedWindowHandle != NULL ? mFocusedWindowHandle->name.string() : "<null>");
dump.appendFormat(INDENT "TouchDown: %s\n", toString(mTouchState.down));
dump.appendFormat(INDENT "TouchSplit: %s\n", toString(mTouchState.split));
@@ -3432,37 +3434,37 @@ void InputDispatcher::dumpDispatchStateLocked(String8& dump) {
for (size_t i = 0; i < mTouchState.windows.size(); i++) {
const TouchedWindow& touchedWindow = mTouchState.windows[i];
dump.appendFormat(INDENT2 "%d: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n",
- i, touchedWindow.window->name.string(), touchedWindow.pointerIds.value,
+ i, touchedWindow.windowHandle->name.string(), touchedWindow.pointerIds.value,
touchedWindow.targetFlags);
}
} else {
dump.append(INDENT "TouchedWindows: <none>\n");
}
- if (!mWindows.isEmpty()) {
+ if (!mWindowHandles.isEmpty()) {
dump.append(INDENT "Windows:\n");
- for (size_t i = 0; i < mWindows.size(); i++) {
- const InputWindow& window = mWindows[i];
+ for (size_t i = 0; i < mWindowHandles.size(); i++) {
+ const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
dump.appendFormat(INDENT2 "%d: name='%s', paused=%s, hasFocus=%s, hasWallpaper=%s, "
"visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
"frame=[%d,%d][%d,%d], scale=%f, "
"touchableRegion=",
- i, window.name.string(),
- toString(window.paused),
- toString(window.hasFocus),
- toString(window.hasWallpaper),
- toString(window.visible),
- toString(window.canReceiveKeys),
- window.layoutParamsFlags, window.layoutParamsType,
- window.layer,
- window.frameLeft, window.frameTop,
- window.frameRight, window.frameBottom,
- window.scaleFactor);
- dumpRegion(dump, window.touchableRegion);
- dump.appendFormat(", inputFeatures=0x%08x", window.inputFeatures);
+ i, windowHandle->name.string(),
+ toString(windowHandle->paused),
+ toString(windowHandle->hasFocus),
+ toString(windowHandle->hasWallpaper),
+ toString(windowHandle->visible),
+ toString(windowHandle->canReceiveKeys),
+ windowHandle->layoutParamsFlags, windowHandle->layoutParamsType,
+ windowHandle->layer,
+ windowHandle->frameLeft, windowHandle->frameTop,
+ windowHandle->frameRight, windowHandle->frameBottom,
+ windowHandle->scaleFactor);
+ dumpRegion(dump, windowHandle->touchableRegion);
+ dump.appendFormat(", inputFeatures=0x%08x", windowHandle->inputFeatures);
dump.appendFormat(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
- window.ownerPid, window.ownerUid,
- window.dispatchingTimeout / 1000000.0);
+ windowHandle->ownerPid, windowHandle->ownerUid,
+ windowHandle->dispatchingTimeout / 1000000.0);
}
} else {
dump.append(INDENT "Windows: <none>\n");
@@ -3634,23 +3636,19 @@ void InputDispatcher::onDispatchCycleBrokenLocked(
}
void InputDispatcher::onANRLocked(
- nsecs_t currentTime, const InputApplication* application, const InputWindow* window,
+ nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle,
+ const sp<InputWindowHandle>& windowHandle,
nsecs_t eventTime, nsecs_t waitStartTime) {
LOGI("Application is not responding: %s. "
"%01.1fms since event, %01.1fms since wait started",
- getApplicationWindowLabelLocked(application, window).string(),
+ getApplicationWindowLabelLocked(applicationHandle, windowHandle).string(),
(currentTime - eventTime) / 1000000.0,
(currentTime - waitStartTime) / 1000000.0);
CommandEntry* commandEntry = postCommandLocked(
& InputDispatcher::doNotifyANRLockedInterruptible);
- if (application) {
- commandEntry->inputApplicationHandle = application->inputApplicationHandle;
- }
- if (window) {
- commandEntry->inputWindowHandle = window->inputWindowHandle;
- commandEntry->inputChannel = window->inputChannel;
- }
+ commandEntry->inputApplicationHandle = applicationHandle;
+ commandEntry->inputWindowHandle = windowHandle;
}
void InputDispatcher::doNotifyConfigurationChangedInterruptible(
@@ -3684,7 +3682,9 @@ void InputDispatcher::doNotifyANRLockedInterruptible(
mLock.lock();
- resumeAfterTargetsNotReadyTimeoutLocked(newTimeout, commandEntry->inputChannel);
+ resumeAfterTargetsNotReadyTimeoutLocked(newTimeout,
+ commandEntry->inputWindowHandle != NULL
+ ? commandEntry->inputWindowHandle->inputChannel : NULL);
}
void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
@@ -4561,7 +4561,7 @@ void InputDispatcher::TouchState::copyFrom(const TouchState& other) {
windows = other.windows;
}
-void InputDispatcher::TouchState::addOrUpdateWindow(const InputWindow* window,
+void InputDispatcher::TouchState::addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle,
int32_t targetFlags, BitSet32 pointerIds) {
if (targetFlags & InputTarget::FLAG_SPLIT) {
split = true;
@@ -4569,7 +4569,7 @@ void InputDispatcher::TouchState::addOrUpdateWindow(const InputWindow* window,
for (size_t i = 0; i < windows.size(); i++) {
TouchedWindow& touchedWindow = windows.editItemAt(i);
- if (touchedWindow.window == window) {
+ if (touchedWindow.windowHandle == windowHandle) {
touchedWindow.targetFlags |= targetFlags;
if (targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
touchedWindow.targetFlags &= ~InputTarget::FLAG_DISPATCH_AS_IS;
@@ -4582,10 +4582,9 @@ void InputDispatcher::TouchState::addOrUpdateWindow(const InputWindow* window,
windows.push();
TouchedWindow& touchedWindow = windows.editTop();
- touchedWindow.window = window;
+ touchedWindow.windowHandle = windowHandle;
touchedWindow.targetFlags = targetFlags;
touchedWindow.pointerIds = pointerIds;
- touchedWindow.channel = window->inputChannel;
}
void InputDispatcher::TouchState::filterNonAsIsTouchWindows() {
@@ -4602,11 +4601,11 @@ void InputDispatcher::TouchState::filterNonAsIsTouchWindows() {
}
}
-const InputWindow* InputDispatcher::TouchState::getFirstForegroundWindow() const {
+sp<InputWindowHandle> InputDispatcher::TouchState::getFirstForegroundWindowHandle() const {
for (size_t i = 0; i < windows.size(); i++) {
const TouchedWindow& window = windows.itemAt(i);
if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
- return window.window;
+ return window.windowHandle;
}
}
return NULL;
@@ -4618,8 +4617,8 @@ bool InputDispatcher::TouchState::isSlippery() const {
for (size_t i = 0; i < windows.size(); i++) {
const TouchedWindow& window = windows.itemAt(i);
if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
- if (haveSlipperyForegroundWindow
- || !(window.window->layoutParamsFlags & InputWindow::FLAG_SLIPPERY)) {
+ if (haveSlipperyForegroundWindow || !(window.windowHandle->layoutParamsFlags
+ & InputWindowHandle::FLAG_SLIPPERY)) {
return false;
}
haveSlipperyForegroundWindow = true;
diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h
index bdd1922..15fd274 100644
--- a/services/input/InputDispatcher.h
+++ b/services/input/InputDispatcher.h
@@ -321,13 +321,14 @@ public:
*
* This method may be called on any thread (usually by the input manager).
*/
- virtual void setInputWindows(const Vector<InputWindow>& inputWindows) = 0;
+ virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) = 0;
/* Sets the focused application.
*
* This method may be called on any thread (usually by the input manager).
*/
- virtual void setFocusedApplication(const InputApplication* inputApplication) = 0;
+ virtual void setFocusedApplication(
+ const sp<InputApplicationHandle>& inputApplicationHandle) = 0;
/* Sets the input dispatching mode.
*
@@ -406,8 +407,8 @@ public:
int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
uint32_t policyFlags);
- virtual void setInputWindows(const Vector<InputWindow>& inputWindows);
- virtual void setFocusedApplication(const InputApplication* inputApplication);
+ virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles);
+ virtual void setFocusedApplication(const sp<InputApplicationHandle>& inputApplicationHandle);
virtual void setInputDispatchMode(bool enabled, bool frozen);
virtual void setInputFilterEnabled(bool enabled);
@@ -578,7 +579,6 @@ private:
sp<Connection> connection;
nsecs_t eventTime;
KeyEntry* keyEntry;
- sp<InputChannel> inputChannel;
sp<InputApplicationHandle> inputApplicationHandle;
sp<InputWindowHandle> inputWindowHandle;
int32_t userActivityEventType;
@@ -894,7 +894,7 @@ private:
// to transfer focus to a new application.
EventEntry* mNextUnblockedEvent;
- const InputWindow* findTouchedWindowAtLocked(int32_t x, int32_t y);
+ sp<InputWindowHandle> findTouchedWindowAtLocked(int32_t x, int32_t y);
// All registered connections mapped by receive pipe file descriptor.
KeyedVector<int, sp<Connection> > mConnectionsByReceiveFd;
@@ -953,19 +953,19 @@ private:
bool mDispatchFrozen;
bool mInputFilterEnabled;
- Vector<InputWindow> mWindows;
+ Vector<sp<InputWindowHandle> > mWindowHandles;
- const InputWindow* getWindowLocked(const sp<InputChannel>& inputChannel);
+ sp<InputWindowHandle> getWindowHandleLocked(const sp<InputChannel>& inputChannel) const;
+ bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const;
// Focus tracking for keys, trackball, etc.
- const InputWindow* mFocusedWindow;
+ sp<InputWindowHandle> mFocusedWindowHandle;
// Focus tracking for touch.
struct TouchedWindow {
- const InputWindow* window;
+ sp<InputWindowHandle> windowHandle;
int32_t targetFlags;
BitSet32 pointerIds; // zero unless target flag FLAG_SPLIT is set
- sp<InputChannel> channel;
};
struct TouchState {
bool down;
@@ -978,9 +978,10 @@ private:
~TouchState();
void reset();
void copyFrom(const TouchState& other);
- void addOrUpdateWindow(const InputWindow* window,int32_t targetFlags, BitSet32 pointerIds);
+ void addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle,
+ int32_t targetFlags, BitSet32 pointerIds);
void filterNonAsIsTouchWindows();
- const InputWindow* getFirstForegroundWindow() const;
+ sp<InputWindowHandle> getFirstForegroundWindowHandle() const;
bool isSlippery() const;
};
@@ -988,9 +989,7 @@ private:
TouchState mTempTouchState;
// Focused application.
- InputApplication* mFocusedApplication;
- InputApplication mFocusedApplicationStorage; // preallocated storage for mFocusedApplication
- void releaseFocusedApplicationLocked();
+ sp<InputApplicationHandle> mFocusedApplicationHandle;
// Dispatch inbound events.
bool dispatchConfigurationChangedLocked(
@@ -1021,16 +1020,17 @@ private:
nsecs_t mInputTargetWaitStartTime;
nsecs_t mInputTargetWaitTimeoutTime;
bool mInputTargetWaitTimeoutExpired;
- sp<InputApplicationHandle> mInputTargetWaitApplication;
+ sp<InputApplicationHandle> mInputTargetWaitApplicationHandle;
// Contains the last window which received a hover event.
- const InputWindow* mLastHoverWindow;
+ sp<InputWindowHandle> mLastHoverWindowHandle;
// Finding targets for input events.
void resetTargetsLocked();
void commitTargetsLocked();
int32_t handleTargetsNotReadyLocked(nsecs_t currentTime, const EventEntry* entry,
- const InputApplication* application, const InputWindow* window,
+ const sp<InputApplicationHandle>& applicationHandle,
+ const sp<InputWindowHandle>& windowHandle,
nsecs_t* nextWakeupTime);
void resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
const sp<InputChannel>& inputChannel);
@@ -1043,15 +1043,17 @@ private:
nsecs_t* nextWakeupTime, bool* outConflictingPointerActions,
const MotionSample** outSplitBatchAfterSample);
- void addWindowTargetLocked(const InputWindow* window, int32_t targetFlags,
- BitSet32 pointerIds);
+ void addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
+ int32_t targetFlags, BitSet32 pointerIds);
void addMonitoringTargetsLocked();
void pokeUserActivityLocked(const EventEntry* eventEntry);
- bool checkInjectionPermission(const InputWindow* window, const InjectionState* injectionState);
- bool isWindowObscuredAtPointLocked(const InputWindow* window, int32_t x, int32_t y) const;
- bool isWindowFinishedWithPreviousInputLocked(const InputWindow* window);
- String8 getApplicationWindowLabelLocked(const InputApplication* application,
- const InputWindow* window);
+ bool checkInjectionPermission(const sp<InputWindowHandle>& windowHandle,
+ const InjectionState* injectionState);
+ bool isWindowObscuredAtPointLocked(const sp<InputWindowHandle>& windowHandle,
+ int32_t x, int32_t y) const;
+ bool isWindowFinishedWithPreviousInputLocked(const sp<InputWindowHandle>& windowHandle);
+ String8 getApplicationWindowLabelLocked(const sp<InputApplicationHandle>& applicationHandle,
+ const sp<InputWindowHandle>& windowHandle);
// Manage the dispatch cycle for a single connection.
// These methods are deliberately not Interruptible because doing all of the work
@@ -1100,7 +1102,8 @@ private:
void onDispatchCycleBrokenLocked(
nsecs_t currentTime, const sp<Connection>& connection);
void onANRLocked(
- nsecs_t currentTime, const InputApplication* application, const InputWindow* window,
+ nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle,
+ const sp<InputWindowHandle>& windowHandle,
nsecs_t eventTime, nsecs_t waitStartTime);
// Outbound policy interactions.
diff --git a/services/input/InputWindow.cpp b/services/input/InputWindow.cpp
index b552f6d..0ce8867 100644
--- a/services/input/InputWindow.cpp
+++ b/services/input/InputWindow.cpp
@@ -22,25 +22,25 @@
namespace android {
-// --- InputWindow ---
+// --- InputWindowHandle ---
-bool InputWindow::touchableRegionContainsPoint(int32_t x, int32_t y) const {
+bool InputWindowHandle::touchableRegionContainsPoint(int32_t x, int32_t y) const {
return touchableRegion.contains(x, y);
}
-bool InputWindow::frameContainsPoint(int32_t x, int32_t y) const {
+bool InputWindowHandle::frameContainsPoint(int32_t x, int32_t y) const {
return x >= frameLeft && x <= frameRight
&& y >= frameTop && y <= frameBottom;
}
-bool InputWindow::isTrustedOverlay() const {
+bool InputWindowHandle::isTrustedOverlay() const {
return layoutParamsType == TYPE_INPUT_METHOD
|| layoutParamsType == TYPE_INPUT_METHOD_DIALOG
|| layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY;
}
-bool InputWindow::supportsSplitTouch() const {
- return layoutParamsFlags & InputWindow::FLAG_SPLIT_TOUCH;
+bool InputWindowHandle::supportsSplitTouch() const {
+ return layoutParamsFlags & FLAG_SPLIT_TOUCH;
}
} // namespace android
diff --git a/services/input/InputWindow.h b/services/input/InputWindow.h
index d166ad4..272081c 100644
--- a/services/input/InputWindow.h
+++ b/services/input/InputWindow.h
@@ -31,29 +31,14 @@ namespace android {
/*
* A handle to a window that can receive input.
+ *
* Used by the native input dispatcher to indirectly refer to the window manager objects
* that describe a window.
*/
class InputWindowHandle : public RefBase {
-protected:
- InputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle) :
- mInputApplicationHandle(inputApplicationHandle) { }
- virtual ~InputWindowHandle() { }
-
public:
- inline sp<InputApplicationHandle> getInputApplicationHandle() {
- return mInputApplicationHandle;
- }
-
-private:
- sp<InputApplicationHandle> mInputApplicationHandle;
-};
-
+ const sp<InputApplicationHandle> inputApplicationHandle;
-/*
- * An input window describes the bounds of a window that can receive input.
- */
-struct InputWindow {
// Window flags from WindowManager.LayoutParams
enum {
FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001,
@@ -164,6 +149,22 @@ struct InputWindow {
bool isTrustedOverlay() const;
bool supportsSplitTouch() const;
+
+ /**
+ * Requests that the state of this object be updated to reflect
+ * the most current available information about the application.
+ *
+ * This method should only be called from within the input dispatcher's
+ * critical section.
+ *
+ * Returns true on success, or false if the handle is no longer valid.
+ */
+ virtual bool update() = 0;
+
+protected:
+ InputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle) :
+ inputApplicationHandle(inputApplicationHandle) { }
+ virtual ~InputWindowHandle() { }
};
} // namespace android
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index 67067de..131894a 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -369,11 +369,12 @@ private:
return INPUT_EVENT_INJECTION_FAILED;
}
- virtual void setInputWindows(const Vector<InputWindow>& inputWindows) {
+ virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) {
ADD_FAILURE() << "Should never be called by input reader.";
}
- virtual void setFocusedApplication(const InputApplication* inputApplication) {
+ virtual void setFocusedApplication(
+ const sp<InputApplicationHandle>& inputApplicationHandle) {
ADD_FAILURE() << "Should never be called by input reader.";
}
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/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index 80cdf6b..f99951fa 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1155,9 +1155,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
| AccessibilityNodeInfo.ACTION_CLEAR_SELECTION;
private static final int RETRIEVAL_ALLOWING_EVENT_TYPES =
- AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END
- | AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START
- | AccessibilityEvent.TYPE_VIEW_CLICKED | AccessibilityEvent.TYPE_VIEW_FOCUSED
+ AccessibilityEvent.TYPE_VIEW_CLICKED | AccessibilityEvent.TYPE_VIEW_FOCUSED
| AccessibilityEvent.TYPE_VIEW_HOVER_ENTER | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
| AccessibilityEvent.TYPE_VIEW_LONG_CLICKED | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
| AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED | AccessibilityEvent.TYPE_VIEW_SELECTED
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index 1af7015..dbd9474 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -838,8 +838,6 @@ public class TouchExplorer implements Explorer {
*/
private void sendAccessibilityEvent(int eventType) {
AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
- event.setPackageName(mContext.getPackageName());
- event.setClassName(getClass().getName());
mAccessibilityManager.sendAccessibilityEvent(event);
}
diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java
index d3d9df4..bfa2b39 100644
--- a/services/java/com/android/server/wm/AppWindowToken.java
+++ b/services/java/com/android/server/wm/AppWindowToken.java
@@ -101,7 +101,7 @@ class AppWindowToken extends WindowToken {
boolean firstWindowDrawn;
// Input application handle used by the input dispatcher.
- InputApplicationHandle mInputApplicationHandle;
+ final InputApplicationHandle mInputApplicationHandle;
AppWindowToken(WindowManagerService _service, IApplicationToken _token) {
super(_service, _token.asBinder(),
diff --git a/services/java/com/android/server/wm/InputApplication.java b/services/java/com/android/server/wm/InputApplication.java
deleted file mode 100644
index e04fd31..0000000
--- a/services/java/com/android/server/wm/InputApplication.java
+++ /dev/null
@@ -1,37 +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.
- */
-
-package com.android.server.wm;
-
-
-/**
- * Describes input-related application properties for use by the input dispatcher.
- * @hide
- */
-public final class InputApplication {
- // Application handle.
- public InputApplicationHandle inputApplicationHandle;
-
- // Application name.
- public String name;
-
- // Dispatching timeout.
- public long dispatchingTimeoutNanos;
-
- public void recycle() {
- inputApplicationHandle = null;
- }
-}
diff --git a/services/java/com/android/server/wm/InputApplicationHandle.java b/services/java/com/android/server/wm/InputApplicationHandle.java
index 64c8e7e..d78b1d9 100644
--- a/services/java/com/android/server/wm/InputApplicationHandle.java
+++ b/services/java/com/android/server/wm/InputApplicationHandle.java
@@ -32,6 +32,12 @@ public final class InputApplicationHandle {
// The window manager's application window token.
public final AppWindowToken appWindowToken;
+ // Application name.
+ public String name;
+
+ // Dispatching timeout.
+ public long dispatchingTimeoutNanos;
+
private native void nativeDispose();
public InputApplicationHandle(AppWindowToken appWindowToken) {
diff --git a/services/java/com/android/server/wm/InputManager.java b/services/java/com/android/server/wm/InputManager.java
index 65007f9..3133a19 100644
--- a/services/java/com/android/server/wm/InputManager.java
+++ b/services/java/com/android/server/wm/InputManager.java
@@ -25,7 +25,6 @@ import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.database.ContentObserver;
import android.os.Environment;
-import android.os.Handler;
import android.os.Looper;
import android.os.MessageQueue;
import android.os.SystemProperties;
@@ -83,10 +82,10 @@ public class InputManager {
private static native int nativeInjectInputEvent(InputEvent event,
int injectorPid, int injectorUid, int syncMode, int timeoutMillis,
int policyFlags);
- private static native void nativeSetInputWindows(InputWindow[] windows);
+ private static native void nativeSetInputWindows(InputWindowHandle[] windowHandles);
private static native void nativeSetInputDispatchMode(boolean enabled, boolean frozen);
private static native void nativeSetSystemUiVisibility(int visibility);
- private static native void nativeSetFocusedApplication(InputApplication application);
+ private static native void nativeSetFocusedApplication(InputApplicationHandle application);
private static native InputDevice nativeGetInputDevice(int deviceId);
private static native void nativeGetInputConfiguration(Configuration configuration);
private static native int[] nativeGetInputDeviceIds();
@@ -372,11 +371,11 @@ public class InputManager {
return nativeGetInputDeviceIds();
}
- public void setInputWindows(InputWindow[] windows) {
- nativeSetInputWindows(windows);
+ public void setInputWindows(InputWindowHandle[] windowHandles) {
+ nativeSetInputWindows(windowHandles);
}
- public void setFocusedApplication(InputApplication application) {
+ public void setFocusedApplication(InputApplicationHandle application) {
nativeSetFocusedApplication(application);
}
diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java
index 6806634..08a3560 100644
--- a/services/java/com/android/server/wm/InputMonitor.java
+++ b/services/java/com/android/server/wm/InputMonitor.java
@@ -17,7 +17,6 @@
package com.android.server.wm;
import android.graphics.Rect;
-import android.os.Binder;
import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
@@ -26,6 +25,7 @@ import android.view.KeyEvent;
import android.view.WindowManager;
import java.util.ArrayList;
+import java.util.Arrays;
final class InputMonitor {
private final WindowManagerService mService;
@@ -42,12 +42,14 @@ final class InputMonitor {
// When true, need to call updateInputWindowsLw().
private boolean mUpdateInputWindowsNeeded = true;
- // Temporary list of windows information to provide to the input dispatcher.
- private InputWindowList mTempInputWindows = new InputWindowList();
-
- // Temporary input application object to provide to the input dispatcher.
- private InputApplication mTempInputApplication = new InputApplication();
-
+ // Fake handles for the drag surface, lazily initialized.
+ private InputApplicationHandle mDragApplicationHandle;
+ private InputWindowHandle mDragWindowHandle;
+
+ // Array of window handles to provide to the input dispatcher.
+ private InputWindowHandle[] mInputWindowHandles;
+ private int mInputWindowHandleCount;
+
// Set to true when the first input device configuration change notification
// is received to indicate that the input devices are ready.
private final Object mInputDevicesReadyMonitor = new Object();
@@ -68,8 +70,10 @@ final class InputMonitor {
synchronized (mService.mWindowMap) {
WindowState windowState = (WindowState) inputWindowHandle.windowState;
- Slog.i(WindowManagerService.TAG, "WINDOW DIED " + windowState);
- mService.removeWindowLocked(windowState.mSession, windowState);
+ if (windowState != null) {
+ Slog.i(WindowManagerService.TAG, "WINDOW DIED " + windowState);
+ mService.removeWindowLocked(windowState.mSession, windowState);
+ }
}
}
@@ -94,8 +98,11 @@ final class InputMonitor {
if (appWindowToken == null && inputApplicationHandle != null) {
appWindowToken = inputApplicationHandle.appWindowToken;
- Slog.i(WindowManagerService.TAG, "Input event dispatching timed out sending to application "
- + appWindowToken.stringName);
+ if (appWindowToken != null) {
+ Slog.i(WindowManagerService.TAG,
+ "Input event dispatching timed out sending to application "
+ + appWindowToken.stringName);
+ }
}
if (appWindowToken != null && appWindowToken.appToken != null) {
@@ -114,32 +121,59 @@ final class InputMonitor {
return 0; // abort dispatching
}
- private void addDragInputWindowLw(InputWindowList windowList) {
- final InputWindow inputWindow = windowList.add();
- inputWindow.inputChannel = mService.mDragState.mServerChannel;
- inputWindow.name = "drag";
- inputWindow.layoutParamsFlags = 0;
- inputWindow.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
- inputWindow.dispatchingTimeoutNanos = WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
- inputWindow.visible = true;
- inputWindow.canReceiveKeys = false;
- inputWindow.hasFocus = true;
- inputWindow.hasWallpaper = false;
- inputWindow.paused = false;
- inputWindow.layer = mService.mDragState.getDragLayerLw();
- inputWindow.ownerPid = Process.myPid();
- inputWindow.ownerUid = Process.myUid();
- inputWindow.inputFeatures = 0;
- inputWindow.scaleFactor = 1.0f;
+ private void addDragInputWindowLw() {
+ if (mDragWindowHandle == null) {
+ mDragApplicationHandle = new InputApplicationHandle(null);
+ mDragApplicationHandle.name = "drag";
+ mDragApplicationHandle.dispatchingTimeoutNanos =
+ WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
+
+ mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null);
+ mDragWindowHandle.name = "drag";
+ mDragWindowHandle.layoutParamsFlags = 0;
+ mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
+ mDragWindowHandle.dispatchingTimeoutNanos =
+ WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
+ mDragWindowHandle.visible = true;
+ mDragWindowHandle.canReceiveKeys = false;
+ mDragWindowHandle.hasFocus = true;
+ mDragWindowHandle.hasWallpaper = false;
+ mDragWindowHandle.paused = false;
+ mDragWindowHandle.ownerPid = Process.myPid();
+ mDragWindowHandle.ownerUid = Process.myUid();
+ mDragWindowHandle.inputFeatures = 0;
+ mDragWindowHandle.scaleFactor = 1.0f;
+
+ // The drag window cannot receive new touches.
+ mDragWindowHandle.touchableRegion.setEmpty();
+ }
+
+ mDragWindowHandle.layer = mService.mDragState.getDragLayerLw();
// The drag window covers the entire display
- inputWindow.frameLeft = 0;
- inputWindow.frameTop = 0;
- inputWindow.frameRight = mService.mDisplay.getRealWidth();
- inputWindow.frameBottom = mService.mDisplay.getRealHeight();
+ mDragWindowHandle.frameLeft = 0;
+ mDragWindowHandle.frameTop = 0;
+ mDragWindowHandle.frameRight = mService.mDisplay.getRealWidth();
+ mDragWindowHandle.frameBottom = mService.mDisplay.getRealHeight();
+
+ addInputWindowHandleLw(mDragWindowHandle);
+ }
- // The drag window cannot receive new touches.
- inputWindow.touchableRegion.setEmpty();
+ private void addInputWindowHandleLw(InputWindowHandle windowHandle) {
+ if (mInputWindowHandles == null) {
+ mInputWindowHandles = new InputWindowHandle[16];
+ }
+ if (mInputWindowHandleCount >= mInputWindowHandles.length) {
+ mInputWindowHandles = Arrays.copyOf(mInputWindowHandles,
+ mInputWindowHandleCount * 2);
+ }
+ mInputWindowHandles[mInputWindowHandleCount++] = windowHandle;
+ }
+
+ private void clearInputWindowHandlesLw() {
+ while (mInputWindowHandleCount != 0) {
+ mInputWindowHandles[--mInputWindowHandleCount] = null;
+ }
}
public void setUpdateInputWindowsNeededLw() {
@@ -154,7 +188,7 @@ final class InputMonitor {
mUpdateInputWindowsNeeded = false;
if (false) Slog.d(WindowManagerService.TAG, ">>>>>> ENTERED updateInputWindowsLw");
-
+
// Populate the input window list with information about all of the windows that
// could potentially receive input.
// As an optimization, we could try to prune the list of windows but this turns
@@ -168,7 +202,7 @@ final class InputMonitor {
if (WindowManagerService.DEBUG_DRAG) {
Log.d(WindowManagerService.TAG, "Inserting drag window");
}
- addDragInputWindowLw(mTempInputWindows);
+ addDragInputWindowLw();
}
final int N = windows.size();
@@ -194,48 +228,48 @@ final class InputMonitor {
}
// Add a window to our list of input windows.
- final InputWindow inputWindow = mTempInputWindows.add();
- inputWindow.inputWindowHandle = child.mInputWindowHandle;
- inputWindow.inputChannel = child.mInputChannel;
- inputWindow.name = child.toString();
- inputWindow.layoutParamsFlags = flags;
- inputWindow.layoutParamsType = type;
- inputWindow.dispatchingTimeoutNanos = child.getInputDispatchingTimeoutNanos();
- inputWindow.visible = isVisible;
- inputWindow.canReceiveKeys = child.canReceiveKeys();
- inputWindow.hasFocus = hasFocus;
- inputWindow.hasWallpaper = hasWallpaper;
- inputWindow.paused = child.mAppToken != null ? child.mAppToken.paused : false;
- inputWindow.layer = child.mLayer;
- inputWindow.ownerPid = child.mSession.mPid;
- inputWindow.ownerUid = child.mSession.mUid;
- inputWindow.inputFeatures = child.mAttrs.inputFeatures;
+ final InputWindowHandle inputWindowHandle = child.mInputWindowHandle;
+ inputWindowHandle.inputChannel = child.mInputChannel;
+ inputWindowHandle.name = child.toString();
+ inputWindowHandle.layoutParamsFlags = flags;
+ inputWindowHandle.layoutParamsType = type;
+ inputWindowHandle.dispatchingTimeoutNanos = child.getInputDispatchingTimeoutNanos();
+ inputWindowHandle.visible = isVisible;
+ inputWindowHandle.canReceiveKeys = child.canReceiveKeys();
+ inputWindowHandle.hasFocus = hasFocus;
+ inputWindowHandle.hasWallpaper = hasWallpaper;
+ inputWindowHandle.paused = child.mAppToken != null ? child.mAppToken.paused : false;
+ inputWindowHandle.layer = child.mLayer;
+ inputWindowHandle.ownerPid = child.mSession.mPid;
+ inputWindowHandle.ownerUid = child.mSession.mUid;
+ inputWindowHandle.inputFeatures = child.mAttrs.inputFeatures;
final Rect frame = child.mFrame;
- inputWindow.frameLeft = frame.left;
- inputWindow.frameTop = frame.top;
- inputWindow.frameRight = frame.right;
- inputWindow.frameBottom = frame.bottom;
+ inputWindowHandle.frameLeft = frame.left;
+ inputWindowHandle.frameTop = frame.top;
+ inputWindowHandle.frameRight = frame.right;
+ inputWindowHandle.frameBottom = frame.bottom;
if (child.mGlobalScale != 1) {
// If we are scaling the window, input coordinates need
// to be inversely scaled to map from what is on screen
// to what is actually being touched in the UI.
- inputWindow.scaleFactor = 1.0f/child.mGlobalScale;
+ inputWindowHandle.scaleFactor = 1.0f/child.mGlobalScale;
} else {
- inputWindow.scaleFactor = 1;
+ inputWindowHandle.scaleFactor = 1;
}
- child.getTouchableRegion(inputWindow.touchableRegion);
+ child.getTouchableRegion(inputWindowHandle.touchableRegion);
+
+ addInputWindowHandleLw(inputWindowHandle);
}
// Send windows to native code.
- mService.mInputManager.setInputWindows(mTempInputWindows.toNullTerminatedArray());
-
+ mService.mInputManager.setInputWindows(mInputWindowHandles);
+
// Clear the list in preparation for the next round.
- // Also avoids keeping InputChannel objects referenced unnecessarily.
- mTempInputWindows.clear();
-
+ clearInputWindowHandlesLw();
+
if (false) Slog.d(WindowManagerService.TAG, "<<<<<<< EXITED updateInputWindowsLw");
}
@@ -329,14 +363,11 @@ final class InputMonitor {
if (newApp == null) {
mService.mInputManager.setFocusedApplication(null);
} else {
- mTempInputApplication.inputApplicationHandle = newApp.mInputApplicationHandle;
- mTempInputApplication.name = newApp.toString();
- mTempInputApplication.dispatchingTimeoutNanos =
- newApp.inputDispatchingTimeoutNanos;
-
- mService.mInputManager.setFocusedApplication(mTempInputApplication);
+ final InputApplicationHandle handle = newApp.mInputApplicationHandle;
+ handle.name = newApp.toString();
+ handle.dispatchingTimeoutNanos = newApp.inputDispatchingTimeoutNanos;
- mTempInputApplication.recycle();
+ mService.mInputManager.setFocusedApplication(handle);
}
}
diff --git a/services/java/com/android/server/wm/InputWindow.java b/services/java/com/android/server/wm/InputWindow.java
deleted file mode 100644
index 655d734..0000000
--- a/services/java/com/android/server/wm/InputWindow.java
+++ /dev/null
@@ -1,85 +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.
- */
-
-package com.android.server.wm;
-
-import android.graphics.Region;
-import android.view.InputChannel;
-
-/**
- * Describes input-related window properties for use by the input dispatcher.
- * @hide
- */
-public final class InputWindow {
- // The window handle.
- public InputWindowHandle inputWindowHandle;
-
- // The input channel associated with the window.
- public InputChannel inputChannel;
-
- // The window name.
- public String name;
-
- // Window layout params attributes. (WindowManager.LayoutParams)
- public int layoutParamsFlags;
- public int layoutParamsType;
-
- // Dispatching timeout.
- public long dispatchingTimeoutNanos;
-
- // Window frame.
- public int frameLeft;
- public int frameTop;
- public int frameRight;
- public int frameBottom;
-
- // Global scaling factor applied to touch events when they are dispatched
- // to the window
- public float scaleFactor;
-
- // Window touchable region.
- public final Region touchableRegion = new Region();
-
- // Window is visible.
- public boolean visible;
-
- // Window can receive keys.
- public boolean canReceiveKeys;
-
- // Window has focus.
- public boolean hasFocus;
-
- // Window has wallpaper. (window is the current wallpaper target)
- public boolean hasWallpaper;
-
- // Input event dispatching is paused.
- public boolean paused;
-
- // Window layer.
- public int layer;
-
- // Id of process and user that owns the window.
- public int ownerPid;
- public int ownerUid;
-
- // Window input features.
- public int inputFeatures;
-
- public void recycle() {
- inputWindowHandle = null;
- inputChannel = null;
- }
-}
diff --git a/services/java/com/android/server/wm/InputWindowHandle.java b/services/java/com/android/server/wm/InputWindowHandle.java
index cc508c6..abf68d9 100644
--- a/services/java/com/android/server/wm/InputWindowHandle.java
+++ b/services/java/com/android/server/wm/InputWindowHandle.java
@@ -16,6 +16,8 @@
package com.android.server.wm;
+import android.graphics.Region;
+import android.view.InputChannel;
import android.view.WindowManagerPolicy;
/**
@@ -35,6 +37,57 @@ public final class InputWindowHandle {
// The window manager's window state.
public final WindowManagerPolicy.WindowState windowState;
+ // The input channel associated with the window.
+ public InputChannel inputChannel;
+
+ // The window name.
+ public String name;
+
+ // Window layout params attributes. (WindowManager.LayoutParams)
+ public int layoutParamsFlags;
+ public int layoutParamsType;
+
+ // Dispatching timeout.
+ public long dispatchingTimeoutNanos;
+
+ // Window frame.
+ public int frameLeft;
+ public int frameTop;
+ public int frameRight;
+ public int frameBottom;
+
+ // Global scaling factor applied to touch events when they are dispatched
+ // to the window
+ public float scaleFactor;
+
+ // Window touchable region.
+ public final Region touchableRegion = new Region();
+
+ // Window is visible.
+ public boolean visible;
+
+ // Window can receive keys.
+ public boolean canReceiveKeys;
+
+ // Window has focus.
+ public boolean hasFocus;
+
+ // Window has wallpaper. (window is the current wallpaper target)
+ public boolean hasWallpaper;
+
+ // Input event dispatching is paused.
+ public boolean paused;
+
+ // Window layer.
+ public int layer;
+
+ // Id of process and user that owns the window.
+ public int ownerPid;
+ public int ownerUid;
+
+ // Window input features.
+ public int inputFeatures;
+
private native void nativeDispose();
public InputWindowHandle(InputApplicationHandle inputApplicationHandle,
diff --git a/services/java/com/android/server/wm/InputWindowList.java b/services/java/com/android/server/wm/InputWindowList.java
deleted file mode 100644
index 6077337..0000000
--- a/services/java/com/android/server/wm/InputWindowList.java
+++ /dev/null
@@ -1,89 +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.
- */
-
-package com.android.server.wm;
-
-
-/**
- * A specialized list of window information objects backed by an array.
- *
- * This class is part of an InputManager optimization to avoid allocating objects and arrays
- * unnecessarily. Internally, it keeps an array full of demand-allocated objects that it
- * recycles each time the list is cleared. The used portion of the array is padded with a null.
- *
- * The contents of the list are intended to be Z-ordered from top to bottom.
- *
- * @hide
- */
-public final class InputWindowList {
- private InputWindow[] mArray;
- private int mCount;
-
- /**
- * Creates an empty list.
- */
- public InputWindowList() {
- mArray = new InputWindow[8];
- }
-
- /**
- * Clears the list.
- */
- public void clear() {
- if (mCount == 0) {
- return;
- }
-
- int count = mCount;
- mCount = 0;
- mArray[count] = mArray[0];
- while (count > 0) {
- count -= 1;
- mArray[count].recycle();
- }
- mArray[0] = null;
- }
-
- /**
- * Adds an uninitialized input window object to the list and returns it.
- */
- public InputWindow add() {
- if (mCount + 1 == mArray.length) {
- InputWindow[] oldArray = mArray;
- mArray = new InputWindow[oldArray.length * 2];
- System.arraycopy(oldArray, 0, mArray, 0, mCount);
- }
-
- // Grab object from tail (after used section) if available.
- InputWindow item = mArray[mCount + 1];
- if (item == null) {
- item = new InputWindow();
- }
-
- mArray[mCount] = item;
- mCount += 1;
- mArray[mCount] = null;
- return item;
- }
-
- /**
- * Gets the input window objects as a null-terminated array.
- * @return The input window array.
- */
- public InputWindow[] toNullTerminatedArray() {
- return mArray;
- }
-} \ No newline at end of file
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index b370ec9..d298ff7 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -272,7 +272,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
float mSurfaceAlpha;
// Input channel and input window handle used by the input dispatcher.
- InputWindowHandle mInputWindowHandle;
+ final InputWindowHandle mInputWindowHandle;
InputChannel mInputChannel;
// Used to improve performance of toString()
@@ -306,6 +306,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
mIsFloatingLayer = false;
mBaseLayer = 0;
mSubLayer = 0;
+ mInputWindowHandle = null;
return;
}
mDeathRecipient = deathRecipient;
diff --git a/services/jni/Android.mk b/services/jni/Android.mk
index e1c7305..6fa5dfa 100644
--- a/services/jni/Android.mk
+++ b/services/jni/Android.mk
@@ -4,10 +4,8 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
com_android_server_AlarmManagerService.cpp \
com_android_server_BatteryService.cpp \
- com_android_server_InputApplication.cpp \
com_android_server_InputApplicationHandle.cpp \
com_android_server_InputManager.cpp \
- com_android_server_InputWindow.cpp \
com_android_server_InputWindowHandle.cpp \
com_android_server_LightsService.cpp \
com_android_server_PowerManagerService.cpp \
diff --git a/services/jni/com_android_server_AlarmManagerService.cpp b/services/jni/com_android_server_AlarmManagerService.cpp
index c9a702a..e80dd04 100644
--- a/services/jni/com_android_server_AlarmManagerService.cpp
+++ b/services/jni/com_android_server_AlarmManagerService.cpp
@@ -32,17 +32,13 @@
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
-
-#ifdef HAVE_ANDROID_OS
#include <linux/ioctl.h>
#include <linux/android_alarm.h>
-#endif
namespace android {
static jint android_server_AlarmManagerService_setKernelTimezone(JNIEnv* env, jobject obj, jint fd, jint minswest)
{
-#ifdef HAVE_ANDROID_OS
struct timezone tz;
tz.tz_minuteswest = minswest;
@@ -57,30 +53,20 @@ static jint android_server_AlarmManagerService_setKernelTimezone(JNIEnv* env, jo
}
return 0;
-#else
- return -ENOSYS;
-#endif
}
static jint android_server_AlarmManagerService_init(JNIEnv* env, jobject obj)
{
-#ifdef HAVE_ANDROID_OS
return open("/dev/alarm", O_RDWR);
-#else
- return -1;
-#endif
}
static void android_server_AlarmManagerService_close(JNIEnv* env, jobject obj, jint fd)
{
-#ifdef HAVE_ANDROID_OS
close(fd);
-#endif
}
static void android_server_AlarmManagerService_set(JNIEnv* env, jobject obj, jint fd, jint type, jlong seconds, jlong nanoseconds)
{
-#ifdef HAVE_ANDROID_OS
struct timespec ts;
ts.tv_sec = seconds;
ts.tv_nsec = nanoseconds;
@@ -90,12 +76,10 @@ static void android_server_AlarmManagerService_set(JNIEnv* env, jobject obj, jin
{
LOGE("Unable to set alarm to %lld.%09lld: %s\n", seconds, nanoseconds, strerror(errno));
}
-#endif
}
static jint android_server_AlarmManagerService_waitForAlarm(JNIEnv* env, jobject obj, jint fd)
{
-#ifdef HAVE_ANDROID_OS
int result = 0;
do
@@ -110,7 +94,6 @@ static jint android_server_AlarmManagerService_waitForAlarm(JNIEnv* env, jobject
}
return result;
-#endif
}
static JNINativeMethod sMethods[] = {
diff --git a/services/jni/com_android_server_BatteryService.cpp b/services/jni/com_android_server_BatteryService.cpp
index 98d0d92..b9f2c1f 100644
--- a/services/jni/com_android_server_BatteryService.cpp
+++ b/services/jni/com_android_server_BatteryService.cpp
@@ -32,10 +32,7 @@
#include <errno.h>
#include <unistd.h>
#include <dirent.h>
-
-#ifdef HAVE_ANDROID_OS
#include <linux/ioctl.h>
-#endif
namespace android {
diff --git a/services/jni/com_android_server_InputApplication.cpp b/services/jni/com_android_server_InputApplication.cpp
deleted file mode 100644
index 1f80242..0000000
--- a/services/jni/com_android_server_InputApplication.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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.
- */
-
-#define LOG_TAG "InputApplication"
-
-#include "JNIHelp.h"
-#include "jni.h"
-#include <android_runtime/AndroidRuntime.h>
-
-#include "com_android_server_InputApplication.h"
-#include "com_android_server_InputApplicationHandle.h"
-
-namespace android {
-
-static struct {
- jfieldID inputApplicationHandle;
- jfieldID name;
- jfieldID dispatchingTimeoutNanos;
-} gInputApplicationClassInfo;
-
-
-// --- Global functions ---
-
-void android_server_InputApplication_toNative(
- JNIEnv* env, jobject inputApplicationObj, InputApplication* outInputApplication) {
- jobject inputApplicationHandleObj = env->GetObjectField(inputApplicationObj,
- gInputApplicationClassInfo.inputApplicationHandle);
- if (inputApplicationHandleObj) {
- outInputApplication->inputApplicationHandle =
- android_server_InputApplicationHandle_getHandle(env, inputApplicationHandleObj);
- env->DeleteLocalRef(inputApplicationHandleObj);
- } else {
- outInputApplication->inputApplicationHandle = NULL;
- }
-
- jstring nameObj = jstring(env->GetObjectField(inputApplicationObj,
- gInputApplicationClassInfo.name));
- if (nameObj) {
- const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
- outInputApplication->name.setTo(nameStr);
- env->ReleaseStringUTFChars(nameObj, nameStr);
- env->DeleteLocalRef(nameObj);
- } else {
- LOGE("InputApplication.name should not be null.");
- outInputApplication->name.setTo("unknown");
- }
-
- outInputApplication->dispatchingTimeout = env->GetLongField(inputApplicationObj,
- gInputApplicationClassInfo.dispatchingTimeoutNanos);
-}
-
-
-// --- JNI ---
-
-#define FIND_CLASS(var, className) \
- var = env->FindClass(className); \
- LOG_FATAL_IF(! var, "Unable to find class " className);
-
-#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
- var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
- LOG_FATAL_IF(! var, "Unable to find field " fieldName);
-
-int register_android_server_InputApplication(JNIEnv* env) {
- jclass clazz;
- FIND_CLASS(clazz, "com/android/server/wm/InputApplication");
-
- GET_FIELD_ID(gInputApplicationClassInfo.inputApplicationHandle,
- clazz,
- "inputApplicationHandle", "Lcom/android/server/wm/InputApplicationHandle;");
-
- GET_FIELD_ID(gInputApplicationClassInfo.name, clazz,
- "name", "Ljava/lang/String;");
-
- GET_FIELD_ID(gInputApplicationClassInfo.dispatchingTimeoutNanos,
- clazz,
- "dispatchingTimeoutNanos", "J");
- return 0;
-}
-
-} /* namespace android */
diff --git a/services/jni/com_android_server_InputApplication.h b/services/jni/com_android_server_InputApplication.h
deleted file mode 100644
index 85fb891..0000000
--- a/services/jni/com_android_server_InputApplication.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef _ANDROID_SERVER_INPUT_APPLICATION_H
-#define _ANDROID_SERVER_INPUT_APPLICATION_H
-
-#include <input/InputApplication.h>
-
-#include "JNIHelp.h"
-#include "jni.h"
-
-namespace android {
-
-extern void android_server_InputApplication_toNative(
- JNIEnv* env, jobject inputApplicationObj, InputApplication* outInputApplication);
-
-} // namespace android
-
-#endif // _ANDROID_SERVER_INPUT_APPLICATION_H
diff --git a/services/jni/com_android_server_InputApplicationHandle.cpp b/services/jni/com_android_server_InputApplicationHandle.cpp
index 9516964..7de67d9 100644
--- a/services/jni/com_android_server_InputApplicationHandle.cpp
+++ b/services/jni/com_android_server_InputApplicationHandle.cpp
@@ -27,6 +27,8 @@ namespace android {
static struct {
jfieldID ptr;
+ jfieldID name;
+ jfieldID dispatchingTimeoutNanos;
} gInputApplicationHandleClassInfo;
static Mutex gHandleMutex;
@@ -47,6 +49,31 @@ jobject NativeInputApplicationHandle::getInputApplicationHandleObjLocalRef(JNIEn
return env->NewLocalRef(mObjWeak);
}
+bool NativeInputApplicationHandle::update() {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ jobject obj = env->NewLocalRef(mObjWeak);
+ if (!obj) {
+ return false;
+ }
+
+ jstring nameObj = jstring(env->GetObjectField(obj,
+ gInputApplicationHandleClassInfo.name));
+ if (nameObj) {
+ const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
+ name.setTo(nameStr);
+ env->ReleaseStringUTFChars(nameObj, nameStr);
+ env->DeleteLocalRef(nameObj);
+ } else {
+ name.setTo("<null>");
+ }
+
+ dispatchingTimeout = env->GetLongField(obj,
+ gInputApplicationHandleClassInfo.dispatchingTimeoutNanos);
+
+ env->DeleteLocalRef(obj);
+ return true;
+}
+
// --- Global functions ---
@@ -113,6 +140,13 @@ int register_android_server_InputApplicationHandle(JNIEnv* env) {
GET_FIELD_ID(gInputApplicationHandleClassInfo.ptr, clazz,
"ptr", "I");
+ GET_FIELD_ID(gInputApplicationHandleClassInfo.name, clazz,
+ "name", "Ljava/lang/String;");
+
+ GET_FIELD_ID(gInputApplicationHandleClassInfo.dispatchingTimeoutNanos,
+ clazz,
+ "dispatchingTimeoutNanos", "J");
+
return 0;
}
diff --git a/services/jni/com_android_server_InputApplicationHandle.h b/services/jni/com_android_server_InputApplicationHandle.h
index 9d18721..04cd9d6 100644
--- a/services/jni/com_android_server_InputApplicationHandle.h
+++ b/services/jni/com_android_server_InputApplicationHandle.h
@@ -31,6 +31,8 @@ public:
jobject getInputApplicationHandleObjLocalRef(JNIEnv* env);
+ virtual bool update();
+
private:
jweak mObjWeak;
};
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index 14a4109..de9c9d0 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -46,9 +46,7 @@
#include <android/graphics/GraphicsJNI.h>
#include "com_android_server_PowerManagerService.h"
-#include "com_android_server_InputApplication.h"
#include "com_android_server_InputApplicationHandle.h"
-#include "com_android_server_InputWindow.h"
#include "com_android_server_InputWindowHandle.h"
namespace android {
@@ -175,8 +173,8 @@ public:
const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
- void setInputWindows(JNIEnv* env, jobjectArray windowObjArray);
- void setFocusedApplication(JNIEnv* env, jobject applicationObj);
+ void setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray);
+ void setFocusedApplication(JNIEnv* env, jobject applicationHandleObj);
void setInputDispatchMode(bool enabled, bool frozen);
void setSystemUiVisibility(int32_t visibility);
void setPointerSpeed(int32_t speed);
@@ -582,31 +580,38 @@ bool NativeInputManager::isKeyRepeatEnabled() {
return isScreenOn();
}
-void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowObjArray) {
- Vector<InputWindow> windows;
+void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray) {
+ Vector<sp<InputWindowHandle> > windowHandles;
- bool newPointerGesturesEnabled = true;
- jsize length = env->GetArrayLength(windowObjArray);
- for (jsize i = 0; i < length; i++) {
- jobject windowObj = env->GetObjectArrayElement(windowObjArray, i);
- if (! windowObj) {
- break; // found null element indicating end of used portion of the array
- }
+ if (windowHandleObjArray) {
+ jsize length = env->GetArrayLength(windowHandleObjArray);
+ for (jsize i = 0; i < length; i++) {
+ jobject windowHandleObj = env->GetObjectArrayElement(windowHandleObjArray, i);
+ if (! windowHandleObj) {
+ break; // found null element indicating end of used portion of the array
+ }
- windows.push();
- InputWindow& window = windows.editTop();
- android_server_InputWindow_toNative(env, windowObj, &window);
- if (window.inputChannel == NULL) {
- windows.pop();
- } else if (window.hasFocus) {
- if (window.inputFeatures & InputWindow::INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES) {
- newPointerGesturesEnabled = false;
+ sp<InputWindowHandle> windowHandle =
+ android_server_InputWindowHandle_getHandle(env, windowHandleObj);
+ if (windowHandle != NULL) {
+ windowHandles.push(windowHandle);
}
+ env->DeleteLocalRef(windowHandleObj);
}
- env->DeleteLocalRef(windowObj);
}
- mInputManager->getDispatcher()->setInputWindows(windows);
+ mInputManager->getDispatcher()->setInputWindows(windowHandles);
+
+ // Do this after the dispatcher has updated the window handle state.
+ bool newPointerGesturesEnabled = true;
+ size_t numWindows = windowHandles.size();
+ for (size_t i = 0; i < numWindows; i++) {
+ const sp<InputWindowHandle>& windowHandle = windowHandles.itemAt(i);
+ if (windowHandle->hasFocus && (windowHandle->inputFeatures
+ & InputWindowHandle::INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES)) {
+ newPointerGesturesEnabled = false;
+ }
+ }
uint32_t changes = 0;
{ // acquire lock
@@ -623,16 +628,10 @@ void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowObjArra
}
}
-void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationObj) {
- if (applicationObj) {
- InputApplication application;
- android_server_InputApplication_toNative(env, applicationObj, &application);
- if (application.inputApplicationHandle != NULL) {
- mInputManager->getDispatcher()->setFocusedApplication(&application);
- return;
- }
- }
- mInputManager->getDispatcher()->setFocusedApplication(NULL);
+void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationHandleObj) {
+ sp<InputApplicationHandle> applicationHandle =
+ android_server_InputApplicationHandle_getHandle(env, applicationHandleObj);
+ mInputManager->getDispatcher()->setFocusedApplication(applicationHandle);
}
void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) {
@@ -1137,21 +1136,21 @@ static jint android_server_InputManager_nativeInjectInputEvent(JNIEnv* env, jcla
}
static void android_server_InputManager_nativeSetInputWindows(JNIEnv* env, jclass clazz,
- jobjectArray windowObjArray) {
+ jobjectArray windowHandleObjArray) {
if (checkInputManagerUnitialized(env)) {
return;
}
- gNativeInputManager->setInputWindows(env, windowObjArray);
+ gNativeInputManager->setInputWindows(env, windowHandleObjArray);
}
static void android_server_InputManager_nativeSetFocusedApplication(JNIEnv* env, jclass clazz,
- jobject applicationObj) {
+ jobject applicationHandleObj) {
if (checkInputManagerUnitialized(env)) {
return;
}
- gNativeInputManager->setFocusedApplication(env, applicationObj);
+ gNativeInputManager->setFocusedApplication(env, applicationHandleObj);
}
static void android_server_InputManager_nativeSetInputDispatchMode(JNIEnv* env,
@@ -1313,9 +1312,9 @@ static JNINativeMethod gInputManagerMethods[] = {
(void*) android_server_InputManager_nativeSetInputFilterEnabled },
{ "nativeInjectInputEvent", "(Landroid/view/InputEvent;IIIII)I",
(void*) android_server_InputManager_nativeInjectInputEvent },
- { "nativeSetInputWindows", "([Lcom/android/server/wm/InputWindow;)V",
+ { "nativeSetInputWindows", "([Lcom/android/server/wm/InputWindowHandle;)V",
(void*) android_server_InputManager_nativeSetInputWindows },
- { "nativeSetFocusedApplication", "(Lcom/android/server/wm/InputApplication;)V",
+ { "nativeSetFocusedApplication", "(Lcom/android/server/wm/InputApplicationHandle;)V",
(void*) android_server_InputManager_nativeSetFocusedApplication },
{ "nativeSetInputDispatchMode", "(ZZ)V",
(void*) android_server_InputManager_nativeSetInputDispatchMode },
diff --git a/services/jni/com_android_server_InputWindow.cpp b/services/jni/com_android_server_InputWindow.cpp
deleted file mode 100644
index 0426f63..0000000
--- a/services/jni/com_android_server_InputWindow.cpp
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * 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.
- */
-
-#define LOG_TAG "InputWindow"
-
-#include "JNIHelp.h"
-#include "jni.h"
-#include <android_runtime/AndroidRuntime.h>
-
-#include <android_view_InputChannel.h>
-#include <android/graphics/Region.h>
-#include "com_android_server_InputWindow.h"
-#include "com_android_server_InputWindowHandle.h"
-
-namespace android {
-
-static struct {
- jfieldID inputWindowHandle;
- jfieldID inputChannel;
- jfieldID name;
- jfieldID layoutParamsFlags;
- jfieldID layoutParamsType;
- jfieldID dispatchingTimeoutNanos;
- jfieldID frameLeft;
- jfieldID frameTop;
- jfieldID frameRight;
- jfieldID frameBottom;
- jfieldID scaleFactor;
- jfieldID touchableRegion;
- jfieldID visible;
- jfieldID canReceiveKeys;
- jfieldID hasFocus;
- jfieldID hasWallpaper;
- jfieldID paused;
- jfieldID layer;
- jfieldID ownerPid;
- jfieldID ownerUid;
- jfieldID inputFeatures;
-} gInputWindowClassInfo;
-
-
-// --- Global functions ---
-
-void android_server_InputWindow_toNative(
- JNIEnv* env, jobject inputWindowObj, InputWindow* outInputWindow) {
- jobject inputWindowHandleObj = env->GetObjectField(inputWindowObj,
- gInputWindowClassInfo.inputWindowHandle);
- if (inputWindowHandleObj) {
- outInputWindow->inputWindowHandle =
- android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj);
- env->DeleteLocalRef(inputWindowHandleObj);
- } else {
- outInputWindow->inputWindowHandle = NULL;
- }
-
- jobject inputChannelObj = env->GetObjectField(inputWindowObj,
- gInputWindowClassInfo.inputChannel);
- if (inputChannelObj) {
- outInputWindow->inputChannel =
- android_view_InputChannel_getInputChannel(env, inputChannelObj);
- env->DeleteLocalRef(inputChannelObj);
- } else {
- outInputWindow->inputChannel = NULL;
- }
-
- jstring nameObj = jstring(env->GetObjectField(inputWindowObj,
- gInputWindowClassInfo.name));
- if (nameObj) {
- const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
- outInputWindow->name.setTo(nameStr);
- env->ReleaseStringUTFChars(nameObj, nameStr);
- env->DeleteLocalRef(nameObj);
- } else {
- LOGE("InputWindow.name should not be null.");
- outInputWindow->name.setTo("unknown");
- }
-
- outInputWindow->layoutParamsFlags = env->GetIntField(inputWindowObj,
- gInputWindowClassInfo.layoutParamsFlags);
- outInputWindow->layoutParamsType = env->GetIntField(inputWindowObj,
- gInputWindowClassInfo.layoutParamsType);
- outInputWindow->dispatchingTimeout = env->GetLongField(inputWindowObj,
- gInputWindowClassInfo.dispatchingTimeoutNanos);
- outInputWindow->frameLeft = env->GetIntField(inputWindowObj,
- gInputWindowClassInfo.frameLeft);
- outInputWindow->frameTop = env->GetIntField(inputWindowObj,
- gInputWindowClassInfo.frameTop);
- outInputWindow->frameRight = env->GetIntField(inputWindowObj,
- gInputWindowClassInfo.frameRight);
- outInputWindow->frameBottom = env->GetIntField(inputWindowObj,
- gInputWindowClassInfo.frameBottom);
- outInputWindow->scaleFactor = env->GetFloatField(inputWindowObj,
- gInputWindowClassInfo.scaleFactor);
-
- jobject regionObj = env->GetObjectField(inputWindowObj,
- gInputWindowClassInfo.touchableRegion);
- if (regionObj) {
- SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj);
- outInputWindow->touchableRegion.set(*region);
- env->DeleteLocalRef(regionObj);
- } else {
- outInputWindow->touchableRegion.setEmpty();
- }
-
- outInputWindow->visible = env->GetBooleanField(inputWindowObj,
- gInputWindowClassInfo.visible);
- outInputWindow->canReceiveKeys = env->GetBooleanField(inputWindowObj,
- gInputWindowClassInfo.canReceiveKeys);
- outInputWindow->hasFocus = env->GetBooleanField(inputWindowObj,
- gInputWindowClassInfo.hasFocus);
- outInputWindow->hasWallpaper = env->GetBooleanField(inputWindowObj,
- gInputWindowClassInfo.hasWallpaper);
- outInputWindow->paused = env->GetBooleanField(inputWindowObj,
- gInputWindowClassInfo.paused);
- outInputWindow->layer = env->GetIntField(inputWindowObj,
- gInputWindowClassInfo.layer);
- outInputWindow->ownerPid = env->GetIntField(inputWindowObj,
- gInputWindowClassInfo.ownerPid);
- outInputWindow->ownerUid = env->GetIntField(inputWindowObj,
- gInputWindowClassInfo.ownerUid);
- outInputWindow->inputFeatures = env->GetIntField(inputWindowObj,
- gInputWindowClassInfo.inputFeatures);
-}
-
-
-// --- JNI ---
-
-#define FIND_CLASS(var, className) \
- var = env->FindClass(className); \
- LOG_FATAL_IF(! var, "Unable to find class " className);
-
-#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
- var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
- LOG_FATAL_IF(! var, "Unable to find field " fieldName);
-
-int register_android_server_InputWindow(JNIEnv* env) {
- jclass clazz;
- FIND_CLASS(clazz, "com/android/server/wm/InputWindow");
-
- GET_FIELD_ID(gInputWindowClassInfo.inputWindowHandle, clazz,
- "inputWindowHandle", "Lcom/android/server/wm/InputWindowHandle;");
-
- GET_FIELD_ID(gInputWindowClassInfo.inputChannel, clazz,
- "inputChannel", "Landroid/view/InputChannel;");
-
- GET_FIELD_ID(gInputWindowClassInfo.name, clazz,
- "name", "Ljava/lang/String;");
-
- GET_FIELD_ID(gInputWindowClassInfo.layoutParamsFlags, clazz,
- "layoutParamsFlags", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.layoutParamsType, clazz,
- "layoutParamsType", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.dispatchingTimeoutNanos, clazz,
- "dispatchingTimeoutNanos", "J");
-
- GET_FIELD_ID(gInputWindowClassInfo.frameLeft, clazz,
- "frameLeft", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.frameTop, clazz,
- "frameTop", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.frameRight, clazz,
- "frameRight", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.frameBottom, clazz,
- "frameBottom", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.scaleFactor, clazz,
- "scaleFactor", "F");
-
- GET_FIELD_ID(gInputWindowClassInfo.touchableRegion, clazz,
- "touchableRegion", "Landroid/graphics/Region;");
-
- GET_FIELD_ID(gInputWindowClassInfo.visible, clazz,
- "visible", "Z");
-
- GET_FIELD_ID(gInputWindowClassInfo.canReceiveKeys, clazz,
- "canReceiveKeys", "Z");
-
- GET_FIELD_ID(gInputWindowClassInfo.hasFocus, clazz,
- "hasFocus", "Z");
-
- GET_FIELD_ID(gInputWindowClassInfo.hasWallpaper, clazz,
- "hasWallpaper", "Z");
-
- GET_FIELD_ID(gInputWindowClassInfo.paused, clazz,
- "paused", "Z");
-
- GET_FIELD_ID(gInputWindowClassInfo.layer, clazz,
- "layer", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.ownerPid, clazz,
- "ownerPid", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.ownerUid, clazz,
- "ownerUid", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.inputFeatures, clazz,
- "inputFeatures", "I");
- return 0;
-}
-
-} /* namespace android */
diff --git a/services/jni/com_android_server_InputWindow.h b/services/jni/com_android_server_InputWindow.h
deleted file mode 100644
index eaf7bde..0000000
--- a/services/jni/com_android_server_InputWindow.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef _ANDROID_SERVER_INPUT_WINDOW_H
-#define _ANDROID_SERVER_INPUT_WINDOW_H
-
-#include <input/InputWindow.h>
-
-#include "JNIHelp.h"
-#include "jni.h"
-
-namespace android {
-
-extern void android_server_InputWindow_toNative(
- JNIEnv* env, jobject inputWindowObj, InputWindow* outInputWindow);
-
-} // namespace android
-
-#endif // _ANDROID_SERVER_INPUT_WINDOW_H
diff --git a/services/jni/com_android_server_InputWindowHandle.cpp b/services/jni/com_android_server_InputWindowHandle.cpp
index aaf679c..09be881 100644
--- a/services/jni/com_android_server_InputWindowHandle.cpp
+++ b/services/jni/com_android_server_InputWindowHandle.cpp
@@ -21,6 +21,9 @@
#include <android_runtime/AndroidRuntime.h>
#include <utils/threads.h>
+#include <android_view_InputChannel.h>
+#include <android/graphics/Region.h>
+
#include "com_android_server_InputWindowHandle.h"
#include "com_android_server_InputApplicationHandle.h"
@@ -29,6 +32,26 @@ namespace android {
static struct {
jfieldID ptr;
jfieldID inputApplicationHandle;
+ jfieldID inputChannel;
+ jfieldID name;
+ jfieldID layoutParamsFlags;
+ jfieldID layoutParamsType;
+ jfieldID dispatchingTimeoutNanos;
+ jfieldID frameLeft;
+ jfieldID frameTop;
+ jfieldID frameRight;
+ jfieldID frameBottom;
+ jfieldID scaleFactor;
+ jfieldID touchableRegion;
+ jfieldID visible;
+ jfieldID canReceiveKeys;
+ jfieldID hasFocus;
+ jfieldID hasWallpaper;
+ jfieldID paused;
+ jfieldID layer;
+ jfieldID ownerPid;
+ jfieldID ownerUid;
+ jfieldID inputFeatures;
} gInputWindowHandleClassInfo;
static Mutex gHandleMutex;
@@ -51,6 +74,83 @@ jobject NativeInputWindowHandle::getInputWindowHandleObjLocalRef(JNIEnv* env) {
return env->NewLocalRef(mObjWeak);
}
+bool NativeInputWindowHandle::update() {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ jobject obj = env->NewLocalRef(mObjWeak);
+ if (!obj) {
+ return false;
+ }
+
+ jobject inputChannelObj = env->GetObjectField(obj,
+ gInputWindowHandleClassInfo.inputChannel);
+ if (inputChannelObj) {
+ inputChannel = android_view_InputChannel_getInputChannel(env, inputChannelObj);
+ env->DeleteLocalRef(inputChannelObj);
+ } else {
+ inputChannel = NULL;
+ }
+
+ jstring nameObj = jstring(env->GetObjectField(obj,
+ gInputWindowHandleClassInfo.name));
+ if (nameObj) {
+ const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
+ name.setTo(nameStr);
+ env->ReleaseStringUTFChars(nameObj, nameStr);
+ env->DeleteLocalRef(nameObj);
+ } else {
+ name.setTo("<null>");
+ }
+
+ layoutParamsFlags = env->GetIntField(obj,
+ gInputWindowHandleClassInfo.layoutParamsFlags);
+ layoutParamsType = env->GetIntField(obj,
+ gInputWindowHandleClassInfo.layoutParamsType);
+ dispatchingTimeout = env->GetLongField(obj,
+ gInputWindowHandleClassInfo.dispatchingTimeoutNanos);
+ frameLeft = env->GetIntField(obj,
+ gInputWindowHandleClassInfo.frameLeft);
+ frameTop = env->GetIntField(obj,
+ gInputWindowHandleClassInfo.frameTop);
+ frameRight = env->GetIntField(obj,
+ gInputWindowHandleClassInfo.frameRight);
+ frameBottom = env->GetIntField(obj,
+ gInputWindowHandleClassInfo.frameBottom);
+ scaleFactor = env->GetFloatField(obj,
+ gInputWindowHandleClassInfo.scaleFactor);
+
+ jobject regionObj = env->GetObjectField(obj,
+ gInputWindowHandleClassInfo.touchableRegion);
+ if (regionObj) {
+ SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj);
+ touchableRegion.set(*region);
+ env->DeleteLocalRef(regionObj);
+ } else {
+ touchableRegion.setEmpty();
+ }
+
+ visible = env->GetBooleanField(obj,
+ gInputWindowHandleClassInfo.visible);
+ canReceiveKeys = env->GetBooleanField(obj,
+ gInputWindowHandleClassInfo.canReceiveKeys);
+ hasFocus = env->GetBooleanField(obj,
+ gInputWindowHandleClassInfo.hasFocus);
+ hasWallpaper = env->GetBooleanField(obj,
+ gInputWindowHandleClassInfo.hasWallpaper);
+ paused = env->GetBooleanField(obj,
+ gInputWindowHandleClassInfo.paused);
+ layer = env->GetIntField(obj,
+ gInputWindowHandleClassInfo.layer);
+ ownerPid = env->GetIntField(obj,
+ gInputWindowHandleClassInfo.ownerPid);
+ ownerUid = env->GetIntField(obj,
+ gInputWindowHandleClassInfo.ownerUid);
+ inputFeatures = env->GetIntField(obj,
+ gInputWindowHandleClassInfo.inputFeatures);
+
+ env->DeleteLocalRef(obj);
+ return true;
+}
+
// --- Global functions ---
@@ -127,6 +227,65 @@ int register_android_server_InputWindowHandle(JNIEnv* env) {
clazz,
"inputApplicationHandle", "Lcom/android/server/wm/InputApplicationHandle;");
+ GET_FIELD_ID(gInputWindowHandleClassInfo.inputChannel, clazz,
+ "inputChannel", "Landroid/view/InputChannel;");
+
+ GET_FIELD_ID(gInputWindowHandleClassInfo.name, clazz,
+ "name", "Ljava/lang/String;");
+
+ GET_FIELD_ID(gInputWindowHandleClassInfo.layoutParamsFlags, clazz,
+ "layoutParamsFlags", "I");
+
+ GET_FIELD_ID(gInputWindowHandleClassInfo.layoutParamsType, clazz,
+ "layoutParamsType", "I");
+
+ GET_FIELD_ID(gInputWindowHandleClassInfo.dispatchingTimeoutNanos, clazz,
+ "dispatchingTimeoutNanos", "J");
+
+ GET_FIELD_ID(gInputWindowHandleClassInfo.frameLeft, clazz,
+ "frameLeft", "I");
+
+ GET_FIELD_ID(gInputWindowHandleClassInfo.frameTop, clazz,
+ "frameTop", "I");
+
+ GET_FIELD_ID(gInputWindowHandleClassInfo.frameRight, clazz,
+ "frameRight", "I");
+
+ GET_FIELD_ID(gInputWindowHandleClassInfo.frameBottom, clazz,
+ "frameBottom", "I");
+
+ GET_FIELD_ID(gInputWindowHandleClassInfo.scaleFactor, clazz,
+ "scaleFactor", "F");
+
+ GET_FIELD_ID(gInputWindowHandleClassInfo.touchableRegion, clazz,
+ "touchableRegion", "Landroid/graphics/Region;");
+
+ GET_FIELD_ID(gInputWindowHandleClassInfo.visible, clazz,
+ "visible", "Z");
+
+ GET_FIELD_ID(gInputWindowHandleClassInfo.canReceiveKeys, clazz,
+ "canReceiveKeys", "Z");
+
+ GET_FIELD_ID(gInputWindowHandleClassInfo.hasFocus, clazz,
+ "hasFocus", "Z");
+
+ GET_FIELD_ID(gInputWindowHandleClassInfo.hasWallpaper, clazz,
+ "hasWallpaper", "Z");
+
+ GET_FIELD_ID(gInputWindowHandleClassInfo.paused, clazz,
+ "paused", "Z");
+
+ GET_FIELD_ID(gInputWindowHandleClassInfo.layer, clazz,
+ "layer", "I");
+
+ GET_FIELD_ID(gInputWindowHandleClassInfo.ownerPid, clazz,
+ "ownerPid", "I");
+
+ GET_FIELD_ID(gInputWindowHandleClassInfo.ownerUid, clazz,
+ "ownerUid", "I");
+
+ GET_FIELD_ID(gInputWindowHandleClassInfo.inputFeatures, clazz,
+ "inputFeatures", "I");
return 0;
}
diff --git a/services/jni/com_android_server_InputWindowHandle.h b/services/jni/com_android_server_InputWindowHandle.h
index 43f2a6b..913c3b1 100644
--- a/services/jni/com_android_server_InputWindowHandle.h
+++ b/services/jni/com_android_server_InputWindowHandle.h
@@ -32,6 +32,8 @@ public:
jobject getInputWindowHandleObjLocalRef(JNIEnv* env);
+ virtual bool update();
+
private:
jweak mObjWeak;
};
diff --git a/services/jni/onload.cpp b/services/jni/onload.cpp
index 9dff48b..4178039 100644
--- a/services/jni/onload.cpp
+++ b/services/jni/onload.cpp
@@ -22,9 +22,7 @@
namespace android {
int register_android_server_AlarmManagerService(JNIEnv* env);
int register_android_server_BatteryService(JNIEnv* env);
-int register_android_server_InputApplication(JNIEnv* env);
int register_android_server_InputApplicationHandle(JNIEnv* env);
-int register_android_server_InputWindow(JNIEnv* env);
int register_android_server_InputWindowHandle(JNIEnv* env);
int register_android_server_InputManager(JNIEnv* env);
int register_android_server_LightsService(JNIEnv* env);
@@ -51,9 +49,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
LOG_ASSERT(env, "Could not retrieve the env!");
register_android_server_PowerManagerService(env);
- register_android_server_InputApplication(env);
register_android_server_InputApplicationHandle(env);
- register_android_server_InputWindow(env);
register_android_server_InputWindowHandle(env);
register_android_server_InputManager(env);
register_android_server_LightsService(env);
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;