diff options
author | Bill Yi <byi@google.com> | 2014-04-29 16:07:29 -0700 |
---|---|---|
committer | Bill Yi <byi@google.com> | 2014-04-29 16:07:29 -0700 |
commit | 293513a59d36cd96a3e474dde5981380d372d8c9 (patch) | |
tree | 4268c9994be194a7f4fccdecd089af58516d0953 /media | |
parent | 1866e5dc8bb04b58a67e54f66cb4ec22e878667d (diff) | |
parent | 0b62467b142b61ee1e449ba958ba37dfd961ef56 (diff) | |
download | frameworks_base-293513a59d36cd96a3e474dde5981380d372d8c9.zip frameworks_base-293513a59d36cd96a3e474dde5981380d372d8c9.tar.gz frameworks_base-293513a59d36cd96a3e474dde5981380d372d8c9.tar.bz2 |
Merge commit '0b62467b142b61ee1e449ba958ba37dfd961ef56' into HEAD
Diffstat (limited to 'media')
-rw-r--r-- | media/java/android/media/AudioService.java | 45 | ||||
-rw-r--r-- | media/java/android/media/ExifInterface.java | 2 | ||||
-rw-r--r-- | media/java/android/media/IAudioService.aidl | 3 | ||||
-rw-r--r-- | media/java/android/media/MediaPlayer.java | 2 | ||||
-rw-r--r-- | media/java/android/media/MediaRouter.java | 65 | ||||
-rw-r--r-- | media/java/android/media/RemoteController.java | 2 | ||||
-rw-r--r-- | media/jni/Android.mk | 4 | ||||
-rw-r--r-- | media/jni/android_mtp_MtpDatabase.cpp | 76 | ||||
-rw-r--r-- | media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp | 4 |
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 63a61e2..dea971e 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( |