104571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee/* 204571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee * Copyright (C) 2014 The Android Open Source Project 304571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee * 404571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee * Licensed under the Apache License, Version 2.0 (the "License"); 504571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee * you may not use this file except in compliance with the License. 604571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee * You may obtain a copy of the License at 704571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee * 804571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee * http://www.apache.org/licenses/LICENSE-2.0 904571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee * 1004571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee * Unless required by applicable law or agreed to in writing, software 1104571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee * distributed under the License is distributed on an "AS IS" BASIS, 1204571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1304571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee * See the License for the specific language governing permissions and 1404571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee * limitations under the License 1504571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee */ 1604571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee 177cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnpackage com.android.server.telecom.testapps; 1804571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee 19b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunnimport com.android.ex.camera2.blocking.BlockingCameraManager; 20b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunnimport com.android.ex.camera2.blocking.BlockingCameraManager.BlockingOpenException; 219399ae6672196db82e491ddb425c48d6a3b67451Eino-Ville Talvalaimport com.android.ex.camera2.blocking.BlockingSessionCallback; 22945a82ea92bf4fcc8b505738760650f9fb74960bIhab Awadimport com.android.server.telecom.testapps.R; 23e09b47b2f8b96780fc5c921785d73082cd932828Yorke Leeimport com.android.server.telecom.testapps.TestConnectionService.TestConnection; 24b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn 25dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Leeimport android.content.Context; 26f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunnimport android.graphics.SurfaceTexture; 27b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunnimport android.hardware.camera2.CameraAccessException; 28b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunnimport android.hardware.camera2.CameraCaptureSession; 29f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunnimport android.hardware.camera2.CameraCharacteristics; 30b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunnimport android.hardware.camera2.CameraDevice; 31b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunnimport android.hardware.camera2.CameraManager; 32b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunnimport android.hardware.camera2.CaptureFailure; 33b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunnimport android.hardware.camera2.CaptureRequest; 34b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunnimport android.hardware.camera2.TotalCaptureResult; 35f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunnimport android.hardware.camera2.params.StreamConfigurationMap; 36dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunnimport android.media.MediaPlayer; 3736004e70d54d4f8063733cc8b85150b1931e1c03Yorke Leeimport android.net.Uri; 38b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunnimport android.os.Handler; 397cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.Connection; 407cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.VideoProfile; 410f215ce43e23f8c72b8caeb710946ae40dac07d3Yorke Leeimport android.telecom.VideoProfile.CameraCapabilities; 42b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunnimport android.text.TextUtils; 4304571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Leeimport android.util.Log; 44f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunnimport android.util.Size; 450b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunnimport android.view.Surface; 4604571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee 47f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunnimport java.lang.IllegalArgumentException; 48f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunnimport java.lang.String; 49b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunnimport java.util.ArrayList; 50b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunnimport java.util.List; 51dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Leeimport java.util.Random; 52dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee 5304571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee/** 543bcf935b25470e94c8c6855862434d15b785c54aAndrew Lee * Implements the VideoCallProvider. 5504571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee */ 566fb37c87836b5245046bd3b14320823ab839a10cIhab Awadpublic class TestVideoProvider extends Connection.VideoProvider { 57e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee private TestConnection mConnection; 586fb37c87836b5245046bd3b14320823ab839a10cIhab Awad private CameraCapabilities mCameraCapabilities; 59dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee private Random random; 60dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn private Surface mDisplaySurface; 61dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn private Surface mPreviewSurface; 62dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn private Context mContext; 63dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn /** Used to play incoming video during a call. */ 64dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn private MediaPlayer mIncomingMediaPlayer; 65b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn 66b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn private CameraManager mCameraManager; 67b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn private CameraDevice mCameraDevice; 68b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn private CameraCaptureSession mCameraSession; 69b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn private CameraThread mLooperThread; 70b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn 71e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee private final Handler mHandler = new Handler(); 72e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee 73b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn private String mCameraId; 74b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn 75b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn private static final long SESSION_TIMEOUT_MS = 2000; 76dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee 77e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee public TestVideoProvider(Context context, TestConnection connection) { 78e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee mConnection = connection; 79dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn mContext = context; 80dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee random = new Random(); 81b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE); 82dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee } 8304571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee 84b9e44bcf88078bcbcbf80b7df356bb0dfef229f3Andrew Lee @Override 85b9e44bcf88078bcbcbf80b7df356bb0dfef229f3Andrew Lee public void onSetCamera(String cameraId) { 8604571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee log("Set camera to " + cameraId); 87b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn mCameraId = cameraId; 88f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn 89f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn stopCamera(); 90b19d23fd57cf17b7d0c66760131319a5fec930adTyler Gunn // Get the capabilities of the camera 91f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn setCameraCapabilities(mCameraId); 9204571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee } 9304571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee 940b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn @Override 95b9e44bcf88078bcbcbf80b7df356bb0dfef229f3Andrew Lee public void onSetPreviewSurface(Surface surface) { 96dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn log("Set preview surface " + (surface == null ? "unset" : "set")); 97f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn if (mPreviewSurface != null) { 98b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn stopCamera(); 99b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn } 100b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn 101f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn mPreviewSurface = surface; 102f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn 103b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn if (!TextUtils.isEmpty(mCameraId) && mPreviewSurface != null) { 104b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn startCamera(mCameraId); 105dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn } 1060b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn } 1070b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn 1080b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn @Override 109b9e44bcf88078bcbcbf80b7df356bb0dfef229f3Andrew Lee public void onSetDisplaySurface(Surface surface) { 110dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn log("Set display surface " + (surface == null ? "unset" : "set")); 111dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn mDisplaySurface = surface; 112dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn 113dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn if (mDisplaySurface != null) { 114dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn if (mIncomingMediaPlayer == null) { 115f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn // For a Rick-Rolling good time use R.raw.test_video 116f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn mIncomingMediaPlayer = createMediaPlayer(mDisplaySurface, R.raw.test_pattern); 117dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn } 118dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn mIncomingMediaPlayer.setSurface(mDisplaySurface); 119dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn if (!mIncomingMediaPlayer.isPlaying()) { 120dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn mIncomingMediaPlayer.start(); 121dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn } 122dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn } else { 123b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn if (mIncomingMediaPlayer != null) { 124b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn mIncomingMediaPlayer.stop(); 125b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn mIncomingMediaPlayer.setSurface(null); 126b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn } 127dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn } 1280b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn } 1290b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn 1300b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn @Override 131b9e44bcf88078bcbcbf80b7df356bb0dfef229f3Andrew Lee public void onSetDeviceOrientation(int rotation) { 132f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn log("Set device orientation " + rotation); 1330b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn } 1340b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn 135dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee /** 136dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee * Sets the zoom value, creating a new CallCameraCapabalities object. If the zoom value is 137dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee * non-positive, assume that zoom is not supported. 138dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee */ 1390b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn @Override 140b9e44bcf88078bcbcbf80b7df356bb0dfef229f3Andrew Lee public void onSetZoom(float value) { 141dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee log("Set zoom to " + value); 1420b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn } 1430b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn 144dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee /** 145dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee * "Sends" a request with a video call profile. Assumes that this response succeeds and sends 146dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee * the response back via the CallVideoClient. 147dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee */ 1480b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn @Override 1490bd4de37ac94b371a1f54891da0fe3df2da8fb6eTyler Gunn public void onSendSessionModifyRequest(final VideoProfile fromProfile, 1500bd4de37ac94b371a1f54891da0fe3df2da8fb6eTyler Gunn final VideoProfile requestProfile) { 151dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee log("Sent session modify request"); 152dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee 153e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee mHandler.postDelayed(new Runnable() { 154e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee @Override 155e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee public void run() { 156e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee final VideoProfile responseProfile = new VideoProfile( 157e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee requestProfile.getVideoState(), requestProfile.getQuality()); 158e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee mConnection.setVideoState(requestProfile.getVideoState()); 159e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee 160e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee receiveSessionModifyResponse( 161e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee SESSION_MODIFY_REQUEST_SUCCESS, 162e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee requestProfile, 163e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee responseProfile); 164e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee } 165e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee }, 2000); 1660b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn } 1670b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn 1680b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn @Override 1696fb37c87836b5245046bd3b14320823ab839a10cIhab Awad public void onSendSessionModifyResponse(VideoProfile responseProfile) { 1700b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn 1710b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn } 1720b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn 173dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee /** 174dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee * Returns a CallCameraCapabilities object without supporting zoom. 175dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee */ 1760b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn @Override 177b9e44bcf88078bcbcbf80b7df356bb0dfef229f3Andrew Lee public void onRequestCameraCapabilities() { 178dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee log("Requested camera capabilities"); 179f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn changeCameraCapabilities(mCameraCapabilities); 1800b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn } 1810b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn 182dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee /** 183dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee * Randomly reports data usage of value ranging from 10MB to 60MB. 184dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee */ 1850b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn @Override 18607bc5ee853bc9a0b4cd46e0c702888b2c7989392Ihab Awad public void onRequestConnectionDataUsage() { 18707bc5ee853bc9a0b4cd46e0c702888b2c7989392Ihab Awad log("Requested connection data usage"); 188d240fe8e16205623eb6cb73c3d42448554690033Rekha Kumar long dataUsageKb = (10 *1024) + random.nextInt(50 * 1024); 1893bcf935b25470e94c8c6855862434d15b785c54aAndrew Lee changeCallDataUsage(dataUsageKb); 1900b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn } 1910b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn 192dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee /** 193dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee * We do not have a need to set a paused image. 194dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee */ 1950b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn @Override 19636004e70d54d4f8063733cc8b85150b1931e1c03Yorke Lee public void onSetPauseImage(Uri uri) { 197dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee // Not implemented. 1980b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn } 1990b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn 200b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn /** 201b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn * Stop and cleanup the media players used for test video playback. 202b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn */ 203b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn public void stopAndCleanupMedia() { 204b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn if (mIncomingMediaPlayer != null) { 205b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn mIncomingMediaPlayer.setSurface(null); 206b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn mIncomingMediaPlayer.stop(); 207b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn mIncomingMediaPlayer.release(); 208b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn mIncomingMediaPlayer = null; 209b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn } 210b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn } 211b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn 21204571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee private static void log(String msg) { 213905dfba7883666f45a0c6958d8bc6c19d68972d9Sailesh Nepal Log.w("TestCallVideoProvider", "[TestCallServiceProvider] " + msg); 21404571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee } 215dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn 216dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn /** 217dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn * Creates a media player to play a video resource on a surface. 218dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn * @param surface The surface. 219dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn * @param videoResource The video resource. 220dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn * @return The {@code MediaPlayer}. 221dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn */ 222dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn private MediaPlayer createMediaPlayer(Surface surface, int videoResource) { 223dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn MediaPlayer mediaPlayer = MediaPlayer.create(mContext.getApplicationContext(), 224dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn videoResource); 225dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn mediaPlayer.setSurface(surface); 226dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn mediaPlayer.setLooping(true); 227dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn return mediaPlayer; 228dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn } 229b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn 230b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn /** 231b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn * Starts displaying the camera image on the preview surface. 232b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn * 233b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn * @param cameraId 234b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn */ 235b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn private void startCamera(String cameraId) { 236b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn stopCamera(); 237b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn 238b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn if (mPreviewSurface == null) { 239b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn return; 240b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn } 241b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn 242b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn // Configure a looper thread. 243b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn mLooperThread = new CameraThread(); 244b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn Handler mHandler; 245b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn try { 246b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn mHandler = mLooperThread.start(); 247b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn } catch (Exception e) { 248b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn log("Exception: " + e); 249b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn return; 250b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn } 251b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn 252b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn // Get the camera device. 253b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn try { 254b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn BlockingCameraManager blockingCameraManager = new BlockingCameraManager(mCameraManager); 255b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn mCameraDevice = blockingCameraManager.openCamera(cameraId, null /* listener */, 256b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn mHandler); 257b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn } catch (CameraAccessException e) { 258b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn log("CameraAccessException: " + e); 259b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn return; 260b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn } catch (BlockingOpenException be) { 261b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn log("BlockingOpenException: " + be); 262b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn return; 263b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn } 264b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn 265b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn // Create a capture session to get the preview and display it on the surface. 266b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn List<Surface> surfaces = new ArrayList<Surface>(); 267b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn surfaces.add(mPreviewSurface); 268b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn CaptureRequest.Builder mCaptureRequest = null; 269b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn try { 2709399ae6672196db82e491ddb425c48d6a3b67451Eino-Ville Talvala BlockingSessionCallback blkSession = new BlockingSessionCallback(); 271b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn mCameraDevice.createCaptureSession(surfaces, blkSession, mHandler); 272b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn mCaptureRequest = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 273b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn mCaptureRequest.addTarget(mPreviewSurface); 274b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn mCameraSession = blkSession.waitAndGetSession(SESSION_TIMEOUT_MS); 275b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn } catch (CameraAccessException e) { 276b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn log("CameraAccessException: " + e); 277b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn return; 278b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn } 279b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn 280b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn // Keep repeating 281b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn try { 2829399ae6672196db82e491ddb425c48d6a3b67451Eino-Ville Talvala mCameraSession.setRepeatingRequest(mCaptureRequest.build(), new CameraCaptureCallback(), 283b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn mHandler); 284b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn } catch (CameraAccessException e) { 285b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn log("CameraAccessException: " + e); 286b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn return; 287b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn } 288b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn } 289b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn 290b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn /** 291b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn * Stops the camera and looper thread. 292b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn */ 293b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn public void stopCamera() { 294b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn try { 295b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn if (mCameraDevice != null) { 296b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn mCameraDevice.close(); 297b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn mCameraDevice = null; 298b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn } 299b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn if (mLooperThread != null) { 300b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn mLooperThread.close(); 301b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn mLooperThread = null; 302b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn } 303b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn } catch (Exception e) { 304b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn log("stopCamera Exception: "+e.toString()); 305b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn } 306b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn } 307b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn 308b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn /** 309b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn * Required listener for camera capture events. 310b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn */ 3119399ae6672196db82e491ddb425c48d6a3b67451Eino-Ville Talvala private class CameraCaptureCallback extends CameraCaptureSession.CaptureCallback { 312b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn @Override 313b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn public void onCaptureCompleted(CameraCaptureSession camera, CaptureRequest request, 314b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn TotalCaptureResult result) { 315b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn } 316b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn 317b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn @Override 318b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn public void onCaptureFailed(CameraCaptureSession camera, CaptureRequest request, 319b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn CaptureFailure failure) { 320b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn } 321b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn } 322f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn 323f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn /** 324f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn * Uses the camera manager to retrieve the camera capabilities for the chosen camera. 325f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn * 326f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn * @param cameraId The camera ID to get the capabilities for. 327f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn */ 328f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn private void setCameraCapabilities(String cameraId) { 329f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn CameraManager cameraManager = (CameraManager) mContext.getSystemService( 330f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn Context.CAMERA_SERVICE); 331f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn 332f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn CameraCharacteristics c = null; 333f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn try { 334f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn c = cameraManager.getCameraCharacteristics(cameraId); 335f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn } catch (IllegalArgumentException | CameraAccessException e) { 336f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn // Ignoring camera problems. 337f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn } 338f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn if (c != null) { 339f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn // Get the video size for the camera 340f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn StreamConfigurationMap map = c.get( 341f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 342f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn Size previewSize = map.getOutputSizes(SurfaceTexture.class)[0]; 343f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn 34431d68d261288a19e9a402efa84b7afcf7cec9dd2Jay Shrauner mCameraCapabilities = new CameraCapabilities(previewSize.getWidth(), 345f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn previewSize.getHeight()); 346f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn } 347f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn } 348905dfba7883666f45a0c6958d8bc6c19d68972d9Sailesh Nepal} 349