/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.media.cts;

import android.media.MediaDrm;
import android.media.MediaDrm.CryptoSession;
import android.media.MediaDrm.KeyRequest;
import android.media.MediaDrm.KeyStatus;
import android.media.MediaDrm.ProvisionRequest;
import android.media.MediaDrmException;
import android.media.NotProvisionedException;
import android.media.ResourceBusyException;
import android.test.AndroidTestCase;
import android.util.Log;
import java.util.HashMap;
import java.util.Arrays;
import java.util.List;
import java.util.Iterator;
import java.util.UUID;
import java.lang.Thread;
import java.lang.Object;
import android.os.Looper;

// This test works with the MediaDrm mock plugin
public class MediaDrmMockTest extends AndroidTestCase {
    private static final String TAG = "MediaDrmMockTest";

    // The scheme supported by the mock drm plugin
    static final UUID mockScheme = new UUID(0x0102030405060708L, 0x090a0b0c0d0e0f10L);
    static final UUID badScheme = new UUID(0xffffffffffffffffL, 0xffffffffffffffffL);

    private boolean isMockPluginInstalled() {
        return MediaDrm.isCryptoSchemeSupported(mockScheme);
    }

    public void testIsCryptoSchemeNotSupported() throws Exception {
        assertFalse(MediaDrm.isCryptoSchemeSupported(badScheme));
    }

    public void testMediaDrmConstructor() throws Exception {
        if (isMockPluginInstalled()) {
            MediaDrm md = new MediaDrm(mockScheme);
        } else {
            Log.w(TAG, "optional plugin libmockdrmcryptoplugin.so is not installed");
            Log.w(TAG, "To verify the MediaDrm APIs, you should install this plugin");
        }
    }

    public void testIsMimeTypeSupported() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }
        String mimeType = "video/mp4";
        assertTrue(MediaDrm.isCryptoSchemeSupported(mockScheme, mimeType));
    }

    public void testIsMimeTypeNotSupported() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }
        String mimeType = "video/foo";
        assertFalse(MediaDrm.isCryptoSchemeSupported(mockScheme, mimeType));
    }

    public void testMediaDrmConstructorFails() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        boolean gotException = false;
        try {
            MediaDrm md = new MediaDrm(badScheme);
        } catch (MediaDrmException e) {
            gotException = true;
        }
        assertTrue(gotException);
    }

    public void testStringProperties() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        MediaDrm md = new MediaDrm(mockScheme);

        md.setPropertyString("test-string", "test-value");
        assertTrue(md.getPropertyString("test-string").equals("test-value"));
    }

    public void testByteArrayProperties() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        MediaDrm md = new MediaDrm(mockScheme);

        byte testArray[] = {0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x12};
        md.setPropertyByteArray("test-array", testArray);
        assertTrue(Arrays.equals(md.getPropertyByteArray("test-array"), testArray));
    }

    public void testMissingPropertyString() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        MediaDrm md = new MediaDrm(mockScheme);

        boolean gotException = false;
        try {
            md.getPropertyString("missing-property");
        } catch (IllegalArgumentException e) {
            gotException = true;
        }
        assertTrue(gotException);
    }

    public void testNullPropertyString() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        MediaDrm md = new MediaDrm(mockScheme);

        boolean gotException = false;
        try {
            md.getPropertyString(null);
        } catch (IllegalArgumentException e) {
            gotException = true;
        }
        assertTrue(gotException);
    }

    public void testMissingPropertyByteArray() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        MediaDrm md = new MediaDrm(mockScheme);

        boolean gotException = false;
        try {
            md.getPropertyByteArray("missing-property");
        } catch (IllegalArgumentException e) {
            gotException = true;
        }
        assertTrue(gotException);
    }

    public void testNullPropertyByteArray() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        MediaDrm md = new MediaDrm(mockScheme);

        boolean gotException = false;
        try {
            md.getPropertyByteArray(null);
        } catch (IllegalArgumentException e) {
            gotException = true;
        }
        assertTrue(gotException);
    }

    public void testOpenCloseSession() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        MediaDrm md = new MediaDrm(mockScheme);
        byte[] sessionId = openSession(md);
        md.closeSession(sessionId);
    }

    public void testBadSession() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        MediaDrm md = new MediaDrm(mockScheme);
        byte[] sessionId = {0x05, 0x6, 0x7, 0x8};
        boolean gotException = false;
        try {
            md.closeSession(sessionId);
        } catch (IllegalArgumentException e) {
            gotException = true;
        }
        assertTrue(gotException);
    }

    public void testNullSession() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        MediaDrm md = new MediaDrm(mockScheme);
        byte[] sessionId = null;
        boolean gotException = false;
        try {
            md.closeSession(sessionId);
        } catch (IllegalArgumentException e) {
            gotException = true;
        }
        assertTrue(gotException);
    }

    public void testGetKeyRequest() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        MediaDrm md = new MediaDrm(mockScheme);
        byte[] sessionId = openSession(md);

        // Set up mock expected responses using properties
        byte testRequest[] = {0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x12};
        md.setPropertyByteArray("mock-request", testRequest);
        String testDefaultUrl = "http://1.2.3.4:8080/blah";
        md.setPropertyString("mock-defaultUrl", testDefaultUrl);
        md.setPropertyString("mock-keyRequestType", "1" /*kKeyRequestType_Initial*/);

        byte[] initData = {0x0a, 0x0b, 0x0c, 0x0d};
        HashMap<String, String> optionalParameters = new HashMap<String, String>();
        optionalParameters.put("param1", "value1");
        optionalParameters.put("param2", "value2");

        String mimeType = "video/iso.segment";
        KeyRequest request = md.getKeyRequest(sessionId, initData, mimeType,
                                                      MediaDrm.KEY_TYPE_STREAMING,
                                                      optionalParameters);
        assertTrue(Arrays.equals(request.getData(), testRequest));
        assertTrue(request.getDefaultUrl().equals(testDefaultUrl));
        assertEquals(request.getRequestType(), MediaDrm.KeyRequest.REQUEST_TYPE_INITIAL);

        assertTrue(Arrays.equals(initData, md.getPropertyByteArray("mock-initdata")));
        assertTrue(mimeType.equals(md.getPropertyString("mock-mimetype")));
        assertTrue(md.getPropertyString("mock-keytype").equals("1"));
        assertTrue(md.getPropertyString("mock-optparams").equals("{param1,value1},{param2,value2}"));

        md.closeSession(sessionId);
    }

    public void testGetKeyRequestNoOptionalParameters() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        MediaDrm md = new MediaDrm(mockScheme);
        byte[] sessionId = openSession(md);

        // Set up mock expected responses using properties
        byte testRequest[] = {0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x12};
        md.setPropertyByteArray("mock-request", testRequest);
        String testDefaultUrl = "http://1.2.3.4:8080/blah";
        md.setPropertyString("mock-defaultUrl", testDefaultUrl);
        md.setPropertyString("mock-keyRequestType", "1" /*kKeyRequestType_Initial*/);

        byte[] initData = {0x0a, 0x0b, 0x0c, 0x0d};

        String mimeType = "video/iso.segment";
        KeyRequest request = md.getKeyRequest(sessionId, initData, mimeType,
                                                      MediaDrm.KEY_TYPE_STREAMING,
                                                      null);
        assertTrue(Arrays.equals(request.getData(), testRequest));
        assertTrue(request.getDefaultUrl().equals(testDefaultUrl));
        assertEquals(request.getRequestType(), MediaDrm.KeyRequest.REQUEST_TYPE_INITIAL);

        assertTrue(Arrays.equals(initData, md.getPropertyByteArray("mock-initdata")));
        assertTrue(mimeType.equals(md.getPropertyString("mock-mimetype")));
        assertTrue(md.getPropertyString("mock-keytype").equals("1"));

        md.closeSession(sessionId);
    }

    public void testGetKeyRequestOffline() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        MediaDrm md = new MediaDrm(mockScheme);
        byte[] sessionId = openSession(md);

        // Set up mock expected responses using properties
        byte testRequest[] = {0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x12};
        md.setPropertyByteArray("mock-request", testRequest);
        String testDefaultUrl = "http://1.2.3.4:8080/blah";
        md.setPropertyString("mock-defaultUrl", testDefaultUrl);
        md.setPropertyString("mock-keyRequestType", "2" /*kKeyRequestType_Renewal*/);

        byte[] initData = {0x0a, 0x0b, 0x0c, 0x0d};

        String mimeType = "video/iso.segment";
        KeyRequest request = md.getKeyRequest(sessionId, initData, mimeType,
                                              MediaDrm.KEY_TYPE_OFFLINE,
                                              null);
        assertTrue(Arrays.equals(request.getData(), testRequest));
        assertTrue(request.getDefaultUrl().equals(testDefaultUrl));
        assertEquals(request.getRequestType(), MediaDrm.KeyRequest.REQUEST_TYPE_RENEWAL);

        assertTrue(Arrays.equals(initData, md.getPropertyByteArray("mock-initdata")));
        assertTrue(mimeType.equals(md.getPropertyString("mock-mimetype")));
        assertTrue(md.getPropertyString("mock-keytype").equals("0"));

        md.closeSession(sessionId);
    }

    public void testGetKeyRequestRelease() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        MediaDrm md = new MediaDrm(mockScheme);
        byte[] sessionId = openSession(md);

        // Set up mock expected responses using properties
        byte testRequest[] = {0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x12};
        md.setPropertyByteArray("mock-request", testRequest);
        String testDefaultUrl = "http://1.2.3.4:8080/blah";
        md.setPropertyString("mock-defaultUrl", testDefaultUrl);
        md.setPropertyString("mock-keyRequestType", "3" /*kKeyRequestType_Release*/);

        String mimeType = "video/iso.segment";
        KeyRequest request = md.getKeyRequest(sessionId, null, mimeType,
                                              MediaDrm.KEY_TYPE_RELEASE,
                                              null);
        assertTrue(Arrays.equals(request.getData(), testRequest));
        assertTrue(request.getDefaultUrl().equals(testDefaultUrl));
        assertEquals(request.getRequestType(), MediaDrm.KeyRequest.REQUEST_TYPE_RELEASE);

        assertTrue(mimeType.equals(md.getPropertyString("mock-mimetype")));
        assertTrue(md.getPropertyString("mock-keytype").equals("2"));

        md.closeSession(sessionId);
    }

    public void testProvideKeyResponse() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        MediaDrm md = new MediaDrm(mockScheme);
        byte[] sessionId = openSession(md);

        // Set up mock expected responses using properties
        byte testResponse[] = {0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20};

        md.provideKeyResponse(sessionId, testResponse);

        assertTrue(Arrays.equals(testResponse, md.getPropertyByteArray("mock-response")));
        md.closeSession(sessionId);
    }

    public void testRemoveKeys() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        MediaDrm md = new MediaDrm(mockScheme);
        byte[] sessionId = openSession(md);

        byte testResponse[] = {0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20};
        byte[] keySetId = md.provideKeyResponse(sessionId, testResponse);
        md.closeSession(sessionId);

        md.removeKeys(keySetId);
    }

    public void testRestoreKeys() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        MediaDrm md = new MediaDrm(mockScheme);
        byte[] sessionId = openSession(md);

        byte testResponse[] = {0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20};
        byte[] keySetId = md.provideKeyResponse(sessionId, testResponse);
        md.closeSession(sessionId);

        sessionId = openSession(md);
        md.restoreKeys(sessionId, keySetId);
        md.closeSession(sessionId);
    }

    public void testQueryKeyStatus() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        MediaDrm md = new MediaDrm(mockScheme);
        byte[] sessionId = openSession(md);
        HashMap<String, String> infoMap = md.queryKeyStatus(sessionId);

        // these are canned strings returned by the mock
        assertTrue(infoMap.containsKey("purchaseDuration"));
        assertTrue(infoMap.get("purchaseDuration").equals(("1000")));
        assertTrue(infoMap.containsKey("licenseDuration"));
        assertTrue(infoMap.get("licenseDuration").equals(("100")));

        md.closeSession(sessionId);
    }

    public void testGetProvisionRequest() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        MediaDrm md = new MediaDrm(mockScheme);

        // Set up mock expected responses using properties
        byte testRequest[] = {0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x60, 0x61, 0x62};
        md.setPropertyByteArray("mock-request", testRequest);
        String testDefaultUrl = "http://1.2.3.4:8080/bar";
        md.setPropertyString("mock-defaultUrl", testDefaultUrl);

        ProvisionRequest request = md.getProvisionRequest();
        assertTrue(Arrays.equals(request.getData(), testRequest));
        assertTrue(request.getDefaultUrl().equals(testDefaultUrl));
    }

    public void testProvideProvisionResponse() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        MediaDrm md = new MediaDrm(mockScheme);

        // Set up mock expected responses using properties
        byte testResponse[] = {0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20};

        md.provideProvisionResponse(testResponse);
        assertTrue(Arrays.equals(testResponse, md.getPropertyByteArray("mock-response")));
    }

    public void testGetSecureStops() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        MediaDrm md = new MediaDrm(mockScheme);

        // Set up mock expected responses using properties
        byte ss1[] = {0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20};
        byte ss2[] = {0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30};

        md.setPropertyByteArray("mock-secure-stop1", ss1);
        md.setPropertyByteArray("mock-secure-stop2", ss2);

        List<byte[]> secureStopList = md.getSecureStops();
        assertTrue(secureStopList != null);

        Iterator<byte[]> iter = secureStopList.iterator();
        assertTrue(iter.hasNext());
        assertTrue(Arrays.equals(iter.next(), ss1));
        assertTrue(iter.hasNext());
        assertTrue(Arrays.equals(iter.next(), ss2));
        assertFalse(iter.hasNext());
    }

    public void testReleaseSecureStops() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        MediaDrm md = new MediaDrm(mockScheme);

        // Set up mock expected responses using properties
        byte ssrelease[] = {0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40};

        md.releaseSecureStops(ssrelease);
        assertTrue(Arrays.equals(ssrelease, md.getPropertyByteArray("mock-ssrelease")));
    }

    public void testMultipleSessions() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        MediaDrm md = new MediaDrm(mockScheme);

        byte[] session1 = openSession(md);
        byte[] session2 = openSession(md);
        byte[] session3 = openSession(md);

        assertFalse(Arrays.equals(session1, session2));
        assertFalse(Arrays.equals(session2, session3));

        md.closeSession(session1);
        md.closeSession(session2);
        md.closeSession(session3);
    }

    public void testCryptoSession() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        MediaDrm md = new MediaDrm(mockScheme);

        byte[] sessionId = openSession(md);
        CryptoSession cs = md.getCryptoSession(sessionId, "AES/CBC/NoPadding", "HmacSHA256");
        assertFalse(cs == null);
    }

    public void testBadCryptoSession() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        MediaDrm md = new MediaDrm(mockScheme);

        boolean gotException = false;
        try {
            byte[] sessionId = openSession(md);
            CryptoSession cs = md.getCryptoSession(sessionId, "bad", "bad");
        } catch (IllegalArgumentException e) {
            gotException = true;
        }
        assertTrue(gotException);
    }

    public void testCryptoSessionEncrypt() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        MediaDrm md = new MediaDrm(mockScheme);

        byte[] sessionId = openSession(md);
        CryptoSession cs = md.getCryptoSession(sessionId, "AES/CBC/NoPadding", "HmacSHA256");
        assertFalse(cs == null);

        byte[] keyId = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09};
        byte[] input = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19};
        byte[] iv = {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29};
        byte[] expected_output = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39};

        md.setPropertyByteArray("mock-output", expected_output);

        byte[] output = cs.encrypt(keyId, input, iv);

        assertTrue(Arrays.equals(keyId, md.getPropertyByteArray("mock-keyid")));
        assertTrue(Arrays.equals(input, md.getPropertyByteArray("mock-input")));
        assertTrue(Arrays.equals(iv, md.getPropertyByteArray("mock-iv")));
        assertTrue(Arrays.equals(output, expected_output));
    }

    public void testCryptoSessionDecrypt() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        MediaDrm md = new MediaDrm(mockScheme);

        byte[] sessionId = openSession(md);
        CryptoSession cs = md.getCryptoSession(sessionId, "AES/CBC/NoPadding", "HmacSHA256");
        assertFalse(cs == null);

        byte[] keyId = {0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49};
        byte[] input = {0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59};
        byte[] iv = {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69};
        byte[] expected_output = {0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79};

        md.setPropertyByteArray("mock-output", expected_output);

        byte[] output = cs.decrypt(keyId, input, iv);

        assertTrue(Arrays.equals(keyId, md.getPropertyByteArray("mock-keyid")));
        assertTrue(Arrays.equals(input, md.getPropertyByteArray("mock-input")));
        assertTrue(Arrays.equals(iv, md.getPropertyByteArray("mock-iv")));
        assertTrue(Arrays.equals(output, expected_output));
    }

    public void testCryptoSessionSign() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        MediaDrm md = new MediaDrm(mockScheme);

        byte[] sessionId = openSession(md);
        CryptoSession cs = md.getCryptoSession(sessionId, "AES/CBC/NoPadding", "HmacSHA256");
        assertFalse(cs == null);

        byte[] keyId = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09};
        byte[] message = {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29};
        byte[] expected_signature = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39};

        md.setPropertyByteArray("mock-signature", expected_signature);

        byte[] signature = cs.sign(keyId, message);

        assertTrue(Arrays.equals(keyId, md.getPropertyByteArray("mock-keyid")));
        assertTrue(Arrays.equals(message, md.getPropertyByteArray("mock-message")));
        assertTrue(Arrays.equals(signature, expected_signature));
    }

    public void testCryptoSessionVerify() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }

        MediaDrm md = new MediaDrm(mockScheme);

        byte[] sessionId = openSession(md);
        CryptoSession cs = md.getCryptoSession(sessionId, "AES/CBC/NoPadding", "HmacSHA256");
        assertFalse(cs == null);

        byte[] keyId = {0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49};
        byte[] message = {0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59};
        byte[] signature = {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69};

        md.setPropertyString("mock-match", "1");
        assertTrue(cs.verify(keyId, message, signature));

        assertTrue(Arrays.equals(keyId, md.getPropertyByteArray("mock-keyid")));
        assertTrue(Arrays.equals(message, md.getPropertyByteArray("mock-message")));
        assertTrue(Arrays.equals(signature, md.getPropertyByteArray("mock-signature")));

        md.setPropertyString("mock-match", "0");
        assertFalse(cs.verify(keyId, message, signature));
    }

    private MediaDrm mMediaDrm = null;
    private Looper mLooper = null;
    private Object mLock = new Object();
    private boolean mGotEvent = false;

    public void testEventNoSessionNoData() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }


        new Thread() {
            @Override
            public void run() {
                // Set up a looper to be used by mMediaPlayer.
                Looper.prepare();

                // Save the looper so that we can terminate this thread
                // after we are done with it.
                mLooper = Looper.myLooper();

                try {
                    mMediaDrm = new MediaDrm(mockScheme);
                } catch (MediaDrmException e) {
                    e.printStackTrace();
                    fail();
                }

                synchronized(mLock) {
                    mLock.notify();
                    mMediaDrm.setOnEventListener(new MediaDrm.OnEventListener() {
                            @Override
                            public void onEvent(MediaDrm md, byte[] sessionId, int event,
                                                int extra, byte[] data) {
                                synchronized(mLock) {
                                    Log.d(TAG,"testEventNoSessionNoData.onEvent");
                                    assertTrue(md == mMediaDrm);
                                    assertTrue(event == 2);
                                    assertTrue(extra == 456);
                                    assertTrue(sessionId == null);
                                    assertTrue(data == null);
                                    mGotEvent = true;
                                    mLock.notify();
                                }
                            }
                        });
                }

                Looper.loop();  // Blocks forever until Looper.quit() is called.
            }
        }.start();

        // wait for mMediaDrm to be created
        synchronized(mLock) {
            try {
                mLock.wait(1000);
            } catch (Exception e) {
            }
        }
        assertTrue(mMediaDrm != null);

        mGotEvent = false;
        mMediaDrm.setPropertyString("mock-send-event", "2 456");

        synchronized(mLock) {
            try {
                mLock.wait(1000);
            } catch (Exception e) {
            }
        }

        mLooper.quit();
        assertTrue(mGotEvent);
    }

    public void testEventWithSessionAndData() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }


        new Thread() {
            @Override
            public void run() {
                // Set up a looper to be used by mMediaPlayer.
                Looper.prepare();

                // Save the looper so that we can terminate this thread
                // after we are done with it.
                mLooper = Looper.myLooper();

                try {
                    mMediaDrm = new MediaDrm(mockScheme);
                } catch (MediaDrmException e) {
                    e.printStackTrace();
                    fail();
                }


                final byte[] expected_sessionId = openSession(mMediaDrm);
                final byte[] expected_data = {0x10, 0x11, 0x12, 0x13, 0x14,
                                              0x15, 0x16, 0x17, 0x18, 0x19};

                mMediaDrm.setPropertyByteArray("mock-event-session-id", expected_sessionId);
                mMediaDrm.setPropertyByteArray("mock-event-data", expected_data);

                synchronized(mLock) {
                    mLock.notify();

                    mMediaDrm.setOnEventListener(new MediaDrm.OnEventListener() {
                            @Override
                            public void onEvent(MediaDrm md, byte[] sessionId, int event,
                                                int extra, byte[] data) {
                                synchronized(mLock) {
                                    Log.d(TAG,"testEventWithSessoinAndData.onEvent");
                                    assertTrue(md == mMediaDrm);
                                    assertTrue(event == 1);
                                    assertTrue(extra == 123);
                                    assertTrue(Arrays.equals(sessionId, expected_sessionId));
                                    assertTrue(Arrays.equals(data, expected_data));
                                    mGotEvent = true;
                                    mLock.notify();
                                }
                            }
                        });
                }
                Looper.loop();  // Blocks forever until Looper.quit() is called.
            }
        }.start();

        // wait for mMediaDrm to be created
        synchronized(mLock) {
            try {
                mLock.wait(1000);
            } catch (Exception e) {
            }
        }
        assertTrue(mMediaDrm != null);

        mGotEvent = false;
        mMediaDrm.setPropertyString("mock-send-event", "1 123");

        synchronized(mLock) {
            try {
                mLock.wait(1000);
            } catch (Exception e) {
            }
        }

        mLooper.quit();
        assertTrue(mGotEvent);
    }

    public void testExpirationUpdate() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }


        new Thread() {
            @Override
            public void run() {
                // Set up a looper to be used by mMediaPlayer.
                Looper.prepare();

                // Save the looper so that we can terminate this thread
                // after we are done with it.
                mLooper = Looper.myLooper();

                try {
                    mMediaDrm = new MediaDrm(mockScheme);
                } catch (MediaDrmException e) {
                    e.printStackTrace();
                    fail();
                }


                final byte[] expected_sessionId = openSession(mMediaDrm);

                mMediaDrm.setPropertyByteArray("mock-event-session-id", expected_sessionId);

                synchronized(mLock) {
                    mLock.notify();

                    mMediaDrm.setOnExpirationUpdateListener(new MediaDrm.OnExpirationUpdateListener() {
                            @Override
                            public void onExpirationUpdate(MediaDrm md, byte[] sessionId,
                                    long expiryTimeMS) {
                                synchronized(mLock) {
                                    Log.d(TAG,"testExpirationUpdate.onExpirationUpdate");
                                    assertTrue(md == mMediaDrm);
                                    assertTrue(Arrays.equals(sessionId, expected_sessionId));
                                    assertTrue(expiryTimeMS == 123456789012345L);
                                    mGotEvent = true;
                                    mLock.notify();
                                }
                            }
                        }, null);
                }
                Looper.loop();  // Blocks forever until Looper.quit() is called.
            }
        }.start();

        // wait for mMediaDrm to be created
        synchronized(mLock) {
            try {
                mLock.wait(1000);
            } catch (Exception e) {
            }
        }
        assertTrue(mMediaDrm != null);

        mGotEvent = false;
        mMediaDrm.setPropertyString("mock-send-expiration-update", "123456789012345");

        synchronized(mLock) {
            try {
                mLock.wait(1000);
            } catch (Exception e) {
            }
        }

        mLooper.quit();
        assertTrue(mGotEvent);
    }

    public void testKeyStatusChange() throws Exception {
        if (!isMockPluginInstalled()) {
            return;
        }


        new Thread() {
            @Override
            public void run() {
                // Set up a looper to be used by mMediaPlayer.
                Looper.prepare();

                // Save the looper so that we can terminate this thread
                // after we are done with it.
                mLooper = Looper.myLooper();

                try {
                    mMediaDrm = new MediaDrm(mockScheme);
                } catch (MediaDrmException e) {
                    e.printStackTrace();
                    fail();
                }


                final byte[] expected_sessionId = openSession(mMediaDrm);

                mMediaDrm.setPropertyByteArray("mock-event-session-id", expected_sessionId);

                synchronized(mLock) {
                    mLock.notify();

                    mMediaDrm.setOnKeyStatusChangeListener(new MediaDrm.OnKeyStatusChangeListener() {
                            @Override
                            public void onKeyStatusChange(MediaDrm md, byte[] sessionId,
                                    List<KeyStatus> keyInformation, boolean hasNewUsableKey) {
                                synchronized(mLock) {
                                    Log.d(TAG,"testKeyStatusChange.onKeyStatusChange");
                                    assertTrue(md == mMediaDrm);
                                    assertTrue(Arrays.equals(sessionId, expected_sessionId));
                                    try {
                                        KeyStatus keyStatus = keyInformation.get(0);
                                        assertTrue(Arrays.equals(keyStatus.getKeyId(), "key1".getBytes()));
                                        assertTrue(keyStatus.getStatusCode() == MediaDrm.KeyStatus.STATUS_USABLE);
                                        keyStatus = keyInformation.get(1);
                                        assertTrue(Arrays.equals(keyStatus.getKeyId(), "key2".getBytes()));
                                        assertTrue(keyStatus.getStatusCode() == MediaDrm.KeyStatus.STATUS_EXPIRED);
                                        keyStatus = keyInformation.get(2);
                                        assertTrue(Arrays.equals(keyStatus.getKeyId(), "key3".getBytes()));
                                        assertTrue(keyStatus.getStatusCode() == MediaDrm.KeyStatus.STATUS_OUTPUT_NOT_ALLOWED);
                                        keyStatus = keyInformation.get(3);
                                        assertTrue(Arrays.equals(keyStatus.getKeyId(), "key4".getBytes()));
                                        assertTrue(keyStatus.getStatusCode() == MediaDrm.KeyStatus.STATUS_PENDING);
                                        keyStatus = keyInformation.get(4);
                                        assertTrue(Arrays.equals(keyStatus.getKeyId(), "key5".getBytes()));
                                        assertTrue(keyStatus.getStatusCode() == MediaDrm.KeyStatus.STATUS_INTERNAL_ERROR);
                                        assertTrue(hasNewUsableKey);
                                        mGotEvent = true;
                                    } catch (IndexOutOfBoundsException e) {
                                    }
                                    mLock.notify();
                                }
                            }
                        }, null);
                }
                Looper.loop();  // Blocks forever until Looper.quit() is called.
            }
        }.start();

        // wait for mMediaDrm to be created
        synchronized(mLock) {
            try {
                mLock.wait(1000);
            } catch (Exception e) {
            }
        }
        assertTrue(mMediaDrm != null);

        mGotEvent = false;
        mMediaDrm.setPropertyString("mock-send-keys-change", "123456789012345");

        synchronized(mLock) {
            try {
                mLock.wait(1000);
            } catch (Exception e) {
            }
        }

        mLooper.quit();
        assertTrue(mGotEvent);
    }

    private byte[] openSession(MediaDrm md) {
        byte[] sessionId = null;
        try {
            sessionId = md.openSession();
        } catch (NotProvisionedException e) {
            // ignore, not thrown by mock
        } catch (ResourceBusyException e) {
            // ignore, not thrown by mock
        }
        return sessionId;
    }
}
