Merge "Fix MediaPlayer2AudioOutput::setAudioAttributes()"
diff --git a/drm/mediadrm/plugins/clearkey/hidl/AesCtrDecryptor.cpp b/drm/mediadrm/plugins/clearkey/hidl/AesCtrDecryptor.cpp
index 2fce0790..0ac879c 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/AesCtrDecryptor.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/AesCtrDecryptor.cpp
@@ -26,7 +26,7 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
 using ::android::hardware::drm::V1_0::SubSample;
@@ -79,7 +79,7 @@
 }
 
 } // namespace clearkey
-} // namespace V1_1
+} // namespace V1_2
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/Android.bp b/drm/mediadrm/plugins/clearkey/hidl/Android.bp
index edf818e..b44a6c7 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/hidl/Android.bp
@@ -15,7 +15,7 @@
 //
 
 cc_binary {
-    name: "android.hardware.drm@1.1-service.clearkey",
+    name: "android.hardware.drm@1.2-service.clearkey",
     vendor: true,
 
     srcs: [
@@ -39,11 +39,12 @@
     relative_install_path: "hw",
 
     cflags: ["-Wall", "-Werror"],
-    init_rc: ["android.hardware.drm@1.1-service.clearkey.rc"],
+    init_rc: ["android.hardware.drm@1.2-service.clearkey.rc"],
 
     shared_libs: [
         "android.hardware.drm@1.0",
         "android.hardware.drm@1.1",
+        "android.hardware.drm@1.2",
         "libbase",
         "libbinder",
         "libcrypto",
@@ -69,7 +70,6 @@
         integer_overflow: true,
     },
 }
-
 cc_library_static {
     name: "libclearkeydevicefiles-protos",
     vendor: true,
diff --git a/drm/mediadrm/plugins/clearkey/hidl/Base64.cpp b/drm/mediadrm/plugins/clearkey/hidl/Base64.cpp
index c2ed751..657a42f 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/Base64.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/Base64.cpp
@@ -21,7 +21,7 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
 sp<Buffer> decodeBase64(const std::string &s) {
@@ -169,7 +169,7 @@
 }
 
 } // namespace clearkey
-} // namespace V1_1
+} // namespace V1_2
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/Buffer.cpp b/drm/mediadrm/plugins/clearkey/hidl/Buffer.cpp
index e58f58a..75f8395 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/Buffer.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/Buffer.cpp
@@ -21,7 +21,7 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
 Buffer::Buffer(size_t capacity)
@@ -47,7 +47,7 @@
 }
 
 } // namespace clearkey
-} // namespace V1_1
+} // namespace V1_2
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/CreatePluginFactories.cpp b/drm/mediadrm/plugins/clearkey/hidl/CreatePluginFactories.cpp
index 1ba5c6a..1410d77 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/CreatePluginFactories.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/CreatePluginFactories.cpp
@@ -22,7 +22,7 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
 extern "C" {
@@ -38,7 +38,7 @@
 } // extern "C"
 
 }  // namespace clearkey
-}  // namespace V1_1
+}  // namespace V1_2
 }  // namespace drm
 }  // namespace hardware
 }  // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/CryptoFactory.cpp b/drm/mediadrm/plugins/clearkey/hidl/CryptoFactory.cpp
index 0848cef..2a48db6 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/CryptoFactory.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/CryptoFactory.cpp
@@ -27,7 +27,7 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
 Return<bool> CryptoFactory::isCryptoSchemeSupported(
@@ -60,7 +60,7 @@
 }
 
 } // namespace clearkey
-} // namespace V1_1
+} // namespace V1_2
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
index f33f94e..a488f86 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
@@ -27,7 +27,7 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
 using ::android::hardware::drm::V1_0::BufferType;
@@ -179,7 +179,7 @@
 }
 
 } // namespace clearkey
-} // namespace V1_1
+} // namespace V1_2
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DeviceFiles.cpp b/drm/mediadrm/plugins/clearkey/hidl/DeviceFiles.cpp
index e23502c..2415b6f 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/DeviceFiles.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/DeviceFiles.cpp
@@ -13,11 +13,11 @@
 #include <openssl/sha.h>
 
 // Protobuf generated classes.
-using android::hardware::drm::V1_1::clearkey::OfflineFile;
-using android::hardware::drm::V1_1::clearkey::HashedFile;
-using android::hardware::drm::V1_1::clearkey::License;
-using android::hardware::drm::V1_1::clearkey::License_LicenseState_ACTIVE;
-using android::hardware::drm::V1_1::clearkey::License_LicenseState_RELEASING;
+using android::hardware::drm::V1_2::clearkey::OfflineFile;
+using android::hardware::drm::V1_2::clearkey::HashedFile;
+using android::hardware::drm::V1_2::clearkey::License;
+using android::hardware::drm::V1_2::clearkey::License_LicenseState_ACTIVE;
+using android::hardware::drm::V1_2::clearkey::License_LicenseState_RELEASING;
 
 namespace {
 const char kLicenseFileNameExt[] = ".lic";
@@ -38,7 +38,7 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
 bool DeviceFiles::StoreLicense(
@@ -158,6 +158,15 @@
     return mFileHandle.FileExists(keySetId + kLicenseFileNameExt);
 }
 
+std::vector<std::string> DeviceFiles::ListLicenses() const {
+    std::vector<std::string> licenses = mFileHandle.ListFiles();
+    for (size_t i = 0; i < licenses.size(); i++) {
+        std::string& license = licenses[i];
+        license = license.substr(0, license.size() - strlen(kLicenseFileNameExt));
+    }
+    return licenses;
+}
+
 bool DeviceFiles::RetrieveHashedFile(const std::string& fileName, OfflineFile* deSerializedFile) {
     if (!deSerializedFile) {
         ALOGE("RetrieveHashedFile: invalid file parameter");
@@ -237,7 +246,7 @@
 }
 
 } // namespace clearkey
-} // namespace V1_1
+} // namespace V1_2
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp
index 77557f9..9d040a8 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp
@@ -30,7 +30,7 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
 using ::android::hardware::drm::V1_0::Status;
@@ -71,7 +71,7 @@
 }
 
 } // namespace clearkey
-} // namespace V1_1
+} // namespace V1_2
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
index 55cbcf9..7184b53 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
@@ -58,9 +58,12 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
+using ::android::hardware::drm::V1_2::KeySetId;
+using ::android::hardware::drm::V1_2::OfflineLicenseState;
+
 DrmPlugin::DrmPlugin(SessionLibrary* sessionLibrary)
         : mSessionLibrary(sessionLibrary),
           mOpenSessionOkCount(0),
@@ -625,6 +628,51 @@
     return Void();
 }
 
+Return<void> DrmPlugin::getOfflineLicenseKeySetIds(getOfflineLicenseKeySetIds_cb _hidl_cb) {
+    std::vector<std::string> licenseNames = mFileHandle.ListLicenses();
+    std::vector<KeySetId> keySetIds;
+    for (const auto& name : licenseNames) {
+        std::vector<uint8_t> keySetId(name.begin(), name.end());
+        keySetIds.push_back(keySetId);
+    }
+    _hidl_cb(Status::OK, keySetIds);
+    return Void();
+}
+
+
+Return<Status> DrmPlugin::removeOfflineLicense(const KeySetId& keySetId) {
+    std::string licenseName(keySetId.begin(), keySetId.end());
+    if (mFileHandle.DeleteLicense(licenseName)) {
+        return Status::OK;
+    }
+    return Status::BAD_VALUE;
+}
+
+Return<void> DrmPlugin::getOfflineLicenseState(const KeySetId& keySetId,
+        getOfflineLicenseState_cb _hidl_cb) {
+    std::string licenseName(keySetId.begin(), keySetId.end());
+    DeviceFiles::LicenseState state;
+    std::string license;
+    OfflineLicenseState hLicenseState;
+    if (mFileHandle.RetrieveLicense(licenseName, &state, &license)) {
+        switch (state) {
+        case DeviceFiles::kLicenseStateActive:
+            hLicenseState = OfflineLicenseState::USABLE;
+            break;
+        case DeviceFiles::kLicenseStateReleasing:
+            hLicenseState = OfflineLicenseState::INACTIVE;
+            break;
+        case DeviceFiles::kLicenseStateUnknown:
+            hLicenseState = OfflineLicenseState::UNKNOWN;
+            break;
+        }
+        _hidl_cb(Status::OK, hLicenseState);
+    } else {
+        _hidl_cb(Status::BAD_VALUE, OfflineLicenseState::UNKNOWN);
+    }
+    return Void();
+}
+
 Return<void> DrmPlugin::getSecureStops(getSecureStops_cb _hidl_cb) {
     std::vector<SecureStop> stops;
     for (auto itr = mSecureStops.begin(); itr != mSecureStops.end(); ++itr) {
@@ -727,7 +775,7 @@
 }
 
 }  // namespace clearkey
-}  // namespace V1_1
+}  // namespace V1_2
 }  // namespace drm
 }  // namespace hardware
 }  // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp b/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp
index deb5d97..8ebb42b 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp
@@ -31,7 +31,7 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
 namespace {
@@ -169,7 +169,7 @@
 }
 
 } // namespace clearkey
-} // namespace V1_1
+} // namespace V1_2
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/JsonWebKey.cpp b/drm/mediadrm/plugins/clearkey/hidl/JsonWebKey.cpp
index 1c32b1b..d93777d 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/JsonWebKey.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/JsonWebKey.cpp
@@ -36,7 +36,7 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
 JsonWebKey::JsonWebKey() {
@@ -271,7 +271,7 @@
 }
 
 } // namespace clearkey
-} // namespace V1_1
+} // namespace V1_2
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/MemoryFileSystem.cpp b/drm/mediadrm/plugins/clearkey/hidl/MemoryFileSystem.cpp
index 43fecbb..2dcd00f 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/MemoryFileSystem.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/MemoryFileSystem.cpp
@@ -11,7 +11,7 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
 std::string MemoryFileSystem::GetFileName(const std::string& path) {
@@ -38,6 +38,14 @@
     }
 }
 
+std::vector<std::string> MemoryFileSystem::ListFiles() const {
+    std::vector<std::string> list;
+    for (const auto& filename : mMemoryFileSystem) {
+        list.push_back(filename.first);
+    }
+    return list;
+}
+
 size_t MemoryFileSystem::Read(const std::string& path, std::string* buffer) {
     std::string key = GetFileName(path);
     auto result = mMemoryFileSystem.find(key);
@@ -78,7 +86,7 @@
 }
 
 } // namespace clearkey
-} // namespace V1_1
+} // namespace V1_2
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/Session.cpp b/drm/mediadrm/plugins/clearkey/hidl/Session.cpp
index 41a8374..f4c49b9 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/Session.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/Session.cpp
@@ -28,7 +28,7 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
 using ::android::hardware::drm::V1_0::KeyValue;
@@ -90,7 +90,7 @@
 }
 
 } // namespace clearkey
-} // namespace V1_1
+} // namespace V1_2
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/SessionLibrary.cpp b/drm/mediadrm/plugins/clearkey/hidl/SessionLibrary.cpp
index d262763..99fb30f 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/SessionLibrary.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/SessionLibrary.cpp
@@ -24,7 +24,7 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
 using ::android::hardware::hidl_string;
@@ -86,7 +86,7 @@
 }
 
 } // namespace clearkey
-} // namespace V1_1
+} // namespace V1_2
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.1-service.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.1-service.clearkey.rc
deleted file mode 100644
index ffe856a..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.1-service.clearkey.rc
+++ /dev/null
@@ -1,6 +0,0 @@
-service vendor.drm-clearkey-hal-1-1 /vendor/bin/hw/android.hardware.drm@1.1-service.clearkey
-    class hal
-    user media
-    group media mediadrm
-    ioprio rt 4
-    writepid /dev/cpuset/foreground/tasks
diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service.clearkey.rc
new file mode 100644
index 0000000..ac184f7
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service.clearkey.rc
@@ -0,0 +1,6 @@
+service vendor.drm-clearkey-hal-1-2 /vendor/bin/hw/android.hardware.drm@1.2-service.clearkey
+    class hal
+    user media
+    group media mediadrm
+    ioprio rt 4
+    writepid /dev/cpuset/foreground/tasks
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/AesCtrDecryptor.h b/drm/mediadrm/plugins/clearkey/hidl/include/AesCtrDecryptor.h
index 0c7ef20..721f4c0 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/AesCtrDecryptor.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/AesCtrDecryptor.h
@@ -22,7 +22,7 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
 using ::android::hardware::drm::V1_0::Status;
@@ -42,7 +42,7 @@
 };
 
 } // namespace clearkey
-} // namespace V1_1
+} // namespace V1_2
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/Base64.h b/drm/mediadrm/plugins/clearkey/hidl/include/Base64.h
index 4a385bd..ec30cc1 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/Base64.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/Base64.h
@@ -25,7 +25,7 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
 using ::android::sp;
@@ -38,7 +38,7 @@
 void encodeBase64Url(const void *data, size_t size, std::string *out);
 
 } // namespace clearkey
-} // namespace V1_1
+} // namespace V1_2
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/Buffer.h b/drm/mediadrm/plugins/clearkey/hidl/include/Buffer.h
index 5bbb28a..c497e37 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/Buffer.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/Buffer.h
@@ -25,7 +25,7 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
 using ::android::sp;
@@ -54,7 +54,7 @@
 };
 
 } // namespace clearkey
-} // namespace V1_1
+} // namespace V1_2
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h b/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h
index 3d6a4a9..f83903c 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h
@@ -22,7 +22,7 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
 static const std::string kVendorKey("vendor");
@@ -49,7 +49,7 @@
 static const uint8_t kMetricsData[] = { 0 };
 
 } // namespace clearkey
-} // namespace V1_1
+} // namespace V1_2
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h b/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h
index 46cb5e4..7e9b6bd 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h
@@ -24,7 +24,7 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
 using ::android::hardware::drm::V1_0::KeyValue;
@@ -47,7 +47,7 @@
   void operator=(const TypeName&) = delete;
 
 } // namespace clearkey
-} // namespace V1_1
+} // namespace V1_2
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/CreatePluginFactories.h b/drm/mediadrm/plugins/clearkey/hidl/include/CreatePluginFactories.h
index 9952027..6368f3d 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/CreatePluginFactories.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/CreatePluginFactories.h
@@ -17,17 +17,17 @@
 #ifndef CLEARKEY_CREATE_PLUGIN_FACTORIES_H_
 #define CLEARKEY_CREATE_PLUGIN_FACTORIES_H_
 
-#include <android/hardware/drm/1.1/ICryptoFactory.h>
-#include <android/hardware/drm/1.1/IDrmFactory.h>
+#include <android/hardware/drm/1.2/ICryptoFactory.h>
+#include <android/hardware/drm/1.2/IDrmFactory.h>
 
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
-using ::android::hardware::drm::V1_1::ICryptoFactory;
-using ::android::hardware::drm::V1_1::IDrmFactory;
+using ::android::hardware::drm::V1_2::ICryptoFactory;
+using ::android::hardware::drm::V1_2::IDrmFactory;
 
 extern "C" {
     IDrmFactory* createDrmFactory();
@@ -35,7 +35,7 @@
 }
 
 }  // namespace clearkey
-}  // namespace V1_1
+}  // namespace V1_2
 }  // namespace drm
 }  // namespace hardware
 }  // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoFactory.h b/drm/mediadrm/plugins/clearkey/hidl/include/CryptoFactory.h
index 175ab76..203bb2d 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoFactory.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/CryptoFactory.h
@@ -18,17 +18,17 @@
 #define CLEARKEY_CRYPTO_FACTORY_H_
 
 #include <android/hardware/drm/1.0/ICryptoPlugin.h>
-#include <android/hardware/drm/1.1/ICryptoFactory.h>
+#include <android/hardware/drm/1.2/ICryptoFactory.h>
 
 #include "ClearKeyTypes.h"
 
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
-using ::android::hardware::drm::V1_1::ICryptoFactory;
+using ::android::hardware::drm::V1_2::ICryptoFactory;
 using ::android::hardware::drm::V1_0::ICryptoPlugin;
 using ::android::hardware::hidl_array;
 using ::android::hardware::hidl_string;
@@ -52,7 +52,7 @@
 };
 
 } // namespace clearkey
-} // namespace V1_1
+} // namespace V1_2
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h b/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h
index 6a73806..480dc7e 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h
@@ -32,7 +32,7 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
 using ::android::hardware::drm::V1_0::DestinationBuffer;
@@ -96,7 +96,7 @@
 };
 
 } // namespace clearkey
-} // namespace V1_1
+} // namespace V1_2
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/DeviceFiles.h b/drm/mediadrm/plugins/clearkey/hidl/include/DeviceFiles.h
index ac13d23..554ae59 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/DeviceFiles.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/DeviceFiles.h
@@ -20,7 +20,7 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
 class DeviceFiles {
@@ -42,6 +42,8 @@
 
     virtual bool LicenseExists(const std::string& keySetId);
 
+    virtual std::vector<std::string> ListLicenses() const;
+
     virtual bool DeleteLicense(const std::string& keySetId);
 
     virtual bool DeleteAllLicenses();
@@ -61,7 +63,7 @@
 };
 
 } // namespace clearkey
-} // namespace V1_1
+} // namespace V1_2
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h b/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h
index 6f58195..ff715ea 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h
@@ -17,15 +17,15 @@
 #ifndef CLEARKEY_DRM_FACTORY_H_
 #define CLEARKEY_DRM_FACTORY_H_
 
-#include <android/hardware/drm/1.1/IDrmPlugin.h>
-#include <android/hardware/drm/1.1/IDrmFactory.h>
+#include <android/hardware/drm/1.2/IDrmPlugin.h>
+#include <android/hardware/drm/1.2/IDrmFactory.h>
 
 #include "ClearKeyTypes.h"
 
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
 using ::android::hardware::hidl_array;
@@ -52,7 +52,7 @@
 };
 
 } // namespace clearkey
-} // namespace V1_1
+} // namespace V1_2
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
index 8e6092f..256c5d6 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
@@ -17,10 +17,12 @@
 #ifndef CLEARKEY_DRM_PLUGIN_H_
 #define CLEARKEY_DRM_PLUGIN_H_
 
-#include <android/hardware/drm/1.1/IDrmPlugin.h>
+#include <android/hardware/drm/1.2/IDrmPlugin.h>
 
-#include <stdio.h>
 #include <map>
+#include <stdio.h>
+
+#include <utils/List.h>
 
 #include "DeviceFiles.h"
 #include "SessionLibrary.h"
@@ -29,7 +31,7 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
 using ::android::hardware::drm::V1_0::EventType;
@@ -42,8 +44,12 @@
 using ::android::hardware::drm::V1_0::SessionId;
 using ::android::hardware::drm::V1_0::Status;
 using ::android::hardware::drm::V1_1::DrmMetricGroup;
-using ::android::hardware::drm::V1_1::IDrmPlugin;
+using ::android::hardware::drm::V1_1::HdcpLevel;
 using ::android::hardware::drm::V1_1::KeyRequestType;
+using ::android::hardware::drm::V1_1::SecureStopRelease;
+using ::android::hardware::drm::V1_1::SecurityLevel;
+using ::android::hardware::drm::V1_2::IDrmPlugin;
+using ::android::hardware::drm::V1_2::OfflineLicenseState;
 
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
@@ -136,6 +142,13 @@
 
     Return<void> getMetrics(getMetrics_cb _hidl_cb) override;
 
+    Return<void> getOfflineLicenseKeySetIds(getOfflineLicenseKeySetIds_cb _hidl_cb) override;
+
+    Return<Status> removeOfflineLicense(const KeySetId &keySetId) override;
+
+    Return<void> getOfflineLicenseState(const KeySetId &keySetId,
+            getOfflineLicenseState_cb _hidl_cb) override;
+
     Return<void> getPropertyString(
         const hidl_string& name,
         getPropertyString_cb _hidl_cb) override;
@@ -334,7 +347,7 @@
 };
 
 } // namespace clearkey
-} // namespace V1_1
+} // namespace V1_2
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/InitDataParser.h b/drm/mediadrm/plugins/clearkey/hidl/include/InitDataParser.h
index 7d7abf2..889f511 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/InitDataParser.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/InitDataParser.h
@@ -24,7 +24,7 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
 using ::android::hardware::drm::V1_0::Status;
@@ -49,7 +49,7 @@
 };
 
 } // namespace clearkey
-} // namespace V1_1
+} // namespace V1_2
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/JsonWebKey.h b/drm/mediadrm/plugins/clearkey/hidl/include/JsonWebKey.h
index 4ab034c..e57470c 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/JsonWebKey.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/JsonWebKey.h
@@ -23,7 +23,7 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
 class JsonWebKey {
@@ -54,7 +54,7 @@
 };
 
 } // namespace clearkey
-} // namespace V1_1
+} // namespace V1_2
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/MemoryFileSystem.h b/drm/mediadrm/plugins/clearkey/hidl/include/MemoryFileSystem.h
index 22f8779..bcd9fd6 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/MemoryFileSystem.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/MemoryFileSystem.h
@@ -13,7 +13,7 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
 // Using android file system requires clearkey plugin to update
@@ -42,6 +42,7 @@
 
     bool FileExists(const std::string& fileName) const;
     ssize_t GetFileSize(const std::string& fileName) const;
+    std::vector<std::string> ListFiles() const;
     size_t Read(const std::string& pathName, std::string* buffer);
     bool RemoveAllFiles();
     bool RemoveFile(const std::string& fileName);
@@ -59,7 +60,7 @@
 };
 
 } // namespace clearkey
-} // namespace V1_1
+} // namespace V1_2
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/Session.h b/drm/mediadrm/plugins/clearkey/hidl/include/Session.h
index 1064dc7..f35560d 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/Session.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/Session.h
@@ -27,7 +27,7 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
 using ::android::hardware::drm::V1_0::Status;
@@ -64,7 +64,7 @@
 };
 
 } // namespace clearkey
-} // namespace V1_1
+} // namespace V1_2
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/SessionLibrary.h b/drm/mediadrm/plugins/clearkey/hidl/include/SessionLibrary.h
index 326a0c1..1e567b8 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/SessionLibrary.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/SessionLibrary.h
@@ -26,7 +26,7 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
 using ::android::sp;
@@ -58,7 +58,7 @@
 };
 
 } // namespace clearkey
-} // namespace V1_1
+} // namespace V1_2
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h b/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h
index cc06329..f6d30c9 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h
@@ -24,7 +24,7 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_1 {
+namespace V1_2 {
 namespace clearkey {
 
 using ::android::hardware::hidl_array;
@@ -69,7 +69,7 @@
 }
 
 }  // namespace clearkey
-}  // namespace V1_1
+}  // namespace V1_2
 }  // namespace drm
 }  // namespace hardware
 }  // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/protos/DeviceFiles.proto b/drm/mediadrm/plugins/clearkey/hidl/protos/DeviceFiles.proto
index 145ac5b..3e11f0b 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/protos/DeviceFiles.proto
+++ b/drm/mediadrm/plugins/clearkey/hidl/protos/DeviceFiles.proto
@@ -10,7 +10,7 @@
 //
 syntax = "proto2";
 
-package android.hardware.drm.V1_1.clearkey;
+package android.hardware.drm.V1_2.clearkey;
 
 // need this if we are using libprotobuf-cpp-2.3.0-lite
 option optimize_for = LITE_RUNTIME;
diff --git a/drm/mediadrm/plugins/clearkey/hidl/service.cpp b/drm/mediadrm/plugins/clearkey/hidl/service.cpp
index 6a97b72..4ca31f3 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/service.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/service.cpp
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#define LOG_TAG "android.hardware.drm@1.1-service.clearkey"
+#define LOG_TAG "android.hardware.drm@1.2-service.clearkey"
 
 #include <CryptoFactory.h>
 #include <DrmFactory.h>
@@ -26,14 +26,14 @@
 using ::android::hardware::joinRpcThreadpool;
 using ::android::sp;
 
-using android::hardware::drm::V1_1::ICryptoFactory;
-using android::hardware::drm::V1_1::IDrmFactory;
-using android::hardware::drm::V1_1::clearkey::CryptoFactory;
-using android::hardware::drm::V1_1::clearkey::DrmFactory;
+using android::hardware::drm::V1_2::ICryptoFactory;
+using android::hardware::drm::V1_2::IDrmFactory;
+using android::hardware::drm::V1_2::clearkey::CryptoFactory;
+using android::hardware::drm::V1_2::clearkey::DrmFactory;
 
 
 int main(int /* argc */, char** /* argv */) {
-    ALOGD("android.hardware.drm@1.1-service.clearkey starting...");
+    ALOGD("android.hardware.drm@1.2-service.clearkey starting...");
 
     // The DRM HAL may communicate to other vendor components via
     // /dev/vndbinder
diff --git a/media/libmediaplayer2/nuplayer2/Android.bp b/media/libmediaplayer2/nuplayer2/Android.bp
index c3c94b6..93c218e 100644
--- a/media/libmediaplayer2/nuplayer2/Android.bp
+++ b/media/libmediaplayer2/nuplayer2/Android.bp
@@ -1,6 +1,7 @@
 cc_library_static {
 
     srcs: [
+        "JMediaPlayer2Utils.cpp",
         "JWakeLock.cpp",
         "GenericSource2.cpp",
         "HTTPLiveSource2.cpp",
@@ -29,6 +30,7 @@
         "frameworks/av/media/libstagefright/rtsp",
         "frameworks/av/media/libstagefright/timedtext",
         "frameworks/av/media/ndk",
+        "frameworks/base/core/jni",
     ],
 
     cflags: [
@@ -57,6 +59,7 @@
     static_libs: [
         "libmedia_helper",
         "libmediaplayer2-protos",
+        "libmedia2_jni_core",
     ],
 
     name: "libstagefright_nuplayer2",
diff --git a/media/libmediaplayer2/nuplayer2/JMediaPlayer2Utils.cpp b/media/libmediaplayer2/nuplayer2/JMediaPlayer2Utils.cpp
new file mode 100644
index 0000000..bbd22bc
--- /dev/null
+++ b/media/libmediaplayer2/nuplayer2/JMediaPlayer2Utils.cpp
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "JMediaPlayer2Utils"
+
+#include "JMediaPlayer2Utils.h"
+#include <mediaplayer2/JavaVMHelper.h>
+
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/Utils.h>
+#include <nativehelper/JNIHelp.h>
+#include <utils/Log.h>
+
+#include "log/log.h"
+
+namespace android {
+
+static const int64_t kOffloadMinDurationSec = 60;
+
+// static
+bool JMediaPlayer2Utils::isOffloadedAudioPlaybackSupported(
+        const sp<MetaData>& meta, bool hasVideo, bool isStreaming, audio_stream_type_t streamType)
+{
+    if (hasVideo || streamType != AUDIO_STREAM_MUSIC) {
+        return false;
+    }
+
+    audio_offload_info_t info = AUDIO_INFO_INITIALIZER;
+    if (OK != getAudioOffloadInfo(meta, hasVideo, isStreaming, streamType, &info)) {
+        return false;
+    }
+
+    if (info.duration_us < kOffloadMinDurationSec * 1000000) {
+        return false;
+    }
+
+    int32_t audioFormat = audioFormatFromNative(info.format);
+    int32_t channelMask = outChannelMaskFromNative(info.channel_mask);
+    if (audioFormat == ENCODING_INVALID || channelMask == CHANNEL_INVALID) {
+        return false;
+    }
+
+    JNIEnv* env = JavaVMHelper::getJNIEnv();
+    jclass jMP2UtilsCls = env->FindClass("android/media/MediaPlayer2Utils");
+    jmethodID jSetAudioOutputDeviceById = env->GetStaticMethodID(
+            jMP2UtilsCls, "isOffloadedAudioPlaybackSupported", "(III)Z");
+    jboolean result = env->CallStaticBooleanMethod(
+            jMP2UtilsCls, jSetAudioOutputDeviceById, audioFormat, info.sample_rate, channelMask);
+    return result;
+}
+
+}  // namespace android
diff --git a/media/libmediaplayer2/nuplayer2/JMediaPlayer2Utils.h b/media/libmediaplayer2/nuplayer2/JMediaPlayer2Utils.h
new file mode 100644
index 0000000..fcbd43c
--- /dev/null
+++ b/media/libmediaplayer2/nuplayer2/JMediaPlayer2Utils.h
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+#ifndef _J_MEDIAPLAYER2_UTILS2_H_
+#define _J_MEDIAPLAYER2_UTILS2_H_
+
+#include <media/stagefright/MetaData.h>
+
+#include "jni.h"
+#include "android_media_AudioFormat.h"
+
+namespace android {
+
+struct JMediaPlayer2Utils {
+    static bool isOffloadedAudioPlaybackSupported(
+            const sp<MetaData>& meta, bool hasVideo, bool isStreaming,
+            audio_stream_type_t streamType);
+};
+
+}  // namespace android
+
+#endif  // _J_MEDIAPLAYER2_UTILS2_H_
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
index c37460b..fef9fae 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
@@ -24,6 +24,7 @@
 #include "NuPlayer2.h"
 
 #include "HTTPLiveSource2.h"
+#include "JMediaPlayer2Utils.h"
 #include "NuPlayer2CCDecoder.h"
 #include "NuPlayer2Decoder.h"
 #include "NuPlayer2DecoderBase.h"
@@ -1699,7 +1700,8 @@
     }
 
     mOffloadAudio =
-        canOffloadStream(audioMeta, hasVideo, mCurrentSourceInfo.mSource->isStreaming(), streamType)
+        JMediaPlayer2Utils::isOffloadedAudioPlaybackSupported(
+                audioMeta, hasVideo, mCurrentSourceInfo.mSource->isStreaming(), streamType)
                 && (mPlaybackSettings.mSpeed == 1.f && mPlaybackSettings.mPitch == 1.f);
 
     // Modular DRM: Disabling audio offload if the source is protected
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 2ee5ab0..a024754 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -1830,43 +1830,43 @@
     return;
 }
 
-bool canOffloadStream(const sp<MetaData>& meta, bool hasVideo,
-                      bool isStreaming, audio_stream_type_t streamType)
+status_t getAudioOffloadInfo(const sp<MetaData>& meta, bool hasVideo,
+        bool isStreaming, audio_stream_type_t streamType, audio_offload_info_t *info)
 {
     const char *mime;
     if (meta == NULL) {
-        return false;
+        return BAD_VALUE;
     }
     CHECK(meta->findCString(kKeyMIMEType, &mime));
 
-    audio_offload_info_t info = AUDIO_INFO_INITIALIZER;
+    (*info) = AUDIO_INFO_INITIALIZER;
 
-    info.format = AUDIO_FORMAT_INVALID;
-    if (mapMimeToAudioFormat(info.format, mime) != OK) {
+    info->format = AUDIO_FORMAT_INVALID;
+    if (mapMimeToAudioFormat(info->format, mime) != OK) {
         ALOGE(" Couldn't map mime type \"%s\" to a valid AudioSystem::audio_format !", mime);
-        return false;
+        return BAD_VALUE;
     } else {
-        ALOGV("Mime type \"%s\" mapped to audio_format %d", mime, info.format);
+        ALOGV("Mime type \"%s\" mapped to audio_format %d", mime, info->format);
     }
 
-    if (AUDIO_FORMAT_INVALID == info.format) {
+    if (AUDIO_FORMAT_INVALID == info->format) {
         // can't offload if we don't know what the source format is
         ALOGE("mime type \"%s\" not a known audio format", mime);
-        return false;
+        return BAD_VALUE;
     }
 
     // Redefine aac format according to its profile
     // Offloading depends on audio DSP capabilities.
     int32_t aacaot = -1;
     if (meta->findInt32(kKeyAACAOT, &aacaot)) {
-        mapAACProfileToAudioFormat(info.format,(OMX_AUDIO_AACPROFILETYPE) aacaot);
+        mapAACProfileToAudioFormat(info->format,(OMX_AUDIO_AACPROFILETYPE) aacaot);
     }
 
     int32_t srate = -1;
     if (!meta->findInt32(kKeySampleRate, &srate)) {
         ALOGV("track of type '%s' does not publish sample rate", mime);
     }
-    info.sample_rate = srate;
+    info->sample_rate = srate;
 
     int32_t cmask = 0;
     if (!meta->findInt32(kKeyChannelMask, &cmask) || cmask == CHANNEL_MASK_USE_CHANNEL_ORDER) {
@@ -1880,25 +1880,34 @@
             cmask = audio_channel_out_mask_from_count(channelCount);
         }
     }
-    info.channel_mask = cmask;
+    info->channel_mask = cmask;
 
     int64_t duration = 0;
     if (!meta->findInt64(kKeyDuration, &duration)) {
         ALOGV("track of type '%s' does not publish duration", mime);
     }
-    info.duration_us = duration;
+    info->duration_us = duration;
 
     int32_t brate = -1;
     if (!meta->findInt32(kKeyBitRate, &brate)) {
         ALOGV("track of type '%s' does not publish bitrate", mime);
     }
-    info.bit_rate = brate;
+    info->bit_rate = brate;
 
 
-    info.stream_type = streamType;
-    info.has_video = hasVideo;
-    info.is_streaming = isStreaming;
+    info->stream_type = streamType;
+    info->has_video = hasVideo;
+    info->is_streaming = isStreaming;
+    return OK;
+}
 
+bool canOffloadStream(const sp<MetaData>& meta, bool hasVideo,
+                      bool isStreaming, audio_stream_type_t streamType)
+{
+    audio_offload_info_t info = AUDIO_INFO_INITIALIZER;
+    if (OK != getAudioOffloadInfo(meta, hasVideo, isStreaming, streamType, &info)) {
+        return false;
+    }
     // Check if offload is possible for given format, stream type, sample rate,
     // bit rate, duration, video and streaming
     return AudioSystem::isOffloadSupported(info);
diff --git a/media/libstagefright/include/media/stagefright/Utils.h b/media/libstagefright/include/media/stagefright/Utils.h
index 46a419d..e8e0a11 100644
--- a/media/libstagefright/include/media/stagefright/Utils.h
+++ b/media/libstagefright/include/media/stagefright/Utils.h
@@ -52,6 +52,10 @@
 // Send information from MetaData to the HAL via AudioSink
 status_t sendMetaDataToHal(sp<MediaPlayerBase::AudioSink>& sink, const sp<MetaData>& meta);
 
+// Return |audio_offload_info_t| filled from given metadata
+status_t getAudioOffloadInfo(const sp<MetaData>& meta, bool hasVideo,
+        bool isStreaming, audio_stream_type_t streamType, audio_offload_info_t *info);
+
 // Check whether the stream defined by meta can be offloaded to hardware
 bool canOffloadStream(const sp<MetaData>& meta, bool hasVideo,
                       bool isStreaming, audio_stream_type_t streamType);
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 58acad3..f39614e 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1070,8 +1070,17 @@
     return output;
 }
 
-sp<DeviceDescriptor> AudioPolicyManager::getMsdAudioInDevice() const {
+sp<HwModule> AudioPolicyManager::getMsdModule() const {
     sp<HwModule> msdModule = mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD);
+    if (msdModule != 0 && property_get_bool("audio.msd.disable", false /* default_value */)) {
+        ALOGI("use of the MSD module is disabled by audio.msd.disable property");
+        return 0;
+    }
+    return msdModule;
+}
+
+sp<DeviceDescriptor> AudioPolicyManager::getMsdAudioInDevice() const {
+    sp<HwModule> msdModule = getMsdModule();
     if (msdModule != 0) {
         DeviceVector msdInputDevices = mAvailableInputDevices.getDevicesFromHwModule(
                 msdModule->getHandle());
@@ -1081,7 +1090,7 @@
 }
 
 audio_devices_t AudioPolicyManager::getMsdAudioOutDeviceTypes() const {
-    sp<HwModule> msdModule = mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD);
+    sp<HwModule> msdModule = getMsdModule();
     if (msdModule != 0) {
         return mAvailableOutputDevices.getDeviceTypesFromHwModule(msdModule->getHandle());
     }
@@ -1090,6 +1099,7 @@
 
 const AudioPatchCollection AudioPolicyManager::getMsdPatches() const {
     AudioPatchCollection msdPatches;
+    // This function ignores audio.msd.disable property to allow patch teardown.
     sp<HwModule> msdModule = mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD);
     if (msdModule != 0) {
         for (size_t i = 0; i < mAudioPatches.size(); ++i) {
@@ -1109,7 +1119,7 @@
 status_t AudioPolicyManager::getBestMsdAudioProfileFor(audio_devices_t outputDevice,
         bool hwAvSync, audio_port_config *sourceConfig, audio_port_config *sinkConfig) const
 {
-    sp<HwModule> msdModule = mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD);
+    sp<HwModule> msdModule = getMsdModule();
     if (msdModule == nullptr) {
         ALOGE("%s() unable to get MSD module", __func__);
         return NO_INIT;
@@ -4627,7 +4637,7 @@
     checkOutputForAllStrategies();
     if (onOutputsChecked != nullptr && onOutputsChecked()) checkA2dpSuspend();
     updateDevicesAndOutputs();
-    if (mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD) != 0) {
+    if (getMsdModule() != 0) {
         setMsdPatch();
     }
 }
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index f559b7f..16186ae 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -616,6 +616,7 @@
         void filterSurroundChannelMasks(ChannelsVector *channelMasksPtr);
 
         // Support for Multi-Stream Decoder (MSD) module
+        sp<HwModule> getMsdModule() const;
         sp<DeviceDescriptor> getMsdAudioInDevice() const;
         audio_devices_t getMsdAudioOutDeviceTypes() const;
         const AudioPatchCollection getMsdPatches() const;