summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
Diffstat (limited to 'media')
-rw-r--r--media/java/android/media/AudioService.java45
-rw-r--r--media/java/android/media/ExifInterface.java2
-rw-r--r--media/java/android/media/IAudioService.aidl3
-rw-r--r--media/java/android/media/MediaPlayer.java2
-rw-r--r--media/java/android/media/MediaRouter.java65
-rw-r--r--media/java/android/media/RemoteController.java2
-rw-r--r--media/jni/Android.mk4
-rw-r--r--media/jni/android_mtp_MtpDatabase.cpp76
-rw-r--r--media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp4
9 files changed, 131 insertions, 72 deletions
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index b836f50..92474df 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -49,6 +49,8 @@ import android.database.ContentObserver;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.net.Uri;
+import android.net.http.CertificateChainValidator;
+import android.net.http.SslError;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -81,10 +83,12 @@ import com.android.internal.util.XmlUtils;
import org.xmlpull.v1.XmlPullParserException;
+import java.io.ByteArrayInputStream;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Field;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
import java.util.HashMap;
@@ -116,6 +120,8 @@ public class AudioService extends IAudioService.Stub {
protected static final boolean DEBUG_RC = false;
/** Debug volumes */
protected static final boolean DEBUG_VOL = false;
+ /** Debug cert verification */
+ private static final boolean DEBUG_CERTS = false;
/** How long to delay before persisting a change in volume/ringer mode. */
private static final int PERSIST_DELAY = 500;
@@ -1019,7 +1025,7 @@ public class AudioService extends IAudioService.Stub {
(flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
synchronized (mA2dpAvrcpLock) {
if (mA2dp != null && mAvrcpAbsVolSupported) {
- mA2dp.setAvrcpAbsoluteVolume(index);
+ mA2dp.setAvrcpAbsoluteVolume(index / 10);
}
}
}
@@ -4581,6 +4587,43 @@ public class AudioService extends IAudioService.Stub {
}
}
+ public int verifyX509CertChain(int numcerts, byte [] chain, String domain, String authType) {
+
+ if (DEBUG_CERTS) {
+ Log.v(TAG, "java side verify for "
+ + numcerts + " certificates (" + chain.length + " bytes"
+ + ")for "+ domain + "/" + authType);
+ }
+
+ byte[][] certChain = new byte[numcerts][];
+
+ ByteBuffer buf = ByteBuffer.wrap(chain);
+ for (int i = 0; i < numcerts; i++) {
+ int certlen = buf.getInt();
+ if (DEBUG_CERTS) {
+ Log.i(TAG, "cert " + i +": " + certlen);
+ }
+ certChain[i] = new byte[certlen];
+ buf.get(certChain[i]);
+ }
+
+ try {
+ SslError err = CertificateChainValidator.verifyServerCertificates(certChain,
+ domain, authType);
+ if (DEBUG_CERTS) {
+ Log.i(TAG, "verified: " + err);
+ }
+ if (err == null) {
+ return -1;
+ } else {
+ return err.getPrimaryError();
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "failed to verify chain: " + e);
+ }
+ return SslError.SSL_INVALID;
+ }
+
//==========================================================================================
// Camera shutter sound policy.
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 20eb356..9db35fc 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -98,7 +98,7 @@ public class ExifInterface {
private static SimpleDateFormat sFormatter;
static {
- System.loadLibrary("exif_jni");
+ System.loadLibrary("jhead_jni");
sFormatter = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
sFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
}
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 2f08325..b5c3631 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -35,6 +35,8 @@ import android.view.KeyEvent;
*/
interface IAudioService {
+ int verifyX509CertChain(int chainsize, in byte[] chain, String host, String authtype);
+
void adjustVolume(int direction, int flags, String callingPackage);
boolean isLocalOrRemoteMusicActive();
@@ -236,4 +238,5 @@ interface IAudioService {
AudioRoutesInfo startWatchingRoutes(in IAudioRoutesObserver observer);
boolean isCameraSoundForced();
+
}
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index b34cea8..41ba5d6 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -3128,7 +3128,7 @@ public class MediaPlayer implements SubtitleController.Listener
if (refreshTime ||
nanoTime >= mLastNanoTime + MAX_NS_WITHOUT_POSITION_CHECK) {
try {
- mLastTimeUs = mPlayer.getCurrentPosition() * 1000;
+ mLastTimeUs = mPlayer.getCurrentPosition() * 1000L;
mPaused = !mPlayer.isPlaying();
if (DEBUG) Log.v(TAG, (mPaused ? "paused" : "playing") + " at " + mLastTimeUs);
} catch (IllegalStateException e) {
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index d17e8f8..a4d491d8 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -60,9 +60,6 @@ public class MediaRouter {
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
static class Static implements DisplayManager.DisplayListener {
- // Time between wifi display scans when actively scanning in milliseconds.
- private static final int WIFI_DISPLAY_SCAN_INTERVAL = 10000;
-
final Context mAppContext;
final Resources mResources;
final IAudioService mAudioService;
@@ -86,6 +83,7 @@ public class MediaRouter {
final boolean mCanConfigureWifiDisplays;
boolean mActivelyScanningWifiDisplays;
+ String mPreviousActiveWifiDisplayAddress;
int mDiscoveryRequestRouteTypes;
boolean mDiscoverRequestActiveScan;
@@ -105,16 +103,6 @@ public class MediaRouter {
}
};
- final Runnable mScanWifiDisplays = new Runnable() {
- @Override
- public void run() {
- if (mActivelyScanningWifiDisplays) {
- mDisplayService.scanWifiDisplays();
- mHandler.postDelayed(this, WIFI_DISPLAY_SCAN_INTERVAL);
- }
- }
- };
-
Static(Context appContext) {
mAppContext = appContext;
mResources = Resources.getSystem();
@@ -278,15 +266,24 @@ public class MediaRouter {
}
// Update wifi display scanning.
- if (activeScanWifiDisplay && mCanConfigureWifiDisplays) {
- if (!mActivelyScanningWifiDisplays) {
- mActivelyScanningWifiDisplays = true;
- mHandler.post(mScanWifiDisplays);
+ // TODO: All of this should be managed by the media router service.
+ if (mCanConfigureWifiDisplays) {
+ if (mSelectedRoute != null
+ && mSelectedRoute.matchesTypes(ROUTE_TYPE_REMOTE_DISPLAY)) {
+ // Don't scan while already connected to a remote display since
+ // it may interfere with the ongoing transmission.
+ activeScanWifiDisplay = false;
}
- } else {
- if (mActivelyScanningWifiDisplays) {
- mActivelyScanningWifiDisplays = false;
- mHandler.removeCallbacks(mScanWifiDisplays);
+ if (activeScanWifiDisplay) {
+ if (!mActivelyScanningWifiDisplays) {
+ mActivelyScanningWifiDisplays = true;
+ mDisplayService.startWifiDisplayScan();
+ }
+ } else {
+ if (mActivelyScanningWifiDisplays) {
+ mActivelyScanningWifiDisplays = false;
+ mDisplayService.stopWifiDisplayScan();
+ }
}
}
@@ -944,6 +941,9 @@ public class MediaRouter {
}
dispatchRouteSelected(types & route.getSupportedTypes(), route);
}
+
+ // The behavior of active scans may depend on the currently selected route.
+ sStatic.updateDiscoveryRequest();
}
static void selectDefaultRouteStatic() {
@@ -1290,10 +1290,8 @@ public class MediaRouter {
}
static void updateWifiDisplayStatus(WifiDisplayStatus status) {
- boolean wantScan = false;
WifiDisplay[] displays;
WifiDisplay activeDisplay;
-
if (status.getFeatureState() == WifiDisplayStatus.FEATURE_STATE_ON) {
displays = status.getDisplays();
activeDisplay = status.getActiveDisplay();
@@ -1313,6 +1311,8 @@ public class MediaRouter {
displays = WifiDisplay.EMPTY_ARRAY;
activeDisplay = null;
}
+ String activeDisplayAddress = activeDisplay != null ?
+ activeDisplay.getDeviceAddress() : null;
// Add or update routes.
for (int i = 0; i < displays.length; i++) {
@@ -1322,9 +1322,11 @@ public class MediaRouter {
if (route == null) {
route = makeWifiDisplayRoute(d, status);
addRouteStatic(route);
- wantScan = true;
} else {
- updateWifiDisplayRoute(route, d, status);
+ String address = d.getDeviceAddress();
+ boolean disconnected = !address.equals(activeDisplayAddress)
+ && address.equals(sStatic.mPreviousActiveWifiDisplayAddress);
+ updateWifiDisplayRoute(route, d, status, disconnected);
}
if (d.equals(activeDisplay)) {
selectRouteStatic(route.getSupportedTypes(), route, false);
@@ -1343,11 +1345,9 @@ public class MediaRouter {
}
}
- // Don't scan if we're already connected to a wifi display,
- // the scanning process can cause a hiccup with some configurations.
- if (wantScan && activeDisplay != null && sStatic.mCanConfigureWifiDisplays) {
- sStatic.mDisplayService.scanWifiDisplays();
- }
+ // Remember the current active wifi display address so that we can infer disconnections.
+ // TODO: This hack will go away once all of this is moved into the media router service.
+ sStatic.mPreviousActiveWifiDisplayAddress = activeDisplayAddress;
}
private static boolean shouldShowWifiDisplay(WifiDisplay d, WifiDisplay activeDisplay) {
@@ -1405,7 +1405,8 @@ public class MediaRouter {
}
private static void updateWifiDisplayRoute(
- RouteInfo route, WifiDisplay display, WifiDisplayStatus wfdStatus) {
+ RouteInfo route, WifiDisplay display, WifiDisplayStatus wfdStatus,
+ boolean disconnected) {
boolean changed = false;
final String newName = display.getFriendlyDisplayName();
if (!route.getName().equals(newName)) {
@@ -1423,7 +1424,7 @@ public class MediaRouter {
dispatchRouteChanged(route);
}
- if (!enabled && route.isSelected()) {
+ if ((!enabled || disconnected) && route.isSelected()) {
// Oops, no longer available. Reselect the default.
selectDefaultRouteStatic();
}
diff --git a/media/java/android/media/RemoteController.java b/media/java/android/media/RemoteController.java
index 6dbb3cd..910b24c 100644
--- a/media/java/android/media/RemoteController.java
+++ b/media/java/android/media/RemoteController.java
@@ -404,7 +404,7 @@ public final class RemoteController
* @throws IllegalArgumentException
*/
public boolean setSynchronizationMode(int sync) throws IllegalArgumentException {
- if ((sync != POSITION_SYNCHRONIZATION_NONE) || (sync != POSITION_SYNCHRONIZATION_CHECK)) {
+ if ((sync != POSITION_SYNCHRONIZATION_NONE) && (sync != POSITION_SYNCHRONIZATION_CHECK)) {
throw new IllegalArgumentException("Unknown synchronization mode " + sync);
}
if (!mIsRegistered) {
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index 037c626..eb4d0d9 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -41,13 +41,13 @@ LOCAL_SHARED_LIBRARIES := \
libstagefright_amrnb_common \
LOCAL_REQUIRED_MODULES := \
- libexif_jni
+ libjhead_jni
LOCAL_STATIC_LIBRARIES := \
libstagefright_amrnbenc
LOCAL_C_INCLUDES += \
- external/jhead \
+ external/libexif/ \
external/tremor/Tremor \
frameworks/base/core/jni \
frameworks/av/media/libmedia \
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 8129c0d..7df56f4 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -38,7 +38,10 @@
#include "mtp.h"
extern "C" {
-#include "jhead.h"
+#include "libexif/exif-content.h"
+#include "libexif/exif-data.h"
+#include "libexif/exif-tag.h"
+#include "libexif/exif-utils.h"
}
using namespace android;
@@ -751,6 +754,22 @@ MtpResponseCode MyMtpDatabase::getObjectPropertyList(MtpObjectHandle handle,
return result;
}
+static void foreachentry(ExifEntry *entry, void *user) {
+ char buf[1024];
+ ALOGI("entry %x, format %d, size %d: %s",
+ entry->tag, entry->format, entry->size, exif_entry_get_value(entry, buf, sizeof(buf)));
+}
+
+static void foreachcontent(ExifContent *content, void *user) {
+ ALOGI("content %d", exif_content_get_ifd(content));
+ exif_content_foreach_entry(content, foreachentry, user);
+}
+
+static long getLongFromExifEntry(ExifEntry *e) {
+ ExifByteOrder o = exif_data_get_byte_order(e->parent->parent);
+ return exif_get_long(e->data, o);
+}
+
MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle,
MtpObjectInfo& info) {
char date[20];
@@ -793,23 +812,22 @@ MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle,
// read EXIF data for thumbnail information
if (info.mFormat == MTP_FORMAT_EXIF_JPEG || info.mFormat == MTP_FORMAT_JFIF) {
- ResetJpgfile();
- // Start with an empty image information structure.
- memset(&ImageInfo, 0, sizeof(ImageInfo));
- ImageInfo.FlashUsed = -1;
- ImageInfo.MeteringMode = -1;
- ImageInfo.Whitebalance = -1;
- strncpy(ImageInfo.FileName, (const char *)path, PATH_MAX);
- if (ReadJpegFile((const char*)path, READ_METADATA)) {
- Section_t* section = FindSection(M_EXIF);
- if (section) {
- info.mThumbCompressedSize = ImageInfo.ThumbnailSize;
- info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
- info.mImagePixWidth = ImageInfo.Width;
- info.mImagePixHeight = ImageInfo.Height;
- }
+
+ ExifData *exifdata = exif_data_new_from_file(path);
+ if (exifdata) {
+ //exif_data_foreach_content(exifdata, foreachcontent, NULL);
+
+ // XXX get this from exif, or parse jpeg header instead?
+ ExifEntry *w = exif_content_get_entry(
+ exifdata->ifd[EXIF_IFD_EXIF], EXIF_TAG_PIXEL_X_DIMENSION);
+ ExifEntry *h = exif_content_get_entry(
+ exifdata->ifd[EXIF_IFD_EXIF], EXIF_TAG_PIXEL_Y_DIMENSION);
+ info.mThumbCompressedSize = exifdata->data ? exifdata->size : 0;
+ info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
+ info.mImagePixWidth = w ? getLongFromExifEntry(w) : 0;
+ info.mImagePixHeight = h ? getLongFromExifEntry(h) : 0;
+ exif_data_unref(exifdata);
}
- DiscardData();
}
checkAndClearExceptionFromCallback(env, __FUNCTION__);
@@ -825,22 +843,16 @@ void* MyMtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize)
if (getObjectFilePath(handle, path, length, format) == MTP_RESPONSE_OK
&& (format == MTP_FORMAT_EXIF_JPEG || format == MTP_FORMAT_JFIF)) {
- ResetJpgfile();
- // Start with an empty image information structure.
- memset(&ImageInfo, 0, sizeof(ImageInfo));
- ImageInfo.FlashUsed = -1;
- ImageInfo.MeteringMode = -1;
- ImageInfo.Whitebalance = -1;
- strncpy(ImageInfo.FileName, (const char *)path, PATH_MAX);
- if (ReadJpegFile((const char*)path, READ_METADATA)) {
- Section_t* section = FindSection(M_EXIF);
- if (section) {
- outThumbSize = ImageInfo.ThumbnailSize;
- result = malloc(outThumbSize);
- if (result)
- memcpy(result, section->Data + ImageInfo.ThumbnailOffset + 8, outThumbSize);
+
+ ExifData *exifdata = exif_data_new_from_file(path);
+ if (exifdata) {
+ if (exifdata->data) {
+ result = malloc(exifdata->size);
+ if (result) {
+ memcpy(result, exifdata->data, exifdata->size);
+ }
}
- DiscardData();
+ exif_data_unref(exifdata);
}
}
diff --git a/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp b/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp
index 6424744..53f04bc 100644
--- a/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp
+++ b/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp
@@ -30,6 +30,7 @@
#include <media/stagefright/MetaData.h>
#include <media/stagefright/OMXClient.h>
#include <media/stagefright/OMXCodec.h>
+#include <SkImage.h>
#include <SkMallocPixelRef.h>
#include "omx_jpeg_decoder.h"
@@ -184,8 +185,7 @@ void OmxJpegImageDecoder::installPixelRef(MediaBuffer *buffer, sp<MediaSource> d
void OmxJpegImageDecoder::configBitmapSize(SkBitmap* bm, SkBitmap::Config pref,
int width, int height) {
- bm->setConfig(getColorSpaceConfig(pref), width, height);
- bm->setIsOpaque(true);
+ bm->setConfig(getColorSpaceConfig(pref), width, height, 0, kOpaque_SkAlphaType);
}
SkBitmap::Config OmxJpegImageDecoder::getColorSpaceConfig(