MediaPlayer2Impl.java revision 371144fcc23f3d0a668d0d51bd3c3f90c964cd7b
10a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia/* 20a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Copyright 2018 The Android Open Source Project 30a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 40a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Licensed under the Apache License, Version 2.0 (the "License"); 50a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * you may not use this file except in compliance with the License. 60a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * You may obtain a copy of the License at 70a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 80a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * http://www.apache.org/licenses/LICENSE-2.0 90a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Unless required by applicable law or agreed to in writing, software 110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * distributed under the License is distributed on an "AS IS" BASIS, 120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * See the License for the specific language governing permissions and 140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * limitations under the License. 150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiapackage android.media; 180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport android.annotation.CallbackExecutor; 200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport android.annotation.NonNull; 210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport android.annotation.Nullable; 220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport android.app.ActivityThread; 230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport android.content.ContentProvider; 240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport android.content.ContentResolver; 250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport android.content.Context; 260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport android.content.res.AssetFileDescriptor; 271789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jiaimport android.graphics.SurfaceTexture; 281789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jiaimport android.media.SubtitleController.Anchor; 291789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jiaimport android.media.SubtitleTrack.RenderingWidget; 300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport android.net.Uri; 310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport android.os.Handler; 320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport android.os.HandlerThread; 330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport android.os.Looper; 340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport android.os.Message; 350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport android.os.Parcel; 360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport android.os.Parcelable; 370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport android.os.PersistableBundle; 380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport android.os.PowerManager; 3947cab8322a01edee503f10e9d5cbec2a5b5cffc3Dongwon Kangimport android.os.Process; 400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport android.os.SystemProperties; 410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport android.provider.Settings; 420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport android.system.ErrnoException; 430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport android.system.Os; 440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport android.system.OsConstants; 4547cab8322a01edee503f10e9d5cbec2a5b5cffc3Dongwon Kangimport android.util.ArrayMap; 460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport android.util.Log; 470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport android.util.Pair; 480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport android.view.Surface; 490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport android.view.SurfaceHolder; 500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport android.widget.VideoView; 510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport com.android.internal.annotations.GuardedBy; 530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport com.android.internal.util.Preconditions; 540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport dalvik.system.CloseGuard; 560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport libcore.io.IoBridge; 580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport libcore.io.Streams; 590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport java.io.ByteArrayOutputStream; 610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport java.io.File; 620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport java.io.FileDescriptor; 630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport java.io.FileInputStream; 640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport java.io.IOException; 650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport java.io.InputStream; 660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport java.lang.ref.WeakReference; 670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport java.net.HttpCookie; 680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport java.net.HttpURLConnection; 690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport java.net.URL; 700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport java.nio.ByteOrder; 710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport java.util.ArrayList; 720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport java.util.Arrays; 730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport java.util.BitSet; 740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport java.util.HashMap; 75adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kangimport java.util.LinkedList; 760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport java.util.List; 770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport java.util.Map; 780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport java.util.Scanner; 790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport java.util.Set; 800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport java.util.UUID; 810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiaimport java.util.Vector; 8247cab8322a01edee503f10e9d5cbec2a5b5cffc3Dongwon Kangimport java.util.concurrent.Executor; 83c3725a94bb9840027a42669a659a0fd11d6f69c6Wei Jiaimport java.util.concurrent.atomic.AtomicInteger; 840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia/** 860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @hide 870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiapublic final class MediaPlayer2Impl extends MediaPlayer2 { 890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia static { 900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia System.loadLibrary("media2_jni"); 910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia native_init(); 920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private final static String TAG = "MediaPlayer2Impl"; 950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private long mNativeContext; // accessed by native methods 970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private long mNativeSurfaceTexture; // accessed by native methods 980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private int mListenerContext; // accessed by native methods 990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private SurfaceHolder mSurfaceHolder; 1000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private EventHandler mEventHandler; 1010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private PowerManager.WakeLock mWakeLock = null; 1020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private boolean mScreenOnWhilePlaying; 1030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private boolean mStayAwake; 1040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private int mStreamType = AudioManager.USE_DEFAULT_STREAM_TYPE; 1050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private final CloseGuard mGuard = CloseGuard.get(); 1060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 107cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia private final Object mSrcLock = new Object(); 108cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia //--- guarded by |mSrcLock| start 109cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia private long mSrcIdGenerator = 0; 1101789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia private DataSourceDesc mCurrentDSD; 111cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia private long mCurrentSrcId = mSrcIdGenerator++; 112cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia private List<DataSourceDesc> mNextDSDs; 113cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia private long mNextSrcId = mSrcIdGenerator++; 114cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia private int mNextSourceState = NEXT_SOURCE_STATE_INIT; 115cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia private boolean mNextSourcePlayPending = false; 116cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia //--- guarded by |mSrcLock| end 1170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 118371144fcc23f3d0a668d0d51bd3c3f90c964cd7bWei Jia private AtomicInteger mBufferedPercentageCurrent = new AtomicInteger(0); 119371144fcc23f3d0a668d0d51bd3c3f90c964cd7bWei Jia private AtomicInteger mBufferedPercentageNext = new AtomicInteger(0); 120096d97ac3e01d3a148f6148180c375f9337b64e5Wei Jia private volatile float mVolume = 1.0f; 121c3725a94bb9840027a42669a659a0fd11d6f69c6Wei Jia 1220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // Modular DRM 1230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private final Object mDrmLock = new Object(); 124cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia //--- guarded by |mDrmLock| start 125cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia private UUID mDrmUUID; 1260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private DrmInfoImpl mDrmInfoImpl; 1270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private MediaDrm mDrmObj; 1280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private byte[] mDrmSessionId; 1290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private boolean mDrmInfoResolved; 1300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private boolean mActiveDrmScheme; 1310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private boolean mDrmConfigAllowed; 1320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private boolean mDrmProvisioningInProgress; 1330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private boolean mPrepareDrmInProgress; 1340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private ProvisioningThread mDrmProvisioningThread; 135cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia //--- guarded by |mDrmLock| end 1360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 137adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang private HandlerThread mHandlerThread; 138adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang private final Handler mTaskHandler; 139adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang private final Object mTaskLock = new Object(); 140adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang @GuardedBy("mTaskLock") 141adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang private final List<Task> mPendingTasks = new LinkedList<>(); 142adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang @GuardedBy("mTaskLock") 143adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang private Task mCurrentTask; 144adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang 1450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 1460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Default constructor. 1470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * <p>When done with the MediaPlayer2Impl, you should call {@link #close()}, 1480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * to free the resources. If not released, too many MediaPlayer2Impl instances may 1490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * result in an exception.</p> 1500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 1510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public MediaPlayer2Impl() { 1520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Looper looper; 1530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if ((looper = Looper.myLooper()) != null) { 1540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mEventHandler = new EventHandler(this, looper); 1550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } else if ((looper = Looper.getMainLooper()) != null) { 1560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mEventHandler = new EventHandler(this, looper); 1570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } else { 1580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mEventHandler = null; 1590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 1600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 161adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang mHandlerThread = new HandlerThread("MediaPlayer2TaskThread"); 162adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang mHandlerThread.start(); 163adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang looper = mHandlerThread.getLooper(); 164adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang mTaskHandler = new Handler(looper); 165adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang 1660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mTimeProvider = new TimeProvider(this); 1670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mOpenSubtitleSources = new Vector<InputStream>(); 1680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mGuard.open("close"); 1690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 1700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /* Native setup requires a weak reference to our object. 1710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * It's easier to create it here than in C++. 1720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 1730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia native_setup(new WeakReference<MediaPlayer2Impl>(this)); 1740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 1750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 1761789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia /** 1771789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Releases the resources held by this {@code MediaPlayer2} object. 1781789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * 1791789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * It is considered good practice to call this method when you're 1801789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * done using the MediaPlayer2. In particular, whenever an Activity 1811789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * of an application is paused (its onPause() method is called), 1821789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * or stopped (its onStop() method is called), this method should be 1831789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * invoked to release the MediaPlayer2 object, unless the application 1841789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * has a special need to keep the object around. In addition to 1851789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * unnecessary resources (such as memory and instances of codecs) 1861789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * being held, failure to call this method immediately if a 1871789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * MediaPlayer2 object is no longer needed may also lead to 1881789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * continuous battery consumption for mobile devices, and playback 1891789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * failure for other applications if no multiple instances of the 1901789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * same codec are supported on a device. Even if multiple instances 1911789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * of the same codec are supported, some performance degradation 1921789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * may be expected when unnecessary multiple instances are used 1931789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * at the same time. 1941789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * 1951789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * {@code close()} may be safely called after a prior {@code close()}. 1961789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * This class implements the Java {@code AutoCloseable} interface and 1971789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * may be used with try-with-resources. 1981789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia */ 1991789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia @Override 2001789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public void close() { 2011789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia synchronized (mGuard) { 2021789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia release(); 2031789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia } 2041789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia } 205de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia 2061789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia /** 2071789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Starts or resumes playback. If playback had previously been paused, 2081789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * playback will continue from where it was paused. If playback had 2091789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * been stopped, or never started before, playback will start at the 2101789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * beginning. 2111789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * 2121789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @throws IllegalStateException if it is called in an invalid state 2130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 2141789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia @Override 2151789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public void play() { 21669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang addTask(new Task(CALL_COMPLETED_PLAY, false) { 21769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang @Override 21869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang void process() { 21969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang stayAwake(true); 22069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang _start(); 22169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 22269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang }); 2231789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia } 2240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 2251789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia private native void _start() throws IllegalStateException; 2261789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia 2271789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia /** 2281789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Prepares the player for playback, asynchronously. 2291789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * 2301789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * After setting the datasource and the display surface, you need to either 2311789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * call prepare(). For streams, you should call prepare(), 2321789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * which returns immediately, rather than blocking until enough data has been 2331789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * buffered. 2341789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * 2351789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @throws IllegalStateException if it is called in an invalid state 2360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 2371789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia @Override 238adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang public void prepare() { 23969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang addTask(new Task(CALL_COMPLETED_PREPARE, true) { 24069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang @Override 24169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang void process() { 24269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang _prepare(); 24369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 24469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang }); 245adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang } 246adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang 247adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang public native void _prepare(); 2480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 2490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 2501789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Pauses playback. Call play() to resume. 2510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 2521789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @throws IllegalStateException if the internal player engine has not been 2531789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * initialized. 2540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 2550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 2561789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public void pause() { 25769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang addTask(new Task(CALL_COMPLETED_PAUSE, false) { 25869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang @Override 25969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang void process() { 26069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang stayAwake(false); 26169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang _pause(); 26269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 26369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang }); 2640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 2650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 2661789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia private native void _pause() throws IllegalStateException; 2671789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia 2680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 2691789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Tries to play next data source if applicable. 2700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 2711789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @throws IllegalStateException if it is called in an invalid state 2720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 2730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 2741789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public void skipToNext() { 27569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang addTask(new Task(CALL_COMPLETED_SKIP_TO_NEXT, false) { 27669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang @Override 27769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang void process() { 27869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang // TODO: switch to next data source and play 27969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 28069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang }); 2810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 2820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 2830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 2841789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Gets the current playback position. 2850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 2861789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @return the current position in milliseconds 2871789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia */ 2881789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia @Override 2891789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public native long getCurrentPosition(); 2901789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia 2911789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia /** 2921789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Gets the duration of the file. 2930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 2941789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @return the duration in milliseconds, if no duration is available 2951789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * (for example, if streaming live content), -1 is returned. 2960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 2970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 2981789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public native long getDuration(); 2990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 3000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 3011789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Gets the current buffered media source position received through progressive downloading. 3021789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * The received buffering percentage indicates how much of the content has been buffered 3031789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * or played. For example a buffering update of 80 percent when half the content 3041789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * has already been played indicates that the next 30 percent of the 3051789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * content to play has been buffered. 3060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 3071789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @return the current buffered media source position in milliseconds 3081789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia */ 3091789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia @Override 3101789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public long getBufferedPosition() { 311c3725a94bb9840027a42669a659a0fd11d6f69c6Wei Jia // Use cached buffered percent for now. 312c3725a94bb9840027a42669a659a0fd11d6f69c6Wei Jia return getDuration() * mBufferedPercentageCurrent.get() / 100; 3131789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia } 3141789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia 3150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 3161789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public @PlayerState int getPlayerState() { 317be6e3024bdab7479e352933194eec36abf2b0bf3Wei Jia int mediaplayer2State = getMediaPlayer2State(); 318be6e3024bdab7479e352933194eec36abf2b0bf3Wei Jia int playerState; 319be6e3024bdab7479e352933194eec36abf2b0bf3Wei Jia switch (mediaplayer2State) { 320be6e3024bdab7479e352933194eec36abf2b0bf3Wei Jia case MEDIAPLAYER2_STATE_IDLE: 321be6e3024bdab7479e352933194eec36abf2b0bf3Wei Jia playerState = PLAYER_STATE_IDLE; 322be6e3024bdab7479e352933194eec36abf2b0bf3Wei Jia break; 323be6e3024bdab7479e352933194eec36abf2b0bf3Wei Jia case MEDIAPLAYER2_STATE_PREPARED: 324be6e3024bdab7479e352933194eec36abf2b0bf3Wei Jia case MEDIAPLAYER2_STATE_PAUSED: 325be6e3024bdab7479e352933194eec36abf2b0bf3Wei Jia playerState = PLAYER_STATE_PAUSED; 326be6e3024bdab7479e352933194eec36abf2b0bf3Wei Jia break; 327be6e3024bdab7479e352933194eec36abf2b0bf3Wei Jia case MEDIAPLAYER2_STATE_PLAYING: 328be6e3024bdab7479e352933194eec36abf2b0bf3Wei Jia playerState = PLAYER_STATE_PLAYING; 329be6e3024bdab7479e352933194eec36abf2b0bf3Wei Jia break; 330be6e3024bdab7479e352933194eec36abf2b0bf3Wei Jia case MEDIAPLAYER2_STATE_ERROR: 331be6e3024bdab7479e352933194eec36abf2b0bf3Wei Jia default: 332be6e3024bdab7479e352933194eec36abf2b0bf3Wei Jia playerState = PLAYER_STATE_ERROR; 333be6e3024bdab7479e352933194eec36abf2b0bf3Wei Jia break; 334be6e3024bdab7479e352933194eec36abf2b0bf3Wei Jia } 335be6e3024bdab7479e352933194eec36abf2b0bf3Wei Jia 336be6e3024bdab7479e352933194eec36abf2b0bf3Wei Jia return playerState; 3370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 3380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 3390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 3401789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Gets the current buffering state of the player. 3411789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * During buffering, see {@link #getBufferedPosition()} for the quantifying the amount already 3421789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * buffered. 3430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 3440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 3451789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public @BuffState int getBufferingState() { 3461789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia // TODO: use cached state or call native function. 3471789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia return BUFFERING_STATE_UNKNOWN; 3480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 3490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 3500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 3511789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Sets the audio attributes for this MediaPlayer2. 3521789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * See {@link AudioAttributes} for how to build and configure an instance of this class. 3531789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * You must call this method before {@link #prepare()} in order 3541789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * for the audio attributes to become effective thereafter. 3551789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @param attributes a non-null set of audio attributes 3561789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @throws IllegalArgumentException if the attributes are null or invalid. 3570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 3580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 3591789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public void setAudioAttributes(@NonNull AudioAttributes attributes) { 36069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang addTask(new Task(CALL_COMPLETED_SET_AUDIO_ATTRIBUTES, false) { 36169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang @Override 36269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang void process() { 36369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang if (attributes == null) { 36469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang final String msg = "Cannot set AudioAttributes to null"; 36569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang throw new IllegalArgumentException(msg); 36669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 36769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang Parcel pattributes = Parcel.obtain(); 36869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang attributes.writeToParcel(pattributes, AudioAttributes.FLATTEN_TAGS); 36969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang setParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES, pattributes); 37069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang pattributes.recycle(); 37169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 37269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang }); 3731789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia } 3741789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia 3751789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia @Override 3761789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public @NonNull AudioAttributes getAudioAttributes() { 3771789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia Parcel pattributes = getParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES); 3781789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia AudioAttributes attributes = AudioAttributes.CREATOR.createFromParcel(pattributes); 3791789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia pattributes.recycle(); 3801789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia return attributes; 3810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 3820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 3830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 3840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Sets the data source as described by a DataSourceDesc. 3850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 3860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param dsd the descriptor of data source you want to play 3870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalStateException if it is called in an invalid state 3880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws NullPointerException if dsd is null 3890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 3900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 3911789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public void setDataSource(@NonNull DataSourceDesc dsd) { 39269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang addTask(new Task(CALL_COMPLETED_SET_DATA_SOURCE, false) { 39369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang @Override 39469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang void process() { 39569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang Preconditions.checkNotNull(dsd, "the DataSourceDesc cannot be null"); 39669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang // TODO: setDataSource could update exist data source 39769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang synchronized (mSrcLock) { 39869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang mCurrentDSD = dsd; 39969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang mCurrentSrcId = mSrcIdGenerator++; 40069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang try { 40169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang handleDataSource(true /* isCurrent */, dsd, mCurrentSrcId); 40269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } catch (IOException e) { 40369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 40469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 4051789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia } 40669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang }); 4070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 4080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 4090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 4101789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Sets a single data source as described by a DataSourceDesc which will be played 4111789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * after current data source is finished. 4120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 4131789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @param dsd the descriptor of data source you want to play after current one 4141789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @throws IllegalStateException if it is called in an invalid state 4151789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @throws NullPointerException if dsd is null 4160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 4170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 4181789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public void setNextDataSource(@NonNull DataSourceDesc dsd) { 41969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang addTask(new Task(CALL_COMPLETED_SET_NEXT_DATA_SOURCE, false) { 42069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang @Override 42169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang void process() { 42269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang Preconditions.checkNotNull(dsd, "the DataSourceDesc cannot be null"); 42369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang synchronized (mSrcLock) { 42469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang mNextDSDs = new ArrayList<DataSourceDesc>(1); 42569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang mNextDSDs.add(dsd); 42669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang mNextSrcId = mSrcIdGenerator++; 42769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang mNextSourceState = NEXT_SOURCE_STATE_INIT; 42869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang mNextSourcePlayPending = false; 42969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 43069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang int state = getMediaPlayer2State(); 43169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang if (state != MEDIAPLAYER2_STATE_IDLE) { 43269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang synchronized (mSrcLock) { 43369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang prepareNextDataSource_l(); 43469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 43569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 436cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia } 43769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang }); 4380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 4390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 4400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 4411789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Sets a list of data sources to be played sequentially after current data source is done. 4420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 4431789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @param dsds the list of data sources you want to play after current one 4440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalStateException if it is called in an invalid state 4451789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @throws IllegalArgumentException if dsds is null or empty, or contains null DataSourceDesc 4460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 4470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 4481789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public void setNextDataSources(@NonNull List<DataSourceDesc> dsds) { 44969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang addTask(new Task(CALL_COMPLETED_SET_NEXT_DATA_SOURCES, false) { 45069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang @Override 45169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang void process() { 45269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang if (dsds == null || dsds.size() == 0) { 45369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang throw new IllegalArgumentException("data source list cannot be null or empty."); 45469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 45569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang for (DataSourceDesc dsd : dsds) { 45669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang if (dsd == null) { 45769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang throw new IllegalArgumentException( 45869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang "DataSourceDesc in the source list cannot be null."); 45969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 46069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 4610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 46269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang synchronized (mSrcLock) { 46369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang mNextDSDs = new ArrayList(dsds); 46469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang mNextSrcId = mSrcIdGenerator++; 46569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang mNextSourceState = NEXT_SOURCE_STATE_INIT; 46669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang mNextSourcePlayPending = false; 46769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 46869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang int state = getMediaPlayer2State(); 46969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang if (state != MEDIAPLAYER2_STATE_IDLE) { 47069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang synchronized (mSrcLock) { 47169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang prepareNextDataSource_l(); 47269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 47369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 474cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia } 47569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang }); 4760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 4770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 4780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 4791789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public @NonNull DataSourceDesc getCurrentDataSource() { 480cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia synchronized (mSrcLock) { 4811789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia return mCurrentDSD; 4820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 4830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 4840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 4850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 4861789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Configures the player to loop on the current data source. 4871789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @param loop true if the current data source is meant to loop. 4880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 4890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 4901789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public void loopCurrent(boolean loop) { 49169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang addTask(new Task(CALL_COMPLETED_LOOP_CURRENT, false) { 49269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang @Override 49369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang void process() { 49469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang // TODO: set the looping mode, send notification 49569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang setLooping(loop); 49669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 49769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang }); 4981789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia } 4990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 5001789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia private native void setLooping(boolean looping); 5010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 5021789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia /** 5031789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Sets the playback speed. 5041789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * A value of 1.0f is the default playback value. 5051789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * A negative value indicates reverse playback, check {@link #isReversePlaybackSupported()} 5061789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * before using negative values.<br> 5071789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * After changing the playback speed, it is recommended to query the actual speed supported 5081789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * by the player, see {@link #getPlaybackSpeed()}. 5091789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @param speed the desired playback speed 5101789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia */ 5111789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia @Override 5121789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public void setPlaybackSpeed(float speed) { 51369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang addTask(new Task(CALL_COMPLETED_SET_PLAYBACK_SPEED, false) { 51469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang @Override 51569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang void process() { 51669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang _setPlaybackParams(getPlaybackParams().setSpeed(speed)); 51769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 51869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang }); 5190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 5200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 5210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 5221789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Returns the actual playback speed to be used by the player when playing. 5231789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Note that it may differ from the speed set in {@link #setPlaybackSpeed(float)}. 5241789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @return the actual playback speed 5250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 5260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 5271789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public float getPlaybackSpeed() { 5281789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia return getPlaybackParams().getSpeed(); 5291789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia } 5300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 5311789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia /** 5321789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Indicates whether reverse playback is supported. 5331789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Reverse playback is indicated by negative playback speeds, see 5341789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * {@link #setPlaybackSpeed(float)}. 5351789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @return true if reverse playback is supported. 5361789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia */ 5371789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia @Override 5381789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public boolean isReversePlaybackSupported() { 5391789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia return false; 5401789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia } 5410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 5421789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia /** 5431789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Sets the volume of the audio of the media to play, expressed as a linear multiplier 5441789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * on the audio samples. 5451789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Note that this volume is specific to the player, and is separate from stream volume 5461789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * used across the platform.<br> 5471789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * A value of 0.0f indicates muting, a value of 1.0f is the nominal unattenuated and unamplified 5481789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * gain. See {@link #getMaxPlayerVolume()} for the volume range supported by this player. 5491789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @param volume a value between 0.0f and {@link #getMaxPlayerVolume()}. 5501789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia */ 5511789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia @Override 5521789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public void setPlayerVolume(float volume) { 55369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang addTask(new Task(CALL_COMPLETED_SET_PLAYER_VOLUME, false) { 55469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang @Override 55569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang void process() { 556096d97ac3e01d3a148f6148180c375f9337b64e5Wei Jia mVolume = volume; 55769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang _setVolume(volume, volume); 55869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 55969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang }); 5600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 5610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 5621789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia private native void _setVolume(float leftVolume, float rightVolume); 5631789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia 5640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 5651789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Returns the current volume of this player to this player. 5661789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Note that it does not take into account the associated stream volume. 5671789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @return the player volume. 5680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 5690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 5701789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public float getPlayerVolume() { 571096d97ac3e01d3a148f6148180c375f9337b64e5Wei Jia return mVolume; 5720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 5730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 5740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 5751789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @return the maximum volume that can be used in {@link #setPlayerVolume(float)}. 5760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 5770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 5781789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public float getMaxPlayerVolume() { 5791789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia return 1.0f; 5801789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia } 5810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 5821789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia /** 5831789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Adds a callback to be notified of events for this player. 5841789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @param e the {@link Executor} to be used for the events. 5851789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @param cb the callback to receive the events. 5861789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia */ 5871789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia @Override 5881789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public void registerPlayerEventCallback(@NonNull Executor e, 5891789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia @NonNull PlayerEventCallback cb) { 5901789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia } 591de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia 5921789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia /** 5931789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Removes a previously registered callback for player events 5941789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @param cb the callback to remove 5951789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia */ 5961789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia @Override 5971789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public void unregisterPlayerEventCallback(@NonNull PlayerEventCallback cb) { 5980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 5990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 6001789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia 6011789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia private static final int NEXT_SOURCE_STATE_ERROR = -1; 6021789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia private static final int NEXT_SOURCE_STATE_INIT = 0; 6031789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia private static final int NEXT_SOURCE_STATE_PREPARING = 1; 6041789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia private static final int NEXT_SOURCE_STATE_PREPARED = 2; 6051789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia 6061789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia /* 6071789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Update the MediaPlayer2Impl SurfaceTexture. 6081789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Call after setting a new display surface. 6091789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia */ 6101789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia private native void _setVideoSurface(Surface surface); 6111789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia 6121789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia /* Do not change these values (starting with INVOKE_ID) without updating 6131789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * their counterparts in include/media/mediaplayer2.h! 6141789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia */ 6151789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia private static final int INVOKE_ID_GET_TRACK_INFO = 1; 6161789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia private static final int INVOKE_ID_ADD_EXTERNAL_SOURCE = 2; 6171789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia private static final int INVOKE_ID_ADD_EXTERNAL_SOURCE_FD = 3; 6181789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia private static final int INVOKE_ID_SELECT_TRACK = 4; 6191789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia private static final int INVOKE_ID_DESELECT_TRACK = 5; 6201789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia private static final int INVOKE_ID_SET_VIDEO_SCALE_MODE = 6; 6211789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia private static final int INVOKE_ID_GET_SELECTED_TRACK = 7; 6221789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia 6230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 6241789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Create a request parcel which can be routed to the native media 6251789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * player using {@link #invoke(Parcel, Parcel)}. The Parcel 6261789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * returned has the proper InterfaceToken set. The caller should 6271789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * not overwrite that token, i.e it can only append data to the 6281789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Parcel. 6290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 6301789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @return A parcel suitable to hold a request for the native 6311789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * player. 6321789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * {@hide} 6330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 6340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 6351789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public Parcel newRequest() { 6361789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia Parcel parcel = Parcel.obtain(); 6371789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia return parcel; 6380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 6390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 6400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 6411789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Invoke a generic method on the native player using opaque 6421789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * parcels for the request and reply. Both payloads' format is a 6431789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * convention between the java caller and the native player. 6441789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Must be called after setDataSource or setPlaylist to make sure a native player 6451789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * exists. On failure, a RuntimeException is thrown. 6460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 6471789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @param request Parcel with the data for the extension. The 6481789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * caller must use {@link #newRequest()} to get one. 6491789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * 6501789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @param reply Output parcel with the data returned by the 6511789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * native player. 6521789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * {@hide} 6530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 6540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 6551789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public void invoke(Parcel request, Parcel reply) { 6561789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia int retcode = native_invoke(request, reply); 6571789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia reply.setDataPosition(0); 6581789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia if (retcode != 0) { 6591789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia throw new RuntimeException("failure code: " + retcode); 6600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 6610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 6620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 6631789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia @Override 6641789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public void notifyWhenCommandLabelReached(Object label) { 66569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang addTask(new Task(CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED, false) { 66669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang @Override 66769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang void process() { 66869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang synchronized (mEventCbLock) { 66969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) { 67069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang cb.first.execute(() -> cb.second.onCommandLabelReached( 67169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang MediaPlayer2Impl.this, label)); 67269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 67369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 67469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 67569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang }); 6761789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia } 6771789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia 6780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 6791789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Sets the {@link SurfaceHolder} to use for displaying the video 6801789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * portion of the media. 6810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 6821789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Either a surface holder or surface must be set if a display or video sink 6831789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * is needed. Not calling this method or {@link #setSurface(Surface)} 6841789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * when playing back a video will result in only the audio track being played. 6851789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * A null surface holder or surface will result in only the audio track being 6861789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * played. 6870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 6881789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @param sh the SurfaceHolder to use for video display 6891789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @throws IllegalStateException if the internal player engine has not been 6901789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * initialized or has been released. 6911789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @hide 6920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 6930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 6941789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public void setDisplay(SurfaceHolder sh) { 6951789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia mSurfaceHolder = sh; 6961789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia Surface surface; 6971789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia if (sh != null) { 6981789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia surface = sh.getSurface(); 6991789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia } else { 7001789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia surface = null; 701de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia } 7021789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia _setVideoSurface(surface); 7031789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia updateSurfaceScreenOn(); 7040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 7050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 7060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 7071789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Sets the {@link Surface} to be used as the sink for the video portion of 7081789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * the media. This is similar to {@link #setDisplay(SurfaceHolder)}, but 7091789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * does not support {@link #setScreenOnWhilePlaying(boolean)}. Setting a 7101789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Surface will un-set any Surface or SurfaceHolder that was previously set. 7111789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * A null surface will result in only the audio track being played. 7120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 7131789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * If the Surface sends frames to a {@link SurfaceTexture}, the timestamps 7141789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * returned from {@link SurfaceTexture#getTimestamp()} will have an 7151789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * unspecified zero point. These timestamps cannot be directly compared 7161789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * between different media sources, different instances of the same media 7171789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * source, or multiple runs of the same program. The timestamp is normally 7181789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * monotonically increasing and is unaffected by time-of-day adjustments, 7191789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * but it is reset when the position is set. 7200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 7211789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @param surface The {@link Surface} to be used for the video portion of 7221789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * the media. 7231789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @throws IllegalStateException if the internal player engine has not been 7241789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * initialized or has been released. 7250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 7260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 7271789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public void setSurface(Surface surface) { 72869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang addTask(new Task(CALL_COMPLETED_SET_SURFACE, false) { 72969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang @Override 73069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang void process() { 73169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang if (mScreenOnWhilePlaying && surface != null) { 73269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective for Surface"); 73369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 73469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang mSurfaceHolder = null; 73569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang _setVideoSurface(surface); 73669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang updateSurfaceScreenOn(); 73769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 73869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang }); 7390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 7400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 7410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 7421789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Sets video scaling mode. To make the target video scaling mode 7431789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * effective during playback, this method must be called after 7441789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * data source is set. If not called, the default video 7451789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * scaling mode is {@link #VIDEO_SCALING_MODE_SCALE_TO_FIT}. 7460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 7471789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * <p> The supported video scaling modes are: 7481789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * <ul> 7491789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * <li> {@link #VIDEO_SCALING_MODE_SCALE_TO_FIT} 7501789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * <li> {@link #VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING} 7511789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * </ul> 7520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 7531789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @param mode target video scaling mode. Must be one of the supported 7541789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * video scaling modes; otherwise, IllegalArgumentException will be thrown. 7550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 7561789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @see MediaPlayer2#VIDEO_SCALING_MODE_SCALE_TO_FIT 7571789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @see MediaPlayer2#VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING 7581789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @hide 7590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 7600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 7611789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public void setVideoScalingMode(int mode) { 76269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang addTask(new Task(CALL_COMPLETED_SET_VIDEO_SCALING_MODE, false) { 76369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang @Override 76469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang void process() { 76569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang if (!isVideoScalingModeSupported(mode)) { 76669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang final String msg = "Scaling mode " + mode + " is not supported"; 76769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang throw new IllegalArgumentException(msg); 76869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 76969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang Parcel request = Parcel.obtain(); 77069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang Parcel reply = Parcel.obtain(); 77169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang try { 77269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang request.writeInt(INVOKE_ID_SET_VIDEO_SCALE_MODE); 77369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang request.writeInt(mode); 77469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang invoke(request, reply); 77569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } finally { 77669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang request.recycle(); 77769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang reply.recycle(); 77869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 77969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 78069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang }); 781de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia } 7820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 7831789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia /** 7841789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Discards all pending commands. 7851789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia */ 7861789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia @Override 7871789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public void clearPendingCommands() { 7880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 7890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 79069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang private void addTask(Task task) { 79169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang synchronized (mTaskLock) { 79269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang mPendingTasks.add(task); 79369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang processPendingTask_l(); 79469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 79569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 79669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang 797adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang @GuardedBy("mTaskLock") 798adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang private void processPendingTask_l() { 799adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang if (mCurrentTask != null) { 800adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang return; 801adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang } 802adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang if (!mPendingTasks.isEmpty()) { 803adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang Task task = mPendingTasks.remove(0); 804adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang mCurrentTask = task; 805adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang mTaskHandler.post(task); 806adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang } 807adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang } 808adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang 809cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia private void handleDataSource(boolean isCurrent, @NonNull DataSourceDesc dsd, long srcId) 810de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia throws IOException { 8110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Preconditions.checkNotNull(dsd, "the DataSourceDesc cannot be null"); 8120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 8130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia switch (dsd.getType()) { 8140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case DataSourceDesc.TYPE_CALLBACK: 815de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia handleDataSource(isCurrent, 816cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia srcId, 817de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia dsd.getMedia2DataSource()); 8180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 8190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 8200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case DataSourceDesc.TYPE_FD: 821de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia handleDataSource(isCurrent, 822cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia srcId, 823de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia dsd.getFileDescriptor(), 824de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia dsd.getFileDescriptorOffset(), 825de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia dsd.getFileDescriptorLength()); 8260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 8270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 8280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case DataSourceDesc.TYPE_URI: 829de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia handleDataSource(isCurrent, 830cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia srcId, 831de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia dsd.getUriContext(), 832de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia dsd.getUri(), 833de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia dsd.getUriHeaders(), 834de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia dsd.getUriCookies()); 8350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 8360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 8370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia default: 8380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 8390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 8400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 8410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 8420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 8430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * To provide cookies for the subsequent HTTP requests, you can install your own default cookie 8440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * handler and use other variants of setDataSource APIs instead. Alternatively, you can use 8450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * this API to pass the cookies as a list of HttpCookie. If the app has not installed 8460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * a CookieHandler already, this API creates a CookieManager and populates its CookieStore with 8470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * the provided cookies. If the app has installed its own handler already, this API requires the 8480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * handler to be of CookieManager type such that the API can update the manager’s CookieStore. 8490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 8500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * <p><strong>Note</strong> that the cross domain redirection is allowed by default, 8510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * but that can be changed with key/value pairs through the headers parameter with 8520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * "android-allow-cross-domain-redirect" as the key and "0" or "1" as the value to 8530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * disallow or allow cross domain redirection. 8540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 8550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalArgumentException if cookies are provided and the installed handler is not 8560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * a CookieManager 8570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalStateException if it is called in an invalid state 8580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws NullPointerException if context or uri is null 8590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IOException if uri has a file scheme and an I/O error occurs 8600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 861de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia private void handleDataSource( 862de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia boolean isCurrent, long srcId, 863de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia @NonNull Context context, @NonNull Uri uri, 8640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Nullable Map<String, String> headers, @Nullable List<HttpCookie> cookies) 8650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throws IOException { 8660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // The context and URI usually belong to the calling user. Get a resolver for that user 8670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // and strip out the userId from the URI if present. 8680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final ContentResolver resolver = context.getContentResolver(); 8690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final String scheme = uri.getScheme(); 8700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final String authority = ContentProvider.getAuthorityWithoutUserId(uri.getAuthority()); 8710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (ContentResolver.SCHEME_FILE.equals(scheme)) { 872de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia handleDataSource(isCurrent, srcId, uri.getPath(), null, null); 8730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 874de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia } 875de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia 876de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia if (ContentResolver.SCHEME_CONTENT.equals(scheme) 8770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia && Settings.AUTHORITY.equals(authority)) { 8780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // Try cached ringtone first since the actual provider may not be 8790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // encryption aware, or it may be stored on CE media storage 8800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final int type = RingtoneManager.getDefaultType(uri); 8810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final Uri cacheUri = RingtoneManager.getCacheForType(type, context.getUserId()); 8820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final Uri actualUri = RingtoneManager.getActualDefaultRingtoneUri(context, type); 883de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia if (attemptDataSource(isCurrent, srcId, resolver, cacheUri)) { 8840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 885de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia } 886de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia if (attemptDataSource(isCurrent, srcId, resolver, actualUri)) { 8870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 8880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 889de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia handleDataSource(isCurrent, srcId, uri.toString(), headers, cookies); 8900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } else { 8910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // Try requested Uri locally first, or fallback to media server 892de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia if (attemptDataSource(isCurrent, srcId, resolver, uri)) { 8930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 8940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 895de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia handleDataSource(isCurrent, srcId, uri.toString(), headers, cookies); 8960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 8970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 8980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 899de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia private boolean attemptDataSource( 900de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia boolean isCurrent, long srcId, ContentResolver resolver, Uri uri) { 9010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try (AssetFileDescriptor afd = resolver.openAssetFileDescriptor(uri, "r")) { 9020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (afd.getDeclaredLength() < 0) { 903de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia handleDataSource(isCurrent, 904de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia srcId, 905de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia afd.getFileDescriptor(), 906de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia 0, 907de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia DataSourceDesc.LONG_MAX); 9080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } else { 909de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia handleDataSource(isCurrent, 910de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia srcId, 911de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia afd.getFileDescriptor(), 912de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia afd.getStartOffset(), 913de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia afd.getDeclaredLength()); 9140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 9150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return true; 9160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (NullPointerException | SecurityException | IOException ex) { 9170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.w(TAG, "Couldn't open " + uri + ": " + ex); 9180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return false; 9190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 9200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 9210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 922de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia private void handleDataSource( 923de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia boolean isCurrent, long srcId, 924de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia String path, Map<String, String> headers, List<HttpCookie> cookies) 925de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia throws IOException { 9260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia String[] keys = null; 9270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia String[] values = null; 9280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 9290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (headers != null) { 9300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia keys = new String[headers.size()]; 9310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia values = new String[headers.size()]; 9320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 9330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia int i = 0; 9340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia for (Map.Entry<String, String> entry: headers.entrySet()) { 9350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia keys[i] = entry.getKey(); 9360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia values[i] = entry.getValue(); 9370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia ++i; 9380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 9390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 940de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia handleDataSource(isCurrent, srcId, path, keys, values, cookies); 9410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 9420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 943de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia private void handleDataSource(boolean isCurrent, long srcId, 944de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia String path, String[] keys, String[] values, List<HttpCookie> cookies) 945de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia throws IOException { 9460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final Uri uri = Uri.parse(path); 9470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final String scheme = uri.getScheme(); 9480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if ("file".equals(scheme)) { 9490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia path = uri.getPath(); 9500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } else if (scheme != null) { 9510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // handle non-file sources 952de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia nativeHandleDataSourceUrl( 953de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia isCurrent, 95434c5bb126b8cc85176645acea841c796a3cc0292Wei Jia srcId, 9550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Media2HTTPService.createHTTPService(path, cookies), 9560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia path, 9570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia keys, 9580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia values); 9590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 9600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 9610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 9620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final File file = new File(path); 9630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (file.exists()) { 9640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia FileInputStream is = new FileInputStream(file); 9650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia FileDescriptor fd = is.getFD(); 966de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia handleDataSource(isCurrent, srcId, fd, 0, DataSourceDesc.LONG_MAX); 9670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia is.close(); 9680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } else { 969de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia throw new IOException("handleDataSource failed."); 9700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 9710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 9720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 973de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia private native void nativeHandleDataSourceUrl( 974de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia boolean isCurrent, long srcId, 975de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia Media2HTTPService httpService, String path, String[] keys, String[] values) 976de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia throws IOException; 9770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 9780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 9790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Sets the data source (FileDescriptor) to use. The FileDescriptor must be 9800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * seekable (N.B. a LocalSocket is not seekable). It is the caller's responsibility 9810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * to close the file descriptor. It is safe to do so as soon as this call returns. 9820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 9830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalStateException if it is called in an invalid state 9840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalArgumentException if fd is not a valid FileDescriptor 9850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IOException if fd can not be read 9860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 987de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia private void handleDataSource( 988de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia boolean isCurrent, long srcId, 989de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia FileDescriptor fd, long offset, long length) throws IOException { 990de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia nativeHandleDataSourceFD(isCurrent, srcId, fd, offset, length); 9910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 9920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 993de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia private native void nativeHandleDataSourceFD(boolean isCurrent, long srcId, 994de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia FileDescriptor fd, long offset, long length) throws IOException; 9950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 9960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 9970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalStateException if it is called in an invalid state 9980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalArgumentException if dataSource is not a valid Media2DataSource 9990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 1000de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia private void handleDataSource(boolean isCurrent, long srcId, Media2DataSource dataSource) { 1001de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia nativeHandleDataSourceCallback(isCurrent, srcId, dataSource); 10020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 10030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 1004de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia private native void nativeHandleDataSourceCallback( 1005de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia boolean isCurrent, long srcId, Media2DataSource dataSource); 10060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 1007cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia // This function shall be called with |mSrcLock| acquired. 1008de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia private void prepareNextDataSource_l() { 1009cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia if (mNextDSDs == null || mNextDSDs.isEmpty() 1010cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia || mNextSourceState != NEXT_SOURCE_STATE_INIT) { 1011de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia // There is no next source or it's in preparing or prepared state. 1012de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia return; 1013de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia } 10140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 1015de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia try { 1016cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia mNextSourceState = NEXT_SOURCE_STATE_PREPARING; 1017cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia handleDataSource(false /* isCurrent */, mNextDSDs.get(0), mNextSrcId); 1018de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia } catch (Exception e) { 1019de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia Message msg2 = mEventHandler.obtainMessage( 1020de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, null); 10211789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia final long nextSrcId = mNextSrcId; 1022de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia mEventHandler.post(new Runnable() { 1023de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia @Override 1024de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia public void run() { 1025de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia mEventHandler.handleMessage(msg2, nextSrcId); 1026de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia } 1027de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia }); 1028de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia } 1029de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia } 1030de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia 1031cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia // This function shall be called with |mSrcLock| acquired. 1032de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia private void playNextDataSource_l() { 1033cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia if (mNextDSDs == null || mNextDSDs.isEmpty()) { 1034de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia return; 1035de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia } 1036de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia 1037cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia if (mNextSourceState == NEXT_SOURCE_STATE_PREPARED) { 1038de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia // Switch to next source only when it's in prepared state. 1039cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia mCurrentDSD = mNextDSDs.get(0); 10401789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia mCurrentSrcId = mNextSrcId; 1041c3725a94bb9840027a42669a659a0fd11d6f69c6Wei Jia mBufferedPercentageCurrent.set(mBufferedPercentageNext.get()); 1042cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia mNextDSDs.remove(0); 1043cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia mNextSrcId = mSrcIdGenerator++; // make it different from mCurrentSrcId 1044c3725a94bb9840027a42669a659a0fd11d6f69c6Wei Jia mBufferedPercentageNext.set(0); 1045cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia mNextSourceState = NEXT_SOURCE_STATE_INIT; 1046cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia mNextSourcePlayPending = false; 1047de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia 10481789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia long srcId = mCurrentSrcId; 1049de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia try { 1050de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia nativePlayNextDataSource(srcId); 1051de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia } catch (Exception e) { 1052de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia Message msg2 = mEventHandler.obtainMessage( 1053de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, null); 1054de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia mEventHandler.post(new Runnable() { 1055de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia @Override 1056de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia public void run() { 1057de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia mEventHandler.handleMessage(msg2, srcId); 1058de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia } 1059de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia }); 1060de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia } 1061de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia 1062de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia // Wait for MEDIA2_INFO_STARTED_AS_NEXT to prepare next source. 1063de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia } else { 1064cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia if (mNextSourceState == NEXT_SOURCE_STATE_INIT) { 1065de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia prepareNextDataSource_l(); 1066de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia } 1067cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia mNextSourcePlayPending = true; 10680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 10690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 10700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 1071de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia private native void nativePlayNextDataSource(long srcId); 10720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 10730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 10740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private int getAudioStreamType() { 10750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) { 10760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mStreamType = _getAudioStreamType(); 10770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 10780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return mStreamType; 10790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 10800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 10810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private native int _getAudioStreamType() throws IllegalStateException; 10820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 10830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 10840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Stops playback after playback has been started or paused. 10850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 10860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalStateException if the internal player engine has not been 10870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * initialized. 10880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * #hide 10890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 10900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 10910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void stop() { 10920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia stayAwake(false); 10930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia _stop(); 10940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 10950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 10960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private native void _stop() throws IllegalStateException; 10970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 10980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia //-------------------------------------------------------------------------- 10990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // Explicit Routing 11000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia //-------------------- 11010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private AudioDeviceInfo mPreferredDevice = null; 11020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 11030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 11040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Specifies an audio device (via an {@link AudioDeviceInfo} object) to route 11050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * the output from this MediaPlayer2. 11060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param deviceInfo The {@link AudioDeviceInfo} specifying the audio sink or source. 11070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * If deviceInfo is null, default routing is restored. 11080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @return true if succesful, false if the specified {@link AudioDeviceInfo} is non-null and 11090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * does not correspond to a valid audio device. 11100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 11110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 11120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public boolean setPreferredDevice(AudioDeviceInfo deviceInfo) { 11130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (deviceInfo != null && !deviceInfo.isSink()) { 11140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return false; 11150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 11160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia int preferredDeviceId = deviceInfo != null ? deviceInfo.getId() : 0; 11170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia boolean status = native_setOutputDevice(preferredDeviceId); 11180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (status == true) { 11190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (this) { 11200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mPreferredDevice = deviceInfo; 11210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 11220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 11230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return status; 11240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 11250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 11260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 11270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Returns the selected output specified by {@link #setPreferredDevice}. Note that this 11280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * is not guaranteed to correspond to the actual device being used for playback. 11290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 11300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 11310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public AudioDeviceInfo getPreferredDevice() { 11320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (this) { 11330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return mPreferredDevice; 11340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 11350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 11360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 11370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 11380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Returns an {@link AudioDeviceInfo} identifying the current routing of this MediaPlayer2 11390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Note: The query is only valid if the MediaPlayer2 is currently playing. 11400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * If the player is not playing, the returned device can be null or correspond to previously 11410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * selected device when the player was last active. 11420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 11430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 11440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public AudioDeviceInfo getRoutedDevice() { 11450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia int deviceId = native_getRoutedDeviceId(); 11460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (deviceId == 0) { 11470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return null; 11480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 11490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia AudioDeviceInfo[] devices = 11500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia AudioManager.getDevicesStatic(AudioManager.GET_DEVICES_OUTPUTS); 11510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia for (int i = 0; i < devices.length; i++) { 11520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (devices[i].getId() == deviceId) { 11530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return devices[i]; 11540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 11550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 11560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return null; 11570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 11580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 11590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /* 11600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Call BEFORE adding a routing callback handler or AFTER removing a routing callback handler. 11610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 116257d03914a1d5680cfe0727c15a3a82e4dfeb0adeAndreas Gampe @GuardedBy("mRoutingChangeListeners") 11630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private void enableNativeRoutingCallbacksLocked(boolean enabled) { 11640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mRoutingChangeListeners.size() == 0) { 11650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia native_enableDeviceCallback(enabled); 11660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 11670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 11680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 11690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 11700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * The list of AudioRouting.OnRoutingChangedListener interfaces added (with 11710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * {@link #addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, Handler)} 11720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * by an app to receive (re)routing notifications. 11730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 11740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @GuardedBy("mRoutingChangeListeners") 11750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private ArrayMap<AudioRouting.OnRoutingChangedListener, 11760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia NativeRoutingEventHandlerDelegate> mRoutingChangeListeners = new ArrayMap<>(); 11770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 11780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 11790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Adds an {@link AudioRouting.OnRoutingChangedListener} to receive notifications of routing 11800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * changes on this MediaPlayer2. 11810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param listener The {@link AudioRouting.OnRoutingChangedListener} interface to receive 11820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * notifications of rerouting events. 11830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param handler Specifies the {@link Handler} object for the thread on which to execute 11840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * the callback. If <code>null</code>, the handler on the main looper will be used. 11850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 11860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 11870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void addOnRoutingChangedListener(AudioRouting.OnRoutingChangedListener listener, 11880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Handler handler) { 11890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mRoutingChangeListeners) { 11900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (listener != null && !mRoutingChangeListeners.containsKey(listener)) { 11910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia enableNativeRoutingCallbacksLocked(true); 11920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mRoutingChangeListeners.put( 11930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia listener, new NativeRoutingEventHandlerDelegate(this, listener, 11940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia handler != null ? handler : mEventHandler)); 11950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 11960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 11970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 11980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 11990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 12000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Removes an {@link AudioRouting.OnRoutingChangedListener} which has been previously added 12010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * to receive rerouting notifications. 12020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param listener The previously added {@link AudioRouting.OnRoutingChangedListener} interface 12030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * to remove. 12040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 12050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 12060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void removeOnRoutingChangedListener(AudioRouting.OnRoutingChangedListener listener) { 12070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mRoutingChangeListeners) { 12080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mRoutingChangeListeners.containsKey(listener)) { 12090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mRoutingChangeListeners.remove(listener); 12100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia enableNativeRoutingCallbacksLocked(false); 12110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 12120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 12130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 12140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 12150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private native final boolean native_setOutputDevice(int deviceId); 12160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private native final int native_getRoutedDeviceId(); 12170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private native final void native_enableDeviceCallback(boolean enabled); 12180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 12190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 12200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Set the low-level power management behavior for this MediaPlayer2. This 12210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * can be used when the MediaPlayer2 is not playing through a SurfaceHolder 12220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * set with {@link #setDisplay(SurfaceHolder)} and thus can use the 12230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * high-level {@link #setScreenOnWhilePlaying(boolean)} feature. 12240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 12250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * <p>This function has the MediaPlayer2 access the low-level power manager 12260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * service to control the device's power usage while playing is occurring. 12270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * The parameter is a combination of {@link android.os.PowerManager} wake flags. 12280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Use of this method requires {@link android.Manifest.permission#WAKE_LOCK} 12290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * permission. 12300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * By default, no attempt is made to keep the device awake during playback. 12310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 12320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param context the Context to use 12330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param mode the power/wake mode to set 12340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @see android.os.PowerManager 12350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @hide 12360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 12370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 12380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void setWakeMode(Context context, int mode) { 12390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia boolean washeld = false; 12400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 12410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /* Disable persistant wakelocks in media player based on property */ 12420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (SystemProperties.getBoolean("audio.offload.ignore_setawake", false) == true) { 12430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.w(TAG, "IGNORING setWakeMode " + mode); 12440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 12450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 12460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 12470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mWakeLock != null) { 12480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mWakeLock.isHeld()) { 12490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia washeld = true; 12500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mWakeLock.release(); 12510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 12520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mWakeLock = null; 12530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 12540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 12550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 12560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mWakeLock = pm.newWakeLock(mode|PowerManager.ON_AFTER_RELEASE, MediaPlayer2Impl.class.getName()); 12570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mWakeLock.setReferenceCounted(false); 12580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (washeld) { 12590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mWakeLock.acquire(); 12600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 12610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 12620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 12630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 12640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Control whether we should use the attached SurfaceHolder to keep the 12650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * screen on while video playback is occurring. This is the preferred 12660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * method over {@link #setWakeMode} where possible, since it doesn't 12670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * require that the application have permission for low-level wake lock 12680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * access. 12690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 12700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param screenOn Supply true to keep the screen on, false to allow it 12710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * to turn off. 12720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @hide 12730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 12740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 12750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void setScreenOnWhilePlaying(boolean screenOn) { 12760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mScreenOnWhilePlaying != screenOn) { 12770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (screenOn && mSurfaceHolder == null) { 12780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective without a SurfaceHolder"); 12790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 12800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mScreenOnWhilePlaying = screenOn; 12810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia updateSurfaceScreenOn(); 12820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 12830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 12840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 12850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private void stayAwake(boolean awake) { 12860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mWakeLock != null) { 12870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (awake && !mWakeLock.isHeld()) { 12880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mWakeLock.acquire(); 12890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } else if (!awake && mWakeLock.isHeld()) { 12900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mWakeLock.release(); 12910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 12920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 12930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mStayAwake = awake; 12940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia updateSurfaceScreenOn(); 12950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 12960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 12970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private void updateSurfaceScreenOn() { 12980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mSurfaceHolder != null) { 12990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mSurfaceHolder.setKeepScreenOn(mScreenOnWhilePlaying && mStayAwake); 13000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 13010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 13020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 13030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 13040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Returns the width of the video. 13050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 13060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @return the width of the video, or 0 if there is no video, 13070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * no display surface was set, or the width has not been determined 13081789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * yet. The {@code MediaPlayer2EventCallback} can be registered via 13091789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * {@link #setMediaPlayer2EventCallback(Executor, MediaPlayer2EventCallback)} to provide a 13101789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * notification {@code MediaPlayer2EventCallback.onVideoSizeChanged} when the width 13111789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * is available. 13120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 13130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 13140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public native int getVideoWidth(); 13150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 13160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 13170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Returns the height of the video. 13180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 13190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @return the height of the video, or 0 if there is no video, 13200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * no display surface was set, or the height has not been determined 13211789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * yet. The {@code MediaPlayer2EventCallback} can be registered via 13221789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * {@link #setMediaPlayer2EventCallback(Executor, MediaPlayer2EventCallback)} to provide a 13231789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * notification {@code MediaPlayer2EventCallback.onVideoSizeChanged} when the height 13241789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * is available. 13250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 13260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 13270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public native int getVideoHeight(); 13280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 13290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 13300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Return Metrics data about the current player. 13310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 13320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @return a {@link PersistableBundle} containing the set of attributes and values 13330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * available for the media being handled by this instance of MediaPlayer2 13340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * The attributes are descibed in {@link MetricsConstants}. 13350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 13360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Additional vendor-specific fields may also be present in 13370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * the return value. 13380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 13390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 13400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public PersistableBundle getMetrics() { 13410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia PersistableBundle bundle = native_getMetrics(); 13420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return bundle; 13430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 13440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 13450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private native PersistableBundle native_getMetrics(); 13460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 13470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 13480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Checks whether the MediaPlayer2 is playing. 13490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 13500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @return true if currently playing, false otherwise 13510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalStateException if the internal player engine has not been 13520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * initialized or has been released. 13531789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @hide 13540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 13550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 13560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public native boolean isPlaying(); 13570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 13581789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia @Override 13591789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public @MediaPlayer2State int getMediaPlayer2State() { 1360cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia return native_getMediaPlayer2State(); 13611789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia } 13621789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia 1363cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia private native int native_getMediaPlayer2State(); 1364cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia 13651789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia /** 13660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Gets the current buffering management params used by the source component. 13670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Calling it only after {@code setDataSource} has been called. 13680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Each type of data source might have different set of default params. 13690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 13700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @return the current buffering management params used by the source component. 13710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalStateException if the internal player engine has not been 13720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * initialized, or {@code setDataSource} has not been called. 13730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @hide 13740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 13750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 13760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @NonNull 13770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public native BufferingParams getBufferingParams(); 13780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 13790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 13800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Sets buffering management params. 13810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * The object sets its internal BufferingParams to the input, except that the input is 13820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * invalid or not supported. 13830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Call it only after {@code setDataSource} has been called. 13840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * The input is a hint to MediaPlayer2. 13850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 13860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param params the buffering management params. 13870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 13880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalStateException if the internal player engine has not been 13890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * initialized or has been released, or {@code setDataSource} has not been called. 13900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalArgumentException if params is invalid or not supported. 13910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @hide 13920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 13930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 139469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang public void setBufferingParams(@NonNull BufferingParams params) { 139569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang addTask(new Task(CALL_COMPLETED_SET_BUFFERING_PARAMS, false) { 139669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang @Override 139769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang void process() { 139869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang Preconditions.checkNotNull(params, "the BufferingParams cannot be null"); 139969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang _setBufferingParams(params); 140069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 140169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang }); 140269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 140369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang 140469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang private native void _setBufferingParams(@NonNull BufferingParams params); 14050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 14060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 14070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Sets playback rate and audio mode. 14080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 14090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param rate the ratio between desired playback rate and normal one. 14100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param audioMode audio playback mode. Must be one of the supported 14110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * audio modes. 14120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 14130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalStateException if the internal player engine has not been 14140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * initialized. 14150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalArgumentException if audioMode is not supported. 14160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 14170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @hide 14180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 14190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 14200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @NonNull 14210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public PlaybackParams easyPlaybackParams(float rate, @PlaybackRateAudioMode int audioMode) { 14220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia PlaybackParams params = new PlaybackParams(); 14230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia params.allowDefaults(); 14240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia switch (audioMode) { 14250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case PLAYBACK_RATE_AUDIO_MODE_DEFAULT: 14260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia params.setSpeed(rate).setPitch(1.0f); 14270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 14280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case PLAYBACK_RATE_AUDIO_MODE_STRETCH: 14290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia params.setSpeed(rate).setPitch(1.0f) 14300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia .setAudioFallbackMode(params.AUDIO_FALLBACK_MODE_FAIL); 14310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 14320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case PLAYBACK_RATE_AUDIO_MODE_RESAMPLE: 14330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia params.setSpeed(rate).setPitch(rate); 14340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 14350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia default: 14360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final String msg = "Audio playback mode " + audioMode + " is not supported"; 14370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throw new IllegalArgumentException(msg); 14380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 14390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return params; 14400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 14410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 14420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 14430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Sets playback rate using {@link PlaybackParams}. The object sets its internal 14440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * PlaybackParams to the input, except that the object remembers previous speed 14450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * when input speed is zero. This allows the object to resume at previous speed 14460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * when play() is called. Calling it before the object is prepared does not change 14470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * the object state. After the object is prepared, calling it with zero speed is 14480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * equivalent to calling pause(). After the object is prepared, calling it with 14490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * non-zero speed is equivalent to calling play(). 14500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 14510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param params the playback params. 14520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 14530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalStateException if the internal player engine has not been 14540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * initialized or has been released. 14550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalArgumentException if params is not supported. 14560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 14570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 145869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang public void setPlaybackParams(@NonNull PlaybackParams params) { 145969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang addTask(new Task(CALL_COMPLETED_SET_PLAYBACK_PARAMS, false) { 146069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang @Override 146169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang void process() { 146269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang Preconditions.checkNotNull(params, "the PlaybackParams cannot be null"); 146369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang _setPlaybackParams(params); 146469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 146569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang }); 146669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 146769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang 146869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang private native void _setPlaybackParams(@NonNull PlaybackParams params); 14690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 14700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 14710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Gets the playback params, containing the current playback rate. 14720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 14730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @return the playback params. 14740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalStateException if the internal player engine has not been 14750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * initialized. 14760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 14770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 14780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @NonNull 14790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public native PlaybackParams getPlaybackParams(); 14800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 14810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 14820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Sets A/V sync mode. 14830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 14840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param params the A/V sync params to apply 14850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 14860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalStateException if the internal player engine has not been 14870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * initialized. 14880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalArgumentException if params are not supported. 14890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 14900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 149169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang public void setSyncParams(@NonNull SyncParams params) { 149269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang addTask(new Task(CALL_COMPLETED_SET_SYNC_PARAMS, false) { 149369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang @Override 149469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang void process() { 149569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang Preconditions.checkNotNull(params, "the SyncParams cannot be null"); 149669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang _setSyncParams(params); 149769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 149869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang }); 149969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 150069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang 150169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang private native void _setSyncParams(@NonNull SyncParams params); 15020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 15030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 15040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Gets the A/V sync mode. 15050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 15060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @return the A/V sync params 15070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 15080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalStateException if the internal player engine has not been 15090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * initialized. 15100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 15110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 15120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @NonNull 15130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public native SyncParams getSyncParams(); 15140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 15150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 15160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Moves the media to specified time position by considering the given mode. 15170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * <p> 15180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * When seekTo is finished, the user will be notified via OnSeekComplete supplied by the user. 15190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * There is at most one active seekTo processed at any time. If there is a to-be-completed 15200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * seekTo, new seekTo requests will be queued in such a way that only the last request 15210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * is kept. When current seekTo is completed, the queued request will be processed if 15220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * that request is different from just-finished seekTo operation, i.e., the requested 15230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * position or mode is different. 15240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 15250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param msec the offset in milliseconds from the start to seek to. 15260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * When seeking to the given time position, there is no guarantee that the data source 15270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * has a frame located at the position. When this happens, a frame nearby will be rendered. 15280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * If msec is negative, time position zero will be used. 15290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * If msec is larger than duration, duration will be used. 15300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param mode the mode indicating where exactly to seek to. 15310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Use {@link #SEEK_PREVIOUS_SYNC} if one wants to seek to a sync frame 15320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * that has a timestamp earlier than or the same as msec. Use 15330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * {@link #SEEK_NEXT_SYNC} if one wants to seek to a sync frame 15340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * that has a timestamp later than or the same as msec. Use 15350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * {@link #SEEK_CLOSEST_SYNC} if one wants to seek to a sync frame 15360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * that has a timestamp closest to or the same as msec. Use 15370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * {@link #SEEK_CLOSEST} if one wants to seek to a frame that may 15380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * or may not be a sync frame but is closest to or the same as msec. 15390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * {@link #SEEK_CLOSEST} often has larger performance overhead compared 15400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * to the other options if there is no sync frame located at msec. 15410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalStateException if the internal player engine has not been 15420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * initialized 15430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalArgumentException if the mode is invalid. 15440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 15450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 154669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang public void seekTo(final long msec, @SeekMode int mode) { 154769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang addTask(new Task(CALL_COMPLETED_SEEK_TO, true) { 154869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang @Override 154969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang void process() { 155069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang if (mode < SEEK_PREVIOUS_SYNC || mode > SEEK_CLOSEST) { 155169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang final String msg = "Illegal seek mode: " + mode; 155269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang throw new IllegalArgumentException(msg); 155369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 155469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang // TODO: pass long to native, instead of truncating here. 155569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang long posMs = msec; 155669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang if (posMs > Integer.MAX_VALUE) { 155769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang Log.w(TAG, "seekTo offset " + posMs + " is too large, cap to " 155869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang + Integer.MAX_VALUE); 155969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang posMs = Integer.MAX_VALUE; 156069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } else if (posMs < Integer.MIN_VALUE) { 156169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang Log.w(TAG, "seekTo offset " + posMs + " is too small, cap to " 156269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang + Integer.MIN_VALUE); 156369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang posMs = Integer.MIN_VALUE; 156469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 156569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang _seekTo(posMs, mode); 156669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 156769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang }); 15680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 15690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 15701789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia private native final void _seekTo(long msec, int mode); 15711789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia 15720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 15730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Get current playback position as a {@link MediaTimestamp}. 15740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * <p> 15750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * The MediaTimestamp represents how the media time correlates to the system time in 15760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * a linear fashion using an anchor and a clock rate. During regular playback, the media 15770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * time moves fairly constantly (though the anchor frame may be rebased to a current 15780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * system time, the linear correlation stays steady). Therefore, this method does not 15790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * need to be called often. 15800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * <p> 15810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * To help users get current playback position, this method always anchors the timestamp 15820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * to the current {@link System#nanoTime system time}, so 15830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * {@link MediaTimestamp#getAnchorMediaTimeUs} can be used as current playback position. 15840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 15850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @return a MediaTimestamp object if a timestamp is available, or {@code null} if no timestamp 15860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * is available, e.g. because the media player has not been initialized. 15870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 15880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @see MediaTimestamp 15890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 15900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 15910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Nullable 15920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public MediaTimestamp getTimestamp() 15930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia { 15940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 15950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // TODO: get the timestamp from native side 15960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return new MediaTimestamp( 15970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia getCurrentPosition() * 1000L, 15980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia System.nanoTime(), 15990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia isPlaying() ? getPlaybackParams().getSpeed() : 0.f); 16000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (IllegalStateException e) { 16010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return null; 16020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 16030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 16040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 16050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 16060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Gets the media metadata. 16070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 16080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param update_only controls whether the full set of available 16090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * metadata is returned or just the set that changed since the 16100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * last call. See {@see #METADATA_UPDATE_ONLY} and {@see 16110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * #METADATA_ALL}. 16120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 16130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param apply_filter if true only metadata that matches the 16140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * filter is returned. See {@see #APPLY_METADATA_FILTER} and {@see 16150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * #BYPASS_METADATA_FILTER}. 16160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 16170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @return The metadata, possibly empty. null if an error occured. 16180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // FIXME: unhide. 16190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * {@hide} 16200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 16210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 16220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public Metadata getMetadata(final boolean update_only, 16230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final boolean apply_filter) { 16240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Parcel reply = Parcel.obtain(); 16250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Metadata data = new Metadata(); 16260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 16270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (!native_getMetadata(update_only, apply_filter, reply)) { 16280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia reply.recycle(); 16290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return null; 16300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 16310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 16320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // Metadata takes over the parcel, don't recycle it unless 16330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // there is an error. 16340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (!data.parse(reply)) { 16350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia reply.recycle(); 16360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return null; 16370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 16380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return data; 16390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 16400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 16410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 16420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Set a filter for the metadata update notification and update 16430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * retrieval. The caller provides 2 set of metadata keys, allowed 16440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * and blocked. The blocked set always takes precedence over the 16450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * allowed one. 16460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Metadata.MATCH_ALL and Metadata.MATCH_NONE are 2 sets available as 16470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * shorthands to allow/block all or no metadata. 16480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 16490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * By default, there is no filter set. 16500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 16510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param allow Is the set of metadata the client is interested 16520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * in receiving new notifications for. 16530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param block Is the set of metadata the client is not interested 16540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * in receiving new notifications for. 16550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @return The call status code. 16560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 16570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // FIXME: unhide. 16580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * {@hide} 16590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 16600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 16610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public int setMetadataFilter(Set<Integer> allow, Set<Integer> block) { 16620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // Do our serialization manually instead of calling 16630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // Parcel.writeArray since the sets are made of the same type 16640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // we avoid paying the price of calling writeValue (used by 16650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // writeArray) which burns an extra int per element to encode 16660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // the type. 16670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Parcel request = newRequest(); 16680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 16690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // The parcel starts already with an interface token. There 16700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // are 2 filters. Each one starts with a 4bytes number to 16710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // store the len followed by a number of int (4 bytes as well) 16720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // representing the metadata type. 16730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia int capacity = request.dataSize() + 4 * (1 + allow.size() + 1 + block.size()); 16740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 16750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (request.dataCapacity() < capacity) { 16760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia request.setDataCapacity(capacity); 16770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 16780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 16790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia request.writeInt(allow.size()); 16800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia for(Integer t: allow) { 16810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia request.writeInt(t); 16820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 16830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia request.writeInt(block.size()); 16840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia for(Integer t: block) { 16850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia request.writeInt(t); 16860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 16870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return native_setMetadataFilter(request); 16880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 16890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 16900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 16910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Resets the MediaPlayer2 to its uninitialized state. After calling 16920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * this method, you will have to initialize it again by setting the 16931789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * data source and calling prepare(). 16940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 16950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 16960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void reset() { 16970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mSelectedSubtitleTrackIndex = -1; 16980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized(mOpenSubtitleSources) { 16990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia for (final InputStream is: mOpenSubtitleSources) { 17000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 17010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia is.close(); 17020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (IOException e) { 17030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 17040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 17050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mOpenSubtitleSources.clear(); 17060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 17070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mSubtitleController != null) { 17080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mSubtitleController.reset(); 17090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 17100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mTimeProvider != null) { 17110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mTimeProvider.close(); 17120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mTimeProvider = null; 17130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 17140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 171563f793f0f3e815c3a4895be7b02941d27d54159cWei Jia synchronized (mEventCbLock) { 171663f793f0f3e815c3a4895be7b02941d27d54159cWei Jia mEventCallbackRecords.clear(); 171763f793f0f3e815c3a4895be7b02941d27d54159cWei Jia } 171863f793f0f3e815c3a4895be7b02941d27d54159cWei Jia synchronized (mDrmEventCbLock) { 171963f793f0f3e815c3a4895be7b02941d27d54159cWei Jia mDrmEventCallbackRecords.clear(); 172063f793f0f3e815c3a4895be7b02941d27d54159cWei Jia } 172163f793f0f3e815c3a4895be7b02941d27d54159cWei Jia 17220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia stayAwake(false); 17230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia _reset(); 17240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // make sure none of the listeners get called anymore 17250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mEventHandler != null) { 17260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mEventHandler.removeCallbacksAndMessages(null); 17270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 17280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 17290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mIndexTrackPairs) { 17300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mIndexTrackPairs.clear(); 17310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mInbandTrackIndices.clear(); 17320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia }; 17330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 17340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia resetDrmState(); 17350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 17360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 17370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private native void _reset(); 17380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 17390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 17400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Set up a timer for {@link #TimeProvider}. {@link #TimeProvider} will be 17410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * notified when the presentation time reaches (becomes greater than or equal to) 17420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * the value specified. 17430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 17440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param mediaTimeUs presentation time to get timed event callback at 17450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @hide 17460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 17470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 17480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void notifyAt(long mediaTimeUs) { 17490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia _notifyAt(mediaTimeUs); 17500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 17510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 17520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private native void _notifyAt(long mediaTimeUs); 17530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 17540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // Keep KEY_PARAMETER_* in sync with include/media/mediaplayer2.h 17550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private final static int KEY_PARAMETER_AUDIO_ATTRIBUTES = 1400; 17560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 17570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Sets the parameter indicated by key. 17580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param key key indicates the parameter to be set. 17590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param value value of the parameter to be set. 17600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @return true if the parameter is set successfully, false otherwise 17610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 17620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private native boolean setParameter(int key, Parcel value); 17630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 1764128875996598b9cfa91bad137d3a73dfcb4a2aedWei Jia private native Parcel getParameter(int key); 1765128875996598b9cfa91bad137d3a73dfcb4a2aedWei Jia 17660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 17670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 17680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Checks whether the MediaPlayer2 is looping or non-looping. 17690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 17700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @return true if the MediaPlayer2 is currently looping, false otherwise 17710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @hide 17720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 17730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 17740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public native boolean isLooping(); 17750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 17760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 17770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Sets the audio session ID. 17780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 17790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param sessionId the audio session ID. 17800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * The audio session ID is a system wide unique identifier for the audio stream played by 17810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * this MediaPlayer2 instance. 17820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * The primary use of the audio session ID is to associate audio effects to a particular 17830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * instance of MediaPlayer2: if an audio session ID is provided when creating an audio effect, 17840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * this effect will be applied only to the audio content of media players within the same 17850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * audio session and not to the output mix. 17860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * When created, a MediaPlayer2 instance automatically generates its own audio session ID. 17870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * However, it is possible to force this player to be part of an already existing audio session 17880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * by calling this method. 17890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * This method must be called before one of the overloaded <code> setDataSource </code> methods. 17900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalStateException if it is called in an invalid state 17910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalArgumentException if the sessionId is invalid. 17920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 17930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 179469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang public void setAudioSessionId(int sessionId) { 179569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang addTask(new Task(CALL_COMPLETED_SET_AUDIO_SESSION_ID, false) { 179669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang @Override 179769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang void process() { 179869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang _setAudioSessionId(sessionId); 179969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 180069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang }); 180169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 180269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang 180369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang private native void _setAudioSessionId(int sessionId); 18040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 18050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 18060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Returns the audio session ID. 18070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 18080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @return the audio session ID. {@see #setAudioSessionId(int)} 18090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Note that the audio session ID is 0 only if a problem occured when the MediaPlayer2 was contructed. 18100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 18110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 18120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public native int getAudioSessionId(); 18130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 18140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 18150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Attaches an auxiliary effect to the player. A typical auxiliary effect is a reverberation 18160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * effect which can be applied on any sound source that directs a certain amount of its 18170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * energy to this effect. This amount is defined by setAuxEffectSendLevel(). 18180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * See {@link #setAuxEffectSendLevel(float)}. 18190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * <p>After creating an auxiliary effect (e.g. 18200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * {@link android.media.audiofx.EnvironmentalReverb}), retrieve its ID with 18210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * {@link android.media.audiofx.AudioEffect#getId()} and use it when calling this method 18220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * to attach the player to the effect. 18230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * <p>To detach the effect from the player, call this method with a null effect id. 18240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * <p>This method must be called after one of the overloaded <code> setDataSource </code> 18250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * methods. 18260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param effectId system wide unique id of the effect to attach 18270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 18280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 182969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang public void attachAuxEffect(int effectId) { 183069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang addTask(new Task(CALL_COMPLETED_ATTACH_AUX_EFFECT, false) { 183169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang @Override 183269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang void process() { 183369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang _attachAuxEffect(effectId); 183469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 183569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang }); 183669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 183769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang 183869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang private native void _attachAuxEffect(int effectId); 18390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 18400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 18410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Sets the send level of the player to the attached auxiliary effect. 18420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * See {@link #attachAuxEffect(int)}. The level value range is 0 to 1.0. 18430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * <p>By default the send level is 0, so even if an effect is attached to the player 18440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * this method must be called for the effect to be applied. 18450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * <p>Note that the passed level value is a raw scalar. UI controls should be scaled 18460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * logarithmically: the gain applied by audio framework ranges from -72dB to 0dB, 18470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * so an appropriate conversion from linear UI input x to level is: 18480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * x == 0 -> level = 0 18490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 0 < x <= R -> level = 10^(72*(x-R)/20/R) 18500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param level send level scalar 18510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 18520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 18530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void setAuxEffectSendLevel(float level) { 185469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang addTask(new Task(CALL_COMPLETED_SET_AUX_EFFECT_SEND_LEVEL, false) { 185569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang @Override 185669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang void process() { 185769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang _setAuxEffectSendLevel(level); 185869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 185969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang }); 18600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 18610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 18620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private native void _setAuxEffectSendLevel(float level); 18630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 18640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /* 18650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param request Parcel destinated to the media player. 18660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param reply[out] Parcel that will contain the reply. 18670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @return The status code. 18680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 18690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private native final int native_invoke(Parcel request, Parcel reply); 18700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 18710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 18720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /* 18730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param update_only If true fetch only the set of metadata that have 18740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * changed since the last invocation of getMetadata. 18750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * The set is built using the unfiltered 18760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * notifications the native player sent to the 18770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * MediaPlayer2Manager during that period of 18780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * time. If false, all the metadatas are considered. 18790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param apply_filter If true, once the metadata set has been built based on 18800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * the value update_only, the current filter is applied. 18810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param reply[out] On return contains the serialized 18820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * metadata. Valid only if the call was successful. 18830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @return The status code. 18840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 18850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private native final boolean native_getMetadata(boolean update_only, 18860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia boolean apply_filter, 18870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Parcel reply); 18880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 18890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /* 18900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param request Parcel with the 2 serialized lists of allowed 18910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * metadata types followed by the one to be 18920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * dropped. Each list starts with an integer 18930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * indicating the number of metadata type elements. 18940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @return The status code. 18950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 18960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private native final int native_setMetadataFilter(Parcel request); 18970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 18980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static native final void native_init(); 18990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private native final void native_setup(Object mediaplayer2_this); 19000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private native final void native_finalize(); 19010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 19028e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon private static native final void native_stream_event_onTearDown( 19038e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon long nativeCallbackPtr, long userDataPtr); 19048e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon private static native final void native_stream_event_onStreamPresentationEnd( 19058e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon long nativeCallbackPtr, long userDataPtr); 19068e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon private static native final void native_stream_event_onStreamDataRequest( 19078e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon long jAudioTrackPtr, long nativeCallbackPtr, long userDataPtr); 19088e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon 19090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 19100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Class for MediaPlayer2 to return each audio/video/subtitle track's metadata. 19110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 19120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @see android.media.MediaPlayer2#getTrackInfo 19130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 19140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public static final class TrackInfoImpl extends TrackInfo { 19150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 19160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Gets the track type. 19170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @return TrackType which indicates if the track is video, audio, timed text. 19180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 19190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 19200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public int getTrackType() { 19210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return mTrackType; 19220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 19230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 19240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 19250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Gets the language code of the track. 19260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @return a language code in either way of ISO-639-1 or ISO-639-2. 19270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * When the language is unknown or could not be determined, 19280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * ISO-639-2 language code, "und", is returned. 19290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 19300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 19310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public String getLanguage() { 19320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia String language = mFormat.getString(MediaFormat.KEY_LANGUAGE); 19330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return language == null ? "und" : language; 19340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 19350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 19360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 19370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Gets the {@link MediaFormat} of the track. If the format is 19380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * unknown or could not be determined, null is returned. 19390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 19400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 19410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public MediaFormat getFormat() { 19420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mTrackType == MEDIA_TRACK_TYPE_TIMEDTEXT 19430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia || mTrackType == MEDIA_TRACK_TYPE_SUBTITLE) { 19440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return mFormat; 19450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 19460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return null; 19470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 19480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 19490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final int mTrackType; 19500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final MediaFormat mFormat; 19510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 19520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia TrackInfoImpl(Parcel in) { 19530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mTrackType = in.readInt(); 19540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // TODO: parcel in the full MediaFormat; currently we are using createSubtitleFormat 19550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // even for audio/video tracks, meaning we only set the mime and language. 19560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia String mime = in.readString(); 19570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia String language = in.readString(); 19580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mFormat = MediaFormat.createSubtitleFormat(mime, language); 19590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 19600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mTrackType == MEDIA_TRACK_TYPE_SUBTITLE) { 19610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mFormat.setInteger(MediaFormat.KEY_IS_AUTOSELECT, in.readInt()); 19620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mFormat.setInteger(MediaFormat.KEY_IS_DEFAULT, in.readInt()); 19630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mFormat.setInteger(MediaFormat.KEY_IS_FORCED_SUBTITLE, in.readInt()); 19640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 19650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 19660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 19670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** @hide */ 19680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia TrackInfoImpl(int type, MediaFormat format) { 19690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mTrackType = type; 19700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mFormat = format; 19710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 19720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 19730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 19740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Flatten this object in to a Parcel. 19750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 19760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param dest The Parcel in which the object should be written. 19770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param flags Additional flags about how the object should be written. 19780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * May be 0 or {@link android.os.Parcelable#PARCELABLE_WRITE_RETURN_VALUE}. 19790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 19800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /* package private */ void writeToParcel(Parcel dest, int flags) { 19810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia dest.writeInt(mTrackType); 19820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia dest.writeString(getLanguage()); 19830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 19840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mTrackType == MEDIA_TRACK_TYPE_SUBTITLE) { 19850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia dest.writeString(mFormat.getString(MediaFormat.KEY_MIME)); 19860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia dest.writeInt(mFormat.getInteger(MediaFormat.KEY_IS_AUTOSELECT)); 19870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia dest.writeInt(mFormat.getInteger(MediaFormat.KEY_IS_DEFAULT)); 19880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia dest.writeInt(mFormat.getInteger(MediaFormat.KEY_IS_FORCED_SUBTITLE)); 19890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 19900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 19910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 19920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 19930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public String toString() { 19940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia StringBuilder out = new StringBuilder(128); 19950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia out.append(getClass().getName()); 19960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia out.append('{'); 19970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia switch (mTrackType) { 19980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case MEDIA_TRACK_TYPE_VIDEO: 19990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia out.append("VIDEO"); 20000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 20010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case MEDIA_TRACK_TYPE_AUDIO: 20020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia out.append("AUDIO"); 20030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 20040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case MEDIA_TRACK_TYPE_TIMEDTEXT: 20050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia out.append("TIMEDTEXT"); 20060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 20070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case MEDIA_TRACK_TYPE_SUBTITLE: 20080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia out.append("SUBTITLE"); 20090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 20100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia default: 20110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia out.append("UNKNOWN"); 20120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 20130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 20140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia out.append(", " + mFormat.toString()); 20150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia out.append("}"); 20160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return out.toString(); 20170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 20180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 20190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 20200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Used to read a TrackInfoImpl from a Parcel. 20210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 20220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /* package private */ static final Parcelable.Creator<TrackInfoImpl> CREATOR 20230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia = new Parcelable.Creator<TrackInfoImpl>() { 20240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 20250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public TrackInfoImpl createFromParcel(Parcel in) { 20260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return new TrackInfoImpl(in); 20270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 20280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 20290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 20300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public TrackInfoImpl[] newArray(int size) { 20310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return new TrackInfoImpl[size]; 20320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 20330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia }; 20340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 20350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia }; 20360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 20370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // We would like domain specific classes with more informative names than the `first` and `second` 20380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // in generic Pair, but we would also like to avoid creating new/trivial classes. As a compromise 20390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // we document the meanings of `first` and `second` here: 20400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // 20410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // Pair.first - inband track index; non-null iff representing an inband track. 20420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // Pair.second - a SubtitleTrack registered with mSubtitleController; non-null iff representing 20430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // an inband subtitle track or any out-of-band track (subtitle or timedtext). 20440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private Vector<Pair<Integer, SubtitleTrack>> mIndexTrackPairs = new Vector<>(); 20450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private BitSet mInbandTrackIndices = new BitSet(); 20460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 20470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 20480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Returns a List of track information. 20490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 20500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @return List of track info. The total number of tracks is the array length. 20510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Must be called again if an external timed text source has been added after 20520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * addTimedTextSource method is called. 20530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalStateException if it is called in an invalid state. 20540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 20550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 20560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public List<TrackInfo> getTrackInfo() { 20570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia TrackInfoImpl trackInfo[] = getInbandTrackInfoImpl(); 20580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // add out-of-band tracks 20590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mIndexTrackPairs) { 20600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia TrackInfoImpl allTrackInfo[] = new TrackInfoImpl[mIndexTrackPairs.size()]; 20610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia for (int i = 0; i < allTrackInfo.length; i++) { 20620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Pair<Integer, SubtitleTrack> p = mIndexTrackPairs.get(i); 20630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (p.first != null) { 20640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // inband track 20650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia allTrackInfo[i] = trackInfo[p.first]; 20660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } else { 20670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia SubtitleTrack track = p.second; 20680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia allTrackInfo[i] = new TrackInfoImpl(track.getTrackType(), track.getFormat()); 20690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 20700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 20710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return Arrays.asList(allTrackInfo); 20720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 20730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 20740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 20750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private TrackInfoImpl[] getInbandTrackInfoImpl() throws IllegalStateException { 20760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Parcel request = Parcel.obtain(); 20770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Parcel reply = Parcel.obtain(); 20780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 20790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia request.writeInt(INVOKE_ID_GET_TRACK_INFO); 20800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia invoke(request, reply); 20810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia TrackInfoImpl trackInfo[] = reply.createTypedArray(TrackInfoImpl.CREATOR); 20820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return trackInfo; 20830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } finally { 20840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia request.recycle(); 20850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia reply.recycle(); 20860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 20870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 20880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 20890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /* 20900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * A helper function to check if the mime type is supported by media framework. 20910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 20920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static boolean availableMimeTypeForExternalSource(String mimeType) { 20930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (MEDIA_MIMETYPE_TEXT_SUBRIP.equals(mimeType)) { 20940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return true; 20950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 20960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return false; 20970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 20980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 20990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private SubtitleController mSubtitleController; 21000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 21010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** @hide */ 21020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 21030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void setSubtitleAnchor( 21040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia SubtitleController controller, 21050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia SubtitleController.Anchor anchor) { 21060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // TODO: create SubtitleController in MediaPlayer2 21070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mSubtitleController = controller; 21080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mSubtitleController.setAnchor(anchor); 21090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 21100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 21110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 21120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * The private version of setSubtitleAnchor is used internally to set mSubtitleController if 21130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * necessary when clients don't provide their own SubtitleControllers using the public version 21140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * {@link #setSubtitleAnchor(SubtitleController, Anchor)} (e.g. {@link VideoView} provides one). 21150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 21160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private synchronized void setSubtitleAnchor() { 21170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if ((mSubtitleController == null) && (ActivityThread.currentApplication() != null)) { 21180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final HandlerThread thread = new HandlerThread("SetSubtitleAnchorThread"); 21190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia thread.start(); 21200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Handler handler = new Handler(thread.getLooper()); 21210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia handler.post(new Runnable() { 21220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 21230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void run() { 21240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Context context = ActivityThread.currentApplication(); 21250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mSubtitleController = new SubtitleController(context, mTimeProvider, MediaPlayer2Impl.this); 21260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mSubtitleController.setAnchor(new Anchor() { 21270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 21280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void setSubtitleWidget(RenderingWidget subtitleWidget) { 21290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 21300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 21310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 21320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public Looper getSubtitleLooper() { 21330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return Looper.getMainLooper(); 21340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 21350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia }); 21360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia thread.getLooper().quitSafely(); 21370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 21380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia }); 21390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 21400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia thread.join(); 21410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (InterruptedException e) { 21420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Thread.currentThread().interrupt(); 21430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.w(TAG, "failed to join SetSubtitleAnchorThread"); 21440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 21450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 21460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 21470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 21480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private int mSelectedSubtitleTrackIndex = -1; 21490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private Vector<InputStream> mOpenSubtitleSources; 21500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 21510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private OnSubtitleDataListener mSubtitleDataListener = new OnSubtitleDataListener() { 21520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 21530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void onSubtitleData(MediaPlayer2 mp, SubtitleData data) { 21540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia int index = data.getTrackIndex(); 21550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mIndexTrackPairs) { 21560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia for (Pair<Integer, SubtitleTrack> p : mIndexTrackPairs) { 21570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (p.first != null && p.first == index && p.second != null) { 21580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // inband subtitle track that owns data 21590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia SubtitleTrack track = p.second; 21600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia track.onData(data); 21610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 21620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 21630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 21640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 21650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia }; 21660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 21670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** @hide */ 21680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 21690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void onSubtitleTrackSelected(SubtitleTrack track) { 21700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mSelectedSubtitleTrackIndex >= 0) { 21710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 21720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia selectOrDeselectInbandTrack(mSelectedSubtitleTrackIndex, false); 21730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (IllegalStateException e) { 21740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 21750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mSelectedSubtitleTrackIndex = -1; 21760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 21770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia setOnSubtitleDataListener(null); 21780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (track == null) { 21790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 21800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 21810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 21820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mIndexTrackPairs) { 21830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia for (Pair<Integer, SubtitleTrack> p : mIndexTrackPairs) { 21840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (p.first != null && p.second == track) { 21850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // inband subtitle track that is selected 21860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mSelectedSubtitleTrackIndex = p.first; 21870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 21880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 21890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 21900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 21910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 21920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mSelectedSubtitleTrackIndex >= 0) { 21930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 21940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia selectOrDeselectInbandTrack(mSelectedSubtitleTrackIndex, true); 21950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (IllegalStateException e) { 21960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 21970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia setOnSubtitleDataListener(mSubtitleDataListener); 21980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 21990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // no need to select out-of-band tracks 22000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 22010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 22020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** @hide */ 22030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 22040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void addSubtitleSource(InputStream is, MediaFormat format) 22050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throws IllegalStateException 22060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia { 22070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final InputStream fIs = is; 22080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final MediaFormat fFormat = format; 22090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 22100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (is != null) { 22110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // Ensure all input streams are closed. It is also a handy 22120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // way to implement timeouts in the future. 22130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized(mOpenSubtitleSources) { 22140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mOpenSubtitleSources.add(is); 22150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 22160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } else { 22170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.w(TAG, "addSubtitleSource called with null InputStream"); 22180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 22190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 22200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia getMediaTimeProvider(); 22210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 22220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // process each subtitle in its own thread 22230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final HandlerThread thread = new HandlerThread("SubtitleReadThread", 22240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Process.THREAD_PRIORITY_BACKGROUND + Process.THREAD_PRIORITY_MORE_FAVORABLE); 22250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia thread.start(); 22260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Handler handler = new Handler(thread.getLooper()); 22270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia handler.post(new Runnable() { 22280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private int addTrack() { 22290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (fIs == null || mSubtitleController == null) { 22300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return MEDIA_INFO_UNSUPPORTED_SUBTITLE; 22310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 22320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 22330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia SubtitleTrack track = mSubtitleController.addTrack(fFormat); 22340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (track == null) { 22350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return MEDIA_INFO_UNSUPPORTED_SUBTITLE; 22360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 22370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 22380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // TODO: do the conversion in the subtitle track 22390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Scanner scanner = new Scanner(fIs, "UTF-8"); 22400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia String contents = scanner.useDelimiter("\\A").next(); 22410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized(mOpenSubtitleSources) { 22420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mOpenSubtitleSources.remove(fIs); 22430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 22440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia scanner.close(); 22450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mIndexTrackPairs) { 22460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mIndexTrackPairs.add(Pair.<Integer, SubtitleTrack>create(null, track)); 22470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 22480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Handler h = mTimeProvider.mEventHandler; 22490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia int what = TimeProvider.NOTIFY; 22500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia int arg1 = TimeProvider.NOTIFY_TRACK_DATA; 22510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Pair<SubtitleTrack, byte[]> trackData = Pair.create(track, contents.getBytes()); 22520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Message m = h.obtainMessage(what, arg1, 0, trackData); 22530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia h.sendMessage(m); 22540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return MEDIA_INFO_EXTERNAL_METADATA_UPDATE; 22550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 22560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 22570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void run() { 22580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia int res = addTrack(); 22590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mEventHandler != null) { 22600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Message m = mEventHandler.obtainMessage(MEDIA_INFO, res, 0, null); 22610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mEventHandler.sendMessage(m); 22620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 22630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia thread.getLooper().quitSafely(); 22640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 22650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia }); 22660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 22670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 22680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private void scanInternalSubtitleTracks() { 22690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia setSubtitleAnchor(); 22700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 22710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia populateInbandTracks(); 22720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 22730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mSubtitleController != null) { 22740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mSubtitleController.selectDefaultTrack(); 22750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 22760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 22770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 22780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private void populateInbandTracks() { 22790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia TrackInfoImpl[] tracks = getInbandTrackInfoImpl(); 22800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mIndexTrackPairs) { 22810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia for (int i = 0; i < tracks.length; i++) { 22820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mInbandTrackIndices.get(i)) { 22830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia continue; 22840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } else { 22850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mInbandTrackIndices.set(i); 22860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 22870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 22880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // newly appeared inband track 22890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (tracks[i].getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) { 22900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia SubtitleTrack track = mSubtitleController.addTrack( 22910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia tracks[i].getFormat()); 22920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mIndexTrackPairs.add(Pair.create(i, track)); 22930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } else { 22940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mIndexTrackPairs.add(Pair.<Integer, SubtitleTrack>create(i, null)); 22950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 22960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 22970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 22980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 22990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 23000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /* TODO: Limit the total number of external timed text source to a reasonable number. 23010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 23020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 23030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Adds an external timed text source file. 23040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 23050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Currently supported format is SubRip with the file extension .srt, case insensitive. 23060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Note that a single external timed text source may contain multiple tracks in it. 23070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * One can find the total number of available tracks using {@link #getTrackInfo()} to see what 23080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * additional tracks become available after this method call. 23090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 23100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param path The file path of external timed text source file. 23110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param mimeType The mime type of the file. Must be one of the mime types listed above. 23120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IOException if the file cannot be accessed or is corrupted. 23130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalArgumentException if the mimeType is not supported. 23140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalStateException if called in an invalid state. 23150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @hide 23160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 23170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 23180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void addTimedTextSource(String path, String mimeType) 23190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throws IOException { 23200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (!availableMimeTypeForExternalSource(mimeType)) { 23210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final String msg = "Illegal mimeType for timed text source: " + mimeType; 23220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throw new IllegalArgumentException(msg); 23230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 23240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 23250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia File file = new File(path); 23260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (file.exists()) { 23270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia FileInputStream is = new FileInputStream(file); 23280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia FileDescriptor fd = is.getFD(); 23290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia addTimedTextSource(fd, mimeType); 23300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia is.close(); 23310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } else { 23320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // We do not support the case where the path is not a file. 23330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throw new IOException(path); 23340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 23350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 23360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 23370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 23380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 23390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Adds an external timed text source file (Uri). 23400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 23410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Currently supported format is SubRip with the file extension .srt, case insensitive. 23420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Note that a single external timed text source may contain multiple tracks in it. 23430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * One can find the total number of available tracks using {@link #getTrackInfo()} to see what 23440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * additional tracks become available after this method call. 23450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 23460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param context the Context to use when resolving the Uri 23470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param uri the Content URI of the data you want to play 23480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param mimeType The mime type of the file. Must be one of the mime types listed above. 23490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IOException if the file cannot be accessed or is corrupted. 23500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalArgumentException if the mimeType is not supported. 23510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalStateException if called in an invalid state. 23520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @hide 23530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 23540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 23550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void addTimedTextSource(Context context, Uri uri, String mimeType) 23560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throws IOException { 23570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia String scheme = uri.getScheme(); 23580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if(scheme == null || scheme.equals("file")) { 23590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia addTimedTextSource(uri.getPath(), mimeType); 23600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 23610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 23620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 23630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia AssetFileDescriptor fd = null; 23640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 23650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia ContentResolver resolver = context.getContentResolver(); 23660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia fd = resolver.openAssetFileDescriptor(uri, "r"); 23670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (fd == null) { 23680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 23690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 23700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia addTimedTextSource(fd.getFileDescriptor(), mimeType); 23710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 23720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (SecurityException ex) { 23730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (IOException ex) { 23740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } finally { 23750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (fd != null) { 23760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia fd.close(); 23770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 23780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 23790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 23800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 23810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 23820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Adds an external timed text source file (FileDescriptor). 23830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 23840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * It is the caller's responsibility to close the file descriptor. 23850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * It is safe to do so as soon as this call returns. 23860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 23870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Currently supported format is SubRip. Note that a single external timed text source may 23880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * contain multiple tracks in it. One can find the total number of available tracks 23890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * using {@link #getTrackInfo()} to see what additional tracks become available 23900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * after this method call. 23910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 23920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param fd the FileDescriptor for the file you want to play 23930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param mimeType The mime type of the file. Must be one of the mime types listed above. 23940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalArgumentException if the mimeType is not supported. 23950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalStateException if called in an invalid state. 23960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @hide 23970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 23980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 23990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void addTimedTextSource(FileDescriptor fd, String mimeType) { 24000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // intentionally less than LONG_MAX 24010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia addTimedTextSource(fd, 0, 0x7ffffffffffffffL, mimeType); 24020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 24030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 24040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 24050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Adds an external timed text file (FileDescriptor). 24060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 24070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * It is the caller's responsibility to close the file descriptor. 24080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * It is safe to do so as soon as this call returns. 24090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 24100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Currently supported format is SubRip. Note that a single external timed text source may 24110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * contain multiple tracks in it. One can find the total number of available tracks 24120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * using {@link #getTrackInfo()} to see what additional tracks become available 24130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * after this method call. 24140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 24150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param fd the FileDescriptor for the file you want to play 24160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param offset the offset into the file where the data to be played starts, in bytes 24170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param length the length in bytes of the data to be played 24180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param mime The mime type of the file. Must be one of the mime types listed above. 24190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalArgumentException if the mimeType is not supported. 24200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalStateException if called in an invalid state. 24210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @hide 24220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 24230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 24240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void addTimedTextSource(FileDescriptor fd, long offset, long length, String mime) { 24250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (!availableMimeTypeForExternalSource(mime)) { 24260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throw new IllegalArgumentException("Illegal mimeType for timed text source: " + mime); 24270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 24280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 24290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final FileDescriptor dupedFd; 24300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 24310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia dupedFd = Os.dup(fd); 24320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (ErrnoException ex) { 24330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.e(TAG, ex.getMessage(), ex); 24340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throw new RuntimeException(ex); 24350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 24360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 24370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final MediaFormat fFormat = new MediaFormat(); 24380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia fFormat.setString(MediaFormat.KEY_MIME, mime); 24390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia fFormat.setInteger(MediaFormat.KEY_IS_TIMED_TEXT, 1); 24400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 24410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // A MediaPlayer2 created by a VideoView should already have its mSubtitleController set. 24420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mSubtitleController == null) { 24430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia setSubtitleAnchor(); 24440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 24450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 24460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (!mSubtitleController.hasRendererFor(fFormat)) { 24470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // test and add not atomic 24480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Context context = ActivityThread.currentApplication(); 24490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mSubtitleController.registerRenderer(new SRTRenderer(context, mEventHandler)); 24500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 24510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final SubtitleTrack track = mSubtitleController.addTrack(fFormat); 24520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mIndexTrackPairs) { 24530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mIndexTrackPairs.add(Pair.<Integer, SubtitleTrack>create(null, track)); 24540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 24550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 24560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia getMediaTimeProvider(); 24570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 24580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final long offset2 = offset; 24590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final long length2 = length; 24600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final HandlerThread thread = new HandlerThread( 24610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia "TimedTextReadThread", 24620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Process.THREAD_PRIORITY_BACKGROUND + Process.THREAD_PRIORITY_MORE_FAVORABLE); 24630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia thread.start(); 24640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Handler handler = new Handler(thread.getLooper()); 24650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia handler.post(new Runnable() { 24660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private int addTrack() { 24670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final ByteArrayOutputStream bos = new ByteArrayOutputStream(); 24680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 24690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Os.lseek(dupedFd, offset2, OsConstants.SEEK_SET); 24700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia byte[] buffer = new byte[4096]; 24710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia for (long total = 0; total < length2;) { 24720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia int bytesToRead = (int) Math.min(buffer.length, length2 - total); 24730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia int bytes = IoBridge.read(dupedFd, buffer, 0, bytesToRead); 24740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (bytes < 0) { 24750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 24760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } else { 24770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia bos.write(buffer, 0, bytes); 24780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia total += bytes; 24790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 24800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 24810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Handler h = mTimeProvider.mEventHandler; 24820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia int what = TimeProvider.NOTIFY; 24830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia int arg1 = TimeProvider.NOTIFY_TRACK_DATA; 24840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Pair<SubtitleTrack, byte[]> trackData = Pair.create(track, bos.toByteArray()); 24850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Message m = h.obtainMessage(what, arg1, 0, trackData); 24860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia h.sendMessage(m); 24870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return MEDIA_INFO_EXTERNAL_METADATA_UPDATE; 24880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (Exception e) { 24890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.e(TAG, e.getMessage(), e); 24900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return MEDIA_INFO_TIMED_TEXT_ERROR; 24910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } finally { 24920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 24930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Os.close(dupedFd); 24940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (ErrnoException e) { 24950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.e(TAG, e.getMessage(), e); 24960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 24970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 24980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 24990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 25000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void run() { 25010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia int res = addTrack(); 25020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mEventHandler != null) { 25030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Message m = mEventHandler.obtainMessage(MEDIA_INFO, res, 0, null); 25040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mEventHandler.sendMessage(m); 25050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 25060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia thread.getLooper().quitSafely(); 25070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 25080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia }); 25090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 25100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 25110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 25120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Returns the index of the audio, video, or subtitle track currently selected for playback, 25130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * The return value is an index into the array returned by {@link #getTrackInfo()}, and can 25140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * be used in calls to {@link #selectTrack(int)} or {@link #deselectTrack(int)}. 25150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 25160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param trackType should be one of {@link TrackInfo#MEDIA_TRACK_TYPE_VIDEO}, 25170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * {@link TrackInfo#MEDIA_TRACK_TYPE_AUDIO}, or 25180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * {@link TrackInfo#MEDIA_TRACK_TYPE_SUBTITLE} 25190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @return index of the audio, video, or subtitle track currently selected for playback; 25200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * a negative integer is returned when there is no selected track for {@code trackType} or 25210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * when {@code trackType} is not one of audio, video, or subtitle. 25220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalStateException if called after {@link #close()} 25230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 25240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @see #getTrackInfo() 25250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @see #selectTrack(int) 25260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @see #deselectTrack(int) 25270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 25280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 25290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public int getSelectedTrack(int trackType) { 25300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mSubtitleController != null 25310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia && (trackType == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE 25320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia || trackType == TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT)) { 25330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia SubtitleTrack subtitleTrack = mSubtitleController.getSelectedTrack(); 25340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (subtitleTrack != null) { 25350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mIndexTrackPairs) { 25360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia for (int i = 0; i < mIndexTrackPairs.size(); i++) { 25370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Pair<Integer, SubtitleTrack> p = mIndexTrackPairs.get(i); 25380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (p.second == subtitleTrack && subtitleTrack.getTrackType() == trackType) { 25390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return i; 25400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 25410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 25420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 25430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 25440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 25450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 25460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Parcel request = Parcel.obtain(); 25470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Parcel reply = Parcel.obtain(); 25480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 25490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia request.writeInt(INVOKE_ID_GET_SELECTED_TRACK); 25500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia request.writeInt(trackType); 25510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia invoke(request, reply); 25520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia int inbandTrackIndex = reply.readInt(); 25530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mIndexTrackPairs) { 25540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia for (int i = 0; i < mIndexTrackPairs.size(); i++) { 25550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Pair<Integer, SubtitleTrack> p = mIndexTrackPairs.get(i); 25560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (p.first != null && p.first == inbandTrackIndex) { 25570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return i; 25580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 25590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 25600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 25610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return -1; 25620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } finally { 25630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia request.recycle(); 25640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia reply.recycle(); 25650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 25660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 25670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 25680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 25690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Selects a track. 25700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * <p> 25710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * If a MediaPlayer2 is in invalid state, it throws an IllegalStateException exception. 25720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * If a MediaPlayer2 is in <em>Started</em> state, the selected track is presented immediately. 25730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * If a MediaPlayer2 is not in Started state, it just marks the track to be played. 25740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * </p> 25750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * <p> 25760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * In any valid state, if it is called multiple times on the same type of track (ie. Video, 25770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Audio, Timed Text), the most recent one will be chosen. 25780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * </p> 25790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * <p> 25800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * The first audio and video tracks are selected by default if available, even though 25810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * this method is not called. However, no timed text track will be selected until 25820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * this function is called. 25830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * </p> 25840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * <p> 25850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Currently, only timed text tracks or audio tracks can be selected via this method. 25860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * In addition, the support for selecting an audio track at runtime is pretty limited 25870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * in that an audio track can only be selected in the <em>Prepared</em> state. 25880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * </p> 25890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param index the index of the track to be selected. The valid range of the index 25900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * is 0..total number of track - 1. The total number of tracks as well as the type of 25910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * each individual track can be found by calling {@link #getTrackInfo()} method. 25920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalStateException if called in an invalid state. 25930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 25940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @see android.media.MediaPlayer2#getTrackInfo 25950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 25960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 25970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void selectTrack(int index) { 259869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang addTask(new Task(CALL_COMPLETED_SELECT_TRACK, false) { 259969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang @Override 260069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang void process() { 260169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang selectOrDeselectTrack(index, true /* select */); 260269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 260369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang }); 26040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 26050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 26060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 26070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Deselect a track. 26080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * <p> 26090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Currently, the track must be a timed text track and no audio or video tracks can be 26100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * deselected. If the timed text track identified by index has not been 26110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * selected before, it throws an exception. 26120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * </p> 26130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param index the index of the track to be deselected. The valid range of the index 26140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * is 0..total number of tracks - 1. The total number of tracks as well as the type of 26150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * each individual track can be found by calling {@link #getTrackInfo()} method. 26160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws IllegalStateException if called in an invalid state. 26170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 26180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @see android.media.MediaPlayer2#getTrackInfo 26190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 26200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 26210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void deselectTrack(int index) { 262269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang addTask(new Task(CALL_COMPLETED_DESELECT_TRACK, false) { 262369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang @Override 262469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang void process() { 262569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang selectOrDeselectTrack(index, false /* select */); 262669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 262769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang }); 26280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 26290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 26300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private void selectOrDeselectTrack(int index, boolean select) 26310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throws IllegalStateException { 26320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // handle subtitle track through subtitle controller 26330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia populateInbandTracks(); 26340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 26350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Pair<Integer,SubtitleTrack> p = null; 26360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 26370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia p = mIndexTrackPairs.get(index); 26380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (ArrayIndexOutOfBoundsException e) { 26390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // ignore bad index 26400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 26410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 26420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 26430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia SubtitleTrack track = p.second; 26440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (track == null) { 26450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // inband (de)select 26460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia selectOrDeselectInbandTrack(p.first, select); 26470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 26480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 26490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 26500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mSubtitleController == null) { 26510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 26520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 26530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 26540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (!select) { 26550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // out-of-band deselect 26560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mSubtitleController.getSelectedTrack() == track) { 26570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mSubtitleController.selectTrack(null); 26580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } else { 26590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.w(TAG, "trying to deselect track that was not selected"); 26600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 26610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 26620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 26630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 26640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // out-of-band select 26650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (track.getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT) { 26660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia int ttIndex = getSelectedTrack(TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT); 26670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mIndexTrackPairs) { 26680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (ttIndex >= 0 && ttIndex < mIndexTrackPairs.size()) { 26690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Pair<Integer,SubtitleTrack> p2 = mIndexTrackPairs.get(ttIndex); 26700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (p2.first != null && p2.second == null) { 26710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // deselect inband counterpart 26720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia selectOrDeselectInbandTrack(p2.first, false); 26730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 26740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 26750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 26760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 26770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mSubtitleController.selectTrack(track); 26780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 26790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 26800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private void selectOrDeselectInbandTrack(int index, boolean select) 26810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throws IllegalStateException { 26820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Parcel request = Parcel.obtain(); 26830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Parcel reply = Parcel.obtain(); 26840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 26850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia request.writeInt(select? INVOKE_ID_SELECT_TRACK: INVOKE_ID_DESELECT_TRACK); 26860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia request.writeInt(index); 26870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia invoke(request, reply); 26880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } finally { 26890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia request.recycle(); 26900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia reply.recycle(); 26910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 26920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 26930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 26940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // Have to declare protected for finalize() since it is protected 26950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // in the base class Object. 26960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 26970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia protected void finalize() throws Throwable { 26980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mGuard != null) { 26990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mGuard.warnIfOpen(); 27000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 27010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 27020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia close(); 27030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia native_finalize(); 27040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 27050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 27060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private void release() { 27070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia stayAwake(false); 27080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia updateSurfaceScreenOn(); 27090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mEventCbLock) { 271063f793f0f3e815c3a4895be7b02941d27d54159cWei Jia mEventCallbackRecords.clear(); 27110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 2712adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang if (mHandlerThread != null) { 2713adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang mHandlerThread.quitSafely(); 2714adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang mHandlerThread = null; 2715adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang } 27160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mTimeProvider != null) { 27170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mTimeProvider.close(); 27180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mTimeProvider = null; 27190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 27200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mOnSubtitleDataListener = null; 27210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 27220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // Modular DRM clean up 27230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mOnDrmConfigHelper = null; 27240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mDrmEventCbLock) { 272563f793f0f3e815c3a4895be7b02941d27d54159cWei Jia mDrmEventCallbackRecords.clear(); 27260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 27270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia resetDrmState(); 27280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 27290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia _release(); 27300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 27310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 27320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private native void _release(); 27330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 27340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /* Do not change these values without updating their counterparts 27350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * in include/media/mediaplayer2.h! 27360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 27370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static final int MEDIA_NOP = 0; // interface test message 27380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static final int MEDIA_PREPARED = 1; 27390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static final int MEDIA_PLAYBACK_COMPLETE = 2; 27400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static final int MEDIA_BUFFERING_UPDATE = 3; 27410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static final int MEDIA_SEEK_COMPLETE = 4; 27420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static final int MEDIA_SET_VIDEO_SIZE = 5; 27430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static final int MEDIA_STARTED = 6; 27440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static final int MEDIA_PAUSED = 7; 27450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static final int MEDIA_STOPPED = 8; 27460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static final int MEDIA_SKIPPED = 9; 27470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static final int MEDIA_NOTIFY_TIME = 98; 27480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static final int MEDIA_TIMED_TEXT = 99; 27490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static final int MEDIA_ERROR = 100; 27500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static final int MEDIA_INFO = 200; 27510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static final int MEDIA_SUBTITLE_DATA = 201; 27520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static final int MEDIA_META_DATA = 202; 27530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static final int MEDIA_DRM_INFO = 210; 27540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static final int MEDIA_AUDIO_ROUTING_CHANGED = 10000; 27550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 27560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private TimeProvider mTimeProvider; 27570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 27580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** @hide */ 27590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 27600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public MediaTimeProvider getMediaTimeProvider() { 27610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mTimeProvider == null) { 27620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mTimeProvider = new TimeProvider(this); 27630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 27640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return mTimeProvider; 27650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 27660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 27670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private class EventHandler extends Handler { 27680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private MediaPlayer2Impl mMediaPlayer; 27690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 27700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public EventHandler(MediaPlayer2Impl mp, Looper looper) { 27710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia super(looper); 27720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mMediaPlayer = mp; 27730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 27740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 27750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 27760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void handleMessage(Message msg) { 277734c5bb126b8cc85176645acea841c796a3cc0292Wei Jia handleMessage(msg, 0); 277834c5bb126b8cc85176645acea841c796a3cc0292Wei Jia } 277934c5bb126b8cc85176645acea841c796a3cc0292Wei Jia 278034c5bb126b8cc85176645acea841c796a3cc0292Wei Jia public void handleMessage(Message msg, long srcId) { 27810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mMediaPlayer.mNativeContext == 0) { 27820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.w(TAG, "mediaplayer2 went away with unhandled events"); 27830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 27840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 278563f793f0f3e815c3a4895be7b02941d27d54159cWei Jia final int what = msg.arg1; 278663f793f0f3e815c3a4895be7b02941d27d54159cWei Jia final int extra = msg.arg2; 2787cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia 27880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia switch(msg.what) { 27890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case MEDIA_PREPARED: 2790cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia { 27910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 27920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia scanInternalSubtitleTracks(); 27930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (RuntimeException e) { 27940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // send error message instead of crashing; 27950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // send error message instead of inlining a call to onError 27960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // to avoid code duplication. 27970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Message msg2 = obtainMessage( 27980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, null); 27990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia sendMessage(msg2); 28000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 28010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 28021789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia final DataSourceDesc dsd; 2803cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia synchronized (mSrcLock) { 2804de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia Log.i(TAG, "MEDIA_PREPARED: srcId=" + srcId 28051789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia + ", currentSrcId=" + mCurrentSrcId + ", nextSrcId=" + mNextSrcId); 28061789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia if (srcId == mCurrentSrcId) { 28071789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia dsd = mCurrentDSD; 2808cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia prepareNextDataSource_l(); 2809cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia } else if (mNextDSDs != null && !mNextDSDs.isEmpty() 2810cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia && srcId == mNextSrcId) { 2811cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia dsd = mNextDSDs.get(0); 2812cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia mNextSourceState = NEXT_SOURCE_STATE_PREPARED; 2813cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia if (mNextSourcePlayPending) { 2814de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia playNextDataSource_l(); 2815de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia } 28161789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia } else { 28171789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia dsd = null; 2818de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia } 2819de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia } 2820de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia 2821cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia if (dsd != null) { 2822cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia synchronized (mEventCbLock) { 2823cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) { 2824cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia cb.first.execute(() -> cb.second.onInfo( 2825cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia mMediaPlayer, dsd, MEDIA_INFO_PREPARED, 0)); 2826cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia } 282763f793f0f3e815c3a4895be7b02941d27d54159cWei Jia } 28280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 2829adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang synchronized (mTaskLock) { 283069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang if (mCurrentTask != null 283169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang && mCurrentTask.mMediaCallType == CALL_COMPLETED_PREPARE 283269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang && mCurrentTask.mDSD == dsd 2833adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang && mCurrentTask.mNeedToWaitForEventToComplete) { 283469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang mCurrentTask.sendCompleteNotification(CALL_STATUS_NO_ERROR); 2835adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang mCurrentTask = null; 2836adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang processPendingTask_l(); 2837adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang } 2838adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang } 28390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 2840cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia } 28410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 28420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case MEDIA_DRM_INFO: 2843cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia { 28440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (msg.obj == null) { 28450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.w(TAG, "MEDIA_DRM_INFO msg.obj=NULL"); 28460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } else if (msg.obj instanceof Parcel) { 284763f793f0f3e815c3a4895be7b02941d27d54159cWei Jia // The parcel was parsed already in postEventFromNative 284863f793f0f3e815c3a4895be7b02941d27d54159cWei Jia final DrmInfoImpl drmInfo; 284963f793f0f3e815c3a4895be7b02941d27d54159cWei Jia 285063f793f0f3e815c3a4895be7b02941d27d54159cWei Jia synchronized (mDrmLock) { 285163f793f0f3e815c3a4895be7b02941d27d54159cWei Jia if (mDrmInfoImpl != null) { 285263f793f0f3e815c3a4895be7b02941d27d54159cWei Jia drmInfo = mDrmInfoImpl.makeCopy(); 285363f793f0f3e815c3a4895be7b02941d27d54159cWei Jia } else { 285463f793f0f3e815c3a4895be7b02941d27d54159cWei Jia drmInfo = null; 28550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 285663f793f0f3e815c3a4895be7b02941d27d54159cWei Jia } 28570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 285863f793f0f3e815c3a4895be7b02941d27d54159cWei Jia // notifying the client outside the lock 285963f793f0f3e815c3a4895be7b02941d27d54159cWei Jia if (drmInfo != null) { 286063f793f0f3e815c3a4895be7b02941d27d54159cWei Jia synchronized (mEventCbLock) { 286163f793f0f3e815c3a4895be7b02941d27d54159cWei Jia for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) { 286263f793f0f3e815c3a4895be7b02941d27d54159cWei Jia cb.first.execute(() -> cb.second.onDrmInfo( 28631789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia mMediaPlayer, mCurrentDSD, drmInfo)); 286463f793f0f3e815c3a4895be7b02941d27d54159cWei Jia } 28650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 28660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 28670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } else { 28680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.w(TAG, "MEDIA_DRM_INFO msg.obj of unexpected type " + msg.obj); 28690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 28700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 2871cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia } 28720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 28730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case MEDIA_PLAYBACK_COMPLETE: 2874cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia { 2875cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia final DataSourceDesc dsd = mCurrentDSD; 2876cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia synchronized (mSrcLock) { 28771789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia if (srcId == mCurrentSrcId) { 2878de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia Log.i(TAG, "MEDIA_PLAYBACK_COMPLETE: srcId=" + srcId 28791789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia + ", currentSrcId=" + mCurrentSrcId + ", nextSrcId=" + mNextSrcId); 2880de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia playNextDataSource_l(); 2881de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia } 2882de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia } 2883de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia 288463f793f0f3e815c3a4895be7b02941d27d54159cWei Jia synchronized (mEventCbLock) { 28851789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) { 288663f793f0f3e815c3a4895be7b02941d27d54159cWei Jia cb.first.execute(() -> cb.second.onInfo( 2887cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia mMediaPlayer, dsd, MEDIA_INFO_PLAYBACK_COMPLETE, 0)); 288863f793f0f3e815c3a4895be7b02941d27d54159cWei Jia } 28890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 28900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia stayAwake(false); 28910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 2892cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia } 28930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 28940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case MEDIA_STOPPED: 2895cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia { 2896cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia TimeProvider timeProvider = mTimeProvider; 2897cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia if (timeProvider != null) { 2898cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia timeProvider.onStopped(); 28990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 29000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 2901cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia } 29020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 29030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case MEDIA_STARTED: 29040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case MEDIA_PAUSED: 2905cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia { 2906cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia TimeProvider timeProvider = mTimeProvider; 2907cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia if (timeProvider != null) { 2908cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia timeProvider.onPaused(msg.what == MEDIA_PAUSED); 29090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 29100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 2911cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia } 29120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 29130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case MEDIA_BUFFERING_UPDATE: 2914cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia { 291563f793f0f3e815c3a4895be7b02941d27d54159cWei Jia final int percent = msg.arg1; 291663f793f0f3e815c3a4895be7b02941d27d54159cWei Jia synchronized (mEventCbLock) { 2917c3725a94bb9840027a42669a659a0fd11d6f69c6Wei Jia if (srcId == mCurrentSrcId) { 2918c3725a94bb9840027a42669a659a0fd11d6f69c6Wei Jia mBufferedPercentageCurrent.set(percent); 2919c3725a94bb9840027a42669a659a0fd11d6f69c6Wei Jia for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) { 2920c3725a94bb9840027a42669a659a0fd11d6f69c6Wei Jia cb.first.execute(() -> cb.second.onInfo( 2921c3725a94bb9840027a42669a659a0fd11d6f69c6Wei Jia mMediaPlayer, mCurrentDSD, MEDIA_INFO_BUFFERING_UPDATE, 2922c3725a94bb9840027a42669a659a0fd11d6f69c6Wei Jia percent)); 2923c3725a94bb9840027a42669a659a0fd11d6f69c6Wei Jia } 2924c3725a94bb9840027a42669a659a0fd11d6f69c6Wei Jia } else if (srcId == mNextSrcId && !mNextDSDs.isEmpty()) { 2925c3725a94bb9840027a42669a659a0fd11d6f69c6Wei Jia mBufferedPercentageNext.set(percent); 2926c3725a94bb9840027a42669a659a0fd11d6f69c6Wei Jia DataSourceDesc nextDSD = mNextDSDs.get(0); 2927c3725a94bb9840027a42669a659a0fd11d6f69c6Wei Jia for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) { 2928c3725a94bb9840027a42669a659a0fd11d6f69c6Wei Jia cb.first.execute(() -> cb.second.onInfo( 2929c3725a94bb9840027a42669a659a0fd11d6f69c6Wei Jia mMediaPlayer, nextDSD, MEDIA_INFO_BUFFERING_UPDATE, 2930c3725a94bb9840027a42669a659a0fd11d6f69c6Wei Jia percent)); 2931c3725a94bb9840027a42669a659a0fd11d6f69c6Wei Jia } 293263f793f0f3e815c3a4895be7b02941d27d54159cWei Jia } 29330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 29340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 2935cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia } 29360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 29370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case MEDIA_SEEK_COMPLETE: 2938cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia { 293969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang synchronized (mTaskLock) { 294069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang if (mCurrentTask != null 294169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang && mCurrentTask.mMediaCallType == CALL_COMPLETED_SEEK_TO 294269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang && mCurrentTask.mNeedToWaitForEventToComplete) { 294369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang mCurrentTask.sendCompleteNotification(CALL_STATUS_NO_ERROR); 294469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang mCurrentTask = null; 294569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang processPendingTask_l(); 294663f793f0f3e815c3a4895be7b02941d27d54159cWei Jia } 29470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 2948cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia } 29490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // fall through 29500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 29510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case MEDIA_SKIPPED: 2952cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia { 2953cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia TimeProvider timeProvider = mTimeProvider; 2954cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia if (timeProvider != null) { 2955cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia timeProvider.onSeekComplete(mMediaPlayer); 29560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 29570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 2958cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia } 29590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 29600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case MEDIA_SET_VIDEO_SIZE: 2961cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia { 296263f793f0f3e815c3a4895be7b02941d27d54159cWei Jia final int width = msg.arg1; 296363f793f0f3e815c3a4895be7b02941d27d54159cWei Jia final int height = msg.arg2; 296463f793f0f3e815c3a4895be7b02941d27d54159cWei Jia synchronized (mEventCbLock) { 29651789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) { 296663f793f0f3e815c3a4895be7b02941d27d54159cWei Jia cb.first.execute(() -> cb.second.onVideoSizeChanged( 29671789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia mMediaPlayer, mCurrentDSD, width, height)); 296863f793f0f3e815c3a4895be7b02941d27d54159cWei Jia } 29690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 29700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 2971cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia } 29720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 29730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case MEDIA_ERROR: 2974cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia { 29750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.e(TAG, "Error (" + msg.arg1 + "," + msg.arg2 + ")"); 297663f793f0f3e815c3a4895be7b02941d27d54159cWei Jia synchronized (mEventCbLock) { 29771789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) { 297863f793f0f3e815c3a4895be7b02941d27d54159cWei Jia cb.first.execute(() -> cb.second.onError( 29791789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia mMediaPlayer, mCurrentDSD, what, extra)); 298063f793f0f3e815c3a4895be7b02941d27d54159cWei Jia cb.first.execute(() -> cb.second.onInfo( 29811789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia mMediaPlayer, mCurrentDSD, MEDIA_INFO_PLAYBACK_COMPLETE, 0)); 298263f793f0f3e815c3a4895be7b02941d27d54159cWei Jia } 29830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 29840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia stayAwake(false); 29850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 2986cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia } 29870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 29880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case MEDIA_INFO: 2989cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia { 29900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia switch (msg.arg1) { 2991de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia case MEDIA_INFO_STARTED_AS_NEXT: 29921789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia if (srcId == mCurrentSrcId) { 2993de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia prepareNextDataSource_l(); 2994de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia } 2995de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia break; 2996de0c3979ce4bdb9464645d6a898b8e1e042cf33fWei Jia 299763f793f0f3e815c3a4895be7b02941d27d54159cWei Jia case MEDIA_INFO_VIDEO_TRACK_LAGGING: 299863f793f0f3e815c3a4895be7b02941d27d54159cWei Jia Log.i(TAG, "Info (" + msg.arg1 + "," + msg.arg2 + ")"); 299963f793f0f3e815c3a4895be7b02941d27d54159cWei Jia break; 300063f793f0f3e815c3a4895be7b02941d27d54159cWei Jia 300163f793f0f3e815c3a4895be7b02941d27d54159cWei Jia case MEDIA_INFO_METADATA_UPDATE: 300263f793f0f3e815c3a4895be7b02941d27d54159cWei Jia try { 300363f793f0f3e815c3a4895be7b02941d27d54159cWei Jia scanInternalSubtitleTracks(); 300463f793f0f3e815c3a4895be7b02941d27d54159cWei Jia } catch (RuntimeException e) { 300563f793f0f3e815c3a4895be7b02941d27d54159cWei Jia Message msg2 = obtainMessage( 300663f793f0f3e815c3a4895be7b02941d27d54159cWei Jia MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, 300763f793f0f3e815c3a4895be7b02941d27d54159cWei Jia null); 300863f793f0f3e815c3a4895be7b02941d27d54159cWei Jia sendMessage(msg2); 300963f793f0f3e815c3a4895be7b02941d27d54159cWei Jia } 301063f793f0f3e815c3a4895be7b02941d27d54159cWei Jia // fall through 30110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 301263f793f0f3e815c3a4895be7b02941d27d54159cWei Jia case MEDIA_INFO_EXTERNAL_METADATA_UPDATE: 301363f793f0f3e815c3a4895be7b02941d27d54159cWei Jia msg.arg1 = MEDIA_INFO_METADATA_UPDATE; 301463f793f0f3e815c3a4895be7b02941d27d54159cWei Jia // update default track selection 301563f793f0f3e815c3a4895be7b02941d27d54159cWei Jia if (mSubtitleController != null) { 301663f793f0f3e815c3a4895be7b02941d27d54159cWei Jia mSubtitleController.selectDefaultTrack(); 301763f793f0f3e815c3a4895be7b02941d27d54159cWei Jia } 301863f793f0f3e815c3a4895be7b02941d27d54159cWei Jia break; 301963f793f0f3e815c3a4895be7b02941d27d54159cWei Jia 302063f793f0f3e815c3a4895be7b02941d27d54159cWei Jia case MEDIA_INFO_BUFFERING_START: 302163f793f0f3e815c3a4895be7b02941d27d54159cWei Jia case MEDIA_INFO_BUFFERING_END: 302263f793f0f3e815c3a4895be7b02941d27d54159cWei Jia TimeProvider timeProvider = mTimeProvider; 302363f793f0f3e815c3a4895be7b02941d27d54159cWei Jia if (timeProvider != null) { 302463f793f0f3e815c3a4895be7b02941d27d54159cWei Jia timeProvider.onBuffering(msg.arg1 == MEDIA_INFO_BUFFERING_START); 302563f793f0f3e815c3a4895be7b02941d27d54159cWei Jia } 302663f793f0f3e815c3a4895be7b02941d27d54159cWei Jia break; 30270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 30280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 302963f793f0f3e815c3a4895be7b02941d27d54159cWei Jia synchronized (mEventCbLock) { 30301789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) { 303163f793f0f3e815c3a4895be7b02941d27d54159cWei Jia cb.first.execute(() -> cb.second.onInfo( 30321789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia mMediaPlayer, mCurrentDSD, what, extra)); 303363f793f0f3e815c3a4895be7b02941d27d54159cWei Jia } 30340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 30350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // No real default action so far. 30360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 3037cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia } 30380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 30390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case MEDIA_NOTIFY_TIME: 3040cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia { 3041cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia TimeProvider timeProvider = mTimeProvider; 3042cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia if (timeProvider != null) { 3043cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia timeProvider.onNotifyTime(); 3044cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia } 30450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 3046cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia } 30470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 30480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case MEDIA_TIMED_TEXT: 3049cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia { 305063f793f0f3e815c3a4895be7b02941d27d54159cWei Jia final TimedText text; 305163f793f0f3e815c3a4895be7b02941d27d54159cWei Jia if (msg.obj instanceof Parcel) { 305263f793f0f3e815c3a4895be7b02941d27d54159cWei Jia Parcel parcel = (Parcel)msg.obj; 305363f793f0f3e815c3a4895be7b02941d27d54159cWei Jia text = new TimedText(parcel); 305463f793f0f3e815c3a4895be7b02941d27d54159cWei Jia parcel.recycle(); 30550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } else { 305663f793f0f3e815c3a4895be7b02941d27d54159cWei Jia text = null; 305763f793f0f3e815c3a4895be7b02941d27d54159cWei Jia } 305863f793f0f3e815c3a4895be7b02941d27d54159cWei Jia 305963f793f0f3e815c3a4895be7b02941d27d54159cWei Jia synchronized (mEventCbLock) { 30601789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) { 30611789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia cb.first.execute(() -> cb.second.onTimedText(mMediaPlayer, mCurrentDSD, text)); 30620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 30630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 30640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 3065cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia } 30660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 30670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case MEDIA_SUBTITLE_DATA: 3068cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia { 30690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia OnSubtitleDataListener onSubtitleDataListener = mOnSubtitleDataListener; 30700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (onSubtitleDataListener == null) { 30710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 30720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 30730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (msg.obj instanceof Parcel) { 30740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Parcel parcel = (Parcel) msg.obj; 30750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia SubtitleData data = new SubtitleData(parcel); 30760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia parcel.recycle(); 30770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia onSubtitleDataListener.onSubtitleData(mMediaPlayer, data); 30780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 30790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 3080cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia } 30810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 30820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case MEDIA_META_DATA: 3083cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia { 308463f793f0f3e815c3a4895be7b02941d27d54159cWei Jia final TimedMetaData data; 30850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (msg.obj instanceof Parcel) { 30860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Parcel parcel = (Parcel) msg.obj; 308763f793f0f3e815c3a4895be7b02941d27d54159cWei Jia data = TimedMetaData.createTimedMetaDataFromParcel(parcel); 30880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia parcel.recycle(); 308963f793f0f3e815c3a4895be7b02941d27d54159cWei Jia } else { 309063f793f0f3e815c3a4895be7b02941d27d54159cWei Jia data = null; 309163f793f0f3e815c3a4895be7b02941d27d54159cWei Jia } 309263f793f0f3e815c3a4895be7b02941d27d54159cWei Jia 309363f793f0f3e815c3a4895be7b02941d27d54159cWei Jia synchronized (mEventCbLock) { 30941789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) { 309563f793f0f3e815c3a4895be7b02941d27d54159cWei Jia cb.first.execute(() -> cb.second.onTimedMetaDataAvailable( 30961789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia mMediaPlayer, mCurrentDSD, data)); 309763f793f0f3e815c3a4895be7b02941d27d54159cWei Jia } 30980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 30990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 3100cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia } 31010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 31020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case MEDIA_NOP: // interface test message - ignore 3103cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia { 31040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 3105cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia } 31060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 31070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case MEDIA_AUDIO_ROUTING_CHANGED: 3108cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia { 31090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia AudioManager.resetAudioPortGeneration(); 31100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mRoutingChangeListeners) { 31110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia for (NativeRoutingEventHandlerDelegate delegate 31120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia : mRoutingChangeListeners.values()) { 31130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia delegate.notifyClient(); 31140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 31150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 31160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 3117cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia } 31180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 31190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia default: 3120cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia { 31210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.e(TAG, "Unknown message type " + msg.what); 31220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 31230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 3124cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia } 31250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 31260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 31270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 31280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /* 31290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Called from native code when an interesting event happens. This method 31300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * just uses the EventHandler system to post the event back to the main app thread. 31310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * We use a weak reference to the original MediaPlayer2 object so that the native 31320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * code is safe from the object disappearing from underneath it. (This is 31330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * the cookie passed to native_setup().) 31340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 313534c5bb126b8cc85176645acea841c796a3cc0292Wei Jia private static void postEventFromNative(Object mediaplayer2_ref, long srcId, 31360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia int what, int arg1, int arg2, Object obj) 31370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia { 31380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final MediaPlayer2Impl mp = (MediaPlayer2Impl)((WeakReference)mediaplayer2_ref).get(); 31390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mp == null) { 31400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 31410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 31420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 31430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia switch (what) { 31440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case MEDIA_INFO: 31450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (arg1 == MEDIA_INFO_STARTED_AS_NEXT) { 31460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia new Thread(new Runnable() { 31470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 31480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void run() { 31490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // this acquires the wakelock if needed, and sets the client side state 31500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mp.play(); 31510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 31520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia }).start(); 31530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Thread.yield(); 31540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 31550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 31560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 31570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case MEDIA_DRM_INFO: 31580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // We need to derive mDrmInfoImpl before prepare() returns so processing it here 31590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // before the notification is sent to EventHandler below. EventHandler runs in the 31600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // notification looper so its handleMessage might process the event after prepare() 31610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // has returned. 31620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.v(TAG, "postEventFromNative MEDIA_DRM_INFO"); 31630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (obj instanceof Parcel) { 31640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Parcel parcel = (Parcel)obj; 31650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia DrmInfoImpl drmInfo = new DrmInfoImpl(parcel); 31660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mp.mDrmLock) { 31670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mp.mDrmInfoImpl = drmInfo; 31680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 31690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } else { 31700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.w(TAG, "MEDIA_DRM_INFO msg.obj of unexpected type " + obj); 31710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 31720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 31730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 31740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case MEDIA_PREPARED: 31750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // By this time, we've learned about DrmInfo's presence or absence. This is meant 31761789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia // mainly for prepare() use case. For prepare(), this still can run to a race 31770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // condition b/c MediaPlayerNative releases the prepare() lock before calling notify 31780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // so we also set mDrmInfoResolved in prepare(). 31790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mp.mDrmLock) { 31800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mp.mDrmInfoResolved = true; 31810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 31820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 31830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 31840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 31850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 31860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mp.mEventHandler != null) { 31870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Message m = mp.mEventHandler.obtainMessage(what, arg1, arg2, obj); 318834c5bb126b8cc85176645acea841c796a3cc0292Wei Jia 318934c5bb126b8cc85176645acea841c796a3cc0292Wei Jia mp.mEventHandler.post(new Runnable() { 319034c5bb126b8cc85176645acea841c796a3cc0292Wei Jia @Override 319134c5bb126b8cc85176645acea841c796a3cc0292Wei Jia public void run() { 319234c5bb126b8cc85176645acea841c796a3cc0292Wei Jia mp.mEventHandler.handleMessage(m, srcId); 319334c5bb126b8cc85176645acea841c796a3cc0292Wei Jia } 319434c5bb126b8cc85176645acea841c796a3cc0292Wei Jia }); 31950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 31960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 31970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 31980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private final Object mEventCbLock = new Object(); 31991789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia private ArrayList<Pair<Executor, MediaPlayer2EventCallback> > mEventCallbackRecords 32001789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia = new ArrayList<Pair<Executor, MediaPlayer2EventCallback> >(); 32010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 32020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 32030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Register a callback to be invoked when the media source is ready 32040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * for playback. 32050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 32060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param eventCallback the callback that will be run 32070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param executor the executor through which the callback should be invoked 32080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 32090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 32101789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public void setMediaPlayer2EventCallback(@NonNull @CallbackExecutor Executor executor, 32111789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia @NonNull MediaPlayer2EventCallback eventCallback) { 32120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (eventCallback == null) { 32131789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia throw new IllegalArgumentException("Illegal null MediaPlayer2EventCallback"); 32140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 32150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (executor == null) { 32161789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia throw new IllegalArgumentException( 32171789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia "Illegal null Executor for the MediaPlayer2EventCallback"); 32180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 32190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mEventCbLock) { 322063f793f0f3e815c3a4895be7b02941d27d54159cWei Jia mEventCallbackRecords.add(new Pair(executor, eventCallback)); 32210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 32220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 32230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 32240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 32251789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Clears the {@link MediaPlayer2EventCallback}. 32260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 32270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 32281789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public void clearMediaPlayer2EventCallback() { 32290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mEventCbLock) { 3230096d97ac3e01d3a148f6148180c375f9337b64e5Wei Jia mEventCallbackRecords.clear(); 32310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 32320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 32330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 32340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 32350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Register a callback to be invoked when a track has data available. 32360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 32370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param listener the callback that will be run 32380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 32390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @hide 32400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 32410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 32420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void setOnSubtitleDataListener(OnSubtitleDataListener listener) { 32430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mOnSubtitleDataListener = listener; 32440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 32450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 32460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private OnSubtitleDataListener mOnSubtitleDataListener; 32470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 32480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 32490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // Modular DRM begin 32500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 32510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 32520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Register a callback to be invoked for configuration of the DRM object before 32530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * the session is created. 32540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * The callback will be invoked synchronously during the execution 32550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * of {@link #prepareDrm(UUID uuid)}. 32560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 32570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param listener the callback that will be run 32580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 32590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 32600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void setOnDrmConfigHelper(OnDrmConfigHelper listener) 32610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia { 32620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mDrmLock) { 32630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mOnDrmConfigHelper = listener; 32640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } // synchronized 32650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 32660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 32670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private OnDrmConfigHelper mOnDrmConfigHelper; 32680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 32690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private final Object mDrmEventCbLock = new Object(); 327063f793f0f3e815c3a4895be7b02941d27d54159cWei Jia private ArrayList<Pair<Executor, DrmEventCallback> > mDrmEventCallbackRecords 327163f793f0f3e815c3a4895be7b02941d27d54159cWei Jia = new ArrayList<Pair<Executor, DrmEventCallback> >(); 32720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 32730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 32740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Register a callback to be invoked when the media source is ready 32750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * for playback. 32760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 32770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param eventCallback the callback that will be run 32780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param executor the executor through which the callback should be invoked 32790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 32800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 32811789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public void setDrmEventCallback(@NonNull @CallbackExecutor Executor executor, 32820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @NonNull DrmEventCallback eventCallback) { 32830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (eventCallback == null) { 32841789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia throw new IllegalArgumentException("Illegal null MediaPlayer2EventCallback"); 32850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 32860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (executor == null) { 32871789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia throw new IllegalArgumentException( 32881789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia "Illegal null Executor for the MediaPlayer2EventCallback"); 32890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 32900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mDrmEventCbLock) { 329163f793f0f3e815c3a4895be7b02941d27d54159cWei Jia mDrmEventCallbackRecords.add(new Pair(executor, eventCallback)); 32920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 32930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 32940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 32950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 32961789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * Clears the {@link DrmEventCallback}. 32970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 32980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 32991789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public void clearDrmEventCallback() { 33000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mDrmEventCbLock) { 3301096d97ac3e01d3a148f6148180c375f9337b64e5Wei Jia mDrmEventCallbackRecords.clear(); 33020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 33030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 33040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 33050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 33060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 33070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Retrieves the DRM Info associated with the current source 33080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 33091789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @throws IllegalStateException if called before prepare() 33100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 33110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 33120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public DrmInfo getDrmInfo() { 33130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia DrmInfoImpl drmInfo = null; 33140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 33150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // there is not much point if the app calls getDrmInfo within an OnDrmInfoListenet; 33160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // regardless below returns drmInfo anyway instead of raising an exception 33170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mDrmLock) { 33180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (!mDrmInfoResolved && mDrmInfoImpl == null) { 33190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final String msg = "The Player has not been prepared yet"; 33200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.v(TAG, msg); 33210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throw new IllegalStateException(msg); 33220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 33230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 33240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mDrmInfoImpl != null) { 33250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia drmInfo = mDrmInfoImpl.makeCopy(); 33260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 33270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } // synchronized 33280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 33290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return drmInfo; 33300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 33310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 33320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 33330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 33340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Prepares the DRM for the current source 33350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * <p> 33360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * If {@code OnDrmConfigHelper} is registered, it will be called during 33370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * preparation to allow configuration of the DRM properties before opening the 33380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * DRM session. Note that the callback is called synchronously in the thread that called 33390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * {@code prepareDrm}. It should be used only for a series of {@code getDrmPropertyString} 33400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * and {@code setDrmPropertyString} calls and refrain from any lengthy operation. 33410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * <p> 33420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * If the device has not been provisioned before, this call also provisions the device 33430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * which involves accessing the provisioning server and can take a variable time to 33440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * complete depending on the network connectivity. 33450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * If {@code OnDrmPreparedListener} is registered, prepareDrm() runs in non-blocking 33460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * mode by launching the provisioning in the background and returning. The listener 33470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * will be called when provisioning and preparation has finished. If a 33480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * {@code OnDrmPreparedListener} is not registered, prepareDrm() waits till provisioning 33490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * and preparation has finished, i.e., runs in blocking mode. 33500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * <p> 33510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * If {@code OnDrmPreparedListener} is registered, it is called to indicate the DRM 33520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * session being ready. The application should not make any assumption about its call 33530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * sequence (e.g., before or after prepareDrm returns), or the thread context that will 33540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * execute the listener (unless the listener is registered with a handler thread). 33550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * <p> 33560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 33570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param uuid The UUID of the crypto scheme. If not known beforehand, it can be retrieved 33580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * from the source through {@code getDrmInfo} or registering a {@code onDrmInfoListener}. 33590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 33601789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * @throws IllegalStateException if called before prepare(), or the DRM was 33610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * prepared already 33620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws UnsupportedSchemeException if the crypto scheme is not supported 33630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws ResourceBusyException if required DRM resources are in use 33640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws ProvisioningNetworkErrorException if provisioning is required but failed due to a 33650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * network error 33660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws ProvisioningServerErrorException if provisioning is required but failed due to 33670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * the request denied by the provisioning server 33680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 33690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 33700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void prepareDrm(@NonNull UUID uuid) 33710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throws UnsupportedSchemeException, ResourceBusyException, 33720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia ProvisioningNetworkErrorException, ProvisioningServerErrorException 33730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia { 33740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.v(TAG, "prepareDrm: uuid: " + uuid + " mOnDrmConfigHelper: " + mOnDrmConfigHelper); 33750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 33760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia boolean allDoneWithoutProvisioning = false; 33770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 33780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mDrmLock) { 33790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 33800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // only allowing if tied to a protected source; might relax for releasing offline keys 33810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mDrmInfoImpl == null) { 33820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final String msg = "prepareDrm(): Wrong usage: The player must be prepared and " + 33830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia "DRM info be retrieved before this call."; 33840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.e(TAG, msg); 33850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throw new IllegalStateException(msg); 33860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 33870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 33880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mActiveDrmScheme) { 33890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final String msg = "prepareDrm(): Wrong usage: There is already " + 33900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia "an active DRM scheme with " + mDrmUUID; 33910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.e(TAG, msg); 33920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throw new IllegalStateException(msg); 33930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 33940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 33950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mPrepareDrmInProgress) { 33960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final String msg = "prepareDrm(): Wrong usage: There is already " + 33970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia "a pending prepareDrm call."; 33980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.e(TAG, msg); 33990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throw new IllegalStateException(msg); 34000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 34010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 34020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mDrmProvisioningInProgress) { 34030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final String msg = "prepareDrm(): Unexpectd: Provisioning is already in progress."; 34040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.e(TAG, msg); 34050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throw new IllegalStateException(msg); 34060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 34070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 34080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // shouldn't need this; just for safeguard 34090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia cleanDrmObj(); 34100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 34110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mPrepareDrmInProgress = true; 34120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 34130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 34140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // only creating the DRM object to allow pre-openSession configuration 3415cde2d3ff1048c13671b0b539f5635a64e088cd7aWei Jia prepareDrm_createDrmStep(uuid); 34160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (Exception e) { 34170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.w(TAG, "prepareDrm(): Exception ", e); 34180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mPrepareDrmInProgress = false; 34190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throw e; 34200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 34210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 34220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mDrmConfigAllowed = true; 34230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } // synchronized 34240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 34250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 34260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // call the callback outside the lock 34270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mOnDrmConfigHelper != null) { 34281789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia mOnDrmConfigHelper.onDrmConfig(this, mCurrentDSD); 34290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 34300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 34310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mDrmLock) { 34320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mDrmConfigAllowed = false; 34330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia boolean earlyExit = false; 34340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 34350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 34360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia prepareDrm_openSessionStep(uuid); 34370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 34380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mDrmUUID = uuid; 34390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mActiveDrmScheme = true; 34400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 34410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia allDoneWithoutProvisioning = true; 34420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (IllegalStateException e) { 34430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final String msg = "prepareDrm(): Wrong usage: The player must be " + 34440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia "in the prepared state to call prepareDrm()."; 34450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.e(TAG, msg); 34460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia earlyExit = true; 34470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throw new IllegalStateException(msg); 34480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (NotProvisionedException e) { 34490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.w(TAG, "prepareDrm: NotProvisionedException"); 34500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 34510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // handle provisioning internally; it'll reset mPrepareDrmInProgress 34520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia int result = HandleProvisioninig(uuid); 34530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 34540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // if blocking mode, we're already done; 34550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // if non-blocking mode, we attempted to launch background provisioning 34560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (result != PREPARE_DRM_STATUS_SUCCESS) { 34570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia earlyExit = true; 34580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia String msg; 34590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 34600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia switch (result) { 34610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR: 34620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia msg = "prepareDrm: Provisioning was required but failed " + 34630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia "due to a network error."; 34640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.e(TAG, msg); 34650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throw new ProvisioningNetworkErrorExceptionImpl(msg); 34660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 34670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR: 34680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia msg = "prepareDrm: Provisioning was required but the request " + 34690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia "was denied by the server."; 34700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.e(TAG, msg); 34710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throw new ProvisioningServerErrorExceptionImpl(msg); 34720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 34730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case PREPARE_DRM_STATUS_PREPARATION_ERROR: 34740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia default: // default for safeguard 34750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia msg = "prepareDrm: Post-provisioning preparation failed."; 34760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.e(TAG, msg); 34770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throw new IllegalStateException(msg); 34780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 34790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 34800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // nothing else to do; 34810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // if blocking or non-blocking, HandleProvisioninig does the re-attempt & cleanup 34820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (Exception e) { 34830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.e(TAG, "prepareDrm: Exception " + e); 34840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia earlyExit = true; 34850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throw e; 34860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } finally { 34870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (!mDrmProvisioningInProgress) {// if early exit other than provisioning exception 34880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mPrepareDrmInProgress = false; 34890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 34900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (earlyExit) { // cleaning up object if didn't succeed 34910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia cleanDrmObj(); 34920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 34930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } // finally 34940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } // synchronized 34950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 34960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 34970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // if finished successfully without provisioning, call the callback outside the lock 34980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (allDoneWithoutProvisioning) { 34990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mDrmEventCbLock) { 350063f793f0f3e815c3a4895be7b02941d27d54159cWei Jia for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) { 350163f793f0f3e815c3a4895be7b02941d27d54159cWei Jia cb.first.execute(() -> cb.second.onDrmPrepared( 35021789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia this, mCurrentDSD, PREPARE_DRM_STATUS_SUCCESS)); 350363f793f0f3e815c3a4895be7b02941d27d54159cWei Jia } 35040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 35050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 35060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 35070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 35080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 35090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 35100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private native void _releaseDrm(); 35110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 35120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 35130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Releases the DRM session 35140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * <p> 35150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * The player has to have an active DRM session and be in stopped, or prepared 35160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * state before this call is made. 35170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * A {@code reset()} call will release the DRM session implicitly. 35180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 35190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws NoDrmSchemeException if there is no active DRM session to release 35200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 35210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 35220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void releaseDrm() 35230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throws NoDrmSchemeException 35240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia { 352569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang addTask(new Task(CALL_COMPLETED_RELEASE_DRM, false) { 352669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang @Override 352769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang void process() throws NoDrmSchemeException { 352869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang synchronized (mDrmLock) { 352969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang Log.v(TAG, "releaseDrm:"); 353069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang 353169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang if (!mActiveDrmScheme) { 353269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang Log.e(TAG, "releaseDrm(): No active DRM scheme to release."); 353369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang throw new NoDrmSchemeExceptionImpl( 353469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang "releaseDrm: No active DRM scheme to release."); 353569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 35360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 353769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang try { 353869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang // we don't have the player's state in this layer. The below call raises 353969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang // exception if we're in a non-stopped/prepared state. 354069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang 354169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang // for cleaning native/mediaserver crypto object 354269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang _releaseDrm(); 354369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang 354469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang // for cleaning client-side MediaDrm object; only called if above has succeeded 354569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang cleanDrmObj(); 354669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang 354769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang mActiveDrmScheme = false; 354869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } catch (IllegalStateException e) { 354969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang Log.w(TAG, "releaseDrm: Exception ", e); 355069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang throw new IllegalStateException( 355169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang "releaseDrm: The player is not in a valid state."); 355269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } catch (Exception e) { 355369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang Log.e(TAG, "releaseDrm: Exception ", e); 355469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 355569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } // synchronized 35560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 355769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang }); 35580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 35590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 35600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 35610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 35620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * A key request/response exchange occurs between the app and a license server 35630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * to obtain or release keys used to decrypt encrypted content. 35640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * <p> 35651789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * getDrmKeyRequest() is used to obtain an opaque key request byte array that is 35660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * delivered to the license server. The opaque key request byte array is returned 35670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * in KeyRequest.data. The recommended URL to deliver the key request to is 35680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * returned in KeyRequest.defaultUrl. 35690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * <p> 35700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * After the app has received the key request response from the server, 35710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * it should deliver to the response to the DRM engine plugin using the method 35721789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * {@link #provideDrmKeyResponse}. 35730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 35740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param keySetId is the key-set identifier of the offline keys being released when keyType is 35750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * {@link MediaDrm#KEY_TYPE_RELEASE}. It should be set to null for other key requests, when 35760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * keyType is {@link MediaDrm#KEY_TYPE_STREAMING} or {@link MediaDrm#KEY_TYPE_OFFLINE}. 35770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 35780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param initData is the container-specific initialization data when the keyType is 35790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * {@link MediaDrm#KEY_TYPE_STREAMING} or {@link MediaDrm#KEY_TYPE_OFFLINE}. Its meaning is 35800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * interpreted based on the mime type provided in the mimeType parameter. It could 35810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * contain, for example, the content ID, key ID or other data obtained from the content 35820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * metadata that is required in generating the key request. 35830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * When the keyType is {@link MediaDrm#KEY_TYPE_RELEASE}, it should be set to null. 35840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 35850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param mimeType identifies the mime type of the content 35860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 35870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param keyType specifies the type of the request. The request may be to acquire 35880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * keys for streaming, {@link MediaDrm#KEY_TYPE_STREAMING}, or for offline content 35890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * {@link MediaDrm#KEY_TYPE_OFFLINE}, or to release previously acquired 35900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * keys ({@link MediaDrm#KEY_TYPE_RELEASE}), which are identified by a keySetId. 35910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 35920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param optionalParameters are included in the key request message to 35930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * allow a client application to provide additional message parameters to the server. 35940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * This may be {@code null} if no additional parameters are to be sent. 35950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 35960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws NoDrmSchemeException if there is no active DRM session 35970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 35980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 35990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @NonNull 36001789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public MediaDrm.KeyRequest getDrmKeyRequest(@Nullable byte[] keySetId, @Nullable byte[] initData, 36010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Nullable String mimeType, @MediaDrm.KeyType int keyType, 36020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Nullable Map<String, String> optionalParameters) 36030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throws NoDrmSchemeException 36040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia { 36051789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia Log.v(TAG, "getDrmKeyRequest: " + 36060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia " keySetId: " + keySetId + " initData:" + initData + " mimeType: " + mimeType + 36070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia " keyType: " + keyType + " optionalParameters: " + optionalParameters); 36080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 36090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mDrmLock) { 36100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (!mActiveDrmScheme) { 36111789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia Log.e(TAG, "getDrmKeyRequest NoDrmSchemeException"); 361269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang throw new NoDrmSchemeExceptionImpl( 361369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang "getDrmKeyRequest: Has to set a DRM scheme first."); 36140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 36150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 36160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 36170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia byte[] scope = (keyType != MediaDrm.KEY_TYPE_RELEASE) ? 36180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mDrmSessionId : // sessionId for KEY_TYPE_STREAMING/OFFLINE 36190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia keySetId; // keySetId for KEY_TYPE_RELEASE 36200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 36210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia HashMap<String, String> hmapOptionalParameters = 36220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia (optionalParameters != null) ? 36230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia new HashMap<String, String>(optionalParameters) : 36240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia null; 36250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 36260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia MediaDrm.KeyRequest request = mDrmObj.getKeyRequest(scope, initData, mimeType, 36270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia keyType, hmapOptionalParameters); 36281789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia Log.v(TAG, "getDrmKeyRequest: --> request: " + request); 36290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 36300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return request; 36310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 36320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (NotProvisionedException e) { 36331789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia Log.w(TAG, "getDrmKeyRequest NotProvisionedException: " + 36340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia "Unexpected. Shouldn't have reached here."); 36351789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia throw new IllegalStateException("getDrmKeyRequest: Unexpected provisioning error."); 36360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (Exception e) { 36371789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia Log.w(TAG, "getDrmKeyRequest Exception " + e); 36380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throw e; 36390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 36400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 36410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } // synchronized 36420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 36430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 36440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 36450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 36460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * A key response is received from the license server by the app, then it is 36471789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * provided to the DRM engine plugin using provideDrmKeyResponse. When the 36480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * response is for an offline key request, a key-set identifier is returned that 36490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * can be used to later restore the keys to a new session with the method 36501789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * {@ link # restoreDrmKeys}. 36510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * When the response is for a streaming or release request, null is returned. 36520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 36530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param keySetId When the response is for a release request, keySetId identifies 36540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * the saved key associated with the release request (i.e., the same keySetId 36551789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * passed to the earlier {@ link #getDrmKeyRequest} call. It MUST be null when the 36560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * response is for either streaming or offline key requests. 36570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 36580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param response the byte array response from the server 36590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 36600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws NoDrmSchemeException if there is no active DRM session 36610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @throws DeniedByServerException if the response indicates that the 36620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * server rejected the request 36630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 36640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 36651789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public byte[] provideDrmKeyResponse(@Nullable byte[] keySetId, @NonNull byte[] response) 36660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throws NoDrmSchemeException, DeniedByServerException 36670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia { 36681789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia Log.v(TAG, "provideDrmKeyResponse: keySetId: " + keySetId + " response: " + response); 36690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 36700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mDrmLock) { 36710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 36720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (!mActiveDrmScheme) { 36731789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia Log.e(TAG, "getDrmKeyRequest NoDrmSchemeException"); 367469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang throw new NoDrmSchemeExceptionImpl( 367569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang "getDrmKeyRequest: Has to set a DRM scheme first."); 36760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 36770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 36780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 36790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia byte[] scope = (keySetId == null) ? 36800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mDrmSessionId : // sessionId for KEY_TYPE_STREAMING/OFFLINE 36810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia keySetId; // keySetId for KEY_TYPE_RELEASE 36820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 36830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia byte[] keySetResult = mDrmObj.provideKeyResponse(scope, response); 36840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 368569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang Log.v(TAG, "provideDrmKeyResponse: keySetId: " + keySetId + " response: " + response 368669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang + " --> " + keySetResult); 36870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 36880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 36890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return keySetResult; 36900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 36910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (NotProvisionedException e) { 36921789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia Log.w(TAG, "provideDrmKeyResponse NotProvisionedException: " + 36930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia "Unexpected. Shouldn't have reached here."); 36941789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia throw new IllegalStateException("provideDrmKeyResponse: " + 36950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia "Unexpected provisioning error."); 36960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (Exception e) { 36971789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia Log.w(TAG, "provideDrmKeyResponse Exception " + e); 36980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throw e; 36990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 37000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } // synchronized 37010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 37020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 37030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 37040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 37050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Restore persisted offline keys into a new session. keySetId identifies the 37061789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia * keys to load, obtained from a prior call to {@link #provideDrmKeyResponse}. 37070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 37080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param keySetId identifies the saved key set to restore 37090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 37100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 37111789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia public void restoreDrmKeys(@NonNull byte[] keySetId) 37120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throws NoDrmSchemeException 37130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia { 371469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang addTask(new Task(CALL_COMPLETED_RESTORE_DRM_KEYS, false) { 371569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang @Override 371669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang void process() throws NoDrmSchemeException { 371769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang Log.v(TAG, "restoreDrmKeys: keySetId: " + keySetId); 37180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 371969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang synchronized (mDrmLock) { 37200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 372169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang if (!mActiveDrmScheme) { 372269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang Log.w(TAG, "restoreDrmKeys NoDrmSchemeException"); 372369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang throw new NoDrmSchemeExceptionImpl( 372469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang "restoreDrmKeys: Has to set a DRM scheme first."); 372569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 37260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 372769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang try { 372869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang mDrmObj.restoreKeys(mDrmSessionId, keySetId); 372969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } catch (Exception e) { 373069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang Log.w(TAG, "restoreKeys Exception " + e); 373169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang throw e; 373269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 37330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 373469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } // synchronized 373569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 373669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang }); 37370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 37380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 37390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 37400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 37410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Read a DRM engine plugin String property value, given the property name string. 37420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * <p> 37430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param propertyName the property name 37440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 37450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Standard fields names are: 37460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * {@link MediaDrm#PROPERTY_VENDOR}, {@link MediaDrm#PROPERTY_VERSION}, 37470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * {@link MediaDrm#PROPERTY_DESCRIPTION}, {@link MediaDrm#PROPERTY_ALGORITHMS} 37480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 37490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 37500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @NonNull 37510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public String getDrmPropertyString(@NonNull @MediaDrm.StringProperty String propertyName) 37520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throws NoDrmSchemeException 37530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia { 37540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.v(TAG, "getDrmPropertyString: propertyName: " + propertyName); 37550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 37560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia String value; 37570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mDrmLock) { 37580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 37590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (!mActiveDrmScheme && !mDrmConfigAllowed) { 37600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.w(TAG, "getDrmPropertyString NoDrmSchemeException"); 376169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang throw new NoDrmSchemeExceptionImpl( 376269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang "getDrmPropertyString: Has to prepareDrm() first."); 37630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 37640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 37650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 37660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia value = mDrmObj.getPropertyString(propertyName); 37670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (Exception e) { 37680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.w(TAG, "getDrmPropertyString Exception " + e); 37690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throw e; 37700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 37710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } // synchronized 37720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 37730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.v(TAG, "getDrmPropertyString: propertyName: " + propertyName + " --> value: " + value); 37740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 37750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return value; 37760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 37770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 37780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 37790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 37800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Set a DRM engine plugin String property value. 37810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * <p> 37820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param propertyName the property name 37830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * @param value the property value 37840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 37850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Standard fields names are: 37860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * {@link MediaDrm#PROPERTY_VENDOR}, {@link MediaDrm#PROPERTY_VERSION}, 37870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * {@link MediaDrm#PROPERTY_DESCRIPTION}, {@link MediaDrm#PROPERTY_ALGORITHMS} 37880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 37890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 37900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void setDrmPropertyString(@NonNull @MediaDrm.StringProperty String propertyName, 37910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @NonNull String value) 37920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throws NoDrmSchemeException 37930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia { 37940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.v(TAG, "setDrmPropertyString: propertyName: " + propertyName + " value: " + value); 37950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 37960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mDrmLock) { 37970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 37980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if ( !mActiveDrmScheme && !mDrmConfigAllowed ) { 37990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.w(TAG, "setDrmPropertyString NoDrmSchemeException"); 380069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang throw new NoDrmSchemeExceptionImpl( 380169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang "setDrmPropertyString: Has to prepareDrm() first."); 38020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 38030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 38040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 38050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mDrmObj.setPropertyString(propertyName, value); 38060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch ( Exception e ) { 38070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.w(TAG, "setDrmPropertyString Exception " + e); 38080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throw e; 38090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 38100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } // synchronized 38110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 38120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 38130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 38140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Encapsulates the DRM properties of the source. 38150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 38160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public static final class DrmInfoImpl extends DrmInfo { 38170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private Map<UUID, byte[]> mapPssh; 38180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private UUID[] supportedSchemes; 38190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 38200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 38210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Returns the PSSH info of the data source for each supported DRM scheme. 38220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 38230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 38240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public Map<UUID, byte[]> getPssh() { 38250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return mapPssh; 38260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 38270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 38280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 38290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Returns the intersection of the data source and the device DRM schemes. 38300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * It effectively identifies the subset of the source's DRM schemes which 38310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * are supported by the device too. 38320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 38330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 38340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public List<UUID> getSupportedSchemes() { 38350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return Arrays.asList(supportedSchemes); 38360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 38370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 38380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private DrmInfoImpl(Map<UUID, byte[]> Pssh, UUID[] SupportedSchemes) { 38390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mapPssh = Pssh; 38400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia supportedSchemes = SupportedSchemes; 38410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 38420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 38430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private DrmInfoImpl(Parcel parcel) { 38440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.v(TAG, "DrmInfoImpl(" + parcel + ") size " + parcel.dataSize()); 38450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 38460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia int psshsize = parcel.readInt(); 38470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia byte[] pssh = new byte[psshsize]; 38480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia parcel.readByteArray(pssh); 38490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 38500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.v(TAG, "DrmInfoImpl() PSSH: " + arrToHex(pssh)); 38510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mapPssh = parsePSSH(pssh, psshsize); 38520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.v(TAG, "DrmInfoImpl() PSSH: " + mapPssh); 38530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 38540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia int supportedDRMsCount = parcel.readInt(); 38550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia supportedSchemes = new UUID[supportedDRMsCount]; 38560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia for (int i = 0; i < supportedDRMsCount; i++) { 38570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia byte[] uuid = new byte[16]; 38580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia parcel.readByteArray(uuid); 38590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 38600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia supportedSchemes[i] = bytesToUUID(uuid); 38610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 38620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.v(TAG, "DrmInfoImpl() supportedScheme[" + i + "]: " + 38630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia supportedSchemes[i]); 38640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 38650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 38660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.v(TAG, "DrmInfoImpl() Parcel psshsize: " + psshsize + 38670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia " supportedDRMsCount: " + supportedDRMsCount); 38680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 38690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 38700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private DrmInfoImpl makeCopy() { 38710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return new DrmInfoImpl(this.mapPssh, this.supportedSchemes); 38720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 38730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 38740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private String arrToHex(byte[] bytes) { 38750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia String out = "0x"; 38760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia for (int i = 0; i < bytes.length; i++) { 38770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia out += String.format("%02x", bytes[i]); 38780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 38790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 38800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return out; 38810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 38820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 38830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private UUID bytesToUUID(byte[] uuid) { 38840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia long msb = 0, lsb = 0; 38850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia for (int i = 0; i < 8; i++) { 38860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia msb |= ( ((long)uuid[i] & 0xff) << (8 * (7 - i)) ); 38870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia lsb |= ( ((long)uuid[i+8] & 0xff) << (8 * (7 - i)) ); 38880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 38890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 38900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return new UUID(msb, lsb); 38910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 38920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 38930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private Map<UUID, byte[]> parsePSSH(byte[] pssh, int psshsize) { 38940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Map<UUID, byte[]> result = new HashMap<UUID, byte[]>(); 38950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 38960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final int UUID_SIZE = 16; 38970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final int DATALEN_SIZE = 4; 38980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 38990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia int len = psshsize; 39000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia int numentries = 0; 39010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia int i = 0; 39020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 39030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia while (len > 0) { 39040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (len < UUID_SIZE) { 39050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.w(TAG, String.format("parsePSSH: len is too short to parse " + 39060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia "UUID: (%d < 16) pssh: %d", len, psshsize)); 39070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return null; 39080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 39090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 39100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia byte[] subset = Arrays.copyOfRange(pssh, i, i + UUID_SIZE); 39110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia UUID uuid = bytesToUUID(subset); 39120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia i += UUID_SIZE; 39130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia len -= UUID_SIZE; 39140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 39150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // get data length 39160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (len < 4) { 39170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.w(TAG, String.format("parsePSSH: len is too short to parse " + 39180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia "datalen: (%d < 4) pssh: %d", len, psshsize)); 39190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return null; 39200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 39210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 39220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia subset = Arrays.copyOfRange(pssh, i, i+DATALEN_SIZE); 39230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia int datalen = (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) ? 39240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia ((subset[3] & 0xff) << 24) | ((subset[2] & 0xff) << 16) | 39250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia ((subset[1] & 0xff) << 8) | (subset[0] & 0xff) : 39260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia ((subset[0] & 0xff) << 24) | ((subset[1] & 0xff) << 16) | 39270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia ((subset[2] & 0xff) << 8) | (subset[3] & 0xff) ; 39280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia i += DATALEN_SIZE; 39290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia len -= DATALEN_SIZE; 39300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 39310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (len < datalen) { 39320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.w(TAG, String.format("parsePSSH: len is too short to parse " + 39330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia "data: (%d < %d) pssh: %d", len, datalen, psshsize)); 39340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return null; 39350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 39360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 39370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia byte[] data = Arrays.copyOfRange(pssh, i, i+datalen); 39380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 39390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // skip the data 39400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia i += datalen; 39410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia len -= datalen; 39420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 39430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.v(TAG, String.format("parsePSSH[%d]: <%s, %s> pssh: %d", 39440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia numentries, uuid, arrToHex(data), psshsize)); 39450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia numentries++; 39460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia result.put(uuid, data); 39470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 39480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 39490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return result; 39500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 39510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 39520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia }; // DrmInfoImpl 39530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 39540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 39550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Thrown when a DRM method is called before preparing a DRM scheme through prepareDrm(). 39560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Extends MediaDrm.MediaDrmException 39570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 39580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public static final class NoDrmSchemeExceptionImpl extends NoDrmSchemeException { 39590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public NoDrmSchemeExceptionImpl(String detailMessage) { 39600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia super(detailMessage); 39610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 39620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 39630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 39640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 39650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Thrown when the device requires DRM provisioning but the provisioning attempt has 39660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * failed due to a network error (Internet reachability, timeout, etc.). 39670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Extends MediaDrm.MediaDrmException 39680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 39690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public static final class ProvisioningNetworkErrorExceptionImpl 39700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia extends ProvisioningNetworkErrorException { 39710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public ProvisioningNetworkErrorExceptionImpl(String detailMessage) { 39720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia super(detailMessage); 39730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 39740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 39750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 39760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** 39770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Thrown when the device requires DRM provisioning but the provisioning attempt has 39780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * failed due to the provisioning server denying the request. 39790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Extends MediaDrm.MediaDrmException 39800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 39810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public static final class ProvisioningServerErrorExceptionImpl 39820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia extends ProvisioningServerErrorException { 39830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public ProvisioningServerErrorExceptionImpl(String detailMessage) { 39840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia super(detailMessage); 39850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 39860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 39870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 39880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 39890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private native void _prepareDrm(@NonNull byte[] uuid, @NonNull byte[] drmSessionId); 39900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 39910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // Modular DRM helpers 39920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 39930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private void prepareDrm_createDrmStep(@NonNull UUID uuid) 39940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throws UnsupportedSchemeException { 39950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.v(TAG, "prepareDrm_createDrmStep: UUID: " + uuid); 39960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 39970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 39980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mDrmObj = new MediaDrm(uuid); 39990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.v(TAG, "prepareDrm_createDrmStep: Created mDrmObj=" + mDrmObj); 40000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (Exception e) { // UnsupportedSchemeException 40010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.e(TAG, "prepareDrm_createDrmStep: MediaDrm failed with " + e); 40020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throw e; 40030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 40040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 40050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 40060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private void prepareDrm_openSessionStep(@NonNull UUID uuid) 40070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throws NotProvisionedException, ResourceBusyException { 40080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.v(TAG, "prepareDrm_openSessionStep: uuid: " + uuid); 40090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 40100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // TODO: don't need an open session for a future specialKeyReleaseDrm mode but we should do 40110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // it anyway so it raises provisioning error if needed. We'd rather handle provisioning 40121789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia // at prepareDrm/openSession rather than getDrmKeyRequest/provideDrmKeyResponse 40130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 40140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mDrmSessionId = mDrmObj.openSession(); 40150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.v(TAG, "prepareDrm_openSessionStep: mDrmSessionId=" + mDrmSessionId); 40160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 40170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // Sending it down to native/mediaserver to create the crypto object 40180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // This call could simply fail due to bad player state, e.g., after play(). 40190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia _prepareDrm(getByteArrayFromUUID(uuid), mDrmSessionId); 40200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.v(TAG, "prepareDrm_openSessionStep: _prepareDrm/Crypto succeeded"); 40210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 40220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (Exception e) { //ResourceBusyException, NotProvisionedException 40230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.e(TAG, "prepareDrm_openSessionStep: open/crypto failed with " + e); 40240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throw e; 40250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 40260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 40270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 40280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 40298e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon // Called from the native side 40308e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon @SuppressWarnings("unused") 40318e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon private static boolean setAudioOutputDeviceById(AudioTrack track, int deviceId) { 40328e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon if (track == null) { 40338e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon return false; 40348e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon } 40358e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon 40368e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon if (deviceId == 0) { 40378e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon // Use default routing. 40388e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon track.setPreferredDevice(null); 40398e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon return true; 40408e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon } 40418e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon 40428e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon // TODO: Unhide AudioManager.getDevicesStatic. 40438e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon AudioDeviceInfo[] outputDevices = 40448e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon AudioManager.getDevicesStatic(AudioManager.GET_DEVICES_OUTPUTS); 40458e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon 40468e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon boolean success = false; 40478e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon for (AudioDeviceInfo device : outputDevices) { 40488e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon if (device.getId() == deviceId) { 40498e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon track.setPreferredDevice(device); 40508e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon success = true; 40518e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon break; 40528e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon } 40538e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon } 40548e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon return success; 40558e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon } 40568e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon 40578e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon // Instantiated from the native side 40588e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon @SuppressWarnings("unused") 40598e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon private static class StreamEventCallback extends AudioTrack.StreamEventCallback { 40608e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon public long mJAudioTrackPtr; 40618e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon public long mNativeCallbackPtr; 40628e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon public long mUserDataPtr; 40638e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon 40648e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon public StreamEventCallback(long jAudioTrackPtr, long nativeCallbackPtr, long userDataPtr) { 40658e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon super(); 40668e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon mJAudioTrackPtr = jAudioTrackPtr; 40678e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon mNativeCallbackPtr = nativeCallbackPtr; 40688e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon mUserDataPtr = userDataPtr; 40698e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon } 40708e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon 40718e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon @Override 40728e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon public void onTearDown(AudioTrack track) { 40738e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon native_stream_event_onTearDown(mNativeCallbackPtr, mUserDataPtr); 40748e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon } 40758e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon 40768e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon @Override 40778e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon public void onStreamPresentationEnd(AudioTrack track) { 40788e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon native_stream_event_onStreamPresentationEnd(mNativeCallbackPtr, mUserDataPtr); 40798e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon } 40808e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon 40818e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon @Override 40828e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon public void onStreamDataRequest(AudioTrack track) { 40838e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon native_stream_event_onStreamDataRequest( 40848e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon mJAudioTrackPtr, mNativeCallbackPtr, mUserDataPtr); 40858e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon } 40868e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon } 40878e5ef909c789d4d8825cf775d90fa9aa251f10b4Hyundo Moon 40880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private class ProvisioningThread extends Thread { 40890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public static final int TIMEOUT_MS = 60000; 40900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 40910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private UUID uuid; 40920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private String urlStr; 40930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private Object drmLock; 40940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private MediaPlayer2Impl mediaPlayer; 40950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private int status; 40960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private boolean finished; 40970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public int status() { 40980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return status; 40990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 41000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 41010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public ProvisioningThread initialize(MediaDrm.ProvisionRequest request, 41020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia UUID uuid, MediaPlayer2Impl mediaPlayer) { 41030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // lock is held by the caller 41040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia drmLock = mediaPlayer.mDrmLock; 41050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia this.mediaPlayer = mediaPlayer; 41060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 41070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia urlStr = request.getDefaultUrl() + "&signedRequest=" + new String(request.getData()); 41080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia this.uuid = uuid; 41090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 41100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia status = PREPARE_DRM_STATUS_PREPARATION_ERROR; 41110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 41120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.v(TAG, "HandleProvisioninig: Thread is initialised url: " + urlStr); 41130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return this; 41140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 41150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 41160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void run() { 41170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 41180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia byte[] response = null; 41190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia boolean provisioningSucceeded = false; 41200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 41210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia URL url = new URL(urlStr); 41220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia final HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 41230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 41240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia connection.setRequestMethod("POST"); 41250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia connection.setDoOutput(false); 41260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia connection.setDoInput(true); 41270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia connection.setConnectTimeout(TIMEOUT_MS); 41280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia connection.setReadTimeout(TIMEOUT_MS); 41290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 41300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia connection.connect(); 41310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia response = Streams.readFully(connection.getInputStream()); 41320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 41330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.v(TAG, "HandleProvisioninig: Thread run: response " + 41340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia response.length + " " + response); 41350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (Exception e) { 41360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia status = PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR; 41370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.w(TAG, "HandleProvisioninig: Thread run: connect " + e + " url: " + url); 41380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } finally { 41390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia connection.disconnect(); 41400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 41410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (Exception e) { 41420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia status = PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR; 41430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.w(TAG, "HandleProvisioninig: Thread run: openConnection " + e); 41440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 41450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 41460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (response != null) { 41470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 41480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mDrmObj.provideProvisionResponse(response); 41490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.v(TAG, "HandleProvisioninig: Thread run: " + 41500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia "provideProvisionResponse SUCCEEDED!"); 41510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 41520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia provisioningSucceeded = true; 41530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (Exception e) { 41540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia status = PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR; 41550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.w(TAG, "HandleProvisioninig: Thread run: " + 41560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia "provideProvisionResponse " + e); 41570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 41580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 41590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 41600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia boolean succeeded = false; 41610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 416263f793f0f3e815c3a4895be7b02941d27d54159cWei Jia boolean hasCallback = false; 41630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mDrmEventCbLock) { 416463f793f0f3e815c3a4895be7b02941d27d54159cWei Jia hasCallback = !mDrmEventCallbackRecords.isEmpty(); 41650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 41660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // non-blocking mode needs the lock 416763f793f0f3e815c3a4895be7b02941d27d54159cWei Jia if (hasCallback) { 41680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 41690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (drmLock) { 41700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // continuing with prepareDrm 41710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (provisioningSucceeded) { 41720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia succeeded = mediaPlayer.resumePrepareDrm(uuid); 41730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia status = (succeeded) ? 41740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia PREPARE_DRM_STATUS_SUCCESS : 41750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia PREPARE_DRM_STATUS_PREPARATION_ERROR; 41760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 41770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mediaPlayer.mDrmProvisioningInProgress = false; 41780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mediaPlayer.mPrepareDrmInProgress = false; 41790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (!succeeded) { 41800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia cleanDrmObj(); // cleaning up if it hasn't gone through while in the lock 41810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 41820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } // synchronized 41830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 41840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // calling the callback outside the lock 418563f793f0f3e815c3a4895be7b02941d27d54159cWei Jia synchronized (mDrmEventCbLock) { 418663f793f0f3e815c3a4895be7b02941d27d54159cWei Jia for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) { 41871789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia cb.first.execute(() -> cb.second.onDrmPrepared( 41881789cc7f8221fd1f682fa08a1aeb1e37c2315887Wei Jia mediaPlayer, mCurrentDSD, status)); 418963f793f0f3e815c3a4895be7b02941d27d54159cWei Jia } 419063f793f0f3e815c3a4895be7b02941d27d54159cWei Jia } 41910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } else { // blocking mode already has the lock 41920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 41930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // continuing with prepareDrm 41940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (provisioningSucceeded) { 41950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia succeeded = mediaPlayer.resumePrepareDrm(uuid); 41960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia status = (succeeded) ? 41970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia PREPARE_DRM_STATUS_SUCCESS : 41980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia PREPARE_DRM_STATUS_PREPARATION_ERROR; 41990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 42000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mediaPlayer.mDrmProvisioningInProgress = false; 42010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mediaPlayer.mPrepareDrmInProgress = false; 42020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (!succeeded) { 42030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia cleanDrmObj(); // cleaning up if it hasn't gone through 42040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 42050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 42060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 42070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia finished = true; 42080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } // run() 42090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 42100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } // ProvisioningThread 42110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 42120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private int HandleProvisioninig(UUID uuid) { 42130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // the lock is already held by the caller 42140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 42150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mDrmProvisioningInProgress) { 42160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.e(TAG, "HandleProvisioninig: Unexpected mDrmProvisioningInProgress"); 42170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return PREPARE_DRM_STATUS_PREPARATION_ERROR; 42180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 42190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 42200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia MediaDrm.ProvisionRequest provReq = mDrmObj.getProvisionRequest(); 42210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (provReq == null) { 42220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.e(TAG, "HandleProvisioninig: getProvisionRequest returned null."); 42230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return PREPARE_DRM_STATUS_PREPARATION_ERROR; 42240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 42250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 42260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.v(TAG, "HandleProvisioninig provReq " + 42270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia " data: " + provReq.getData() + " url: " + provReq.getDefaultUrl()); 42280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 42290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // networking in a background thread 42300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mDrmProvisioningInProgress = true; 42310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 42320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mDrmProvisioningThread = new ProvisioningThread().initialize(provReq, uuid, this); 42330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mDrmProvisioningThread.start(); 42340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 42350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia int result; 42360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 42370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // non-blocking: this is not the final result 423863f793f0f3e815c3a4895be7b02941d27d54159cWei Jia boolean hasCallback = false; 42390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mDrmEventCbLock) { 424063f793f0f3e815c3a4895be7b02941d27d54159cWei Jia hasCallback = !mDrmEventCallbackRecords.isEmpty(); 42410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 424263f793f0f3e815c3a4895be7b02941d27d54159cWei Jia if (hasCallback) { 42430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia result = PREPARE_DRM_STATUS_SUCCESS; 42440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } else { 42450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // if blocking mode, wait till provisioning is done 42460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 42470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mDrmProvisioningThread.join(); 42480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (Exception e) { 42490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.w(TAG, "HandleProvisioninig: Thread.join Exception " + e); 42500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 42510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia result = mDrmProvisioningThread.status(); 42520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // no longer need the thread 42530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mDrmProvisioningThread = null; 42540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 42550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 42560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return result; 42570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 42580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 42590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private boolean resumePrepareDrm(UUID uuid) { 42600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.v(TAG, "resumePrepareDrm: uuid: " + uuid); 42610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 42620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // mDrmLock is guaranteed to be held 42630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia boolean success = false; 42640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 42650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // resuming 42660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia prepareDrm_openSessionStep(uuid); 42670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 42680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mDrmUUID = uuid; 42690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mActiveDrmScheme = true; 42700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 42710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia success = true; 42720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (Exception e) { 42730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.w(TAG, "HandleProvisioninig: Thread run _prepareDrm resume failed with " + e); 42740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // mDrmObj clean up is done by the caller 42750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 42760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 42770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return success; 42780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 42790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 42800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private void resetDrmState() { 42810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (mDrmLock) { 42820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.v(TAG, "resetDrmState: " + 42830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia " mDrmInfoImpl=" + mDrmInfoImpl + 42840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia " mDrmProvisioningThread=" + mDrmProvisioningThread + 42850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia " mPrepareDrmInProgress=" + mPrepareDrmInProgress + 42860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia " mActiveDrmScheme=" + mActiveDrmScheme); 42870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 42880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mDrmInfoResolved = false; 42890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mDrmInfoImpl = null; 42900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 42910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mDrmProvisioningThread != null) { 42920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // timeout; relying on HttpUrlConnection 42930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 42940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mDrmProvisioningThread.join(); 42950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 42960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia catch (InterruptedException e) { 42970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.w(TAG, "resetDrmState: ProvThread.join Exception " + e); 42980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 42990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mDrmProvisioningThread = null; 43000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 43010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 43020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mPrepareDrmInProgress = false; 43030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mActiveDrmScheme = false; 43040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 43050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia cleanDrmObj(); 43060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } // synchronized 43070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 43080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 43090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private void cleanDrmObj() { 43100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // the caller holds mDrmLock 43110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.v(TAG, "cleanDrmObj: mDrmObj=" + mDrmObj + " mDrmSessionId=" + mDrmSessionId); 43120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 43130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mDrmSessionId != null) { 43140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mDrmObj.closeSession(mDrmSessionId); 43150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mDrmSessionId = null; 43160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 43170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mDrmObj != null) { 43180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mDrmObj.release(); 43190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mDrmObj = null; 43200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 43210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 43220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 43230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static final byte[] getByteArrayFromUUID(@NonNull UUID uuid) { 43240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia long msb = uuid.getMostSignificantBits(); 43250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia long lsb = uuid.getLeastSignificantBits(); 43260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 43270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia byte[] uuidBytes = new byte[16]; 43280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia for (int i = 0; i < 8; ++i) { 43290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia uuidBytes[i] = (byte)(msb >>> (8 * (7 - i))); 43300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia uuidBytes[8 + i] = (byte)(lsb >>> (8 * (7 - i))); 43310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 43320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 43330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return uuidBytes; 43340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 43350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 43360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // Modular DRM end 43370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 43380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /* 43390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Test whether a given video scaling mode is supported. 43400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 43410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private boolean isVideoScalingModeSupported(int mode) { 43420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return (mode == VIDEO_SCALING_MODE_SCALE_TO_FIT || 43430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mode == VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING); 43440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 43450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 43460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** @hide */ 43470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia static class TimeProvider implements MediaTimeProvider { 43480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static final String TAG = "MTP"; 43490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static final long MAX_NS_WITHOUT_POSITION_CHECK = 5000000000L; 43500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static final long MAX_EARLY_CALLBACK_US = 1000; 43510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static final long TIME_ADJUSTMENT_RATE = 2; /* meaning 1/2 */ 43520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private long mLastTimeUs = 0; 43530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private MediaPlayer2Impl mPlayer; 43540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private boolean mPaused = true; 43550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private boolean mStopped = true; 43560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private boolean mBuffering; 43570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private long mLastReportedTime; 43580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // since we are expecting only a handful listeners per stream, there is 43590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // no need for log(N) search performance 43600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private MediaTimeProvider.OnMediaTimeListener mListeners[]; 43610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private long mTimes[]; 436234c5bb126b8cc85176645acea841c796a3cc0292Wei Jia private EventHandler mEventHandler; 43630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private boolean mRefresh = false; 43640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private boolean mPausing = false; 43650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private boolean mSeeking = false; 43660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static final int NOTIFY = 1; 43670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static final int NOTIFY_TIME = 0; 43680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static final int NOTIFY_STOP = 2; 43690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static final int NOTIFY_SEEK = 3; 43700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private static final int NOTIFY_TRACK_DATA = 4; 43710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private HandlerThread mHandlerThread; 43720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 43730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** @hide */ 43740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public boolean DEBUG = false; 43750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 43760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public TimeProvider(MediaPlayer2Impl mp) { 43770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mPlayer = mp; 43780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 43790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia getCurrentTimeUs(true, false); 43800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (IllegalStateException e) { 43810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // we assume starting position 43820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mRefresh = true; 43830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 43840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 43850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Looper looper; 43860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if ((looper = Looper.myLooper()) == null && 43870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia (looper = Looper.getMainLooper()) == null) { 43880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // Create our own looper here in case MP was created without one 43890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mHandlerThread = new HandlerThread("MediaPlayer2MTPEventThread", 43900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Process.THREAD_PRIORITY_FOREGROUND); 43910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mHandlerThread.start(); 43920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia looper = mHandlerThread.getLooper(); 43930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 43940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mEventHandler = new EventHandler(looper); 43950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 43960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mListeners = new MediaTimeProvider.OnMediaTimeListener[0]; 43970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mTimes = new long[0]; 43980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mLastTimeUs = 0; 43990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 44000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 44010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private void scheduleNotification(int type, long delayUs) { 44020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // ignore time notifications until seek is handled 44030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mSeeking && type == NOTIFY_TIME) { 44040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 44050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 44060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 44070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (DEBUG) Log.v(TAG, "scheduleNotification " + type + " in " + delayUs); 44080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mEventHandler.removeMessages(NOTIFY); 44090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Message msg = mEventHandler.obtainMessage(NOTIFY, type, 0); 44100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mEventHandler.sendMessageDelayed(msg, (int) (delayUs / 1000)); 44110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 44120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 44130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** @hide */ 44140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void close() { 44150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mEventHandler.removeMessages(NOTIFY); 44160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mHandlerThread != null) { 44170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mHandlerThread.quitSafely(); 44180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mHandlerThread = null; 44190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 44200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 44210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 44220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** @hide */ 44230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia protected void finalize() { 44240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mHandlerThread != null) { 44250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mHandlerThread.quitSafely(); 44260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 44270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 44280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 44290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** @hide */ 44300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void onNotifyTime() { 44310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (this) { 44320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (DEBUG) Log.d(TAG, "onNotifyTime: "); 44330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia scheduleNotification(NOTIFY_TIME, 0 /* delay */); 44340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 44350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 44360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 44370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** @hide */ 44380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void onPaused(boolean paused) { 44390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized(this) { 44400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (DEBUG) Log.d(TAG, "onPaused: " + paused); 44410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mStopped) { // handle as seek if we were stopped 44420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mStopped = false; 44430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mSeeking = true; 44440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia scheduleNotification(NOTIFY_SEEK, 0 /* delay */); 44450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } else { 44460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mPausing = paused; // special handling if player disappeared 44470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mSeeking = false; 44480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia scheduleNotification(NOTIFY_TIME, 0 /* delay */); 44490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 44500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 44510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 44520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 44530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** @hide */ 44540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void onBuffering(boolean buffering) { 44550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (this) { 44560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (DEBUG) Log.d(TAG, "onBuffering: " + buffering); 44570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mBuffering = buffering; 44580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia scheduleNotification(NOTIFY_TIME, 0 /* delay */); 44590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 44600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 44610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 44620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** @hide */ 44630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void onStopped() { 44640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized(this) { 44650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (DEBUG) Log.d(TAG, "onStopped"); 44660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mPaused = true; 44670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mStopped = true; 44680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mSeeking = false; 44690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mBuffering = false; 44700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia scheduleNotification(NOTIFY_STOP, 0 /* delay */); 44710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 44720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 44730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 44740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** @hide */ 44750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void onSeekComplete(MediaPlayer2Impl mp) { 44760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized(this) { 44770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mStopped = false; 44780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mSeeking = true; 44790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia scheduleNotification(NOTIFY_SEEK, 0 /* delay */); 44800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 44810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 44820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 44830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /** @hide */ 44840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void onNewPlayer() { 44850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mRefresh) { 44860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized(this) { 44870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mStopped = false; 44880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mSeeking = true; 44890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mBuffering = false; 44900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia scheduleNotification(NOTIFY_SEEK, 0 /* delay */); 44910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 44920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 44930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 44940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 44950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private synchronized void notifySeek() { 44960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mSeeking = false; 44970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 44980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia long timeUs = getCurrentTimeUs(true, false); 44990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (DEBUG) Log.d(TAG, "onSeekComplete at " + timeUs); 45000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 45010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia for (MediaTimeProvider.OnMediaTimeListener listener: mListeners) { 45020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (listener == null) { 45030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 45040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 45050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia listener.onSeek(timeUs); 45060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 45070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (IllegalStateException e) { 45080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // we should not be there, but at least signal pause 45090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (DEBUG) Log.d(TAG, "onSeekComplete but no player"); 45100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mPausing = true; // special handling if player disappeared 45110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia notifyTimedEvent(false /* refreshTime */); 45120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 45130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 45140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 45150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private synchronized void notifyTrackData(Pair<SubtitleTrack, byte[]> trackData) { 45160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia SubtitleTrack track = trackData.first; 45170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia byte[] data = trackData.second; 45180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia track.onData(data, true /* eos */, ~0 /* runID: keep forever */); 45190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 45200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 45210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private synchronized void notifyStop() { 45220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia for (MediaTimeProvider.OnMediaTimeListener listener: mListeners) { 45230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (listener == null) { 45240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 45250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 45260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia listener.onStop(); 45270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 45280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 45290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 45300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private int registerListener(MediaTimeProvider.OnMediaTimeListener listener) { 45310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia int i = 0; 45320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia for (; i < mListeners.length; i++) { 45330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mListeners[i] == listener || mListeners[i] == null) { 45340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 45350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 45360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 45370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 45380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // new listener 45390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (i >= mListeners.length) { 45400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia MediaTimeProvider.OnMediaTimeListener[] newListeners = 45410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia new MediaTimeProvider.OnMediaTimeListener[i + 1]; 45420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia long[] newTimes = new long[i + 1]; 45430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia System.arraycopy(mListeners, 0, newListeners, 0, mListeners.length); 45440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia System.arraycopy(mTimes, 0, newTimes, 0, mTimes.length); 45450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mListeners = newListeners; 45460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mTimes = newTimes; 45470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 45480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 45490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mListeners[i] == null) { 45500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mListeners[i] = listener; 45510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mTimes[i] = MediaTimeProvider.NO_TIME; 45520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 45530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return i; 45540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 45550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 45560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void notifyAt( 45570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia long timeUs, MediaTimeProvider.OnMediaTimeListener listener) { 45580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized(this) { 45590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (DEBUG) Log.d(TAG, "notifyAt " + timeUs); 45600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mTimes[registerListener(listener)] = timeUs; 45610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia scheduleNotification(NOTIFY_TIME, 0 /* delay */); 45620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 45630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 45640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 45650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void scheduleUpdate(MediaTimeProvider.OnMediaTimeListener listener) { 45660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized(this) { 45670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (DEBUG) Log.d(TAG, "scheduleUpdate"); 45680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia int i = registerListener(listener); 45690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 45700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (!mStopped) { 45710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mTimes[i] = 0; 45720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia scheduleNotification(NOTIFY_TIME, 0 /* delay */); 45730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 45740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 45750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 45760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 45770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void cancelNotifications( 45780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia MediaTimeProvider.OnMediaTimeListener listener) { 45790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized(this) { 45800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia int i = 0; 45810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia for (; i < mListeners.length; i++) { 45820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mListeners[i] == listener) { 45830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia System.arraycopy(mListeners, i + 1, 45840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mListeners, i, mListeners.length - i - 1); 45850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia System.arraycopy(mTimes, i + 1, 45860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mTimes, i, mTimes.length - i - 1); 45870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mListeners[mListeners.length - 1] = null; 45880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mTimes[mTimes.length - 1] = NO_TIME; 45890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 45900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } else if (mListeners[i] == null) { 45910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 45920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 45930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 45940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 45950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia scheduleNotification(NOTIFY_TIME, 0 /* delay */); 45960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 45970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 45980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 45990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private synchronized void notifyTimedEvent(boolean refreshTime) { 46000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // figure out next callback 46010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia long nowUs; 46020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 46030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia nowUs = getCurrentTimeUs(refreshTime, true); 46040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (IllegalStateException e) { 46050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // assume we paused until new player arrives 46060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mRefresh = true; 46070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mPausing = true; // this ensures that call succeeds 46080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia nowUs = getCurrentTimeUs(refreshTime, true); 46090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 46100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia long nextTimeUs = nowUs; 46110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 46120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mSeeking) { 46130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // skip timed-event notifications until seek is complete 46140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return; 46150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 46160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 46170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (DEBUG) { 46180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia StringBuilder sb = new StringBuilder(); 46190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia sb.append("notifyTimedEvent(").append(mLastTimeUs).append(" -> ") 46200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia .append(nowUs).append(") from {"); 46210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia boolean first = true; 46220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia for (long time: mTimes) { 46230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (time == NO_TIME) { 46240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia continue; 46250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 46260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (!first) sb.append(", "); 46270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia sb.append(time); 46280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia first = false; 46290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 46300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia sb.append("}"); 46310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Log.d(TAG, sb.toString()); 46320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 46330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 46340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Vector<MediaTimeProvider.OnMediaTimeListener> activatedListeners = 46350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia new Vector<MediaTimeProvider.OnMediaTimeListener>(); 46360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia for (int ix = 0; ix < mTimes.length; ix++) { 46370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mListeners[ix] == null) { 46380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 46390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 46400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mTimes[ix] <= NO_TIME) { 46410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // ignore, unless we were stopped 46420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } else if (mTimes[ix] <= nowUs + MAX_EARLY_CALLBACK_US) { 46430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia activatedListeners.add(mListeners[ix]); 46440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (DEBUG) Log.d(TAG, "removed"); 46450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mTimes[ix] = NO_TIME; 46460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } else if (nextTimeUs == nowUs || mTimes[ix] < nextTimeUs) { 46470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia nextTimeUs = mTimes[ix]; 46480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 46490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 46500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 46510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (nextTimeUs > nowUs && !mPaused) { 46520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // schedule callback at nextTimeUs 46530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (DEBUG) Log.d(TAG, "scheduling for " + nextTimeUs + " and " + nowUs); 46540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mPlayer.notifyAt(nextTimeUs); 46550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } else { 46560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mEventHandler.removeMessages(NOTIFY); 46570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // no more callbacks 46580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 46590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 46600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia for (MediaTimeProvider.OnMediaTimeListener listener: activatedListeners) { 46610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia listener.onTimedEvent(nowUs); 46620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 46630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 46640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 46650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public long getCurrentTimeUs(boolean refreshTime, boolean monotonic) 46660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throws IllegalStateException { 46670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia synchronized (this) { 46680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // we always refresh the time when the paused-state changes, because 46690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // we expect to have received the pause-change event delayed. 46700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mPaused && !refreshTime) { 46710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return mLastReportedTime; 46720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 46730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 46740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia try { 46750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mLastTimeUs = mPlayer.getCurrentPosition() * 1000L; 46760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mPaused = !mPlayer.isPlaying() || mBuffering; 46770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (DEBUG) Log.v(TAG, (mPaused ? "paused" : "playing") + " at " + mLastTimeUs); 46780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } catch (IllegalStateException e) { 46790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mPausing) { 46800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // if we were pausing, get last estimated timestamp 46810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mPausing = false; 46820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (!monotonic || mLastReportedTime < mLastTimeUs) { 46830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mLastReportedTime = mLastTimeUs; 46840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 46850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mPaused = true; 46860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (DEBUG) Log.d(TAG, "illegal state, but pausing: estimating at " + mLastReportedTime); 46870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return mLastReportedTime; 46880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 46890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // TODO get time when prepared 46900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia throw e; 46910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 46920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (monotonic && mLastTimeUs < mLastReportedTime) { 46930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia /* have to adjust time */ 46940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mLastReportedTime - mLastTimeUs > 1000000) { 46950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // schedule seeked event if time jumped significantly 46960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // TODO: do this properly by introducing an exception 46970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mStopped = false; 46980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mSeeking = true; 46990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia scheduleNotification(NOTIFY_SEEK, 0 /* delay */); 47000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 47010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } else { 47020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mLastReportedTime = mLastTimeUs; 47030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 47040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 47050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return mLastReportedTime; 47060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 47070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 47080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 47090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia private class EventHandler extends Handler { 47100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public EventHandler(Looper looper) { 47110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia super(looper); 47120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 47130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 47140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia @Override 47150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia public void handleMessage(Message msg) { 47160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (msg.what == NOTIFY) { 47170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia switch (msg.arg1) { 47180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case NOTIFY_TIME: 47190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia notifyTimedEvent(true /* refreshTime */); 47200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 47210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case NOTIFY_STOP: 47220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia notifyStop(); 47230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 47240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case NOTIFY_SEEK: 47250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia notifySeek(); 47260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 47270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia case NOTIFY_TRACK_DATA: 47280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia notifyTrackData((Pair<SubtitleTrack, byte[]>)msg.obj); 47290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia break; 47300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 47310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 47320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 47330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 47340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 4735adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang 4736adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang private abstract class Task implements Runnable { 4737adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang private final int mMediaCallType; 4738adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang private final boolean mNeedToWaitForEventToComplete; 473969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang private DataSourceDesc mDSD; 4740adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang 4741adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang public Task (int mediaCallType, boolean needToWaitForEventToComplete) { 4742adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang mMediaCallType = mediaCallType; 4743adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang mNeedToWaitForEventToComplete = needToWaitForEventToComplete; 4744adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang } 4745adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang 474669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang abstract void process() throws IOException, NoDrmSchemeException; 4747adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang 4748adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang @Override 4749adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang public void run() { 475069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang int status = CALL_STATUS_NO_ERROR; 475169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang try { 475269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang process(); 475369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } catch (IllegalStateException e) { 475469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang status = CALL_STATUS_INVALID_OPERATION; 475569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } catch (IllegalArgumentException e) { 475669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang status = CALL_STATUS_BAD_VALUE; 475769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } catch (SecurityException e) { 475869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang status = CALL_STATUS_PERMISSION_DENIED; 475969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } catch (IOException e) { 476069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang status = CALL_STATUS_ERROR_IO; 476169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } catch (NoDrmSchemeException e) { 476269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang status = CALL_STATUS_NO_DRM_SCHEME; 476369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } catch (Exception e) { 476469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang status = CALL_STATUS_ERROR_UNKNOWN; 476569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 476669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang synchronized (mSrcLock) { 476769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang mDSD = mCurrentDSD; 476869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 476969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang 477069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang // TODO: Make native implementations asynchronous and let them send notifications. 477169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang if (!mNeedToWaitForEventToComplete || status != CALL_STATUS_NO_ERROR) { 477269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang 477369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang sendCompleteNotification(status); 4774adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang 4775adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang synchronized (mTaskLock) { 4776adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang mCurrentTask = null; 4777adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang processPendingTask_l(); 4778adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang } 4779adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang } 4780adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang } 478169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang 478269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang private void sendCompleteNotification(int status) { 478369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang // In {@link #notifyWhenCommandLabelReached} case, a separate callback 478469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang // {#link #onCommandLabelReached} is already called in {@code process()}. 478569d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang if (mMediaCallType == CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED) { 478669d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang return; 478769d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 478869d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang synchronized (mEventCbLock) { 478969d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) { 479069d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang cb.first.execute(() -> cb.second.onCallCompleted( 479169d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang MediaPlayer2Impl.this, mDSD, mMediaCallType, status)); 479269d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 479369d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 479469d2d51a59ecb30742673fbe56b68397185a08c5Dongwon Kang } 4795adf77a01e8142a5abb496997beddead7b48f43b7Dongwon Kang }; 47960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia} 4797