Merge "Codec2: C2Block2D rework"
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
index 9506cd1..bf97db9 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
@@ -45,10 +45,12 @@
namespace clearkey {
DrmPlugin::DrmPlugin(SessionLibrary* sessionLibrary)
- : mSessionLibrary(sessionLibrary) {
+ : mSessionLibrary(sessionLibrary),
+ mOpenSessionOkCount(0),
+ mCloseSessionOkCount(0),
+ mCloseSessionNotOpenedCount(0) {
mPlayPolicy.clear();
initProperties();
-
}
void DrmPlugin::initProperties() {
@@ -77,6 +79,7 @@
setSecurityLevel(sessionId, SecurityLevel::SW_SECURE_CRYPTO);
_hidl_cb(Status::OK, toHidlVec(sessionId));
+ mOpenSessionOkCount++;
return Void();
}
@@ -87,9 +90,11 @@
sp<Session> session = mSessionLibrary->findSession(toVector(sessionId));
if (session.get()) {
+ mCloseSessionOkCount++;
mSessionLibrary->destroySession(session);
return Status::OK;
}
+ mCloseSessionNotOpenedCount++;
return Status::ERROR_DRM_SESSION_NOT_OPENED;
}
@@ -364,6 +369,50 @@
return Status::OK;
}
+Return<void> DrmPlugin::getMetrics(getMetrics_cb _hidl_cb) {
+ // Set the open session count metric.
+ DrmMetricGroup::Attribute openSessionOkAttribute = {
+ "status", DrmMetricGroup::ValueType::INT64_TYPE, (int64_t) Status::OK, 0.0, ""
+ };
+ DrmMetricGroup::Value openSessionMetricValue = {
+ "count", DrmMetricGroup::ValueType::INT64_TYPE, mOpenSessionOkCount, 0.0, ""
+ };
+ DrmMetricGroup::Metric openSessionMetric = {
+ "open_session", { openSessionOkAttribute }, { openSessionMetricValue }
+ };
+
+ // Set the close session count metric.
+ DrmMetricGroup::Attribute closeSessionOkAttribute = {
+ "status", DrmMetricGroup::ValueType::INT64_TYPE, (int64_t) Status::OK, 0.0, ""
+ };
+ DrmMetricGroup::Value closeSessionMetricValue = {
+ "count", DrmMetricGroup::ValueType::INT64_TYPE, mCloseSessionOkCount, 0.0, ""
+ };
+ DrmMetricGroup::Metric closeSessionMetric = {
+ "close_session", { closeSessionOkAttribute }, { closeSessionMetricValue }
+ };
+
+ // Set the close session, not opened metric.
+ DrmMetricGroup::Attribute closeSessionNotOpenedAttribute = {
+ "status", DrmMetricGroup::ValueType::INT64_TYPE,
+ (int64_t) Status::ERROR_DRM_SESSION_NOT_OPENED, 0.0, ""
+ };
+ DrmMetricGroup::Value closeSessionNotOpenedMetricValue = {
+ "count", DrmMetricGroup::ValueType::INT64_TYPE, mCloseSessionNotOpenedCount, 0.0, ""
+ };
+ DrmMetricGroup::Metric closeSessionNotOpenedMetric = {
+ "close_session", { closeSessionNotOpenedAttribute }, { closeSessionNotOpenedMetricValue }
+ };
+
+ DrmMetricGroup metrics = { { openSessionMetric, closeSessionMetric,
+ closeSessionNotOpenedMetric } };
+
+ _hidl_cb(Status::OK, hidl_vec<DrmMetricGroup>({metrics}));
+ return Void();
+}
+
+
+
} // namespace clearkey
} // namespace V1_1
} // namespace drm
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
index 5ae9833..64c8262 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
@@ -38,6 +38,7 @@
using ::android::hardware::drm::V1_0::SecureStop;
using ::android::hardware::drm::V1_0::SecureStopId;
using ::android::hardware::drm::V1_0::Status;
+using ::android::hardware::drm::V1_1::DrmMetricGroup;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
@@ -45,6 +46,7 @@
using ::android::hardware::Void;
using ::android::sp;
+
struct DrmPlugin : public IDrmPlugin {
explicit DrmPlugin(SessionLibrary* sessionLibrary);
@@ -163,6 +165,8 @@
Return<Status> setSecurityLevel(const hidl_vec<uint8_t>& sessionId,
SecurityLevel level) override;
+ Return<void> getMetrics(getMetrics_cb _hidl_cb) override;
+
Return<void> getPropertyString(
const hidl_string& name,
getPropertyString_cb _hidl_cb) override;
@@ -302,11 +306,6 @@
return Void();
}
- Return<void> getMetrics(getMetrics_cb _hidl_cb) {
- _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<DrmMetricGroup>());
- return Void();
- }
-
Return<void> getSecureStopIds(getSecureStopIds_cb _hidl_cb) {
_hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<SecureStopId>());
return Void();
@@ -340,6 +339,9 @@
std::map<std::vector<uint8_t>, SecurityLevel> mSecurityLevel;
sp<IDrmPluginListener> mListener;
SessionLibrary *mSessionLibrary;
+ int64_t mOpenSessionOkCount;
+ int64_t mCloseSessionOkCount;
+ int64_t mCloseSessionNotOpenedCount;
CLEARKEY_DISALLOW_COPY_AND_ASSIGN_AND_NEW(DrmPlugin);
};
diff --git a/media/extractors/mpeg2/MPEG2TSExtractor.cpp b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
index 6d0b1cc..a8a366b 100644
--- a/media/extractors/mpeg2/MPEG2TSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
@@ -165,9 +165,9 @@
|| !strcasecmp(MEDIA_MIMETYPE_AUDIO_SCRAMBLED, mime));
}
-status_t MPEG2TSExtractor::setMediaCas(const HInterfaceToken &casToken) {
+status_t MPEG2TSExtractor::setMediaCas(const uint8_t* casToken, size_t size) {
HalToken halToken;
- halToken.setToExternal((uint8_t*)casToken.data(), casToken.size());
+ halToken.setToExternal((uint8_t*)casToken, size);
sp<ICas> cas = ICas::castFrom(retrieveHalInterface(halToken));
ALOGD("setMediaCas: %p", cas.get());
diff --git a/media/extractors/mpeg2/MPEG2TSExtractor.h b/media/extractors/mpeg2/MPEG2TSExtractor.h
index 57cb675..fc15501 100644
--- a/media/extractors/mpeg2/MPEG2TSExtractor.h
+++ b/media/extractors/mpeg2/MPEG2TSExtractor.h
@@ -45,7 +45,7 @@
virtual sp<MetaData> getMetaData();
- virtual status_t setMediaCas(const HInterfaceToken &casToken) override;
+ virtual status_t setMediaCas(const uint8_t* /*casToken*/, size_t /*size*/) override;
virtual uint32_t flags() const;
virtual const char * name() { return "MPEG2TSExtractor"; }
diff --git a/media/libmedia/MediaPlayer2Manager.cpp b/media/libmedia/MediaPlayer2Manager.cpp
index 76b4c0b..4c0a7ac 100644
--- a/media/libmedia/MediaPlayer2Manager.cpp
+++ b/media/libmedia/MediaPlayer2Manager.cpp
@@ -82,7 +82,6 @@
using android::BAD_VALUE;
using android::NOT_ENOUGH_DATA;
using android::Parcel;
-using android::media::VolumeShaper;
// Max number of entries in the filter.
const int kMaxFilterSize = 64; // I pulled that out of thin air.
@@ -503,7 +502,6 @@
mStatus = NO_INIT;
mAudioSessionId = audioSessionId;
mUid = uid;
- mRetransmitEndpointValid = false;
mAudioAttributes = NULL;
#if CALLBACK_ANTAGONIZER
@@ -605,14 +603,6 @@
return status;
}
- // Set the re-transmission endpoint if one was chosen.
- if (mRetransmitEndpointValid) {
- status = p->setRetransmitEndpoint(&mRetransmitEndpoint);
- if (status != NO_ERROR) {
- ALOGE("setRetransmitEndpoint error: %d", status);
- }
- }
-
return status;
}
@@ -927,34 +917,6 @@
return OK;
}
-VolumeShaper::Status MediaPlayer2Manager::Client::applyVolumeShaper(
- const sp<VolumeShaper::Configuration>& configuration,
- const sp<VolumeShaper::Operation>& operation) {
- // for hardware output, call player instead
- ALOGV("Client::applyVolumeShaper(%p)", this);
- sp<MediaPlayer2Interface> p = getPlayer();
- {
- Mutex::Autolock l(mLock);
- if (mAudioOutput.get() != nullptr) {
- return mAudioOutput->applyVolumeShaper(configuration, operation);
- }
- }
- return VolumeShaper::Status(INVALID_OPERATION);
-}
-
-sp<VolumeShaper::State> MediaPlayer2Manager::Client::getVolumeShaperState(int id) {
- // for hardware output, call player instead
- ALOGV("Client::getVolumeShaperState(%p)", this);
- sp<MediaPlayer2Interface> p = getPlayer();
- {
- Mutex::Autolock l(mLock);
- if (mAudioOutput.get() != nullptr) {
- return mAudioOutput->getVolumeShaperState(id);
- }
- }
- return nullptr;
-}
-
status_t MediaPlayer2Manager::Client::seekTo(int msec, MediaPlayer2SeekMode mode)
{
ALOGV("[%d] seekTo(%d, %d)", mConnId, msec, mode);
@@ -966,7 +928,6 @@
status_t MediaPlayer2Manager::Client::reset()
{
ALOGV("[%d] reset", mConnId);
- mRetransmitEndpointValid = false;
sp<MediaPlayer2Interface> p = getPlayer();
if (p == 0) return UNKNOWN_ERROR;
return p->reset();
@@ -1069,53 +1030,6 @@
return p->getParameter(key, reply);
}
-status_t MediaPlayer2Manager::Client::setRetransmitEndpoint(
- const struct sockaddr_in* endpoint) {
-
- if (NULL != endpoint) {
- uint32_t a = ntohl(endpoint->sin_addr.s_addr);
- uint16_t p = ntohs(endpoint->sin_port);
- ALOGV("[%d] setRetransmitEndpoint(%u.%u.%u.%u:%hu)", mConnId,
- (a >> 24), (a >> 16) & 0xFF, (a >> 8) & 0xFF, (a & 0xFF), p);
- } else {
- ALOGV("[%d] setRetransmitEndpoint = <none>", mConnId);
- }
-
- // Right now, the only valid time to set a retransmit endpoint is before
- // setDataSource.
-
- if (NULL != endpoint) {
- Mutex::Autolock lock(mLock);
- mRetransmitEndpoint = *endpoint;
- mRetransmitEndpointValid = true;
- } else {
- Mutex::Autolock lock(mLock);
- mRetransmitEndpointValid = false;
- }
-
- return NO_ERROR;
-}
-
-status_t MediaPlayer2Manager::Client::getRetransmitEndpoint(
- struct sockaddr_in* endpoint)
-{
- if (NULL == endpoint)
- return BAD_VALUE;
-
- sp<MediaPlayer2Interface> p = getPlayer();
-
- if (p != NULL)
- return p->getRetransmitEndpoint(endpoint);
-
- Mutex::Autolock lock(mLock);
- if (!mRetransmitEndpointValid)
- return NO_INIT;
-
- *endpoint = mRetransmitEndpoint;
-
- return NO_ERROR;
-}
-
void MediaPlayer2Manager::Client::notify(
const wp<MediaPlayer2Engine> &listener, int msg, int ext1, int ext2, const Parcel *obj)
{
@@ -1319,7 +1233,6 @@
mSendLevel(0.0),
mAuxEffectId(0),
mFlags(AUDIO_OUTPUT_FLAG_NONE),
- mVolumeHandler(new media::VolumeHandler()),
mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
mRoutedDeviceId(AUDIO_PORT_HANDLE_NONE),
mDeviceCallbackEnabled(false),
@@ -1790,24 +1703,6 @@
ALOGV("setVolume");
t->setVolume(mLeftVolume, mRightVolume);
- // Restore VolumeShapers for the MediaPlayer2 in case the track was recreated
- // due to an output sink error (e.g. offload to non-offload switch).
- mVolumeHandler->forall([&t](const VolumeShaper &shaper) -> VolumeShaper::Status {
- sp<VolumeShaper::Operation> operationToEnd =
- new VolumeShaper::Operation(shaper.mOperation);
- // TODO: Ideally we would restore to the exact xOffset position
- // as returned by getVolumeShaperState(), but we don't have that
- // information when restoring at the client unless we periodically poll
- // the server or create shared memory state.
- //
- // For now, we simply advance to the end of the VolumeShaper effect
- // if it has been started.
- if (shaper.isStarted()) {
- operationToEnd->setNormalizedTime(1.f);
- }
- return t->applyVolumeShaper(shaper.mConfiguration, operationToEnd);
- });
-
mSampleRateHz = sampleRate;
mFlags = flags;
mMsecsPerFrame = 1E3f / (mPlaybackRate.mSpeed * sampleRate);
@@ -1852,9 +1747,6 @@
mTrack->setVolume(mLeftVolume, mRightVolume);
mTrack->setAuxEffectSendLevel(mSendLevel);
status_t status = mTrack->start();
- if (status == NO_ERROR) {
- mVolumeHandler->setStarted();
- }
return status;
}
return NO_INIT;
@@ -2091,67 +1983,6 @@
return NO_ERROR;
}
-VolumeShaper::Status MediaPlayer2Manager::AudioOutput::applyVolumeShaper(
- const sp<VolumeShaper::Configuration>& configuration,
- const sp<VolumeShaper::Operation>& operation)
-{
- Mutex::Autolock lock(mLock);
- ALOGV("AudioOutput::applyVolumeShaper");
-
- mVolumeHandler->setIdIfNecessary(configuration);
-
- VolumeShaper::Status status;
- if (mTrack != 0) {
- status = mTrack->applyVolumeShaper(configuration, operation);
- if (status >= 0) {
- (void)mVolumeHandler->applyVolumeShaper(configuration, operation);
- if (mTrack->isPlaying()) { // match local AudioTrack to properly restore.
- mVolumeHandler->setStarted();
- }
- }
- } else {
- // VolumeShapers are not affected when a track moves between players for
- // gapless playback (setNextMediaPlayer).
- // We forward VolumeShaper operations that do not change configuration
- // to the new player so that unducking may occur as expected.
- // Unducking is an idempotent operation, same if applied back-to-back.
- if (configuration->getType() == VolumeShaper::Configuration::TYPE_ID
- && mNextOutput != nullptr) {
- ALOGV("applyVolumeShaper: Attempting to forward missed operation: %s %s",
- configuration->toString().c_str(), operation->toString().c_str());
- Mutex::Autolock nextLock(mNextOutput->mLock);
-
- // recycled track should be forwarded from this AudioSink by switchToNextOutput
- sp<AudioTrack> track = mNextOutput->mRecycledTrack;
- if (track != nullptr) {
- ALOGD("Forward VolumeShaper operation to recycled track %p", track.get());
- (void)track->applyVolumeShaper(configuration, operation);
- } else {
- // There is a small chance that the unduck occurs after the next
- // player has already started, but before it is registered to receive
- // the unduck command.
- track = mNextOutput->mTrack;
- if (track != nullptr) {
- ALOGD("Forward VolumeShaper operation to track %p", track.get());
- (void)track->applyVolumeShaper(configuration, operation);
- }
- }
- }
- status = mVolumeHandler->applyVolumeShaper(configuration, operation);
- }
- return status;
-}
-
-sp<VolumeShaper::State> MediaPlayer2Manager::AudioOutput::getVolumeShaperState(int id)
-{
- Mutex::Autolock lock(mLock);
- if (mTrack != 0) {
- return mTrack->getVolumeShaperState(id);
- } else {
- return mVolumeHandler->getVolumeShaperState(id);
- }
-}
-
// static
void MediaPlayer2Manager::AudioOutput::CallbackWrapper(
int event, void *cookie, void *info) {
diff --git a/media/libmedia/MediaPlayer2Manager.h b/media/libmedia/MediaPlayer2Manager.h
index cdbbc70..95b875b 100644
--- a/media/libmedia/MediaPlayer2Manager.h
+++ b/media/libmedia/MediaPlayer2Manager.h
@@ -132,11 +132,6 @@
virtual status_t setParameters(const String8& keyValuePairs);
virtual String8 getParameters(const String8& keys);
- virtual media::VolumeShaper::Status applyVolumeShaper(
- const sp<media::VolumeShaper::Configuration>& configuration,
- const sp<media::VolumeShaper::Operation>& operation) override;
- virtual sp<media::VolumeShaper::State> getVolumeShaperState(int id) override;
-
// AudioRouting
virtual status_t setOutputDevice(audio_port_handle_t deviceId);
virtual status_t getRoutedDeviceId(audio_port_handle_t* deviceId);
@@ -170,7 +165,6 @@
float mSendLevel;
int mAuxEffectId;
audio_output_flags_t mFlags;
- sp<media::VolumeHandler> mVolumeHandler;
audio_port_handle_t mSelectedDeviceId;
audio_port_handle_t mRoutedDeviceId;
bool mDeviceCallbackEnabled;
@@ -278,15 +272,8 @@
virtual status_t attachAuxEffect(int effectId);
virtual status_t setParameter(int key, const Parcel &request);
virtual status_t getParameter(int key, Parcel *reply);
- virtual status_t setRetransmitEndpoint(const struct sockaddr_in* endpoint);
- virtual status_t getRetransmitEndpoint(struct sockaddr_in* endpoint);
virtual status_t setNextPlayer(const sp<MediaPlayer2Engine>& player);
- virtual media::VolumeShaper::Status applyVolumeShaper(
- const sp<media::VolumeShaper::Configuration>& configuration,
- const sp<media::VolumeShaper::Operation>& operation) override;
- virtual sp<media::VolumeShaper::State> getVolumeShaperState(int id) override;
-
virtual status_t setDataSource(const sp<DataSourceDesc> &dsd);
static void notify(const wp<MediaPlayer2Engine> &listener, int msg,
@@ -363,8 +350,6 @@
audio_attributes_t * mAudioAttributes;
uid_t mUid;
sp<ANativeWindowWrapper> mConnectedWindow;
- struct sockaddr_in mRetransmitEndpoint;
- bool mRetransmitEndpointValid;
sp<Client> mNextClient;
// Metadata filters.
diff --git a/media/libmedia/include/media/MediaPlayer2Engine.h b/media/libmedia/include/media/MediaPlayer2Engine.h
index 29df2d6..2d1a24b 100644
--- a/media/libmedia/include/media/MediaPlayer2Engine.h
+++ b/media/libmedia/include/media/MediaPlayer2Engine.h
@@ -23,7 +23,6 @@
#include <system/audio.h>
#include <media/MediaSource.h>
-#include <media/VolumeShaper.h>
// Fwd decl to make sure everyone agrees that the scope of struct sockaddr_in is
// global, and not in android::
@@ -77,15 +76,8 @@
virtual status_t attachAuxEffect(int effectId) = 0;
virtual status_t setParameter(int key, const Parcel& request) = 0;
virtual status_t getParameter(int key, Parcel* reply) = 0;
- virtual status_t setRetransmitEndpoint(const struct sockaddr_in* endpoint) = 0;
- virtual status_t getRetransmitEndpoint(struct sockaddr_in* endpoint) = 0;
virtual status_t setNextPlayer(const sp<MediaPlayer2Engine>& next) = 0;
- virtual media::VolumeShaper::Status applyVolumeShaper(
- const sp<media::VolumeShaper::Configuration>& configuration,
- const sp<media::VolumeShaper::Operation>& operation) = 0;
- virtual sp<media::VolumeShaper::State> getVolumeShaperState(int id) = 0;
-
// Modular DRM
virtual status_t prepareDrm(const uint8_t uuid[16],
const Vector<uint8_t>& drmSessionId) = 0;
diff --git a/media/libmedia/include/media/MediaPlayer2Interface.h b/media/libmedia/include/media/MediaPlayer2Interface.h
index c2cc6e6..be300bb 100644
--- a/media/libmedia/include/media/MediaPlayer2Interface.h
+++ b/media/libmedia/include/media/MediaPlayer2Interface.h
@@ -138,11 +138,6 @@
virtual status_t setParameters(const String8& /* keyValuePairs */) { return NO_ERROR; }
virtual String8 getParameters(const String8& /* keys */) { return String8::empty(); }
- virtual media::VolumeShaper::Status applyVolumeShaper(
- const sp<media::VolumeShaper::Configuration>& configuration,
- const sp<media::VolumeShaper::Operation>& operation);
- virtual sp<media::VolumeShaper::State> getVolumeShaperState(int id);
-
// AudioRouting
virtual status_t setOutputDevice(audio_port_handle_t deviceId);
virtual status_t getRoutedDeviceId(audio_port_handle_t* deviceId);
@@ -218,13 +213,6 @@
virtual status_t setParameter(int key, const Parcel &request) = 0;
virtual status_t getParameter(int key, Parcel *reply) = 0;
- // default no-op implementation of optional extensions
- virtual status_t setRetransmitEndpoint(const struct sockaddr_in* /* endpoint */) {
- return INVALID_OPERATION;
- }
- virtual status_t getRetransmitEndpoint(struct sockaddr_in* /* endpoint */) {
- return INVALID_OPERATION;
- }
virtual status_t setNextPlayer(const sp<MediaPlayer2Interface>& /* next */) {
return OK;
}
diff --git a/media/libmedia/include/media/mediaplayer2.h b/media/libmedia/include/media/mediaplayer2.h
index f2fc901..c8b124c 100644
--- a/media/libmedia/include/media/mediaplayer2.h
+++ b/media/libmedia/include/media/mediaplayer2.h
@@ -244,13 +244,8 @@
status_t attachAuxEffect(int effectId);
status_t setParameter(int key, const Parcel& request);
status_t getParameter(int key, Parcel* reply);
- status_t setRetransmitEndpoint(const char* addrString, uint16_t port);
status_t setNextMediaPlayer(const sp<MediaPlayer2>& player);
- media::VolumeShaper::Status applyVolumeShaper(
- const sp<media::VolumeShaper::Configuration>& configuration,
- const sp<media::VolumeShaper::Operation>& operation);
- sp<media::VolumeShaper::State> getVolumeShaperState(int id);
// Modular DRM
status_t prepareDrm(const uint8_t uuid[16], const Vector<uint8_t>& drmSessionId);
status_t releaseDrm();
@@ -266,7 +261,6 @@
status_t getDuration_l(int *msec);
status_t attachNewPlayer(const sp<MediaPlayer2Engine>& player);
status_t reset_l();
- status_t doSetRetransmitEndpoint(const sp<MediaPlayer2Engine>& player);
status_t checkStateForKeySet_l(int key);
sp<MediaPlayer2Engine> mPlayer;
@@ -292,8 +286,6 @@
int mVideoHeight;
audio_session_t mAudioSessionId;
float mSendLevel;
- struct sockaddr_in mRetransmitEndpoint;
- bool mRetransmitEndpointValid;
};
}; // namespace android
diff --git a/media/libmedia/mediaplayer2.cpp b/media/libmedia/mediaplayer2.cpp
index ba24da7..1eb3795 100644
--- a/media/libmedia/mediaplayer2.cpp
+++ b/media/libmedia/mediaplayer2.cpp
@@ -50,8 +50,6 @@
namespace android {
-using media::VolumeShaper;
-
MediaPlayer2::MediaPlayer2()
{
ALOGV("constructor");
@@ -73,7 +71,6 @@
mAudioSessionId = (audio_session_t) AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
AudioSystem::acquireAudioSessionId(mAudioSessionId, -1);
mSendLevel = 0;
- mRetransmitEndpointValid = false;
}
MediaPlayer2::~MediaPlayer2()
@@ -111,7 +108,6 @@
mSeekPosition = -1;
mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
mVideoWidth = mVideoHeight = 0;
- mRetransmitEndpointValid = false;
}
status_t MediaPlayer2::setListener(const sp<MediaPlayer2Listener>& listener)
@@ -162,8 +158,7 @@
ALOGV("setDataSource type(%d)", dsd->mType);
status_t err = UNKNOWN_ERROR;
sp<MediaPlayer2Engine> player(MediaPlayer2Manager::get().create(this, mAudioSessionId));
- if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
- (NO_ERROR != player->setDataSource(dsd))) {
+ if (NO_ERROR != player->setDataSource(dsd)) {
player.clear();
}
err = attachNewPlayer(player);
@@ -589,20 +584,6 @@
return NO_ERROR;
}
-status_t MediaPlayer2::doSetRetransmitEndpoint(const sp<MediaPlayer2Engine>& player) {
- Mutex::Autolock _l(mLock);
-
- if (player == NULL) {
- return UNKNOWN_ERROR;
- }
-
- if (mRetransmitEndpointValid) {
- return player->setRetransmitEndpoint(&mRetransmitEndpoint);
- }
-
- return OK;
-}
-
status_t MediaPlayer2::reset()
{
ALOGV("reset");
@@ -782,34 +763,6 @@
return INVALID_OPERATION;
}
-status_t MediaPlayer2::setRetransmitEndpoint(const char* addrString,
- uint16_t port) {
- ALOGV("MediaPlayer2::setRetransmitEndpoint(%s:%hu)",
- addrString ? addrString : "(null)", port);
-
- Mutex::Autolock _l(mLock);
- if ((mPlayer != NULL) || (mCurrentState != MEDIA_PLAYER2_IDLE))
- return INVALID_OPERATION;
-
- if (NULL == addrString) {
- mRetransmitEndpointValid = false;
- return OK;
- }
-
- struct in_addr saddr;
- if(!inet_aton(addrString, &saddr)) {
- return BAD_VALUE;
- }
-
- memset(&mRetransmitEndpoint, 0, sizeof(mRetransmitEndpoint));
- mRetransmitEndpoint.sin_family = AF_INET;
- mRetransmitEndpoint.sin_addr = saddr;
- mRetransmitEndpoint.sin_port = htons(port);
- mRetransmitEndpointValid = true;
-
- return OK;
-}
-
void MediaPlayer2::notify(int msg, int ext1, int ext2, const Parcel *obj)
{
ALOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
@@ -949,27 +902,6 @@
return mPlayer->setNextPlayer(next == NULL ? NULL : next->mPlayer);
}
-VolumeShaper::Status MediaPlayer2::applyVolumeShaper(
- const sp<VolumeShaper::Configuration>& configuration,
- const sp<VolumeShaper::Operation>& operation)
-{
- Mutex::Autolock _l(mLock);
- if (mPlayer == nullptr) {
- return VolumeShaper::Status(NO_INIT);
- }
- VolumeShaper::Status status = mPlayer->applyVolumeShaper(configuration, operation);
- return status;
-}
-
-sp<VolumeShaper::State> MediaPlayer2::getVolumeShaperState(int id)
-{
- Mutex::Autolock _l(mLock);
- if (mPlayer == nullptr) {
- return nullptr;
- }
- return mPlayer->getVolumeShaperState(id);
-}
-
// Modular DRM
status_t MediaPlayer2::prepareDrm(const uint8_t uuid[16], const Vector<uint8_t>& drmSessionId)
{
diff --git a/media/libmedia/nuplayer2/Android.bp b/media/libmedia/nuplayer2/Android.bp
index 700c840..1f4455f 100644
--- a/media/libmedia/nuplayer2/Android.bp
+++ b/media/libmedia/nuplayer2/Android.bp
@@ -2,8 +2,8 @@
srcs: [
"JWakeLock.cpp",
- "GenericSource.cpp",
- "HTTPLiveSource.cpp",
+ "GenericSource2.cpp",
+ "HTTPLiveSource2.cpp",
"NuPlayer2.cpp",
"NuPlayer2CCDecoder.cpp",
"NuPlayer2Decoder.cpp",
@@ -12,9 +12,7 @@
"NuPlayer2Driver.cpp",
"NuPlayer2Drm.cpp",
"NuPlayer2Renderer.cpp",
- "NuPlayer2StreamListener.cpp",
- "RTSPSource.cpp",
- "StreamingSource.cpp",
+ "RTSPSource2.cpp",
],
header_libs: [
diff --git a/media/libmedia/nuplayer2/GenericSource.cpp b/media/libmedia/nuplayer2/GenericSource2.cpp
similarity index 93%
rename from media/libmedia/nuplayer2/GenericSource.cpp
rename to media/libmedia/nuplayer2/GenericSource2.cpp
index 6907216..0351a76 100644
--- a/media/libmedia/nuplayer2/GenericSource.cpp
+++ b/media/libmedia/nuplayer2/GenericSource2.cpp
@@ -15,9 +15,9 @@
*/
//#define LOG_NDEBUG 0
-#define LOG_TAG "GenericSource"
+#define LOG_TAG "GenericSource2"
-#include "GenericSource.h"
+#include "GenericSource2.h"
#include "NuPlayer2Drm.h"
#include "AnotherPacketSource.h"
@@ -52,7 +52,7 @@
//static const int kPausePlaybackMarkMs = 2000; // 2secs
static const int kResumePlaybackMarkMs = 15000; // 15secs
-NuPlayer2::GenericSource::GenericSource(
+NuPlayer2::GenericSource2::GenericSource2(
const sp<AMessage> ¬ify,
bool uidValid,
uid_t uid,
@@ -79,7 +79,7 @@
mFd(-1),
mBitrate(-1ll),
mPendingReadBufferTypes(0) {
- ALOGV("GenericSource");
+ ALOGV("GenericSource2");
CHECK(mediaClock != NULL);
mBufferingSettings.mInitialMarkMs = kInitialMarkMs;
@@ -87,7 +87,7 @@
resetDataSource();
}
-void NuPlayer2::GenericSource::resetDataSource() {
+void NuPlayer2::GenericSource2::resetDataSource() {
ALOGV("resetDataSource");
mHTTPService.clear();
@@ -110,7 +110,7 @@
mMimes.clear();
}
-status_t NuPlayer2::GenericSource::setDataSource(
+status_t NuPlayer2::GenericSource2::setDataSource(
const sp<MediaHTTPService> &httpService,
const char *url,
const KeyedVector<String8, String8> *headers) {
@@ -131,7 +131,7 @@
return OK;
}
-status_t NuPlayer2::GenericSource::setDataSource(
+status_t NuPlayer2::GenericSource2::setDataSource(
int fd, int64_t offset, int64_t length) {
Mutex::Autolock _l(mLock);
ALOGV("setDataSource %d/%lld/%lld", fd, (long long)offset, (long long)length);
@@ -147,7 +147,7 @@
return OK;
}
-status_t NuPlayer2::GenericSource::setDataSource(const sp<DataSource>& source) {
+status_t NuPlayer2::GenericSource2::setDataSource(const sp<DataSource>& source) {
Mutex::Autolock _l(mLock);
ALOGV("setDataSource (source: %p)", source.get());
@@ -156,12 +156,12 @@
return OK;
}
-sp<MetaData> NuPlayer2::GenericSource::getFileFormatMeta() const {
+sp<MetaData> NuPlayer2::GenericSource2::getFileFormatMeta() const {
Mutex::Autolock _l(mLock);
return mFileMeta;
}
-status_t NuPlayer2::GenericSource::initFromDataSource() {
+status_t NuPlayer2::GenericSource2::initFromDataSource() {
sp<IMediaExtractor> extractor;
CHECK(mDataSource != NULL || mFd != -1);
sp<DataSource> dataSource = mDataSource;
@@ -294,7 +294,7 @@
return OK;
}
-status_t NuPlayer2::GenericSource::getBufferingSettings(
+status_t NuPlayer2::GenericSource2::getBufferingSettings(
BufferingSettings* buffering /* nonnull */) {
{
Mutex::Autolock _l(mLock);
@@ -305,7 +305,7 @@
return OK;
}
-status_t NuPlayer2::GenericSource::setBufferingSettings(const BufferingSettings& buffering) {
+status_t NuPlayer2::GenericSource2::setBufferingSettings(const BufferingSettings& buffering) {
ALOGV("setBufferingSettings{%s}", buffering.toString().string());
Mutex::Autolock _l(mLock);
@@ -313,7 +313,7 @@
return OK;
}
-status_t NuPlayer2::GenericSource::startSources() {
+status_t NuPlayer2::GenericSource2::startSources() {
// Start the selected A/V tracks now before we start buffering.
// Widevine sources might re-initialize crypto when starting, if we delay
// this to start(), all data buffered during prepare would be wasted.
@@ -334,7 +334,7 @@
return OK;
}
-int64_t NuPlayer2::GenericSource::getLastReadPosition() {
+int64_t NuPlayer2::GenericSource2::getLastReadPosition() {
if (mAudioTrack.mSource != NULL) {
return mAudioTimeUs;
} else if (mVideoTrack.mSource != NULL) {
@@ -344,13 +344,13 @@
}
}
-bool NuPlayer2::GenericSource::isStreaming() const {
+bool NuPlayer2::GenericSource2::isStreaming() const {
Mutex::Autolock _l(mLock);
return mIsStreaming;
}
-NuPlayer2::GenericSource::~GenericSource() {
- ALOGV("~GenericSource");
+NuPlayer2::GenericSource2::~GenericSource2() {
+ ALOGV("~GenericSource2");
if (mLooper != NULL) {
mLooper->unregisterHandler(id());
mLooper->stop();
@@ -361,7 +361,7 @@
resetDataSource();
}
-void NuPlayer2::GenericSource::prepareAsync() {
+void NuPlayer2::GenericSource2::prepareAsync() {
Mutex::Autolock _l(mLock);
ALOGV("prepareAsync: (looper: %d)", (mLooper != NULL));
@@ -379,7 +379,7 @@
msg->post();
}
-void NuPlayer2::GenericSource::onPrepareAsync() {
+void NuPlayer2::GenericSource2::onPrepareAsync() {
ALOGV("onPrepareAsync: mDataSource: %d", (mDataSource != NULL));
// delayed data source creation
@@ -460,7 +460,7 @@
ALOGV("onPrepareAsync: Done");
}
-void NuPlayer2::GenericSource::finishPrepareAsync() {
+void NuPlayer2::GenericSource2::finishPrepareAsync() {
ALOGV("finishPrepareAsync");
status_t err = startSources();
@@ -487,7 +487,7 @@
}
}
-void NuPlayer2::GenericSource::notifyPreparedAndCleanup(status_t err) {
+void NuPlayer2::GenericSource2::notifyPreparedAndCleanup(status_t err) {
if (err != OK) {
mDataSource.clear();
mCachedSource.clear();
@@ -500,7 +500,7 @@
notifyPrepared(err);
}
-void NuPlayer2::GenericSource::start() {
+void NuPlayer2::GenericSource2::start() {
Mutex::Autolock _l(mLock);
ALOGI("start");
@@ -515,22 +515,22 @@
mStarted = true;
}
-void NuPlayer2::GenericSource::stop() {
+void NuPlayer2::GenericSource2::stop() {
Mutex::Autolock _l(mLock);
mStarted = false;
}
-void NuPlayer2::GenericSource::pause() {
+void NuPlayer2::GenericSource2::pause() {
Mutex::Autolock _l(mLock);
mStarted = false;
}
-void NuPlayer2::GenericSource::resume() {
+void NuPlayer2::GenericSource2::resume() {
Mutex::Autolock _l(mLock);
mStarted = true;
}
-void NuPlayer2::GenericSource::disconnect() {
+void NuPlayer2::GenericSource2::disconnect() {
sp<DataSource> dataSource, httpSource;
{
Mutex::Autolock _l(mLock);
@@ -549,11 +549,11 @@
}
}
-status_t NuPlayer2::GenericSource::feedMoreTSData() {
+status_t NuPlayer2::GenericSource2::feedMoreTSData() {
return OK;
}
-void NuPlayer2::GenericSource::sendCacheStats() {
+void NuPlayer2::GenericSource2::sendCacheStats() {
int32_t kbps = 0;
status_t err = UNKNOWN_ERROR;
@@ -569,7 +569,7 @@
}
}
-void NuPlayer2::GenericSource::onMessageReceived(const sp<AMessage> &msg) {
+void NuPlayer2::GenericSource2::onMessageReceived(const sp<AMessage> &msg) {
Mutex::Autolock _l(mLock);
switch (msg->what()) {
case kWhatPrepareAsync:
@@ -686,7 +686,7 @@
}
}
-void NuPlayer2::GenericSource::fetchTextData(
+void NuPlayer2::GenericSource2::fetchTextData(
uint32_t sendWhat,
media_track_type type,
int32_t curGen,
@@ -723,7 +723,7 @@
mMediaClock->addTimer(msg2, subTimeUs);
}
-void NuPlayer2::GenericSource::sendTextData(
+void NuPlayer2::GenericSource2::sendTextData(
uint32_t what,
media_track_type type,
int32_t curGen,
@@ -759,7 +759,7 @@
}
}
-void NuPlayer2::GenericSource::sendGlobalTextData(
+void NuPlayer2::GenericSource2::sendGlobalTextData(
uint32_t what,
int32_t curGen,
sp<AMessage> msg) {
@@ -790,12 +790,12 @@
}
}
-sp<MetaData> NuPlayer2::GenericSource::getFormatMeta(bool audio) {
+sp<MetaData> NuPlayer2::GenericSource2::getFormatMeta(bool audio) {
Mutex::Autolock _l(mLock);
return getFormatMeta_l(audio);
}
-sp<MetaData> NuPlayer2::GenericSource::getFormatMeta_l(bool audio) {
+sp<MetaData> NuPlayer2::GenericSource2::getFormatMeta_l(bool audio) {
sp<IMediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource;
if (source == NULL) {
@@ -805,7 +805,7 @@
return source->getFormat();
}
-status_t NuPlayer2::GenericSource::dequeueAccessUnit(
+status_t NuPlayer2::GenericSource2::dequeueAccessUnit(
bool audio, sp<ABuffer> *accessUnit) {
Mutex::Autolock _l(mLock);
// If has gone through stop/releaseDrm sequence, we no longer send down any buffer b/c
@@ -901,18 +901,18 @@
return result;
}
-status_t NuPlayer2::GenericSource::getDuration(int64_t *durationUs) {
+status_t NuPlayer2::GenericSource2::getDuration(int64_t *durationUs) {
Mutex::Autolock _l(mLock);
*durationUs = mDurationUs;
return OK;
}
-size_t NuPlayer2::GenericSource::getTrackCount() const {
+size_t NuPlayer2::GenericSource2::getTrackCount() const {
Mutex::Autolock _l(mLock);
return mSources.size();
}
-sp<AMessage> NuPlayer2::GenericSource::getTrackInfo(size_t trackIndex) const {
+sp<AMessage> NuPlayer2::GenericSource2::getTrackInfo(size_t trackIndex) const {
Mutex::Autolock _l(mLock);
size_t trackCount = mSources.size();
if (trackIndex >= trackCount) {
@@ -962,7 +962,7 @@
return format;
}
-ssize_t NuPlayer2::GenericSource::getSelectedTrack(media_track_type type) const {
+ssize_t NuPlayer2::GenericSource2::getSelectedTrack(media_track_type type) const {
Mutex::Autolock _l(mLock);
const Track *track = NULL;
switch (type) {
@@ -989,7 +989,7 @@
return -1;
}
-status_t NuPlayer2::GenericSource::selectTrack(size_t trackIndex, bool select, int64_t timeUs) {
+status_t NuPlayer2::GenericSource2::selectTrack(size_t trackIndex, bool select, int64_t timeUs) {
Mutex::Autolock _l(mLock);
ALOGV("%s track: %zu", select ? "select" : "deselect", trackIndex);
@@ -1083,7 +1083,7 @@
return INVALID_OPERATION;
}
-status_t NuPlayer2::GenericSource::seekTo(int64_t seekTimeUs, MediaPlayer2SeekMode mode) {
+status_t NuPlayer2::GenericSource2::seekTo(int64_t seekTimeUs, MediaPlayer2SeekMode mode) {
ALOGV("seekTo: %lld, %d", (long long)seekTimeUs, mode);
sp<AMessage> msg = new AMessage(kWhatSeek, this);
msg->setInt64("seekTimeUs", seekTimeUs);
@@ -1101,7 +1101,7 @@
return err;
}
-void NuPlayer2::GenericSource::onSeek(const sp<AMessage>& msg) {
+void NuPlayer2::GenericSource2::onSeek(const sp<AMessage>& msg) {
int64_t seekTimeUs;
int32_t mode;
CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
@@ -1116,7 +1116,7 @@
response->postReply(replyID);
}
-status_t NuPlayer2::GenericSource::doSeek(int64_t seekTimeUs, MediaPlayer2SeekMode mode) {
+status_t NuPlayer2::GenericSource2::doSeek(int64_t seekTimeUs, MediaPlayer2SeekMode mode) {
if (mVideoTrack.mSource != NULL) {
++mVideoDataGeneration;
@@ -1150,7 +1150,7 @@
return OK;
}
-sp<ABuffer> NuPlayer2::GenericSource::mediaBufferToABuffer(
+sp<ABuffer> NuPlayer2::GenericSource2::mediaBufferToABuffer(
MediaBuffer* mb,
media_track_type trackType) {
bool audio = trackType == MEDIA_TRACK_TYPE_AUDIO;
@@ -1248,7 +1248,7 @@
return ab;
}
-int32_t NuPlayer2::GenericSource::getDataGeneration(media_track_type type) const {
+int32_t NuPlayer2::GenericSource2::getDataGeneration(media_track_type type) const {
int32_t generation = -1;
switch (type) {
case MEDIA_TRACK_TYPE_VIDEO:
@@ -1270,7 +1270,7 @@
return generation;
}
-void NuPlayer2::GenericSource::postReadBuffer(media_track_type trackType) {
+void NuPlayer2::GenericSource2::postReadBuffer(media_track_type trackType) {
if ((mPendingReadBufferTypes & (1 << trackType)) == 0) {
mPendingReadBufferTypes |= (1 << trackType);
sp<AMessage> msg = new AMessage(kWhatReadBuffer, this);
@@ -1279,7 +1279,7 @@
}
}
-void NuPlayer2::GenericSource::onReadBuffer(const sp<AMessage>& msg) {
+void NuPlayer2::GenericSource2::onReadBuffer(const sp<AMessage>& msg) {
int32_t tmpType;
CHECK(msg->findInt32("trackType", &tmpType));
media_track_type trackType = (media_track_type)tmpType;
@@ -1287,7 +1287,7 @@
readBuffer(trackType);
}
-void NuPlayer2::GenericSource::readBuffer(
+void NuPlayer2::GenericSource2::readBuffer(
media_track_type trackType, int64_t seekTimeUs, MediaPlayer2SeekMode mode,
int64_t *actualTimeUs, bool formatChange) {
Track *track;
@@ -1460,7 +1460,7 @@
}
}
-void NuPlayer2::GenericSource::queueDiscontinuityIfNeeded(
+void NuPlayer2::GenericSource2::queueDiscontinuityIfNeeded(
bool seeking, bool formatChange, media_track_type trackType, Track *track) {
// formatChange && seeking: track whose source is changed during selection
// formatChange && !seeking: track whose source is not changed during selection
@@ -1475,7 +1475,7 @@
}
}
-void NuPlayer2::GenericSource::notifyBufferingUpdate(int32_t percentage) {
+void NuPlayer2::GenericSource2::notifyBufferingUpdate(int32_t percentage) {
// Buffering percent could go backward as it's estimated from remaining
// data and last access time. This could cause the buffering position
// drawn on media control to jitter slightly. Remember previously reported
@@ -1496,14 +1496,14 @@
notify->post();
}
-void NuPlayer2::GenericSource::schedulePollBuffering() {
+void NuPlayer2::GenericSource2::schedulePollBuffering() {
sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
msg->setInt32("generation", mPollBufferingGeneration);
// Enquires buffering status every second.
msg->post(1000000ll);
}
-void NuPlayer2::GenericSource::onPollBuffering() {
+void NuPlayer2::GenericSource2::onPollBuffering() {
status_t finalStatus = UNKNOWN_ERROR;
int64_t cachedDurationUs = -1ll;
ssize_t cachedDataRemaining = -1;
@@ -1554,7 +1554,7 @@
}
// Modular DRM
-status_t NuPlayer2::GenericSource::prepareDrm(
+status_t NuPlayer2::GenericSource2::prepareDrm(
const uint8_t uuid[16],
const Vector<uint8_t> &drmSessionId,
sp<AMediaCryptoWrapper> *outCrypto) {
@@ -1611,7 +1611,7 @@
return status;
}
-status_t NuPlayer2::GenericSource::releaseDrm() {
+status_t NuPlayer2::GenericSource2::releaseDrm() {
Mutex::Autolock _l(mLock);
ALOGV("releaseDrm");
@@ -1627,7 +1627,7 @@
return OK;
}
-status_t NuPlayer2::GenericSource::checkDrmInfo()
+status_t NuPlayer2::GenericSource2::checkDrmInfo()
{
// clearing the flag at prepare in case the player is reused after stop/releaseDrm with the
// same source without being reset (called by prepareAsync/initFromDataSource)
@@ -1661,7 +1661,7 @@
return OK;
}
-void NuPlayer2::GenericSource::signalBufferReturned(MediaBuffer *buffer)
+void NuPlayer2::GenericSource2::signalBufferReturned(MediaBuffer *buffer)
{
//ALOGV("signalBufferReturned %p refCount: %d", buffer, buffer->localRefcount());
diff --git a/media/libmedia/nuplayer2/GenericSource.h b/media/libmedia/nuplayer2/GenericSource2.h
similarity index 93%
rename from media/libmedia/nuplayer2/GenericSource.h
rename to media/libmedia/nuplayer2/GenericSource2.h
index 5a71edb..2016304 100644
--- a/media/libmedia/nuplayer2/GenericSource.h
+++ b/media/libmedia/nuplayer2/GenericSource2.h
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-#ifndef GENERIC_SOURCE_H_
+#ifndef GENERIC_SOURCE2_H_
-#define GENERIC_SOURCE_H_
+#define GENERIC_SOURCE2_H_
#include "NuPlayer2.h"
#include "NuPlayer2Source.h"
@@ -40,11 +40,11 @@
struct MediaClock;
struct NuCachedSource2;
-struct NuPlayer2::GenericSource : public NuPlayer2::Source,
- public MediaBufferObserver // Modular DRM
+struct NuPlayer2::GenericSource2 : public NuPlayer2::Source,
+ public MediaBufferObserver // Modular DRM
{
- GenericSource(const sp<AMessage> ¬ify, bool uidValid, uid_t uid,
- const sp<MediaClock> &mediaClock);
+ GenericSource2(const sp<AMessage> ¬ify, bool uidValid, uid_t uid,
+ const sp<MediaClock> &mediaClock);
status_t setDataSource(
const sp<MediaHTTPService> &httpService,
@@ -97,7 +97,7 @@
protected:
- virtual ~GenericSource();
+ virtual ~GenericSource2();
virtual void onMessageReceived(const sp<AMessage> &msg);
@@ -240,9 +240,9 @@
status_t checkDrmInfo();
- DISALLOW_EVIL_CONSTRUCTORS(GenericSource);
+ DISALLOW_EVIL_CONSTRUCTORS(GenericSource2);
};
} // namespace android
-#endif // GENERIC_SOURCE_H_
+#endif // GENERIC_SOURCE2_H_
diff --git a/media/libmedia/nuplayer2/HTTPLiveSource.cpp b/media/libmedia/nuplayer2/HTTPLiveSource2.cpp
similarity index 89%
rename from media/libmedia/nuplayer2/HTTPLiveSource.cpp
rename to media/libmedia/nuplayer2/HTTPLiveSource2.cpp
index e0e3df9..a61cacd 100644
--- a/media/libmedia/nuplayer2/HTTPLiveSource.cpp
+++ b/media/libmedia/nuplayer2/HTTPLiveSource2.cpp
@@ -15,10 +15,10 @@
*/
//#define LOG_NDEBUG 0
-#define LOG_TAG "HTTPLiveSource"
+#define LOG_TAG "HTTPLiveSource2"
#include <utils/Log.h>
-#include "HTTPLiveSource.h"
+#include "HTTPLiveSource2.h"
#include "AnotherPacketSource.h"
#include "LiveDataSource.h"
@@ -38,7 +38,7 @@
namespace android {
-NuPlayer2::HTTPLiveSource::HTTPLiveSource(
+NuPlayer2::HTTPLiveSource2::HTTPLiveSource2(
const sp<AMessage> ¬ify,
const sp<MediaHTTPService> &httpService,
const char *url,
@@ -69,7 +69,7 @@
}
}
-NuPlayer2::HTTPLiveSource::~HTTPLiveSource() {
+NuPlayer2::HTTPLiveSource2::~HTTPLiveSource2() {
if (mLiveSession != NULL) {
mLiveSession->disconnect();
@@ -82,14 +82,14 @@
}
}
-status_t NuPlayer2::HTTPLiveSource::getBufferingSettings(
+status_t NuPlayer2::HTTPLiveSource2::getBufferingSettings(
BufferingSettings* buffering /* nonnull */) {
*buffering = mBufferingSettings;
return OK;
}
-status_t NuPlayer2::HTTPLiveSource::setBufferingSettings(const BufferingSettings& buffering) {
+status_t NuPlayer2::HTTPLiveSource2::setBufferingSettings(const BufferingSettings& buffering) {
mBufferingSettings = buffering;
if (mLiveSession != NULL) {
@@ -99,7 +99,7 @@
return OK;
}
-void NuPlayer2::HTTPLiveSource::prepareAsync() {
+void NuPlayer2::HTTPLiveSource2::prepareAsync() {
if (mLiveLooper == NULL) {
mLiveLooper = new ALooper;
mLiveLooper->setName("http live");
@@ -123,10 +123,10 @@
mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
}
-void NuPlayer2::HTTPLiveSource::start() {
+void NuPlayer2::HTTPLiveSource2::start() {
}
-sp<MetaData> NuPlayer2::HTTPLiveSource::getFormatMeta(bool audio) {
+sp<MetaData> NuPlayer2::HTTPLiveSource2::getFormatMeta(bool audio) {
sp<MetaData> meta;
if (mLiveSession != NULL) {
mLiveSession->getStreamFormatMeta(
@@ -138,7 +138,7 @@
return meta;
}
-sp<AMessage> NuPlayer2::HTTPLiveSource::getFormat(bool audio) {
+sp<AMessage> NuPlayer2::HTTPLiveSource2::getFormat(bool audio) {
sp<MetaData> meta;
status_t err = -EWOULDBLOCK;
if (mLiveSession != NULL) {
@@ -161,11 +161,11 @@
return format;
}
-status_t NuPlayer2::HTTPLiveSource::feedMoreTSData() {
+status_t NuPlayer2::HTTPLiveSource2::feedMoreTSData() {
return OK;
}
-status_t NuPlayer2::HTTPLiveSource::dequeueAccessUnit(
+status_t NuPlayer2::HTTPLiveSource2::dequeueAccessUnit(
bool audio, sp<ABuffer> *accessUnit) {
return mLiveSession->dequeueAccessUnit(
audio ? LiveSession::STREAMTYPE_AUDIO
@@ -173,19 +173,19 @@
accessUnit);
}
-status_t NuPlayer2::HTTPLiveSource::getDuration(int64_t *durationUs) {
+status_t NuPlayer2::HTTPLiveSource2::getDuration(int64_t *durationUs) {
return mLiveSession->getDuration(durationUs);
}
-size_t NuPlayer2::HTTPLiveSource::getTrackCount() const {
+size_t NuPlayer2::HTTPLiveSource2::getTrackCount() const {
return mLiveSession->getTrackCount();
}
-sp<AMessage> NuPlayer2::HTTPLiveSource::getTrackInfo(size_t trackIndex) const {
+sp<AMessage> NuPlayer2::HTTPLiveSource2::getTrackInfo(size_t trackIndex) const {
return mLiveSession->getTrackInfo(trackIndex);
}
-ssize_t NuPlayer2::HTTPLiveSource::getSelectedTrack(media_track_type type) const {
+ssize_t NuPlayer2::HTTPLiveSource2::getSelectedTrack(media_track_type type) const {
if (mLiveSession == NULL) {
return -1;
} else if (type == MEDIA_TRACK_TYPE_METADATA) {
@@ -197,7 +197,7 @@
}
}
-status_t NuPlayer2::HTTPLiveSource::selectTrack(size_t trackIndex, bool select, int64_t /*timeUs*/) {
+status_t NuPlayer2::HTTPLiveSource2::selectTrack(size_t trackIndex, bool select, int64_t /*timeUs*/) {
if (mLiveSession == NULL) {
return INVALID_OPERATION;
}
@@ -239,7 +239,7 @@
return (err == OK || err == BAD_VALUE) ? (status_t)OK : err;
}
-status_t NuPlayer2::HTTPLiveSource::seekTo(int64_t seekTimeUs, MediaPlayer2SeekMode mode) {
+status_t NuPlayer2::HTTPLiveSource2::seekTo(int64_t seekTimeUs, MediaPlayer2SeekMode mode) {
if (mLiveSession->isSeekable()) {
return mLiveSession->seekTo(seekTimeUs, mode);
} else {
@@ -247,7 +247,7 @@
}
}
-void NuPlayer2::HTTPLiveSource::pollForRawData(
+void NuPlayer2::HTTPLiveSource2::pollForRawData(
const sp<AMessage> &msg, int32_t currentGeneration,
LiveSession::StreamType fetchType, int32_t pushWhat) {
@@ -290,7 +290,7 @@
msg->post(1000000ll);
}
-void NuPlayer2::HTTPLiveSource::onMessageReceived(const sp<AMessage> &msg) {
+void NuPlayer2::HTTPLiveSource2::onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
case kWhatSessionNotify:
{
@@ -328,7 +328,7 @@
}
}
-void NuPlayer2::HTTPLiveSource::onSessionNotify(const sp<AMessage> &msg) {
+void NuPlayer2::HTTPLiveSource2::onSessionNotify(const sp<AMessage> &msg) {
int32_t what;
CHECK(msg->findInt32("what", &what));
diff --git a/media/libmedia/nuplayer2/HTTPLiveSource.h b/media/libmedia/nuplayer2/HTTPLiveSource2.h
similarity index 91%
rename from media/libmedia/nuplayer2/HTTPLiveSource.h
rename to media/libmedia/nuplayer2/HTTPLiveSource2.h
index 7b6a312..97d3653 100644
--- a/media/libmedia/nuplayer2/HTTPLiveSource.h
+++ b/media/libmedia/nuplayer2/HTTPLiveSource2.h
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-#ifndef HTTP_LIVE_SOURCE_H_
+#ifndef HTTP_LIVE_SOURCE2_H_
-#define HTTP_LIVE_SOURCE_H_
+#define HTTP_LIVE_SOURCE2_H_
#include "NuPlayer2.h"
#include "NuPlayer2Source.h"
@@ -27,8 +27,8 @@
struct LiveSession;
-struct NuPlayer2::HTTPLiveSource : public NuPlayer2::Source {
- HTTPLiveSource(
+struct NuPlayer2::HTTPLiveSource2 : public NuPlayer2::Source {
+ HTTPLiveSource2(
const sp<AMessage> ¬ify,
const sp<MediaHTTPService> &httpService,
const char *url,
@@ -56,7 +56,7 @@
MediaPlayer2SeekMode mode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC) override;
protected:
- virtual ~HTTPLiveSource();
+ virtual ~HTTPLiveSource2();
virtual void onMessageReceived(const sp<AMessage> &msg);
@@ -91,9 +91,9 @@
const sp<AMessage> &msg, int32_t currentGeneration,
LiveSession::StreamType fetchType, int32_t pushWhat);
- DISALLOW_EVIL_CONSTRUCTORS(HTTPLiveSource);
+ DISALLOW_EVIL_CONSTRUCTORS(HTTPLiveSource2);
};
} // namespace android
-#endif // HTTP_LIVE_SOURCE_H_
+#endif // HTTP_LIVE_SOURCE2_H_
diff --git a/media/libmedia/nuplayer2/NuPlayer2.cpp b/media/libmedia/nuplayer2/NuPlayer2.cpp
index 35e20e8..65e0957 100644
--- a/media/libmedia/nuplayer2/NuPlayer2.cpp
+++ b/media/libmedia/nuplayer2/NuPlayer2.cpp
@@ -23,7 +23,7 @@
#include "NuPlayer2.h"
-#include "HTTPLiveSource.h"
+#include "HTTPLiveSource2.h"
#include "NuPlayer2CCDecoder.h"
#include "NuPlayer2Decoder.h"
#include "NuPlayer2DecoderBase.h"
@@ -31,9 +31,8 @@
#include "NuPlayer2Driver.h"
#include "NuPlayer2Renderer.h"
#include "NuPlayer2Source.h"
-#include "RTSPSource.h"
-#include "StreamingSource.h"
-#include "GenericSource.h"
+#include "RTSPSource2.h"
+#include "GenericSource2.h"
#include "TextDescriptions.h"
#include "ATSParser.h"
@@ -291,27 +290,27 @@
KeyedVector<String8, String8> *headers = &(dsd->mHeaders);
if (IsHTTPLiveURL(url)) {
- source = new HTTPLiveSource(notify, httpService, url, headers);
- ALOGV("setDataSourceAsync HTTPLiveSource %s", url);
+ source = new HTTPLiveSource2(notify, httpService, url, headers);
+ ALOGV("setDataSourceAsync HTTPLiveSource2 %s", url);
mDataSourceType = DATA_SOURCE_TYPE_HTTP_LIVE;
} else if (!strncasecmp(url, "rtsp://", 7)) {
- source = new RTSPSource(
+ source = new RTSPSource2(
notify, httpService, url, headers, mUIDValid, mUID);
- ALOGV("setDataSourceAsync RTSPSource %s", url);
+ ALOGV("setDataSourceAsync RTSPSource2 %s", url);
mDataSourceType = DATA_SOURCE_TYPE_RTSP;
} else if ((!strncasecmp(url, "http://", 7)
|| !strncasecmp(url, "https://", 8))
&& ((len >= 4 && !strcasecmp(".sdp", &url[len - 4]))
|| strstr(url, ".sdp?"))) {
- source = new RTSPSource(
+ source = new RTSPSource2(
notify, httpService, url, headers, mUIDValid, mUID, true);
- ALOGV("setDataSourceAsync RTSPSource http/https/.sdp %s", url);
+ ALOGV("setDataSourceAsync RTSPSource2 http/https/.sdp %s", url);
mDataSourceType = DATA_SOURCE_TYPE_RTSP;
} else {
- ALOGV("setDataSourceAsync GenericSource %s", url);
+ ALOGV("setDataSourceAsync GenericSource2 %s", url);
- sp<GenericSource> genericSource =
- new GenericSource(notify, mUIDValid, mUID, mMediaClock);
+ sp<GenericSource2> genericSource =
+ new GenericSource2(notify, mUIDValid, mUID, mMediaClock);
status_t err = genericSource->setDataSource(httpService, url, headers);
@@ -329,8 +328,8 @@
case DataSourceDesc::TYPE_FD:
{
- sp<GenericSource> genericSource =
- new GenericSource(notify, mUIDValid, mUID, mMediaClock);
+ sp<GenericSource2> genericSource =
+ new GenericSource2(notify, mUIDValid, mUID, mMediaClock);
ALOGV("setDataSourceAsync fd %d/%lld/%lld source: %p",
dsd->mFD, (long long)dsd->mFDOffset, (long long)dsd->mFDLength, source.get());
@@ -350,8 +349,8 @@
case DataSourceDesc::TYPE_CALLBACK:
{
- sp<GenericSource> genericSource =
- new GenericSource(notify, mUIDValid, mUID, mMediaClock);
+ sp<GenericSource2> genericSource =
+ new GenericSource2(notify, mUIDValid, mUID, mMediaClock);
status_t err = genericSource->setDataSource(dsd->mCallbackSource);
if (err != OK) {
diff --git a/media/libmedia/nuplayer2/NuPlayer2.h b/media/libmedia/nuplayer2/NuPlayer2.h
index 0764ec3..1d74b55 100644
--- a/media/libmedia/nuplayer2/NuPlayer2.h
+++ b/media/libmedia/nuplayer2/NuPlayer2.h
@@ -106,11 +106,10 @@
struct DecoderBase;
struct DecoderPassThrough;
struct CCDecoder;
- struct GenericSource;
- struct HTTPLiveSource;
+ struct GenericSource2;
+ struct HTTPLiveSource2;
struct Renderer;
- struct RTSPSource;
- struct StreamingSource;
+ struct RTSPSource2;
struct Action;
struct SeekAction;
struct SetSurfaceAction;
diff --git a/media/libmedia/nuplayer2/NuPlayer2StreamListener.cpp b/media/libmedia/nuplayer2/NuPlayer2StreamListener.cpp
deleted file mode 100644
index 0769711..0000000
--- a/media/libmedia/nuplayer2/NuPlayer2StreamListener.cpp
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright 2017 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 "NuPlayer2StreamListener"
-#include <utils/Log.h>
-
-#include "NuPlayer2StreamListener.h"
-
-#include <binder/MemoryDealer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/MediaErrors.h>
-
-namespace android {
-
-NuPlayer2::StreamListener::StreamListener(
- const sp<IStreamSource> &source,
- const sp<AHandler> &targetHandler)
- : mSource(source),
- mTargetHandler(targetHandler),
- mEOS(false),
- mSendDataNotification(true) {
- mSource->setListener(this);
-
- mMemoryDealer = new MemoryDealer(kNumBuffers * kBufferSize);
- for (size_t i = 0; i < kNumBuffers; ++i) {
- sp<IMemory> mem = mMemoryDealer->allocate(kBufferSize);
- CHECK(mem != NULL);
-
- mBuffers.push(mem);
- }
- mSource->setBuffers(mBuffers);
-}
-
-void NuPlayer2::StreamListener::start() {
- for (size_t i = 0; i < kNumBuffers; ++i) {
- mSource->onBufferAvailable(i);
- }
-}
-
-void NuPlayer2::StreamListener::queueBuffer(size_t index, size_t size) {
- QueueEntry entry;
- entry.mIsCommand = false;
- entry.mIndex = index;
- entry.mSize = size;
- entry.mOffset = 0;
-
- Mutex::Autolock autoLock(mLock);
- mQueue.push_back(entry);
-
- if (mSendDataNotification) {
- mSendDataNotification = false;
-
- if (mTargetHandler != NULL) {
- (new AMessage(kWhatMoreDataQueued, mTargetHandler))->post();
- }
- }
-}
-
-void NuPlayer2::StreamListener::issueCommand(
- Command cmd, bool synchronous, const sp<AMessage> &extra) {
- CHECK(!synchronous);
-
- QueueEntry entry;
- entry.mIsCommand = true;
- entry.mCommand = cmd;
- entry.mExtra = extra;
-
- Mutex::Autolock autoLock(mLock);
- mQueue.push_back(entry);
-
- if (mSendDataNotification) {
- mSendDataNotification = false;
-
- if (mTargetHandler != NULL) {
- (new AMessage(kWhatMoreDataQueued, mTargetHandler))->post();
- }
- }
-}
-
-ssize_t NuPlayer2::StreamListener::read(
- void *data, size_t size, sp<AMessage> *extra) {
- CHECK_GT(size, 0u);
-
- extra->clear();
-
- Mutex::Autolock autoLock(mLock);
-
- if (mEOS) {
- return 0;
- }
-
- if (mQueue.empty()) {
- mSendDataNotification = true;
-
- return -EWOULDBLOCK;
- }
-
- QueueEntry *entry = &*mQueue.begin();
-
- if (entry->mIsCommand) {
- switch (entry->mCommand) {
- case EOS:
- {
- mQueue.erase(mQueue.begin());
- entry = NULL;
-
- mEOS = true;
- return 0;
- }
-
- case DISCONTINUITY:
- {
- *extra = entry->mExtra;
-
- mQueue.erase(mQueue.begin());
- entry = NULL;
-
- return INFO_DISCONTINUITY;
- }
-
- default:
- TRESPASS();
- break;
- }
- }
-
- size_t copy = entry->mSize;
- if (copy > size) {
- copy = size;
- }
-
- if (entry->mIndex >= mBuffers.size()) {
- return ERROR_MALFORMED;
- }
-
- sp<IMemory> mem = mBuffers.editItemAt(entry->mIndex);
- if (mem == NULL || mem->size() < copy || mem->size() - copy < entry->mOffset) {
- return ERROR_MALFORMED;
- }
-
- memcpy(data,
- (const uint8_t *)mem->pointer()
- + entry->mOffset,
- copy);
-
- entry->mOffset += copy;
- entry->mSize -= copy;
-
- if (entry->mSize == 0) {
- mSource->onBufferAvailable(entry->mIndex);
- mQueue.erase(mQueue.begin());
- entry = NULL;
- }
-
- return copy;
-}
-
-} // namespace android
diff --git a/media/libmedia/nuplayer2/NuPlayer2StreamListener.h b/media/libmedia/nuplayer2/NuPlayer2StreamListener.h
deleted file mode 100644
index 4327b24..0000000
--- a/media/libmedia/nuplayer2/NuPlayer2StreamListener.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2017 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 NUPLAYER2_STREAM_LISTENER_H_
-
-#define NUPLAYER2_STREAM_LISTENER_H_
-
-#include "NuPlayer2.h"
-
-#include <media/IStreamSource.h>
-
-namespace android {
-
-class MemoryDealer;
-
-struct NuPlayer2::StreamListener : public BnStreamListener {
- StreamListener(
- const sp<IStreamSource> &source,
- const sp<AHandler> &targetHandler);
-
- virtual void queueBuffer(size_t index, size_t size);
-
- virtual void issueCommand(
- Command cmd, bool synchronous, const sp<AMessage> &extra);
-
- void start();
- ssize_t read(void *data, size_t size, sp<AMessage> *extra);
-
-private:
- enum {
- kNumBuffers = 8,
- kBufferSize = 188 * 10
- };
-
- struct QueueEntry {
- bool mIsCommand;
-
- size_t mIndex;
- size_t mSize;
- size_t mOffset;
-
- Command mCommand;
- sp<AMessage> mExtra;
- };
-
- Mutex mLock;
-
- sp<IStreamSource> mSource;
- sp<AHandler> mTargetHandler;
- sp<MemoryDealer> mMemoryDealer;
- Vector<sp<IMemory> > mBuffers;
- List<QueueEntry> mQueue;
- bool mEOS;
- bool mSendDataNotification;
-
- DISALLOW_EVIL_CONSTRUCTORS(StreamListener);
-};
-
-} // namespace android
-
-#endif // NUPLAYER2_STREAM_LISTENER_H_
diff --git a/media/libmedia/nuplayer2/RTSPSource.cpp b/media/libmedia/nuplayer2/RTSPSource2.cpp
similarity index 91%
rename from media/libmedia/nuplayer2/RTSPSource.cpp
rename to media/libmedia/nuplayer2/RTSPSource2.cpp
index 3f6966d..8b67ae5 100644
--- a/media/libmedia/nuplayer2/RTSPSource.cpp
+++ b/media/libmedia/nuplayer2/RTSPSource2.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 The Android Open Source Project
+ * Copyright 2017 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.
@@ -15,10 +15,10 @@
*/
//#define LOG_NDEBUG 0
-#define LOG_TAG "RTSPSource"
+#define LOG_TAG "RTSPSource2"
#include <utils/Log.h>
-#include "RTSPSource.h"
+#include "RTSPSource2.h"
#include "AnotherPacketSource.h"
#include "MyHandler.h"
@@ -38,7 +38,7 @@
//static const int kStartServerMarkMs = 5000;
static const int kOverflowMarkMs = 10000; // 10 seconds
-NuPlayer2::RTSPSource::RTSPSource(
+NuPlayer2::RTSPSource2::RTSPSource2(
const sp<AMessage> ¬ify,
const sp<MediaHTTPService> &httpService,
const char *url,
@@ -78,27 +78,27 @@
}
}
-NuPlayer2::RTSPSource::~RTSPSource() {
+NuPlayer2::RTSPSource2::~RTSPSource2() {
if (mLooper != NULL) {
mLooper->unregisterHandler(id());
mLooper->stop();
}
}
-status_t NuPlayer2::RTSPSource::getBufferingSettings(
+status_t NuPlayer2::RTSPSource2::getBufferingSettings(
BufferingSettings* buffering /* nonnull */) {
Mutex::Autolock _l(mBufferingSettingsLock);
*buffering = mBufferingSettings;
return OK;
}
-status_t NuPlayer2::RTSPSource::setBufferingSettings(const BufferingSettings& buffering) {
+status_t NuPlayer2::RTSPSource2::setBufferingSettings(const BufferingSettings& buffering) {
Mutex::Autolock _l(mBufferingSettingsLock);
mBufferingSettings = buffering;
return OK;
}
-void NuPlayer2::RTSPSource::prepareAsync() {
+void NuPlayer2::RTSPSource2::prepareAsync() {
if (mIsSDP && mHTTPService == NULL) {
notifyPrepared(BAD_VALUE);
return;
@@ -137,10 +137,10 @@
startBufferingIfNecessary();
}
-void NuPlayer2::RTSPSource::start() {
+void NuPlayer2::RTSPSource2::start() {
}
-void NuPlayer2::RTSPSource::stop() {
+void NuPlayer2::RTSPSource2::stop() {
if (mLooper == NULL) {
return;
}
@@ -150,12 +150,12 @@
msg->postAndAwaitResponse(&dummy);
}
-status_t NuPlayer2::RTSPSource::feedMoreTSData() {
+status_t NuPlayer2::RTSPSource2::feedMoreTSData() {
Mutex::Autolock _l(mBufferingLock);
return mFinalResult;
}
-sp<MetaData> NuPlayer2::RTSPSource::getFormatMeta(bool audio) {
+sp<MetaData> NuPlayer2::RTSPSource2::getFormatMeta(bool audio) {
sp<AnotherPacketSource> source = getSource(audio);
if (source == NULL) {
@@ -165,7 +165,7 @@
return source->getFormat();
}
-bool NuPlayer2::RTSPSource::haveSufficientDataOnAllTracks() {
+bool NuPlayer2::RTSPSource2::haveSufficientDataOnAllTracks() {
// We're going to buffer at least 2 secs worth data on all tracks before
// starting playback (both at startup and after a seek).
@@ -201,7 +201,7 @@
return true;
}
-status_t NuPlayer2::RTSPSource::dequeueAccessUnit(
+status_t NuPlayer2::RTSPSource2::dequeueAccessUnit(
bool audio, sp<ABuffer> *accessUnit) {
if (!stopBufferingIfNecessary()) {
return -EWOULDBLOCK;
@@ -253,7 +253,7 @@
return source->dequeueAccessUnit(accessUnit);
}
-sp<AnotherPacketSource> NuPlayer2::RTSPSource::getSource(bool audio) {
+sp<AnotherPacketSource> NuPlayer2::RTSPSource2::getSource(bool audio) {
if (mTSParser != NULL) {
sp<MediaSource> source = mTSParser->getSource(
audio ? ATSParser::AUDIO : ATSParser::VIDEO);
@@ -264,7 +264,7 @@
return audio ? mAudioTrack : mVideoTrack;
}
-void NuPlayer2::RTSPSource::setEOSTimeout(bool audio, int64_t timeout) {
+void NuPlayer2::RTSPSource2::setEOSTimeout(bool audio, int64_t timeout) {
if (audio) {
mEOSTimeoutAudio = timeout;
} else {
@@ -272,7 +272,7 @@
}
}
-status_t NuPlayer2::RTSPSource::getDuration(int64_t *durationUs) {
+status_t NuPlayer2::RTSPSource2::getDuration(int64_t *durationUs) {
*durationUs = -1ll;
int64_t audioDurationUs;
@@ -294,7 +294,7 @@
return OK;
}
-status_t NuPlayer2::RTSPSource::seekTo(int64_t seekTimeUs, MediaPlayer2SeekMode mode) {
+status_t NuPlayer2::RTSPSource2::seekTo(int64_t seekTimeUs, MediaPlayer2SeekMode mode) {
sp<AMessage> msg = new AMessage(kWhatPerformSeek, this);
msg->setInt32("generation", ++mSeekGeneration);
msg->setInt64("timeUs", seekTimeUs);
@@ -309,7 +309,7 @@
return err;
}
-void NuPlayer2::RTSPSource::performSeek(int64_t seekTimeUs) {
+void NuPlayer2::RTSPSource2::performSeek(int64_t seekTimeUs) {
if (mState != CONNECTED) {
finishSeek(INVALID_OPERATION);
return;
@@ -320,12 +320,12 @@
mEOSPending = false;
}
-void NuPlayer2::RTSPSource::schedulePollBuffering() {
+void NuPlayer2::RTSPSource2::schedulePollBuffering() {
sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
msg->post(1000000ll); // 1 second intervals
}
-void NuPlayer2::RTSPSource::checkBuffering(
+void NuPlayer2::RTSPSource2::checkBuffering(
bool *prepared, bool *underflow, bool *overflow, bool *startServer, bool *finished) {
size_t numTracks = mTracks.size();
size_t preparedCount, underflowCount, overflowCount, startCount, finishedCount;
@@ -383,7 +383,7 @@
*finished = (finishedCount > 0);
}
-void NuPlayer2::RTSPSource::onPollBuffering() {
+void NuPlayer2::RTSPSource2::onPollBuffering() {
bool prepared, underflow, overflow, startServer, finished;
checkBuffering(&prepared, &underflow, &overflow, &startServer, &finished);
@@ -415,7 +415,7 @@
schedulePollBuffering();
}
-void NuPlayer2::RTSPSource::signalSourceEOS(status_t result) {
+void NuPlayer2::RTSPSource2::signalSourceEOS(status_t result) {
const bool audio = true;
const bool video = false;
@@ -430,7 +430,7 @@
}
}
-bool NuPlayer2::RTSPSource::sourceReachedEOS(bool audio) {
+bool NuPlayer2::RTSPSource2::sourceReachedEOS(bool audio) {
sp<AnotherPacketSource> source = getSource(audio);
status_t finalResult;
return (source != NULL &&
@@ -438,14 +438,14 @@
finalResult == ERROR_END_OF_STREAM);
}
-bool NuPlayer2::RTSPSource::sourceNearEOS(bool audio) {
+bool NuPlayer2::RTSPSource2::sourceNearEOS(bool audio) {
sp<AnotherPacketSource> source = getSource(audio);
int64_t mediaDurationUs = 0;
getDuration(&mediaDurationUs);
return (source != NULL && source->isFinished(mediaDurationUs));
}
-void NuPlayer2::RTSPSource::onSignalEOS(const sp<AMessage> &msg) {
+void NuPlayer2::RTSPSource2::onSignalEOS(const sp<AMessage> &msg) {
int32_t generation;
CHECK(msg->findInt32("generation", &generation));
@@ -459,7 +459,7 @@
}
}
-void NuPlayer2::RTSPSource::postSourceEOSIfNecessary() {
+void NuPlayer2::RTSPSource2::postSourceEOSIfNecessary() {
const bool audio = true;
const bool video = false;
// If a source has detected near end, give it some time to retrieve more
@@ -474,7 +474,7 @@
}
}
-void NuPlayer2::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
+void NuPlayer2::RTSPSource2::onMessageReceived(const sp<AMessage> &msg) {
if (msg->what() == kWhatDisconnect) {
sp<AReplyToken> replyID;
CHECK(msg->senderAwaitsResponse(&replyID));
@@ -722,7 +722,7 @@
}
}
-void NuPlayer2::RTSPSource::onConnected() {
+void NuPlayer2::RTSPSource2::onConnected() {
CHECK(mAudioTrack == NULL);
CHECK(mVideoTrack == NULL);
@@ -770,7 +770,7 @@
mState = CONNECTED;
}
-void NuPlayer2::RTSPSource::onSDPLoaded(const sp<AMessage> &msg) {
+void NuPlayer2::RTSPSource2::onSDPLoaded(const sp<AMessage> &msg) {
status_t err;
CHECK(msg->findInt32("result", &err));
@@ -816,7 +816,7 @@
}
}
-void NuPlayer2::RTSPSource::onDisconnected(const sp<AMessage> &msg) {
+void NuPlayer2::RTSPSource2::onDisconnected(const sp<AMessage> &msg) {
if (mState == DISCONNECTED) {
return;
}
@@ -842,7 +842,7 @@
}
}
-void NuPlayer2::RTSPSource::finishDisconnectIfPossible() {
+void NuPlayer2::RTSPSource2::finishDisconnectIfPossible() {
if (mState != DISCONNECTED) {
if (mHandler != NULL) {
mHandler->disconnect();
@@ -856,12 +856,12 @@
mDisconnectReplyID = 0;
}
-void NuPlayer2::RTSPSource::setError(status_t err) {
+void NuPlayer2::RTSPSource2::setError(status_t err) {
Mutex::Autolock _l(mBufferingLock);
mFinalResult = err;
}
-void NuPlayer2::RTSPSource::startBufferingIfNecessary() {
+void NuPlayer2::RTSPSource2::startBufferingIfNecessary() {
Mutex::Autolock _l(mBufferingLock);
if (!mBuffering) {
@@ -873,7 +873,7 @@
}
}
-bool NuPlayer2::RTSPSource::stopBufferingIfNecessary() {
+bool NuPlayer2::RTSPSource2::stopBufferingIfNecessary() {
Mutex::Autolock _l(mBufferingLock);
if (mBuffering) {
@@ -891,7 +891,7 @@
return true;
}
-void NuPlayer2::RTSPSource::finishSeek(status_t err) {
+void NuPlayer2::RTSPSource2::finishSeek(status_t err) {
if (mSeekReplyID == NULL) {
return;
}
diff --git a/media/libmedia/nuplayer2/RTSPSource.h b/media/libmedia/nuplayer2/RTSPSource2.h
similarity index 94%
rename from media/libmedia/nuplayer2/RTSPSource.h
rename to media/libmedia/nuplayer2/RTSPSource2.h
index 9bce473..739bd53 100644
--- a/media/libmedia/nuplayer2/RTSPSource.h
+++ b/media/libmedia/nuplayer2/RTSPSource2.h
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-#ifndef RTSP_SOURCE_H_
+#ifndef RTSP_SOURCE2_H_
-#define RTSP_SOURCE_H_
+#define RTSP_SOURCE2_H_
#include "NuPlayer2Source.h"
@@ -30,8 +30,8 @@
struct MyHandler;
struct SDPLoader;
-struct NuPlayer2::RTSPSource : public NuPlayer2::Source {
- RTSPSource(
+struct NuPlayer2::RTSPSource2 : public NuPlayer2::Source {
+ RTSPSource2(
const sp<AMessage> ¬ify,
const sp<MediaHTTPService> &httpService,
const char *url,
@@ -60,7 +60,7 @@
void onMessageReceived(const sp<AMessage> &msg);
protected:
- virtual ~RTSPSource();
+ virtual ~RTSPSource2();
virtual sp<MetaData> getFormatMeta(bool audio);
@@ -161,9 +161,9 @@
bool sourceNearEOS(bool audio);
bool sourceReachedEOS(bool audio);
- DISALLOW_EVIL_CONSTRUCTORS(RTSPSource);
+ DISALLOW_EVIL_CONSTRUCTORS(RTSPSource2);
};
} // namespace android
-#endif // RTSP_SOURCE_H_
+#endif // RTSP_SOURCE2_H_
diff --git a/media/libmedia/nuplayer2/StreamingSource.cpp b/media/libmedia/nuplayer2/StreamingSource.cpp
deleted file mode 100644
index 1c370b6..0000000
--- a/media/libmedia/nuplayer2/StreamingSource.cpp
+++ /dev/null
@@ -1,310 +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 "StreamingSource"
-#include <utils/Log.h>
-
-#include "StreamingSource.h"
-
-#include "ATSParser.h"
-#include "AnotherPacketSource.h"
-#include "NuPlayer2StreamListener.h"
-
-#include <media/MediaSource.h>
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/foundation/MediaKeys.h>
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/Utils.h>
-
-namespace android {
-
-const int32_t kNumListenerQueuePackets = 80;
-
-NuPlayer2::StreamingSource::StreamingSource(
- const sp<AMessage> ¬ify,
- const sp<IStreamSource> &source)
- : Source(notify),
- mSource(source),
- mFinalResult(OK),
- mBuffering(false) {
-}
-
-NuPlayer2::StreamingSource::~StreamingSource() {
- if (mLooper != NULL) {
- mLooper->unregisterHandler(id());
- mLooper->stop();
- }
-}
-
-status_t NuPlayer2::StreamingSource::getBufferingSettings(
- BufferingSettings *buffering /* nonnull */) {
- *buffering = BufferingSettings();
- return OK;
-}
-
-status_t NuPlayer2::StreamingSource::setBufferingSettings(
- const BufferingSettings & /* buffering */) {
- return OK;
-}
-
-void NuPlayer2::StreamingSource::prepareAsync() {
- if (mLooper == NULL) {
- mLooper = new ALooper;
- mLooper->setName("streaming");
- mLooper->start();
-
- mLooper->registerHandler(this);
- }
-
- notifyVideoSizeChanged();
- notifyFlagsChanged(0);
- notifyPrepared();
-}
-
-void NuPlayer2::StreamingSource::start() {
- mStreamListener = new StreamListener(mSource, NULL);
-
- uint32_t sourceFlags = mSource->flags();
-
- uint32_t parserFlags = ATSParser::TS_TIMESTAMPS_ARE_ABSOLUTE;
- if (sourceFlags & IStreamSource::kFlagAlignedVideoData) {
- parserFlags |= ATSParser::ALIGNED_VIDEO_DATA;
- }
-
- mTSParser = new ATSParser(parserFlags);
-
- mStreamListener->start();
-
- postReadBuffer();
-}
-
-status_t NuPlayer2::StreamingSource::feedMoreTSData() {
- return postReadBuffer();
-}
-
-void NuPlayer2::StreamingSource::onReadBuffer() {
- for (int32_t i = 0; i < kNumListenerQueuePackets; ++i) {
- char buffer[188];
- sp<AMessage> extra;
- ssize_t n = mStreamListener->read(buffer, sizeof(buffer), &extra);
-
- if (n == 0) {
- ALOGI("input data EOS reached.");
- mTSParser->signalEOS(ERROR_END_OF_STREAM);
- setError(ERROR_END_OF_STREAM);
- break;
- } else if (n == INFO_DISCONTINUITY) {
- int32_t type = ATSParser::DISCONTINUITY_TIME;
-
- int32_t mask;
- if (extra != NULL
- && extra->findInt32(
- kIStreamListenerKeyDiscontinuityMask, &mask)) {
- if (mask == 0) {
- ALOGE("Client specified an illegal discontinuity type.");
- setError(ERROR_UNSUPPORTED);
- break;
- }
-
- type = mask;
- }
-
- mTSParser->signalDiscontinuity(
- (ATSParser::DiscontinuityType)type, extra);
- } else if (n < 0) {
- break;
- } else {
- if (buffer[0] == 0x00) {
- // XXX legacy
-
- if (extra == NULL) {
- extra = new AMessage;
- }
-
- uint8_t type = buffer[1];
-
- if (type & 2) {
- int64_t mediaTimeUs;
- memcpy(&mediaTimeUs, &buffer[2], sizeof(mediaTimeUs));
-
- extra->setInt64(kATSParserKeyMediaTimeUs, mediaTimeUs);
- }
-
- mTSParser->signalDiscontinuity(
- ((type & 1) == 0)
- ? ATSParser::DISCONTINUITY_TIME
- : ATSParser::DISCONTINUITY_FORMATCHANGE,
- extra);
- } else {
- status_t err = mTSParser->feedTSPacket(buffer, sizeof(buffer));
-
- if (err != OK) {
- ALOGE("TS Parser returned error %d", err);
-
- mTSParser->signalEOS(err);
- setError(err);
- break;
- }
- }
- }
- }
-}
-
-status_t NuPlayer2::StreamingSource::postReadBuffer() {
- {
- Mutex::Autolock _l(mBufferingLock);
- if (mFinalResult != OK) {
- return mFinalResult;
- }
- if (mBuffering) {
- return OK;
- }
- mBuffering = true;
- }
-
- (new AMessage(kWhatReadBuffer, this))->post();
- return OK;
-}
-
-bool NuPlayer2::StreamingSource::haveSufficientDataOnAllTracks() {
- // We're going to buffer at least 2 secs worth data on all tracks before
- // starting playback (both at startup and after a seek).
-
- static const int64_t kMinDurationUs = 2000000ll;
-
- sp<AnotherPacketSource> audioTrack = getSource(true /*audio*/);
- sp<AnotherPacketSource> videoTrack = getSource(false /*audio*/);
-
- status_t err;
- int64_t durationUs;
- if (audioTrack != NULL
- && (durationUs = audioTrack->getBufferedDurationUs(&err))
- < kMinDurationUs
- && err == OK) {
- ALOGV("audio track doesn't have enough data yet. (%.2f secs buffered)",
- durationUs / 1E6);
- return false;
- }
-
- if (videoTrack != NULL
- && (durationUs = videoTrack->getBufferedDurationUs(&err))
- < kMinDurationUs
- && err == OK) {
- ALOGV("video track doesn't have enough data yet. (%.2f secs buffered)",
- durationUs / 1E6);
- return false;
- }
-
- return true;
-}
-
-void NuPlayer2::StreamingSource::setError(status_t err) {
- Mutex::Autolock _l(mBufferingLock);
- mFinalResult = err;
-}
-
-sp<AnotherPacketSource> NuPlayer2::StreamingSource::getSource(bool audio) {
- if (mTSParser == NULL) {
- return NULL;
- }
-
- sp<MediaSource> source = mTSParser->getSource(
- audio ? ATSParser::AUDIO : ATSParser::VIDEO);
-
- return static_cast<AnotherPacketSource *>(source.get());
-}
-
-sp<AMessage> NuPlayer2::StreamingSource::getFormat(bool audio) {
- sp<AnotherPacketSource> source = getSource(audio);
-
- sp<AMessage> format = new AMessage;
- if (source == NULL) {
- format->setInt32("err", -EWOULDBLOCK);
- return format;
- }
-
- sp<MetaData> meta = source->getFormat();
- if (meta == NULL) {
- format->setInt32("err", -EWOULDBLOCK);
- return format;
- }
- status_t err = convertMetaDataToMessage(meta, &format);
- if (err != OK) { // format may have been cleared on error
- return NULL;
- }
- return format;
-}
-
-status_t NuPlayer2::StreamingSource::dequeueAccessUnit(
- bool audio, sp<ABuffer> *accessUnit) {
- sp<AnotherPacketSource> source = getSource(audio);
-
- if (source == NULL) {
- return -EWOULDBLOCK;
- }
-
- if (!haveSufficientDataOnAllTracks()) {
- postReadBuffer();
- }
-
- status_t finalResult;
- if (!source->hasBufferAvailable(&finalResult)) {
- return finalResult == OK ? -EWOULDBLOCK : finalResult;
- }
-
- status_t err = source->dequeueAccessUnit(accessUnit);
-
-#if !defined(LOG_NDEBUG) || LOG_NDEBUG == 0
- if (err == OK) {
- int64_t timeUs;
- CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs));
- ALOGV("dequeueAccessUnit timeUs=%lld us", timeUs);
- }
-#endif
-
- return err;
-}
-
-bool NuPlayer2::StreamingSource::isRealTime() const {
- return mSource->flags() & IStreamSource::kFlagIsRealTimeData;
-}
-
-void NuPlayer2::StreamingSource::onMessageReceived(
- const sp<AMessage> &msg) {
- switch (msg->what()) {
- case kWhatReadBuffer:
- {
- onReadBuffer();
-
- {
- Mutex::Autolock _l(mBufferingLock);
- mBuffering = false;
- }
- break;
- }
- default:
- {
- TRESPASS();
- }
- }
-}
-
-
-} // namespace android
-
diff --git a/media/libmedia/nuplayer2/StreamingSource.h b/media/libmedia/nuplayer2/StreamingSource.h
deleted file mode 100644
index 4b89c38..0000000
--- a/media/libmedia/nuplayer2/StreamingSource.h
+++ /dev/null
@@ -1,79 +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 STREAMING_SOURCE_H_
-
-#define STREAMING_SOURCE_H_
-
-#include "NuPlayer2.h"
-#include "NuPlayer2Source.h"
-
-namespace android {
-
-struct ABuffer;
-struct ATSParser;
-struct AnotherPacketSource;
-
-struct NuPlayer2::StreamingSource : public NuPlayer2::Source {
- StreamingSource(
- const sp<AMessage> ¬ify,
- const sp<IStreamSource> &source);
-
- virtual status_t getBufferingSettings(
- BufferingSettings* buffering /* nonnull */) override;
- virtual status_t setBufferingSettings(const BufferingSettings& buffering) override;
-
- virtual void prepareAsync();
- virtual void start();
-
- virtual status_t feedMoreTSData();
-
- virtual status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
-
- virtual bool isRealTime() const;
-
-protected:
- virtual ~StreamingSource();
-
- virtual void onMessageReceived(const sp<AMessage> &msg);
-
- virtual sp<AMessage> getFormat(bool audio);
-
-private:
- enum {
- kWhatReadBuffer,
- };
- sp<IStreamSource> mSource;
- status_t mFinalResult;
- sp<StreamListener> mStreamListener;
- sp<ATSParser> mTSParser;
-
- bool mBuffering;
- Mutex mBufferingLock;
- sp<ALooper> mLooper;
-
- void setError(status_t err);
- sp<AnotherPacketSource> getSource(bool audio);
- bool haveSufficientDataOnAllTracks();
- status_t postReadBuffer();
- void onReadBuffer();
-
- DISALLOW_EVIL_CONSTRUCTORS(StreamingSource);
-};
-
-} // namespace android
-
-#endif // STREAMING_SOURCE_H_
diff --git a/media/libmediaextractor/include/media/MediaExtractor.h b/media/libmediaextractor/include/media/MediaExtractor.h
index 60495ec..73c5f10 100644
--- a/media/libmediaextractor/include/media/MediaExtractor.h
+++ b/media/libmediaextractor/include/media/MediaExtractor.h
@@ -32,7 +32,6 @@
class String8;
struct AMessage;
struct MediaSourceBase;
-typedef std::vector<uint8_t> HInterfaceToken;
class ExtractorAllocTracker {
@@ -81,7 +80,7 @@
}
virtual void setUID(uid_t /*uid*/) {
}
- virtual status_t setMediaCas(const HInterfaceToken &/*casToken*/) {
+ virtual status_t setMediaCas(const uint8_t* /*casToken*/, size_t /*size*/) {
return INVALID_OPERATION;
}
diff --git a/media/libstagefright/RemoteMediaExtractor.cpp b/media/libstagefright/RemoteMediaExtractor.cpp
index 601c9fa..d190780 100644
--- a/media/libstagefright/RemoteMediaExtractor.cpp
+++ b/media/libstagefright/RemoteMediaExtractor.cpp
@@ -127,7 +127,7 @@
}
status_t RemoteMediaExtractor::setMediaCas(const HInterfaceToken &casToken) {
- return mExtractor->setMediaCas(casToken);
+ return mExtractor->setMediaCas((uint8_t*)casToken.data(), casToken.size());
}
const char * RemoteMediaExtractor::name() {
diff --git a/packages/MediaComponents/res/values/themes.xml b/packages/MediaComponents/res/values/themes.xml
index 51098e9..d9a754b 100644
--- a/packages/MediaComponents/res/values/themes.xml
+++ b/packages/MediaComponents/res/values/themes.xml
@@ -16,8 +16,8 @@
<resources>
- <style name="Theme.MediaRouter" parent="ThemeOverlay.AppCompat.Dark">
- <item name="windowNoTitle">true</item>
+ <style name="Theme.MediaRouter" parent="android:Theme.Material">
+ <item name="android:windowNoTitle">true</item>
<item name="mediaRouteButtonStyle">@style/Widget.MediaRouter.MediaRouteButton</item>
<item name="mediaRouteCloseDrawable">@drawable/mr_dialog_close_dark</item>
@@ -37,8 +37,8 @@
<item name="mediaRouteControlPanelThemeOverlay">@style/ThemeOverlay.MediaRouter.Light</item>
</style>
- <style name="Theme.MediaRouter.Light" parent="ThemeOverlay.AppCompat.Light">
- <item name="windowNoTitle">true</item>
+ <style name="Theme.MediaRouter.Light" parent="android:Theme.Material.Light">
+ <item name="android:windowNoTitle">true</item>
<item name="mediaRouteButtonStyle">@style/Widget.MediaRouter.Light.MediaRouteButton</item>
<item name="mediaRouteCloseDrawable">@drawable/mr_dialog_close_light</item>
@@ -58,14 +58,14 @@
<item name="mediaRouteControlPanelThemeOverlay">@style/ThemeOverlay.MediaRouter.Dark</item>
</style>
- <style name="ThemeOverlay.MediaRouter.Dark" parent="ThemeOverlay.AppCompat.Dark">
+ <style name="ThemeOverlay.MediaRouter.Dark" parent="android:Theme.Material">
<item name="mediaRoutePlayDrawable">@drawable/mr_media_play_dark</item>
<item name="mediaRoutePauseDrawable">@drawable/mr_media_pause_dark</item>
<item name="mediaRouteStopDrawable">@drawable/mr_media_stop_dark</item>
<item name="mediaRouteAudioTrackDrawable">@drawable/mr_vol_type_audiotrack_dark</item>
</style>
- <style name="ThemeOverlay.MediaRouter.Light" parent="ThemeOverlay.AppCompat.Light">
+ <style name="ThemeOverlay.MediaRouter.Light" parent="android:Theme.Material.Light">
<item name="mediaRoutePlayDrawable">@drawable/mr_media_play_light</item>
<item name="mediaRoutePauseDrawable">@drawable/mr_media_pause_light</item>
<item name="mediaRouteStopDrawable">@drawable/mr_media_stop_light</item>
diff --git a/packages/MediaComponents/src/com/android/media/IMediaSession2.aidl b/packages/MediaComponents/src/com/android/media/IMediaSession2.aidl
index d5bd354..7702bda 100644
--- a/packages/MediaComponents/src/com/android/media/IMediaSession2.aidl
+++ b/packages/MediaComponents/src/com/android/media/IMediaSession2.aidl
@@ -18,6 +18,7 @@
import android.os.Bundle;
import android.os.ResultReceiver;
+import android.net.Uri;
import com.android.media.IMediaSession2Callback;
@@ -27,8 +28,7 @@
* Keep this interface oneway. Otherwise a malicious app may implement fake version of this,
* and holds calls from session to make session owner(s) frozen.
*/
-// TODO: Consider to make some methods oneway
-interface IMediaSession2 {
+oneway interface IMediaSession2 {
// TODO(jaewan): add onCommand() to send private command
// TODO(jaewan): Due to the nature of oneway calls, APIs can be called in out of order
// Add id for individual calls to address this.
@@ -40,6 +40,9 @@
void connect(String callingPackage, IMediaSession2Callback callback);
void release(IMediaSession2Callback caller);
+ void setVolumeTo(IMediaSession2Callback caller, int value, int flags);
+ void adjustVolume(IMediaSession2Callback caller, int direction, int flags);
+
//////////////////////////////////////////////////////////////////////////////////////////////
// send command
//////////////////////////////////////////////////////////////////////////////////////////////
@@ -49,7 +52,14 @@
void sendCustomCommand(IMediaSession2Callback caller, in Bundle command, in Bundle args,
in ResultReceiver receiver);
- //////////////////////////////////////////////////////////////////////////////////////////////
+ void prepareFromUri(IMediaSession2Callback caller, in Uri uri, in Bundle extra);
+ void prepareFromSearch(IMediaSession2Callback caller, String query, in Bundle extra);
+ void prepareFromMediaId(IMediaSession2Callback caller, String mediaId, in Bundle extra);
+ void playFromUri(IMediaSession2Callback caller, in Uri uri, in Bundle extra);
+ void playFromSearch(IMediaSession2Callback caller, String query, in Bundle extra);
+ void playFromMediaId(IMediaSession2Callback caller, String mediaId, in Bundle extra);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
// Get library service specific
//////////////////////////////////////////////////////////////////////////////////////////////
void getBrowserRoot(IMediaSession2Callback callback, in Bundle rootHints);
diff --git a/packages/MediaComponents/src/com/android/media/IMediaSession2Callback.aidl b/packages/MediaComponents/src/com/android/media/IMediaSession2Callback.aidl
index eaf404c..a443bf8 100644
--- a/packages/MediaComponents/src/com/android/media/IMediaSession2Callback.aidl
+++ b/packages/MediaComponents/src/com/android/media/IMediaSession2Callback.aidl
@@ -16,6 +16,7 @@
package com.android.media;
+import android.app.PendingIntent;
import android.os.Bundle;
import android.os.ResultReceiver;
@@ -33,19 +34,11 @@
void onPlaylistParamsChanged(in Bundle params);
void onPlaybackInfoChanged(in Bundle playbackInfo);
- /**
- * Called only when the controller is created with service's token.
- *
- * @param sessionBinder {@code null} if the connect is rejected or is disconnected. a session
- * binder if the connect is accepted.
- * @param commands initially allowed commands.
- */
- // TODO(jaewan): Also need to pass flags for allowed actions for permission check.
- // For example, a media can allow setRating only for whitelisted apps
- // it's better for controller to know such information in advance.
- // Follow-up TODO: Add similar functions to the session.
- // TODO(jaewan): Is term 'accepted/rejected' correct? For permission, 'grant' is used.
- void onConnectionChanged(IMediaSession2 sessionBinder, in Bundle commandGroup);
+ // TODO(jaewan): Handle when the playlist becomes too huge.
+ void onConnected(IMediaSession2 sessionBinder, in Bundle commandGroup, in Bundle playbackState,
+ in Bundle playbackInfo, in Bundle params, in List<Bundle> playlist, int ratingType,
+ in PendingIntent sessionActivity);
+ void onDisconnected();
void onCustomLayoutChanged(in List<Bundle> commandButtonlist);
diff --git a/packages/MediaComponents/src/com/android/media/MediaController2Impl.java b/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
index 6ee79a0..a477d1d 100644
--- a/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
@@ -76,6 +76,12 @@
private PlaylistParams mPlaylistParams;
@GuardedBy("mLock")
private PlaybackInfo mPlaybackInfo;
+ @GuardedBy("mLock")
+ private int mRatingType;
+ @GuardedBy("mLock")
+ private PendingIntent mSessionActivity;
+ @GuardedBy("mLock")
+ private CommandGroup mCommandGroup;
// Assignment should be used with the lock hold, but should be used without a lock to prevent
// potential deadlock.
@@ -274,56 +280,127 @@
//////////////////////////////////////////////////////////////////////////////////////
@Override
public PendingIntent getSessionActivity_impl() {
- // TODO(jaewan): Implement
- return null;
+ return mSessionActivity;
}
@Override
public int getRatingType_impl() {
- // TODO(jaewan): Implement
- return 0;
+ return mRatingType;
}
@Override
public void setVolumeTo_impl(int value, int flags) {
- // TODO(jaewan): Implement
+ // TODO(hdmoon): sanity check
+ final IMediaSession2 binder = mSessionBinder;
+ if (binder != null) {
+ try {
+ binder.setVolumeTo(mSessionCallbackStub, value, flags);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Cannot connect to the service or the session is gone", e);
+ }
+ } else {
+ Log.w(TAG, "Session isn't active", new IllegalStateException());
+ }
}
@Override
public void adjustVolume_impl(int direction, int flags) {
- // TODO(jaewan): Implement
+ // TODO(hdmoon): sanity check
+ final IMediaSession2 binder = mSessionBinder;
+ if (binder != null) {
+ try {
+ binder.adjustVolume(mSessionCallbackStub, direction, flags);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Cannot connect to the service or the session is gone", e);
+ }
+ } else {
+ Log.w(TAG, "Session isn't active", new IllegalStateException());
+ }
}
@Override
public void prepareFromUri_impl(Uri uri, Bundle extras) {
- // TODO(jaewan): Implement
+ final IMediaSession2 binder = mSessionBinder;
+ if (binder != null) {
+ try {
+ binder.prepareFromUri(mSessionCallbackStub, uri, extras);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Cannot connect to the service or the session is gone", e);
+ }
+ } else {
+ // TODO(jaewan): Handle.
+ }
}
@Override
public void prepareFromSearch_impl(String query, Bundle extras) {
- // TODO(jaewan): Implement
+ final IMediaSession2 binder = mSessionBinder;
+ if (binder != null) {
+ try {
+ binder.prepareFromSearch(mSessionCallbackStub, query, extras);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Cannot connect to the service or the session is gone", e);
+ }
+ } else {
+ // TODO(jaewan): Handle.
+ }
}
@Override
public void prepareMediaId_impl(String mediaId, Bundle extras) {
- // TODO(jaewan): Implement
+ final IMediaSession2 binder = mSessionBinder;
+ if (binder != null) {
+ try {
+ binder.prepareFromMediaId(mSessionCallbackStub, mediaId, extras);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Cannot connect to the service or the session is gone", e);
+ }
+ } else {
+ // TODO(jaewan): Handle.
+ }
+ }
+
+ @Override
+ public void playFromUri_impl(Uri uri, Bundle extras) {
+ final IMediaSession2 binder = mSessionBinder;
+ if (binder != null) {
+ try {
+ binder.playFromUri(mSessionCallbackStub, uri, extras);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Cannot connect to the service or the session is gone", e);
+ }
+ } else {
+ // TODO(jaewan): Handle.
+ }
}
@Override
public void playFromSearch_impl(String query, Bundle extras) {
- // TODO(jaewan): Implement
- }
-
- @Override
- public void playFromUri_impl(String uri, Bundle extras) {
- // TODO(jaewan): Implement
+ final IMediaSession2 binder = mSessionBinder;
+ if (binder != null) {
+ try {
+ binder.playFromSearch(mSessionCallbackStub, query, extras);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Cannot connect to the service or the session is gone", e);
+ }
+ } else {
+ // TODO(jaewan): Handle.
+ }
}
@Override
public void playFromMediaId_impl(String mediaId, Bundle extras) {
- // TODO(jaewan): Implement
+ final IMediaSession2 binder = mSessionBinder;
+ if (binder != null) {
+ try {
+ binder.playFromMediaId(mSessionCallbackStub, mediaId, extras);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Cannot connect to the service or the session is gone", e);
+ }
+ } else {
+ // TODO(jaewan): Handle.
+ }
}
-
@Override
public void setRating_impl(Rating2 rating) {
// TODO(jaewan): Implement
@@ -484,19 +561,20 @@
}
}
- // Called when the result for connecting to the session was delivered.
// Should be used without a lock to prevent potential deadlock.
- private void onConnectionChangedNotLocked(IMediaSession2 sessionBinder,
- CommandGroup commandGroup) {
+ private void onConnectedNotLocked(IMediaSession2 sessionBinder,
+ final CommandGroup commandGroup, final PlaybackState2 state, final PlaybackInfo info,
+ final PlaylistParams params, final List<MediaItem2> playlist, final int ratingType,
+ final PendingIntent sessionActivity) {
if (DEBUG) {
- Log.d(TAG, "onConnectionChangedNotLocked sessionBinder=" + sessionBinder
+ Log.d(TAG, "onConnectedNotLocked sessionBinder=" + sessionBinder
+ ", commands=" + commandGroup);
}
- boolean release = false;
+ boolean close = false;
try {
if (sessionBinder == null || commandGroup == null) {
// Connection rejected.
- release = true;
+ close = true;
return;
}
synchronized (mLock) {
@@ -506,9 +584,16 @@
if (mSessionBinder != null) {
Log.e(TAG, "Cannot be notified about the connection result many times."
+ " Probably a bug or malicious app.");
- release = true;
+ close = true;
return;
}
+ mCommandGroup = commandGroup;
+ mPlaybackState = state;
+ mPlaybackInfo = info;
+ mPlaylistParams = params;
+ mPlaylist = playlist;
+ mRatingType = ratingType;
+ mSessionActivity = sessionActivity;
mSessionBinder = sessionBinder;
try {
// Implementation for the local binder is no-op,
@@ -518,16 +603,19 @@
if (DEBUG) {
Log.d(TAG, "Session died too early.", e);
}
- release = true;
+ close = true;
return;
}
}
// TODO(jaewan): Keep commands to prevents illegal API calls.
mCallbackExecutor.execute(() -> {
+ // Note: We may trigger ControllerCallbacks with the initial values
+ // But it's hard to define the order of the controller callbacks
+ // Only notify about the
mCallback.onConnected(commandGroup);
});
} finally {
- if (release) {
+ if (close) {
// Trick to call release() without holding the lock, to prevent potential deadlock
// with the developer's custom lock within the ControllerCallback.onDisconnected().
mInstance.close();
@@ -619,6 +707,9 @@
@Override
public void onPlaybackInfoChanged(Bundle playbackInfo) throws RuntimeException {
+ if (DEBUG) {
+ Log.d(TAG, "onPlaybackInfoChanged");
+ }
final MediaController2Impl controller;
try {
controller = getController();
@@ -631,17 +722,42 @@
}
@Override
- public void onConnectionChanged(IMediaSession2 sessionBinder, Bundle commandGroup)
- throws RuntimeException {
- final MediaController2Impl controller;
- try {
- controller = getController();
- } catch (IllegalStateException e) {
- Log.w(TAG, "Don't fail silently here. Highly likely a bug");
+ public void onConnected(IMediaSession2 sessionBinder, Bundle commandGroup,
+ Bundle playbackState, Bundle playbackInfo, Bundle playlistParams, List<Bundle>
+ playlist, int ratingType, PendingIntent sessionActivity) {
+ final MediaController2Impl controller = mController.get();
+ if (controller == null) {
+ if (DEBUG) {
+ Log.d(TAG, "onConnected after MediaController2.close()");
+ }
return;
}
- controller.onConnectionChangedNotLocked(
- sessionBinder, CommandGroup.fromBundle(controller.getContext(), commandGroup));
+ final Context context = controller.getContext();
+ List<MediaItem2> list = new ArrayList<>();
+ for (int i = 0; i < playlist.size(); i++) {
+ MediaItem2 item = MediaItem2.fromBundle(context, playlist.get(i));
+ if (item != null) {
+ list.add(item);
+ }
+ }
+ controller.onConnectedNotLocked(sessionBinder,
+ CommandGroup.fromBundle(context, commandGroup),
+ PlaybackState2.fromBundle(context, playbackState),
+ PlaybackInfoImpl.fromBundle(context, playbackInfo),
+ PlaylistParams.fromBundle(context, playlistParams),
+ list, ratingType, sessionActivity);
+ }
+
+ @Override
+ public void onDisconnected() {
+ final MediaController2Impl controller = mController.get();
+ if (controller == null) {
+ if (DEBUG) {
+ Log.d(TAG, "onDisconnected after MediaController2.close()");
+ }
+ return;
+ }
+ controller.mInstance.close();
}
@Override
@@ -667,6 +783,7 @@
// Illegal call. Ignore
return;
}
+ // TODO(jaewan): Fix here. It's controller feature so shouldn't use browser
final MediaBrowser2Impl browser;
try {
browser = getBrowser();
diff --git a/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java b/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
index cde98d2..f323a17 100644
--- a/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
@@ -85,6 +85,8 @@
private final SessionToken2 mSessionToken;
private final AudioManager mAudioManager;
private final List<PlaybackListenerHolder> mListeners = new ArrayList<>();
+ private final int mRatingType;
+ private final PendingIntent mSessionActivity;
@GuardedBy("mLock")
private MediaPlayerInterface mPlayer;
@@ -102,7 +104,6 @@
/**
* Can be only called by the {@link Builder#build()}.
*
- * @param instance
* @param context
* @param player
* @param id
@@ -123,6 +124,8 @@
mId = id;
mCallback = callback;
mCallbackExecutor = callbackExecutor;
+ mRatingType = ratingType;
+ mSessionActivity = sessionActivity;
mSessionStub = new MediaSession2Stub(this);
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
@@ -195,9 +198,6 @@
if (player == null) {
throw new IllegalArgumentException("player shouldn't be null");
}
- if (player == mPlayer) {
- return;
- }
PlaybackInfo info =
createPlaybackInfo(null /* VolumeProvider */, player.getAudioAttributes());
synchronized (mLock) {
@@ -218,10 +218,6 @@
if (volumeProvider == null) {
throw new IllegalArgumentException("volumeProvider shouldn't be null");
}
- if (player == mPlayer) {
- return;
- }
-
PlaybackInfo info = createPlaybackInfo(volumeProvider, player.getAudioAttributes());
synchronized (mLock) {
setPlayerLocked(player);
@@ -244,12 +240,25 @@
private PlaybackInfo createPlaybackInfo(VolumeProvider2 volumeProvider, AudioAttributes attrs) {
PlaybackInfo info;
if (volumeProvider == null) {
- int stream = attrs == null ? AudioManager.STREAM_MUSIC : attrs.getVolumeControlStream();
+ int stream;
+ if (attrs == null) {
+ stream = AudioManager.STREAM_MUSIC;
+ } else {
+ stream = attrs.getVolumeControlStream();
+ if (stream == AudioManager.USE_DEFAULT_STREAM_TYPE) {
+ // It may happen if the AudioAttributes doesn't have usage.
+ // Change it to the STREAM_MUSIC because it's not supported by audio manager
+ // for querying volume level.
+ stream = AudioManager.STREAM_MUSIC;
+ }
+ }
info = PlaybackInfoImpl.createPlaybackInfo(
mContext,
PlaybackInfo.PLAYBACK_TYPE_LOCAL,
attrs,
- VolumeProvider2.VOLUME_CONTROL_ABSOLUTE,
+ mAudioManager.isVolumeFixed()
+ ? VolumeProvider2.VOLUME_CONTROL_FIXED
+ : VolumeProvider2.VOLUME_CONTROL_ABSOLUTE,
mAudioManager.getStreamMaxVolume(stream),
mAudioManager.getStreamVolume(stream));
} else {
@@ -559,6 +568,24 @@
return mCallback;
}
+ VolumeProvider2 getVolumeProvider() {
+ return mVolumeProvider;
+ }
+
+ PlaybackInfo getPlaybackInfo() {
+ synchronized (mLock) {
+ return mPlaybackInfo;
+ }
+ }
+
+ int getRatingType() {
+ return mRatingType;
+ }
+
+ PendingIntent getSessionActivity() {
+ return mSessionActivity;
+ }
+
private static class MyPlaybackListener implements MediaPlayerInterface.PlaybackListener {
private final WeakReference<MediaSession2Impl> mSession;
private final MediaPlayerInterface mPlayer;
diff --git a/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java b/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
index 5d3a06e..2380fc0 100644
--- a/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
+++ b/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
@@ -16,8 +16,10 @@
package com.android.media;
+import android.app.PendingIntent;
import android.content.Context;
import android.media.MediaController2;
+import android.media.MediaController2.PlaybackInfo;
import android.media.MediaItem2;
import android.media.MediaLibraryService2.LibraryRoot;
import android.media.MediaLibraryService2.MediaLibrarySessionCallback;
@@ -28,7 +30,9 @@
import android.media.MediaSession2.ControllerInfo;
import android.media.MediaSession2.PlaylistParams;
import android.media.PlaybackState2;
+import android.media.VolumeProvider2;
import android.media.update.MediaSession2Provider.CommandButtonProvider;
+import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
@@ -77,7 +81,7 @@
((ControllerInfoImpl) list.get(i).getProvider()).getControllerBinder();
try {
// Should be used without a lock hold to prevent potential deadlock.
- callbackBinder.onConnectionChanged(null, null);
+ callbackBinder.onDisconnected();
} catch (RemoteException e) {
// Controller is gone. Should be fine because we're destroying.
}
@@ -110,7 +114,11 @@
// media keys to.
boolean accept = allowedCommands != null || request.isTrusted();
ControllerInfoImpl impl = ControllerInfoImpl.from(request);
- if (accept) {
+ if (accept && allowedCommands != null) {
+ if (DEBUG) {
+ Log.d(TAG, "Accepting connection, request=" + request
+ + " allowedCommands=" + allowedCommands);
+ }
synchronized (mLock) {
mControllers.put(impl.getId(), request);
}
@@ -118,20 +126,6 @@
// For trusted apps, send non-null allowed commands to keep connection.
allowedCommands = new CommandGroup(context);
}
- }
- if (DEBUG) {
- Log.d(TAG, "onConnectResult, request=" + request
- + " accept=" + accept);
- }
- try {
- callback.onConnectionChanged(
- accept ? MediaSession2Stub.this : null,
- allowedCommands == null ? null : allowedCommands.toBundle());
- } catch (RemoteException e) {
- // Controller may be died prematurely.
- }
- if (accept) {
- // TODO(jaewan): We need to send current PlaybackInfo.
// If connection is accepted, notify the current state to the controller.
// It's needed because we cannot call synchronous calls between session/controller.
// Note: We're doing this after the onConnectionChanged(), but there's no guarantee
@@ -140,12 +134,50 @@
// use thread poll for incoming calls.
// TODO(jaewan): Should we protect getting playback state?
final PlaybackState2 state = session.getInstance().getPlaybackState();
- final Bundle bundle = state != null ? state.toBundle() : null;
+ final Bundle playbackStateBundle = (state != null) ? state.toBundle() : null;
+ final Bundle playbackInfoBundle =
+ ((PlaybackInfoImpl) session.getPlaybackInfo().getProvider()).toBundle();
+ final PlaylistParams params = session.getInstance().getPlaylistParams();
+ final Bundle paramsBundle = (params != null) ? params.toBundle() : null;
+ final int ratingType = session.getRatingType();
+ final PendingIntent sessionActivity = session.getSessionActivity();
+ final List<MediaItem2> playlist = session.getInstance().getPlaylist();
+ final List<Bundle> playlistBundle = new ArrayList<>();
+ if (playlist != null) {
+ // TODO(jaewan): Find a way to avoid concurrent modification exception.
+ for (int i = 0; i < playlist.size(); i++) {
+ final MediaItem2 item = playlist.get(i);
+ if (item != null) {
+ final Bundle itemBundle = item.toBundle();
+ if (itemBundle != null) {
+ playlistBundle.add(itemBundle);
+ }
+ }
+ }
+ }
+
+ // Double check if session is still there, because close() can be called in another
+ // thread.
+ if (mSession.get() == null) {
+ return;
+ }
try {
- callback.onPlaybackStateChanged(bundle);
+ callback.onConnected(MediaSession2Stub.this,
+ allowedCommands.toBundle(), playbackStateBundle, playbackInfoBundle,
+ paramsBundle, playlistBundle, ratingType, sessionActivity);
} catch (RemoteException e) {
- // TODO(jaewan): Handle this.
// Controller may be died prematurely.
+ // TODO(jaewan): Handle here.
+ }
+ } else {
+ if (DEBUG) {
+ Log.d(TAG, "Rejecting connection, request=" + request);
+ }
+ try {
+ callback.onDisconnected();
+ } catch (RemoteException e) {
+ // Controller may be died prematurely.
+ // Not an issue because we'll ignore it anyway.
}
}
});
@@ -162,6 +194,82 @@
}
@Override
+ public void setVolumeTo(IMediaSession2Callback caller, int value, int flags)
+ throws RuntimeException {
+ final MediaSession2Impl sessionImpl = getSession();
+ final ControllerInfo controller = getController(caller);
+ if (controller == null) {
+ if (DEBUG) {
+ Log.d(TAG, "Command from a controller that hasn't connected. Ignore");
+ }
+ return;
+ }
+ sessionImpl.getCallbackExecutor().execute(() -> {
+ final MediaSession2Impl session = mSession.get();
+ if (session == null) {
+ return;
+ }
+ // TODO(jaewan): Sanity check.
+ Command command = new Command(
+ session.getContext(), MediaSession2.COMMAND_CODE_SET_VOLUME);
+ boolean accepted = session.getCallback().onCommandRequest(controller, command);
+ if (!accepted) {
+ // Don't run rejected command.
+ if (DEBUG) {
+ Log.d(TAG, "Command " + MediaSession2.COMMAND_CODE_SET_VOLUME + " from "
+ + controller + " was rejected by " + session);
+ }
+ return;
+ }
+
+ VolumeProvider2 volumeProvider = session.getVolumeProvider();
+ if (volumeProvider == null) {
+ // TODO(jaewan): Set local stream volume
+ } else {
+ volumeProvider.onSetVolumeTo(value);
+ }
+ });
+ }
+
+ @Override
+ public void adjustVolume(IMediaSession2Callback caller, int direction, int flags)
+ throws RuntimeException {
+ final MediaSession2Impl sessionImpl = getSession();
+ final ControllerInfo controller = getController(caller);
+ if (controller == null) {
+ if (DEBUG) {
+ Log.d(TAG, "Command from a controller that hasn't connected. Ignore");
+ }
+ return;
+ }
+ sessionImpl.getCallbackExecutor().execute(() -> {
+ final MediaSession2Impl session = mSession.get();
+ if (session == null) {
+ return;
+ }
+ // TODO(jaewan): Sanity check.
+ Command command = new Command(
+ session.getContext(), MediaSession2.COMMAND_CODE_SET_VOLUME);
+ boolean accepted = session.getCallback().onCommandRequest(controller, command);
+ if (!accepted) {
+ // Don't run rejected command.
+ if (DEBUG) {
+ Log.d(TAG, "Command " + MediaSession2.COMMAND_CODE_SET_VOLUME + " from "
+ + controller + " was rejected by " + session);
+ }
+ return;
+ }
+
+ VolumeProvider2 volumeProvider = session.getVolumeProvider();
+ if (volumeProvider == null) {
+ // TODO(jaewan): Adjust local stream volume
+ } else {
+ volumeProvider.onAdjustVolume(direction);
+ }
+ });
+ }
+
+ @Override
public void sendCommand(IMediaSession2Callback caller, Bundle command, Bundle args)
throws RuntimeException {
// TODO(jaewan): Generic command
@@ -260,6 +368,126 @@
}
@Override
+ public void prepareFromUri(final IMediaSession2Callback caller, final Uri uri,
+ final Bundle extra) {
+ final MediaSession2Impl sessionImpl = getSession();
+ final ControllerInfo controller = getController(caller);
+ if (controller == null) {
+ if (DEBUG) {
+ Log.d(TAG, "Command from a controller that hasn't connected. Ignore");
+ }
+ return;
+ }
+ sessionImpl.getCallbackExecutor().execute(() -> {
+ final MediaSession2Impl session = mSession.get();
+ if (session == null) {
+ return;
+ }
+ session.getCallback().onPrepareFromUri(controller, uri, extra);
+ });
+ }
+
+ @Override
+ public void prepareFromSearch(final IMediaSession2Callback caller, final String query,
+ final Bundle extra) {
+ final MediaSession2Impl sessionImpl = getSession();
+ final ControllerInfo controller = getController(caller);
+ if (controller == null) {
+ if (DEBUG) {
+ Log.d(TAG, "Command from a controller that hasn't connected. Ignore");
+ }
+ return;
+ }
+ sessionImpl.getCallbackExecutor().execute(() -> {
+ final MediaSession2Impl session = mSession.get();
+ if (session == null) {
+ return;
+ }
+ session.getCallback().onPrepareFromSearch(controller, query, extra);
+ });
+ }
+
+ @Override
+ public void prepareFromMediaId(final IMediaSession2Callback caller, final String mediaId,
+ final Bundle extra) {
+ final MediaSession2Impl sessionImpl = getSession();
+ final ControllerInfo controller = getController(caller);
+ if (controller == null) {
+ if (DEBUG) {
+ Log.d(TAG, "Command from a controller that hasn't connected. Ignore");
+ }
+ return;
+ }
+ sessionImpl.getCallbackExecutor().execute(() -> {
+ final MediaSession2Impl session = mSession.get();
+ if (session == null) {
+ return;
+ }
+ session.getCallback().onPrepareFromMediaId(controller, mediaId, extra);
+ });
+ }
+
+ @Override
+ public void playFromUri(final IMediaSession2Callback caller, final Uri uri,
+ final Bundle extra) {
+ final MediaSession2Impl sessionImpl = getSession();
+ final ControllerInfo controller = getController(caller);
+ if (controller == null) {
+ if (DEBUG) {
+ Log.d(TAG, "Command from a controller that hasn't connected. Ignore");
+ }
+ return;
+ }
+ sessionImpl.getCallbackExecutor().execute(() -> {
+ final MediaSession2Impl session = mSession.get();
+ if (session == null) {
+ return;
+ }
+ session.getCallback().onPlayFromUri(controller, uri, extra);
+ });
+ }
+
+ @Override
+ public void playFromSearch(final IMediaSession2Callback caller, final String query,
+ final Bundle extra) {
+ final MediaSession2Impl sessionImpl = getSession();
+ final ControllerInfo controller = getController(caller);
+ if (controller == null) {
+ if (DEBUG) {
+ Log.d(TAG, "Command from a controller that hasn't connected. Ignore");
+ }
+ return;
+ }
+ sessionImpl.getCallbackExecutor().execute(() -> {
+ final MediaSession2Impl session = mSession.get();
+ if (session == null) {
+ return;
+ }
+ session.getCallback().onPlayFromSearch(controller, query, extra);
+ });
+ }
+
+ @Override
+ public void playFromMediaId(final IMediaSession2Callback caller, final String mediaId,
+ final Bundle extra) {
+ final MediaSession2Impl sessionImpl = getSession();
+ final ControllerInfo controller = getController(caller);
+ if (controller == null) {
+ if (DEBUG) {
+ Log.d(TAG, "Command from a controller that hasn't connected. Ignore");
+ }
+ return;
+ }
+ sessionImpl.getCallbackExecutor().execute(() -> {
+ final MediaSession2Impl session = mSession.get();
+ if (session == null) {
+ return;
+ }
+ session.getCallback().onPlayFromMediaId(controller, mediaId, extra);
+ });
+ }
+
+ @Override
public void getBrowserRoot(IMediaSession2Callback caller, Bundle rootHints)
throws RuntimeException {
final MediaSession2Impl sessionImpl = getSession();
diff --git a/packages/MediaComponents/src/com/android/media/update/ApiHelper.java b/packages/MediaComponents/src/com/android/media/update/ApiHelper.java
index b0ca1bd..06f463f 100644
--- a/packages/MediaComponents/src/com/android/media/update/ApiHelper.java
+++ b/packages/MediaComponents/src/com/android/media/update/ApiHelper.java
@@ -16,6 +16,7 @@
package com.android.media.update;
+import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
@@ -24,6 +25,7 @@
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewGroup;
import com.android.support.mediarouter.app.MediaRouteButton;
@@ -51,13 +53,23 @@
return sInstance.mLibResources;
}
- public static Resources.Theme getLibTheme() {
+ public static Theme getLibTheme() {
return sInstance.mLibTheme;
}
+ public static Theme getLibTheme(int themeId) {
+ Theme theme = sInstance.mLibResources.newTheme();
+ theme.applyStyle(themeId, true);
+ return theme;
+ }
+
public static LayoutInflater getLayoutInflater(Context context) {
+ return getLayoutInflater(context, getLibTheme());
+ }
+
+ public static LayoutInflater getLayoutInflater(Context context, Theme theme) {
LayoutInflater layoutInflater = LayoutInflater.from(context).cloneInContext(
- new ContextThemeWrapper(context, getLibTheme()));
+ new ContextThemeWrapper(context, theme));
layoutInflater.setFactory2(new LayoutInflater.Factory2() {
@Override
public View onCreateView(
@@ -77,8 +89,17 @@
}
public static View inflateLibLayout(Context context, int libResId) {
+ return inflateLibLayout(context, getLibTheme(), libResId, null, false);
+ }
+
+ public static View inflateLibLayout(Context context, Theme theme, int libResId) {
+ return inflateLibLayout(context, theme, libResId, null, false);
+ }
+
+ public static View inflateLibLayout(Context context, Theme theme, int libResId,
+ @Nullable ViewGroup root, boolean attachToRoot) {
try (XmlResourceParser parser = getLibResources().getLayout(libResId)) {
- return getLayoutInflater(context).inflate(parser, null);
+ return getLayoutInflater(context, theme).inflate(parser, root, attachToRoot);
}
}
}
diff --git a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteButton.java b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteButton.java
index 7fdcfe4..fa94a81 100644
--- a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteButton.java
+++ b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteButton.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.app.Activity;
+import android.app.FragmentManager;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.ColorStateList;
@@ -27,8 +28,6 @@
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
-import android.support.v4.app.FragmentActivity;
-import android.support.v4.app.FragmentManager;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v7.widget.TooltipCompat;
import android.util.AttributeSet;
@@ -259,7 +258,7 @@
return false;
}
- final FragmentManager fm = getFragmentManager();
+ final FragmentManager fm = getActivity().getFragmentManager();
if (fm == null) {
throw new IllegalStateException("The activity must be a subclass of FragmentActivity");
}
@@ -286,13 +285,6 @@
return true;
}
- private FragmentManager getFragmentManager() {
- Activity activity = getActivity();
- if (activity instanceof FragmentActivity) {
- return ((FragmentActivity)activity).getSupportFragmentManager();
- }
- return null;
- }
private Activity getActivity() {
// Gross way of unwrapping the Activity so we can get the FragmentManager
diff --git a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteChooserDialog.java b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteChooserDialog.java
index cc7c3d5..aeb4408 100644
--- a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteChooserDialog.java
+++ b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteChooserDialog.java
@@ -20,7 +20,9 @@
import static com.android.support.mediarouter.media.MediaRouter.RouteInfo.CONNECTION_STATE_CONNECTING;
import android.annotation.NonNull;
+import android.app.Dialog;
import android.content.Context;
+import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.net.Uri;
@@ -31,6 +33,7 @@
import android.support.v7.app.AppCompatDialog;
import android.text.TextUtils;
import android.util.Log;
+import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
@@ -41,6 +44,7 @@
import android.widget.ListView;
import android.widget.TextView;
+import com.android.media.update.ApiHelper;
import com.android.media.update.R;
import com.android.support.mediarouter.media.MediaRouteSelector;
import com.android.support.mediarouter.media.MediaRouter;
@@ -61,7 +65,7 @@
* @see MediaRouteButton
* @see MediaRouteActionProvider
*/
-public class MediaRouteChooserDialog extends AppCompatDialog {
+public class MediaRouteChooserDialog extends Dialog {
static final String TAG = "MediaRouteChooserDialog";
// Do not update the route list immediately to avoid unnatural dialog change.
@@ -94,8 +98,9 @@
}
public MediaRouteChooserDialog(Context context, int theme) {
- super(context = MediaRouterThemeHelper.createThemedDialogContext(context, theme, false),
- MediaRouterThemeHelper.createThemedDialogStyle(context));
+ super(new ContextThemeWrapper(context,
+ ApiHelper.getLibTheme(MediaRouterThemeHelper.getRouterThemeId(context))),
+ theme == 0 ? android.R.style.Animation : theme);
context = getContext();
mRouter = MediaRouter.getInstance(context);
@@ -182,7 +187,9 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.mr_chooser_dialog);
+ setContentView(ApiHelper.inflateLibLayout(getContext(),
+ ApiHelper.getLibTheme(MediaRouterThemeHelper.getRouterThemeId(getContext())),
+ R.layout.mr_chooser_dialog));
mRoutes = new ArrayList<>();
mAdapter = new RouteAdapter(getContext(), mRoutes);
@@ -199,7 +206,7 @@
* Sets the width of the dialog. Also called when configuration changes.
*/
void updateLayout() {
- getWindow().setLayout(MediaRouteDialogHelper.getDialogWidth(getContext()),
+ getWindow().setLayout(MediaRouteDialogHelper.getDialogWidth(),
ViewGroup.LayoutParams.WRAP_CONTENT);
}
@@ -248,7 +255,6 @@
private final class RouteAdapter extends ArrayAdapter<MediaRouter.RouteInfo>
implements ListView.OnItemClickListener {
- private final LayoutInflater mInflater;
private final Drawable mDefaultIcon;
private final Drawable mTvIcon;
private final Drawable mSpeakerIcon;
@@ -256,12 +262,16 @@
public RouteAdapter(Context context, List<MediaRouter.RouteInfo> routes) {
super(context, 0, routes);
- mInflater = LayoutInflater.from(context);
- TypedArray styledAttributes = getContext().obtainStyledAttributes(new int[] {
- R.attr.mediaRouteDefaultIconDrawable,
- R.attr.mediaRouteTvIconDrawable,
- R.attr.mediaRouteSpeakerIconDrawable,
- R.attr.mediaRouteSpeakerGroupIconDrawable});
+
+ TypedArray styledAttributes = ApiHelper.getLibTheme(
+ MediaRouterThemeHelper.getRouterThemeId(context)).obtainStyledAttributes(
+ new int[] {
+ R.attr.mediaRouteDefaultIconDrawable,
+ R.attr.mediaRouteTvIconDrawable,
+ R.attr.mediaRouteSpeakerIconDrawable,
+ R.attr.mediaRouteSpeakerGroupIconDrawable
+ });
+
mDefaultIcon = styledAttributes.getDrawable(0);
mTvIcon = styledAttributes.getDrawable(1);
mSpeakerIcon = styledAttributes.getDrawable(2);
@@ -283,7 +293,10 @@
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
- view = mInflater.inflate(R.layout.mr_chooser_list_item, parent, false);
+ view = ApiHelper.inflateLibLayout(getContext(),
+ ApiHelper.getLibTheme(
+ MediaRouterThemeHelper.getRouterThemeId(getContext())),
+ R.layout.mr_chooser_list_item, parent, false);
}
MediaRouter.RouteInfo route = getItem(position);
diff --git a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteChooserDialogFragment.java b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteChooserDialogFragment.java
index 2f85fb3..65e6b29 100644
--- a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteChooserDialogFragment.java
+++ b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteChooserDialogFragment.java
@@ -17,10 +17,10 @@
package com.android.support.mediarouter.app;
import android.app.Dialog;
+import android.app.DialogFragment;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
-import android.support.v4.app.DialogFragment;
import com.android.support.mediarouter.media.MediaRouteSelector;
diff --git a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteControllerDialog.java b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteControllerDialog.java
index 942797b..123ab21 100644
--- a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteControllerDialog.java
+++ b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteControllerDialog.java
@@ -455,7 +455,7 @@
* Sets the width of the dialog. Also called when configuration changes.
*/
void updateLayout() {
- int width = MediaRouteDialogHelper.getDialogWidth(mContext);
+ int width = MediaRouteDialogHelper.getDialogWidth();
getWindow().setLayout(width, ViewGroup.LayoutParams.WRAP_CONTENT);
View decorView = getWindow().getDecorView();
diff --git a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteControllerDialogFragment.java b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteControllerDialogFragment.java
index 9442df7..215d74f 100644
--- a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteControllerDialogFragment.java
+++ b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteControllerDialogFragment.java
@@ -17,10 +17,10 @@
package com.android.support.mediarouter.app;
import android.app.Dialog;
+import android.app.DialogFragment;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
-import android.support.v4.app.DialogFragment;
/**
* Media route controller dialog fragment.
diff --git a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteDialogHelper.java b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteDialogHelper.java
index 6f75b46..62c050b 100644
--- a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteDialogHelper.java
+++ b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteDialogHelper.java
@@ -28,6 +28,7 @@
import android.widget.ArrayAdapter;
import android.widget.ListView;
+import com.android.media.update.ApiHelper;
import com.android.media.update.R;
import java.util.HashMap;
@@ -40,12 +41,12 @@
* The framework should set the dialog width properly, but somehow it doesn't work, hence
* duplicating a similar logic here to determine the appropriate dialog width.
*/
- public static int getDialogWidth(Context context) {
- DisplayMetrics metrics = context.getResources().getDisplayMetrics();
+ public static int getDialogWidth() {
+ DisplayMetrics metrics = ApiHelper.getLibResources().getDisplayMetrics();
boolean isPortrait = metrics.widthPixels < metrics.heightPixels;
TypedValue value = new TypedValue();
- context.getResources().getValue(isPortrait ? R.dimen.mr_dialog_fixed_width_minor
+ ApiHelper.getLibResources().getValue(isPortrait ? R.dimen.mr_dialog_fixed_width_minor
: R.dimen.mr_dialog_fixed_width_major, value, true);
if (value.type == TypedValue.TYPE_DIMENSION) {
return (int) value.getDimension(metrics);
diff --git a/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java b/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java
index 1cdaaee..dfc0792 100644
--- a/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java
+++ b/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java
@@ -29,7 +29,6 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
-import android.view.accessibility.AccessibilityManager;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.MediaControlView2;
@@ -64,8 +63,6 @@
private static final int REWIND_TIME_MS = 10000;
private static final int FORWARD_TIME_MS = 30000;
- private AccessibilityManager mAccessibilityManager;
-
private MediaController mController;
private MediaController.TransportControls mControls;
private PlaybackState mPlaybackState;
@@ -76,7 +73,6 @@
private int mDuration;
private int mPrevState;
private int mCurrentVisibility;
- private long mTimeout;
private long mPlaybackActions;
private boolean mShowing;
private boolean mDragging;
@@ -122,14 +118,9 @@
@Override
public void initialize(@Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- mAccessibilityManager = AccessibilityManager.getInstance(mInstance.getContext());
-
// Inflate MediaControlView2 from XML
View root = makeControllerView();
mInstance.addView(root);
-
- // Set default timeout
- mTimeout = 2000;
}
@Override
@@ -223,16 +214,6 @@
}
@Override
- public void setTimeout_impl(long timeout) {
- mTimeout = timeout;
- }
-
- @Override
- public long getTimeout_impl() {
- return mTimeout;
- }
-
- @Override
public CharSequence getAccessibilityClassName_impl() {
return MediaControlView2.class.getName();
}
@@ -245,7 +226,6 @@
// TODO: Should this function be removed?
@Override
public boolean onTrackballEvent_impl(MotionEvent ev) {
- resetFadeOutRunnable();
return false;
}
@@ -290,11 +270,8 @@
// was already true. This happens, for example, if we're
// paused with the progress bar showing the user hits play.
mInstance.post(mShowProgress);
- resetFadeOutRunnable();
} else if (visibility == View.GONE) {
mInstance.removeCallbacks(mShowProgress);
- // Remove existing call to mFadeOut to avoid from being called later.
- mInstance.removeCallbacks(mFadeOut);
}
}
}
@@ -488,15 +465,6 @@
}
}
- private final Runnable mFadeOut = new Runnable() {
- @Override
- public void run() {
- if (isPlaying()) {
- mInstance.setVisibility(View.GONE);
- }
- }
- };
-
private final Runnable mShowProgress = new Runnable() {
@Override
public void run() {
@@ -508,13 +476,6 @@
}
};
- private void resetFadeOutRunnable() {
- if (mTimeout != 0 && !mAccessibilityManager.isTouchExplorationEnabled()) {
- mInstance.removeCallbacks(mFadeOut);
- mInstance.postDelayed(mFadeOut, mTimeout);
- }
- }
-
private String stringForTime(int timeMs) {
int totalSeconds = timeMs / 1000;
@@ -590,7 +551,6 @@
}
mDragging = true;
- mInstance.removeCallbacks(mFadeOut);
// By removing these pending progress messages we make sure
// that a) we won't update the progress while the user adjusts
@@ -639,8 +599,6 @@
setProgress();
- resetFadeOutRunnable();
-
// Ensure that progress is properly updated in the future,
// the call to show() does not guarantee this because it is a
// no-op if we are already showing.
@@ -652,7 +610,6 @@
@Override
public void onClick(View v) {
togglePausePlayState();
- resetFadeOutRunnable();
}
};
@@ -662,8 +619,6 @@
int pos = getCurrentPosition() - REWIND_TIME_MS;
mControls.seekTo(pos);
setProgress();
-
- resetFadeOutRunnable();
}
};
@@ -673,8 +628,6 @@
int pos = getCurrentPosition() + FORWARD_TIME_MS;
mControls.seekTo(pos);
setProgress();
-
- resetFadeOutRunnable();
}
};
@@ -682,7 +635,6 @@
@Override
public void onClick(View v) {
mControls.skipToNext();
- resetFadeOutRunnable();
}
};
@@ -690,7 +642,6 @@
@Override
public void onClick(View v) {
mControls.skipToPrevious();
- resetFadeOutRunnable();
}
};
@@ -710,7 +661,6 @@
mController.sendCommand(MediaControlView2.COMMAND_HIDE_SUBTITLE, null, null);
mSubtitleIsEnabled = false;
}
- resetFadeOutRunnable();
}
};
@@ -732,7 +682,6 @@
mController.sendCommand(MediaControlView2.COMMAND_SET_FULLSCREEN, args, null);
mIsFullScreen = isEnteringFullScreen;
- resetFadeOutRunnable();
}
};
@@ -741,7 +690,6 @@
public void onClick(View v) {
mBasicControls.setVisibility(View.GONE);
mExtraControls.setVisibility(View.VISIBLE);
- resetFadeOutRunnable();
}
};
@@ -750,7 +698,6 @@
public void onClick(View v) {
mBasicControls.setVisibility(View.VISIBLE);
mExtraControls.setVisibility(View.GONE);
- resetFadeOutRunnable();
}
};
diff --git a/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java b/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
index 9f207b1..256003f 100644
--- a/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
+++ b/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
@@ -49,6 +49,7 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
+import android.view.accessibility.AccessibilityManager;
import android.widget.MediaControlView2;
import android.widget.VideoView2;
@@ -70,6 +71,7 @@
implements VideoView2Provider, VideoViewInterface.SurfaceListener {
private static final String TAG = "VideoView2";
private static final boolean DEBUG = true; // STOPSHIP: Log.isLoggable(TAG, Log.DEBUG);
+ private static final long DEFAULT_SHOW_CONTROLLER_INTERVAL_MS = 2000;
private final VideoView2 mInstance;
@@ -81,6 +83,9 @@
private static final int STATE_PAUSED = 4;
private static final int STATE_PLAYBACK_COMPLETED = 5;
+ private static final int INVALID_TRACK_INDEX = -1;
+
+ private AccessibilityManager mAccessibilityManager;
private AudioManager mAudioManager;
private AudioAttributes mAudioAttributes;
private int mAudioFocusType = AudioManager.AUDIOFOCUS_GAIN; // legacy focus gain
@@ -117,15 +122,17 @@
private int mVideoWidth;
private int mVideoHeight;
- private boolean mCCEnabled;
- private int mSelectedTrackIndex;
-
private SubtitleView mSubtitleView;
+ private boolean mSubtitleEnabled;
+ private int mSelectedTrackIndex; // selected subtitle track index as MediaPlayer2 returns
+
private float mSpeed;
// TODO: Remove mFallbackSpeed when integration with MediaPlayer2's new setPlaybackParams().
// Refer: https://docs.google.com/document/d/1nzAfns6i2hJ3RkaUre3QMT6wsDedJ5ONLiA_OOBFFX8/edit
private float mFallbackSpeed; // keep the original speed before 'pause' is called.
+ private long mShowControllerIntervalMs;
+
public VideoView2Impl(VideoView2 instance,
ViewGroupProvider superProvider, ViewGroupProvider privateProvider) {
super(instance, superProvider, privateProvider);
@@ -138,6 +145,11 @@
mVideoHeight = 0;
mSpeed = 1.0f;
mFallbackSpeed = mSpeed;
+ mSelectedTrackIndex = INVALID_TRACK_INDEX;
+ // TODO: add attributes to get this value.
+ mShowControllerIntervalMs = DEFAULT_SHOW_CONTROLLER_INTERVAL_MS;
+
+ mAccessibilityManager = AccessibilityManager.getInstance(mInstance.getContext());
mAudioManager = (AudioManager) mInstance.getContext()
.getSystemService(Context.AUDIO_SERVICE);
@@ -179,11 +191,11 @@
if (enableControlView) {
mMediaControlView = new MediaControlView2(mInstance.getContext());
}
- boolean showSubtitle = (attrs == null) || attrs.getAttributeBooleanValue(
+ boolean enableSubtitle = (attrs == null) || attrs.getAttributeBooleanValue(
"http://schemas.android.com/apk/res/android",
- "showSubtitle", true);
- if (showSubtitle) {
- Log.d(TAG, "showSubtitle attribute is true.");
+ "enableSubtitle", true);
+ if (enableSubtitle) {
+ Log.d(TAG, "enableSubtitle attribute is true.");
// TODO: implement
}
int viewType = (attrs == null) ? VideoView2.VIEW_TYPE_SURFACEVIEW
@@ -200,8 +212,9 @@
}
@Override
- public void setMediaControlView2_impl(MediaControlView2 mediaControlView) {
+ public void setMediaControlView2_impl(MediaControlView2 mediaControlView, long intervalMs) {
mMediaControlView = mediaControlView;
+ mShowControllerIntervalMs = intervalMs;
if (mRouteSelector != null) {
((MediaControlView2Impl) mMediaControlView.getProvider())
.setRouteSelector(mRouteSelector);
@@ -226,8 +239,8 @@
}
@Override
- public void showSubtitle_impl(boolean show) {
- if (show) {
+ public void setSubtitleEnabled_impl(boolean enable) {
+ if (enable) {
// Retrieve all tracks that belong to the current video.
MediaPlayer.TrackInfo[] trackInfos = mMediaPlayer.getTrackInfo();
@@ -240,16 +253,21 @@
}
if (subtitleTrackIndices.size() > 0) {
// Select first subtitle track
- mCCEnabled = true;
mSelectedTrackIndex = subtitleTrackIndices.get(0);
mMediaPlayer.selectTrack(mSelectedTrackIndex);
}
} else {
- if (mCCEnabled) {
+ if (mSelectedTrackIndex != INVALID_TRACK_INDEX) {
mMediaPlayer.deselectTrack(mSelectedTrackIndex);
- mCCEnabled = false;
+ mSelectedTrackIndex = INVALID_TRACK_INDEX;
}
}
+ mSubtitleEnabled = enable;
+ }
+
+ @Override
+ public boolean isSubtitleEnabled_impl() {
+ return mSubtitleEnabled;
}
// TODO: remove setSpeed_impl once MediaController2 is ready.
@@ -431,8 +449,7 @@
Log.d(TAG, "onTouchEvent(). mCurrentState=" + mCurrentState
+ ", mTargetState=" + mTargetState);
}
- if (ev.getAction() == MotionEvent.ACTION_UP
- && isInPlaybackState() && mMediaControlView != null) {
+ if (ev.getAction() == MotionEvent.ACTION_UP && mMediaControlView != null) {
toggleMediaControlViewVisibility();
}
@@ -441,14 +458,19 @@
@Override
public boolean onTrackballEvent_impl(MotionEvent ev) {
- if (ev.getAction() == MotionEvent.ACTION_UP
- && isInPlaybackState() && mMediaControlView != null) {
+ if (ev.getAction() == MotionEvent.ACTION_UP && mMediaControlView != null) {
toggleMediaControlViewVisibility();
}
return super.onTrackballEvent_impl(ev);
}
+ @Override
+ public boolean dispatchTouchEvent_impl(MotionEvent ev) {
+ // TODO: Test touch event handling logic thoroughly and simplify the logic.
+ return super.dispatchTouchEvent_impl(ev);
+ }
+
///////////////////////////////////////////////////
// Implements VideoViewInterface.SurfaceListener
///////////////////////////////////////////////////
@@ -471,9 +493,6 @@
Log.d(TAG, "onSurfaceDestroyed(). mCurrentState=" + mCurrentState
+ ", mTargetState=" + mTargetState + ", " + view.toString());
}
- if (mMediaControlView != null) {
- mMediaControlView.setVisibility(View.GONE);
- }
}
@Override
@@ -661,8 +680,12 @@
}
mStateBuilder.setState(getCorrespondingPlaybackState(),
mMediaPlayer.getCurrentPosition(), mSpeed);
- mStateBuilder.setBufferedPosition(
- (long) (mCurrentBufferPercentage / 100.0) * mMediaPlayer.getDuration());
+ if (mCurrentState != STATE_ERROR
+ && mCurrentState != STATE_IDLE
+ && mCurrentState != STATE_PREPARING) {
+ mStateBuilder.setBufferedPosition(
+ (long) (mCurrentBufferPercentage / 100.0) * mMediaPlayer.getDuration());
+ }
// Set PlaybackState for MediaSession
if (mMediaSession != null) {
@@ -692,11 +715,34 @@
}
}
+ private final Runnable mFadeOut = new Runnable() {
+ @Override
+ public void run() {
+ if (mCurrentState == STATE_PLAYING) {
+ mMediaControlView.setVisibility(View.GONE);
+ }
+ }
+ };
+
+ private void showController() {
+ // TODO: Decide what to show when the state is not in playback state
+ if (mMediaControlView == null || !isInPlaybackState()) {
+ return;
+ }
+ mMediaControlView.removeCallbacks(mFadeOut);
+ mMediaControlView.setVisibility(View.VISIBLE);
+ if (mShowControllerIntervalMs != 0
+ && !mAccessibilityManager.isTouchExplorationEnabled()) {
+ mMediaControlView.postDelayed(mFadeOut, mShowControllerIntervalMs);
+ }
+ }
+
private void toggleMediaControlViewVisibility() {
if (mMediaControlView.getVisibility() == View.VISIBLE) {
+ mMediaControlView.removeCallbacks(mFadeOut);
mMediaControlView.setVisibility(View.GONE);
} else {
- mMediaControlView.setVisibility(View.VISIBLE);
+ showController();
}
}
@@ -757,6 +803,9 @@
+ ", mTargetState=" + mTargetState);
}
mCurrentState = STATE_PREPARED;
+ // Create and set playback state for MediaControlView2
+ updatePlaybackState();
+
if (mOnPreparedListener != null) {
mOnPreparedListener.onPrepared(mInstance);
}
@@ -790,19 +839,6 @@
if (needToStart()) {
mMediaController.getTransportControls().play();
- if (mMediaControlView != null) {
- mMediaControlView.setVisibility(View.VISIBLE);
- }
- } else if (!(isInPlaybackState() && mMediaPlayer.isPlaying())
- && (seekToPosition != 0 || mMediaPlayer.getCurrentPosition() > 0)) {
- if (mMediaControlView != null) {
- // Show the media controls when we're paused into a video and
- // make them stick.
- long currTimeout = mMediaControlView.getTimeout();
- mMediaControlView.setTimeout(0L);
- mMediaControlView.setVisibility(View.VISIBLE);
- mMediaControlView.setTimeout(currTimeout);
- }
}
} else {
// We don't know the video size yet, but should start anyway.
@@ -811,8 +847,6 @@
mMediaController.getTransportControls().play();
}
}
- // Create and set playback state for MediaControlView2
- updatePlaybackState();
// Get and set duration and title values as MediaMetadata for MediaControlView2
MediaMetadata.Builder builder = new MediaMetadata.Builder();
@@ -928,10 +962,10 @@
} else {
switch (command) {
case MediaControlView2.COMMAND_SHOW_SUBTITLE:
- mInstance.showSubtitle(true);
+ mInstance.setSubtitleEnabled(true);
break;
case MediaControlView2.COMMAND_HIDE_SUBTITLE:
- mInstance.showSubtitle(false);
+ mInstance.setSubtitleEnabled(false);
break;
case MediaControlView2.COMMAND_SET_FULLSCREEN:
if (mOnFullScreenRequestListener != null) {
@@ -942,11 +976,13 @@
break;
}
}
+ showController();
}
@Override
public void onCustomAction(String action, Bundle extras) {
mOnCustomActionListener.onCustomAction(action, extras);
+ showController();
}
@Override
@@ -966,6 +1002,7 @@
+ ", mTargetState=" + mTargetState);
}
}
+ showController();
}
@Override
@@ -986,6 +1023,7 @@
+ ", mTargetState=" + mTargetState);
}
}
+ showController();
}
@Override
@@ -1001,6 +1039,7 @@
mSeekWhenPrepared = pos;
}
}
+ showController();
}
@Override
@@ -1010,6 +1049,7 @@
} else {
resetPlayer();
}
+ showController();
}
}
diff --git a/packages/MediaComponents/src/com/android/widget/ViewGroupImpl.java b/packages/MediaComponents/src/com/android/widget/ViewGroupImpl.java
index 8598bb2..5a06826 100644
--- a/packages/MediaComponents/src/com/android/widget/ViewGroupImpl.java
+++ b/packages/MediaComponents/src/com/android/widget/ViewGroupImpl.java
@@ -96,6 +96,11 @@
}
@Override
+ public boolean dispatchTouchEvent_impl(MotionEvent ev) {
+ return mSuperProvider.dispatchTouchEvent_impl(ev);
+ }
+
+ @Override
public boolean checkLayoutParams_impl(ViewGroup.LayoutParams p) {
return mSuperProvider.checkLayoutParams_impl(p);
}
diff --git a/packages/MediaComponents/test/AndroidManifest.xml b/packages/MediaComponents/test/AndroidManifest.xml
index 30bac87..48e4292 100644
--- a/packages/MediaComponents/test/AndroidManifest.xml
+++ b/packages/MediaComponents/test/AndroidManifest.xml
@@ -20,14 +20,7 @@
<application android:label="Media API Test">
<uses-library android:name="android.test.runner" />
- <activity android:name="android.widget2.VideoView2TestActivity"
- android:configChanges="keyboardHidden|orientation|screenSize"
- android:label="VideoView2TestActivity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
+ <activity android:name="android.media.MockActivity" />
<!-- Keep the test services synced together with the TestUtils.java -->
<service android:name="android.media.MockMediaSessionService2">
diff --git a/packages/MediaComponents/test/src/android/media/MediaController2Test.java b/packages/MediaComponents/test/src/android/media/MediaController2Test.java
index e8eaa20..07baf58 100644
--- a/packages/MediaComponents/test/src/android/media/MediaController2Test.java
+++ b/packages/MediaComponents/test/src/android/media/MediaController2Test.java
@@ -16,14 +16,16 @@
package android.media;
-import android.media.MediaController2.ControllerCallback;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
import android.media.MediaPlayerInterface.PlaybackListener;
import android.media.MediaSession2.Command;
import android.media.MediaSession2.ControllerInfo;
import android.media.MediaSession2.PlaylistParams;
import android.media.MediaSession2.SessionCallback;
import android.media.TestUtils.SyncHandler;
-import android.media.session.PlaybackState;
+import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
@@ -57,7 +59,9 @@
@FlakyTest
public class MediaController2Test extends MediaSession2TestBase {
private static final String TAG = "MediaController2Test";
+ private static final int DEFAULT_RATING_TYPE = Rating2.RATING_5_STARS;
+ PendingIntent mIntent;
MediaSession2 mSession;
MediaController2 mController;
MockPlayer mPlayer;
@@ -66,10 +70,15 @@
@Override
public void setUp() throws Exception {
super.setUp();
+ final Intent sessionActivity = new Intent(mContext, MockActivity.class);
// Create this test specific MediaSession2 to use our own Handler.
+ mIntent = PendingIntent.getActivity(mContext, 0, sessionActivity, 0);
+
mPlayer = new MockPlayer(1);
mSession = new MediaSession2.Builder(mContext, mPlayer)
.setSessionCallback(sHandlerExecutor, new SessionCallback(mContext))
+ .setRatingType(DEFAULT_RATING_TYPE)
+ .setSessionActivity(mIntent)
.setId(TAG).build();
mController = createController(mSession.getToken());
TestServiceRegistry.getInstance().setHandler(sHandler);
@@ -200,6 +209,18 @@
}
@Test
+ public void testGetRatingType() throws InterruptedException {
+ assertEquals(DEFAULT_RATING_TYPE, mController.getRatingType());
+ }
+
+ @Test
+ public void testGetSessionActivity() throws InterruptedException {
+ PendingIntent sessionActivity = mController.getSessionActivity();
+ assertEquals(mContext.getPackageName(), sessionActivity.getCreatorPackage());
+ assertEquals(Process.myUid(), sessionActivity.getCreatorUid());
+ }
+
+ @Test
public void testGetSetPlaylistParams() throws Exception {
final PlaylistParams params = new PlaylistParams(mContext,
PlaylistParams.REPEAT_MODE_ALL,
@@ -224,34 +245,64 @@
}
@Test
+ public void testSetVolumeTo() throws Exception {
+ final int maxVolume = 100;
+ final int currentVolume = 23;
+ final int volumeControlType = VolumeProvider2.VOLUME_CONTROL_ABSOLUTE;
+ TestVolumeProvider volumeProvider =
+ new TestVolumeProvider(mContext, volumeControlType, maxVolume, currentVolume);
+
+ mSession.setPlayer(new MockPlayer(0), volumeProvider);
+ final MediaController2 controller = createController(mSession.getToken(), true, null);
+
+ final int targetVolume = 50;
+ controller.setVolumeTo(targetVolume, 0 /* flags */);
+ assertTrue(volumeProvider.mLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ assertTrue(volumeProvider.mSetVolumeToCalled);
+ assertEquals(targetVolume, volumeProvider.mVolume);
+ }
+
+ @Test
+ public void testAdjustVolume() throws Exception {
+ final int maxVolume = 100;
+ final int currentVolume = 23;
+ final int volumeControlType = VolumeProvider2.VOLUME_CONTROL_ABSOLUTE;
+ TestVolumeProvider volumeProvider =
+ new TestVolumeProvider(mContext, volumeControlType, maxVolume, currentVolume);
+
+ mSession.setPlayer(new MockPlayer(0), volumeProvider);
+ final MediaController2 controller = createController(mSession.getToken(), true, null);
+
+ final int direction = AudioManager.ADJUST_RAISE;
+ controller.adjustVolume(direction, 0 /* flags */);
+ assertTrue(volumeProvider.mLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ assertTrue(volumeProvider.mAdjustVolumeCalled);
+ assertEquals(direction, volumeProvider.mDirection);
+ }
+
+ @Test
public void testGetPackageName() {
assertEquals(mContext.getPackageName(), mController.getSessionToken().getPackageName());
}
- // This also tests testGetPlaybackState().
+ // This also tests getPlaybackState().
@Test
public void testControllerCallback_onPlaybackStateChanged() throws InterruptedException {
- final CountDownLatch latch = new CountDownLatch(2);
+ final CountDownLatch latch = new CountDownLatch(1);
final TestControllerCallbackInterface callback = new TestControllerCallbackInterface() {
@Override
public void onPlaybackStateChanged(PlaybackState2 state) {
- switch ((int) latch.getCount()) {
- case 2:
- assertEquals(PlaybackState.STATE_PLAYING, state.getState());
- break;
- case 1:
- assertEquals(PlaybackState.STATE_PAUSED, state.getState());
- break;
- }
+ // Called only once when the player's playback state is changed after this.
+ assertEquals(PlaybackState2.STATE_PAUSED, state.getState());
latch.countDown();
}
};
-
- mPlayer.notifyPlaybackState(createPlaybackState(PlaybackState.STATE_PLAYING));
+ mPlayer.notifyPlaybackState(createPlaybackState(PlaybackState2.STATE_PLAYING));
mController = createController(mSession.getToken(), true, callback);
- mPlayer.notifyPlaybackState(createPlaybackState(PlaybackState.STATE_PAUSED));
+ assertEquals(PlaybackState2.STATE_PLAYING, mController.getPlaybackState().getState());
+ mPlayer.notifyPlaybackState(createPlaybackState(PlaybackState2.STATE_PAUSED));
assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
- assertEquals(PlaybackState.STATE_PAUSED, mController.getPlaybackState().getState());
+ assertEquals(PlaybackState2.STATE_PAUSED, mController.getPlaybackState().getState());
}
@Test
@@ -326,6 +377,151 @@
}
@Test
+ public void testPlayFromSearch() throws InterruptedException {
+ final String request = "random query";
+ final Bundle bundle = new Bundle();
+ bundle.putString("key", "value");
+ final CountDownLatch latch = new CountDownLatch(1);
+ final SessionCallback callback = new SessionCallback(mContext) {
+ @Override
+ public void onPlayFromSearch(ControllerInfo controller, String query, Bundle extras) {
+ assertEquals(mContext.getPackageName(), controller.getPackageName());
+ assertEquals(request, query);
+ assertTrue(TestUtils.equals(bundle, extras));
+ latch.countDown();;
+ }
+ };
+ try (MediaSession2 session = new MediaSession2.Builder(mContext, mPlayer)
+ .setSessionCallback(sHandlerExecutor, callback)
+ .setId("testPlayFromSearch").build()) {
+ MediaController2 controller = createController(session.getToken());
+ controller.playFromSearch(request, bundle);
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }
+ }
+
+ @Test
+ public void testPlayFromUri() throws InterruptedException {
+ final Uri request = Uri.parse("foo://boo");
+ final Bundle bundle = new Bundle();
+ bundle.putString("key", "value");
+ final CountDownLatch latch = new CountDownLatch(1);
+ final SessionCallback callback = new SessionCallback(mContext) {
+ @Override
+ public void onPlayFromUri(ControllerInfo controller, Uri uri, Bundle extras) {
+ assertEquals(mContext.getPackageName(), controller.getPackageName());
+ assertEquals(request, uri);
+ assertTrue(TestUtils.equals(bundle, extras));
+ latch.countDown();;
+ }
+ };
+ try (MediaSession2 session = new MediaSession2.Builder(mContext, mPlayer)
+ .setSessionCallback(sHandlerExecutor, callback)
+ .setId("testPlayFromUri").build()) {
+ MediaController2 controller = createController(session.getToken());
+ controller.playFromUri(request, bundle);
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }
+ }
+
+ @Test
+ public void testPlayFromMediaId() throws InterruptedException {
+ final String request = "media_id";
+ final Bundle bundle = new Bundle();
+ bundle.putString("key", "value");
+ final CountDownLatch latch = new CountDownLatch(1);
+ final SessionCallback callback = new SessionCallback(mContext) {
+ @Override
+ public void onPlayFromMediaId(ControllerInfo controller, String id, Bundle extras) {
+ assertEquals(mContext.getPackageName(), controller.getPackageName());
+ assertEquals(request, id);
+ assertTrue(TestUtils.equals(bundle, extras));
+ latch.countDown();;
+ }
+ };
+ try (MediaSession2 session = new MediaSession2.Builder(mContext, mPlayer)
+ .setSessionCallback(sHandlerExecutor, callback)
+ .setId("testPlayFromMediaId").build()) {
+ MediaController2 controller = createController(session.getToken());
+ controller.playFromMediaId(request, bundle);
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }
+ }
+
+
+ @Test
+ public void testPrepareFromSearch() throws InterruptedException {
+ final String request = "random query";
+ final Bundle bundle = new Bundle();
+ bundle.putString("key", "value");
+ final CountDownLatch latch = new CountDownLatch(1);
+ final SessionCallback callback = new SessionCallback(mContext) {
+ @Override
+ public void onPrepareFromSearch(ControllerInfo controller, String query, Bundle extras) {
+ assertEquals(mContext.getPackageName(), controller.getPackageName());
+ assertEquals(request, query);
+ assertTrue(TestUtils.equals(bundle, extras));
+ latch.countDown();;
+ }
+ };
+ try (MediaSession2 session = new MediaSession2.Builder(mContext, mPlayer)
+ .setSessionCallback(sHandlerExecutor, callback)
+ .setId("testPrepareFromSearch").build()) {
+ MediaController2 controller = createController(session.getToken());
+ controller.prepareFromSearch(request, bundle);
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }
+ }
+
+ @Test
+ public void testPrepareFromUri() throws InterruptedException {
+ final Uri request = Uri.parse("foo://boo");
+ final Bundle bundle = new Bundle();
+ bundle.putString("key", "value");
+ final CountDownLatch latch = new CountDownLatch(1);
+ final SessionCallback callback = new SessionCallback(mContext) {
+ @Override
+ public void onPrepareFromUri(ControllerInfo controller, Uri uri, Bundle extras) {
+ assertEquals(mContext.getPackageName(), controller.getPackageName());
+ assertEquals(request, uri);
+ assertTrue(TestUtils.equals(bundle, extras));
+ latch.countDown();;
+ }
+ };
+ try (MediaSession2 session = new MediaSession2.Builder(mContext, mPlayer)
+ .setSessionCallback(sHandlerExecutor, callback)
+ .setId("testPrepareFromUri").build()) {
+ MediaController2 controller = createController(session.getToken());
+ controller.prepareFromUri(request, bundle);
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }
+ }
+
+ @Test
+ public void testPrepareFromMediaId() throws InterruptedException {
+ final String request = "media_id";
+ final Bundle bundle = new Bundle();
+ bundle.putString("key", "value");
+ final CountDownLatch latch = new CountDownLatch(1);
+ final SessionCallback callback = new SessionCallback(mContext) {
+ @Override
+ public void onPrepareFromMediaId(ControllerInfo controller, String id, Bundle extras) {
+ assertEquals(mContext.getPackageName(), controller.getPackageName());
+ assertEquals(request, id);
+ assertTrue(TestUtils.equals(bundle, extras));
+ latch.countDown();;
+ }
+ };
+ try (MediaSession2 session = new MediaSession2.Builder(mContext, mPlayer)
+ .setSessionCallback(sHandlerExecutor, callback)
+ .setId("testPrepareFromMediaId").build()) {
+ MediaController2 controller = createController(session.getToken());
+ controller.prepareFromMediaId(request, bundle);
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }
+ }
+
+ @Test
public void testIsConnected() throws InterruptedException {
assertTrue(mController.isConnected());
sHandler.postAndSync(()->{
@@ -364,7 +560,7 @@
});
final MediaController2 controller = createController(mSession.getToken());
testHandler.post(() -> {
- final PlaybackState2 state = createPlaybackState(PlaybackState.STATE_ERROR);
+ final PlaybackState2 state = createPlaybackState(PlaybackState2.STATE_ERROR);
for (int i = 0; i < 100; i++) {
// triggers call from session to controller.
player.notifyPlaybackState(state);
@@ -461,11 +657,14 @@
*/
}
+ // TODO(jaewan): Re-enable after b/72792686 is fixed
+ @Ignore
@Test
public void testControllerAfterSessionIsGone_session() throws InterruptedException {
testControllerAfterSessionIsGone(mSession.getToken().getId());
}
+ // TODO(jaewan): Re-enable after b/72792686 is fixed
@Ignore
@Test
public void testControllerAfterSessionIsGone_sessionService() throws InterruptedException {
@@ -570,4 +769,31 @@
// TODO(jaewan): Add test for service connect rejection, when we differentiate session
// active/inactive and connection accept/refuse
+
+ class TestVolumeProvider extends VolumeProvider2 {
+ final CountDownLatch mLatch = new CountDownLatch(1);
+ boolean mSetVolumeToCalled;
+ boolean mAdjustVolumeCalled;
+ int mVolume;
+ int mDirection;
+
+ public TestVolumeProvider(Context context, int controlType, int maxVolume,
+ int currentVolume) {
+ super(context, controlType, maxVolume, currentVolume);
+ }
+
+ @Override
+ public void onSetVolumeTo(int volume) {
+ mSetVolumeToCalled = true;
+ mVolume = volume;
+ mLatch.countDown();
+ }
+
+ @Override
+ public void onAdjustVolume(int direction) {
+ mAdjustVolumeCalled = true;
+ mDirection = direction;
+ mLatch.countDown();
+ }
+ }
}
diff --git a/packages/MediaComponents/test/src/android/media/MediaSession2Test.java b/packages/MediaComponents/test/src/android/media/MediaSession2Test.java
index 43a6c2c..b00633b 100644
--- a/packages/MediaComponents/test/src/android/media/MediaSession2Test.java
+++ b/packages/MediaComponents/test/src/android/media/MediaSession2Test.java
@@ -27,6 +27,9 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
+import android.content.Context;
+import android.media.AudioManager;
+import android.media.MediaController2.PlaybackInfo;
import android.media.MediaPlayerInterface.PlaybackListener;
import android.media.MediaSession2.Builder;
import android.media.MediaSession2.Command;
@@ -99,17 +102,15 @@
@Test
public void testSetPlayer() throws Exception {
- sHandler.postAndSync(() -> {
- MockPlayer player = new MockPlayer(0);
- // Test if setPlayer doesn't crash with various situations.
- mSession.setPlayer(mPlayer);
- mSession.setPlayer(player);
- mSession.close();
- });
+ MockPlayer player = new MockPlayer(0);
+ // Test if setPlayer doesn't crash with various situations.
+ mSession.setPlayer(mPlayer);
+ mSession.setPlayer(player);
+ mSession.close();
}
@Test
- public void testSetPlayerWithVolumeProvider() throws Exception {
+ public void testSetPlayer_playbackInfo() throws Exception {
MockPlayer player = new MockPlayer(0);
AudioAttributes attrs = new AudioAttributes.Builder()
.setContentType(CONTENT_TYPE_MUSIC)
@@ -125,7 +126,7 @@
final CountDownLatch latch = new CountDownLatch(1);
final TestControllerCallbackInterface callback = new TestControllerCallbackInterface() {
@Override
- public void onPlaybackInfoChanged(MediaController2.PlaybackInfo info) {
+ public void onPlaybackInfoChanged(PlaybackInfo info) {
assertEquals(MediaController2.PlaybackInfo.PLAYBACK_TYPE_REMOTE,
info.getPlaybackType());
assertEquals(attrs, info.getAudioAttributes());
@@ -136,18 +137,30 @@
}
};
+ mSession.setPlayer(player);
+
final MediaController2 controller = createController(mSession.getToken(), true, callback);
- assertNull(controller.getPlaybackInfo());
+ PlaybackInfo info = controller.getPlaybackInfo();
+ assertNotNull(info);
+ assertEquals(PlaybackInfo.PLAYBACK_TYPE_LOCAL, info.getPlaybackType());
+ assertEquals(attrs, info.getAudioAttributes());
+ AudioManager manager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+ int localVolumeControlType = manager.isVolumeFixed()
+ ? VolumeProvider2.VOLUME_CONTROL_FIXED : VolumeProvider2.VOLUME_CONTROL_ABSOLUTE;
+ assertEquals(localVolumeControlType, info.getControlType());
+ assertEquals(manager.getStreamMaxVolume(AudioManager.STREAM_MUSIC), info.getMaxVolume());
+ assertEquals(manager.getStreamVolume(AudioManager.STREAM_MUSIC), info.getCurrentVolume());
mSession.setPlayer(player, volumeProvider);
assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
- MediaController2.PlaybackInfo infoOut = controller.getPlaybackInfo();
- assertEquals(MediaController2.PlaybackInfo.PLAYBACK_TYPE_REMOTE, infoOut.getPlaybackType());
- assertEquals(attrs, infoOut.getAudioAttributes());
- assertEquals(volumeControlType, infoOut.getPlaybackType());
- assertEquals(maxVolume, infoOut.getMaxVolume());
- assertEquals(currentVolume, infoOut.getCurrentVolume());
+ info = controller.getPlaybackInfo();
+ assertNotNull(info);
+ assertEquals(PlaybackInfo.PLAYBACK_TYPE_REMOTE, info.getPlaybackType());
+ assertEquals(attrs, info.getAudioAttributes());
+ assertEquals(volumeControlType, info.getControlType());
+ assertEquals(maxVolume, info.getMaxVolume());
+ assertEquals(currentVolume, info.getCurrentVolume());
}
@Test
diff --git a/packages/MediaComponents/test/src/android/media/MockActivity.java b/packages/MediaComponents/test/src/android/media/MockActivity.java
new file mode 100644
index 0000000..4627530
--- /dev/null
+++ b/packages/MediaComponents/test/src/android/media/MockActivity.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.app.Activity;
+
+public class MockActivity extends Activity {
+}
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 1ebaea9..8e112a1 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -122,8 +122,7 @@
}
binder::Status CameraDeviceClient::insertGbpLocked(const sp<IGraphicBufferProducer>& gbp,
- SurfaceMap* outSurfaceMap,
- Vector<int32_t>* outputStreamIds) {
+ SurfaceMap* outSurfaceMap, Vector<int32_t>* outputStreamIds, int32_t *currentStreamId) {
int idx = mStreamMap.indexOfKey(IInterface::asBinder(gbp));
// Trying to submit request with surface that wasn't created
@@ -146,6 +145,10 @@
__FUNCTION__, mCameraIdStr.string(), streamSurfaceId.streamId(),
streamSurfaceId.surfaceId());
+ if (currentStreamId != nullptr) {
+ *currentStreamId = streamSurfaceId.streamId();
+ }
+
return binder::Status::ok();
}
@@ -218,40 +221,6 @@
"Invalid camera request settings");
}
- CameraDeviceBase::PhysicalCameraSettingsList physicalSettingsList;
- for (const auto& it : request.mPhysicalCameraSettings) {
- String8 physicalId(it.id.c_str());
- if ((physicalId != mDevice->getId()) && !checkPhysicalCameraId(physicalId)) {
- ALOGE("%s: Camera %s: Physical camera id: %s is invalid.", __FUNCTION__,
- mCameraIdStr.string(), physicalId.string());
- return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
- "Invalid physical camera id");
- }
-
- CameraMetadata metadata(it.settings);
- if (metadata.isEmpty()) {
- ALOGE("%s: Camera %s: Sent empty metadata packet. Rejecting request.",
- __FUNCTION__, mCameraIdStr.string());
- return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
- "Request settings are empty");
- }
-
- if (!enforceRequestPermissions(metadata)) {
- // Callee logs
- return STATUS_ERROR(CameraService::ERROR_PERMISSION_DENIED,
- "Caller does not have permission to change restricted controls");
- }
-
- physicalSettingsList.push_back({it.id, metadata});
- }
-
- if (streaming && (physicalSettingsList.size() > 1)) {
- ALOGE("%s: Camera %s: Individual physical camera settings are not supported in "
- "streaming requests. Rejecting request.", __FUNCTION__, mCameraIdStr.string());
- return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
- "Streaming request contains individual physical requests");
- }
-
if (request.mSurfaceList.isEmpty() && request.mStreamIdxList.size() == 0) {
ALOGE("%s: Camera %s: Requests must have at least one surface target. "
"Rejecting request.", __FUNCTION__, mCameraIdStr.string());
@@ -265,15 +234,26 @@
*/
SurfaceMap surfaceMap;
Vector<int32_t> outputStreamIds;
+ std::vector<std::string> requestedPhysicalIds;
if (request.mSurfaceList.size() > 0) {
for (sp<Surface> surface : request.mSurfaceList) {
if (surface == 0) continue;
+ int32_t streamId;
sp<IGraphicBufferProducer> gbp = surface->getIGraphicBufferProducer();
- res = insertGbpLocked(gbp, &surfaceMap, &outputStreamIds);
+ res = insertGbpLocked(gbp, &surfaceMap, &outputStreamIds, &streamId);
if (!res.isOk()) {
return res;
}
+
+ ssize_t index = mConfiguredOutputs.indexOfKey(streamId);
+ if (index >= 0) {
+ String8 requestedPhysicalId(
+ mConfiguredOutputs.valueAt(index).getPhysicalCameraId());
+ requestedPhysicalIds.push_back(requestedPhysicalId.string());
+ } else {
+ ALOGW("%s: Output stream Id not found among configured outputs!", __FUNCTION__);
+ }
}
} else {
for (size_t i = 0; i < request.mStreamIdxList.size(); i++) {
@@ -298,13 +278,55 @@
"Request targets Surface has invalid surface index");
}
- res = insertGbpLocked(gbps[surfaceIdx], &surfaceMap, &outputStreamIds);
+ res = insertGbpLocked(gbps[surfaceIdx], &surfaceMap, &outputStreamIds, nullptr);
if (!res.isOk()) {
return res;
}
+
+ String8 requestedPhysicalId(
+ mConfiguredOutputs.valueAt(index).getPhysicalCameraId());
+ requestedPhysicalIds.push_back(requestedPhysicalId.string());
}
}
+ CameraDeviceBase::PhysicalCameraSettingsList physicalSettingsList;
+ for (const auto& it : request.mPhysicalCameraSettings) {
+ String8 physicalId(it.id.c_str());
+ if (physicalId != mDevice->getId()) {
+ auto found = std::find(requestedPhysicalIds.begin(), requestedPhysicalIds.end(),
+ it.id);
+ if (found == requestedPhysicalIds.end()) {
+ ALOGE("%s: Camera %s: Physical camera id: %s not part of attached outputs.",
+ __FUNCTION__, mCameraIdStr.string(), physicalId.string());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+ "Invalid physical camera id");
+ }
+ }
+
+ CameraMetadata metadata(it.settings);
+ if (metadata.isEmpty()) {
+ ALOGE("%s: Camera %s: Sent empty metadata packet. Rejecting request.",
+ __FUNCTION__, mCameraIdStr.string());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+ "Request settings are empty");
+ }
+
+ physicalSettingsList.push_back({it.id, metadata});
+ }
+
+ if (streaming && (physicalSettingsList.size() > 1)) {
+ ALOGE("%s: Camera %s: Individual physical camera settings are not supported in "
+ "streaming requests. Rejecting request.", __FUNCTION__, mCameraIdStr.string());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+ "Streaming request contains individual physical requests");
+ }
+
+ if (!enforceRequestPermissions(physicalSettingsList.begin()->metadata)) {
+ // Callee logs
+ return STATUS_ERROR(CameraService::ERROR_PERMISSION_DENIED,
+ "Caller does not have permission to change restricted controls");
+ }
+
physicalSettingsList.begin()->metadata.update(ANDROID_REQUEST_OUTPUT_STREAMS,
&outputStreamIds[0], outputStreamIds.size());
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 14aeed0..435c99d 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -259,8 +259,8 @@
// Utility method to insert the surface into SurfaceMap
binder::Status insertGbpLocked(const sp<IGraphicBufferProducer>& gbp,
- /*out*/SurfaceMap* surfaceMap,
- /*out*/Vector<int32_t>* streamIds);
+ /*out*/SurfaceMap* surfaceMap, /*out*/Vector<int32_t>* streamIds,
+ /*out*/int32_t* currentStreamId);
// Check that the physicalCameraId passed in is spported by the camera
// device.