1 /* 2 * Copyright 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package android.media.misc.cts; 17 18 import static org.junit.Assume.assumeTrue; 19 20 import android.app.Activity; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.os.Bundle; 24 import android.util.Log; 25 26 import junit.framework.Assert; 27 28 public class ResourceManagerStubActivity extends Activity { 29 // Define all the error codes specific to this test case here 30 // Test case was skipped as there aren't any supported decoder(s). 31 public static final int RESULT_CODE_NO_DECODER = Activity.RESULT_FIRST_USER + 1; 32 // Test case was skipped as there aren't any supported encoder(s). 33 public static final int RESULT_CODE_NO_ENCODER = Activity.RESULT_FIRST_USER + 2; 34 // Test case was skipped as the device doesn't have any camera available for recording. 35 public static final int RESULT_CODE_NO_CAMERA = Activity.RESULT_FIRST_USER + 3; 36 37 private static final String TAG = "ResourceManagerStubActivity"; 38 private final Object mFinishEvent = new Object(); 39 private int[] mRequestCodes = {0, 1}; 40 private int[] mResults = {RESULT_CANCELED, RESULT_CANCELED}; 41 private int mNumResults = 0; 42 private int mType1 = ResourceManagerTestActivityBase.TYPE_NONSECURE; 43 private int mType2 = ResourceManagerTestActivityBase.TYPE_NONSECURE; 44 private boolean mWaitForReclaim = true; 45 private boolean mStartedOnlyOneActivity = false; 46 47 private static final String ERROR_INSUFFICIENT_RESOURCES = 48 "* Please check if the omx component is returning OMX_ErrorInsufficientResources " + 49 "properly when the codec failure is due to insufficient resource.\n"; 50 private static final String ERROR_SUPPORTS_MULTIPLE_SECURE_CODECS = 51 "* Please check if this platform supports multiple concurrent secure codec " + 52 "instances. If not, please add below setting in /etc/media_codecs.xml in order " + 53 "to pass the test:\n" + 54 " <Settings>\n" + 55 " <Setting name=\"supports-multiple-secure-codecs\" value=\"false\" />\n" + 56 " </Settings>\n"; 57 private static final String ERROR_SUPPORTS_SECURE_WITH_NON_SECURE_CODEC = 58 "* Please check if this platform supports co-exist of secure and non-secure codec. " + 59 "If not, please add below setting in /etc/media_codecs.xml in order to pass the " + 60 "test:\n" + 61 " <Settings>\n" + 62 " <Setting name=\"supports-secure-with-non-secure-codec\" value=\"false\" />\n" + 63 " </Settings>\n"; 64 65 @Override onCreate(Bundle savedInstanceState)66 protected void onCreate(Bundle savedInstanceState) { 67 super.onCreate(savedInstanceState); 68 } 69 70 @Override onActivityResult(int requestCode, int resultCode, Intent data)71 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 72 Log.d(TAG, "Activity " + requestCode + " finished with resultCode " + resultCode); 73 mResults[requestCode] = resultCode; 74 if (++mNumResults == mResults.length || mStartedOnlyOneActivity) { 75 synchronized (mFinishEvent) { 76 mFinishEvent.notify(); 77 } 78 } 79 } 80 processActivityResults()81 private void processActivityResults() { 82 boolean result = true; 83 for (int i = 0; result && i < mResults.length; ++i) { 84 switch (mResults[i]) { 85 case RESULT_OK: 86 // Activity completed successfully. 87 break; 88 case RESULT_CODE_NO_DECODER: 89 assumeTrue("Test case was skipped as there aren't any supported decoder(s).", 90 false); 91 break; 92 case RESULT_CODE_NO_ENCODER: 93 assumeTrue("Test case was skipped as there aren't any supported encoder(s).", 94 false); 95 break; 96 case RESULT_CODE_NO_CAMERA: 97 assumeTrue("Test case was skipped as the device doesn't have any " 98 + "camera available for recording.", false); 99 break; 100 default: 101 Log.e(TAG, "Result from activity " + i + " is a fail."); 102 result = false; 103 break; 104 } 105 } 106 107 if (!result) { 108 String failMessage = "The potential reasons for the failure:\n"; 109 StringBuilder reasons = new StringBuilder(); 110 reasons.append(ERROR_INSUFFICIENT_RESOURCES); 111 if (mType1 != mType2) { 112 reasons.append(ERROR_SUPPORTS_SECURE_WITH_NON_SECURE_CODEC); 113 } 114 if (mType1 == ResourceManagerTestActivityBase.TYPE_MIX 115 && mType2 == ResourceManagerTestActivityBase.TYPE_SECURE) { 116 reasons.append(ERROR_SUPPORTS_MULTIPLE_SECURE_CODECS); 117 } 118 Assert.assertTrue(failMessage + reasons.toString(), result); 119 } 120 } 121 waitForActivitiesToComplete()122 private void waitForActivitiesToComplete() throws InterruptedException { 123 // Wait for all the activities to complete. 124 synchronized (mFinishEvent) { 125 while (mNumResults < mResults.length) { 126 mFinishEvent.wait(); 127 } 128 } 129 } 130 waitForOneActivityToComplete()131 private void waitForOneActivityToComplete() throws InterruptedException { 132 // Wait for one activity to complete. 133 synchronized (mFinishEvent) { 134 while (mNumResults != 1) { 135 mFinishEvent.wait(); 136 } 137 } 138 } 139 testReclaimResource(int type1, int type2, boolean highResolutionForActivity1, boolean highResolutionForActivity2)140 public void testReclaimResource(int type1, int type2, boolean highResolutionForActivity1, 141 boolean highResolutionForActivity2) throws InterruptedException { 142 mType1 = type1; 143 mType2 = type2; 144 if (type1 != ResourceManagerTestActivityBase.TYPE_MIX && type1 != type2) { 145 // in this case, activity2 may not need to reclaim codec from activity1. 146 mWaitForReclaim = false; 147 } else { 148 mWaitForReclaim = true; 149 } 150 Thread thread = new Thread() { 151 @Override 152 public void run() { 153 try { 154 Context context = getApplicationContext(); 155 Intent intent1 = new Intent(context, ResourceManagerTestActivity1.class); 156 intent1.putExtra("test-type", mType1); 157 intent1.putExtra("wait-for-reclaim", mWaitForReclaim); 158 intent1.putExtra("high-resolution", highResolutionForActivity1); 159 startActivityForResult(intent1, mRequestCodes[0]); 160 Thread.sleep(5000); // wait for process to launch and allocate all codecs. 161 162 Intent intent2 = new Intent(context, ResourceManagerTestActivity2.class); 163 intent2.putExtra("test-type", mType2); 164 intent2.putExtra("high-resolution", highResolutionForActivity2); 165 startActivityForResult(intent2, mRequestCodes[1]); 166 167 waitForActivitiesToComplete(); 168 } catch (Exception e) { 169 Log.d(TAG, "testReclaimResource got exception " + e.toString()); 170 } 171 } 172 }; 173 thread.start(); 174 Log.i(TAG, "Started and waiting for Activities"); 175 thread.join(); 176 Log.i(TAG, "Activities completed"); 177 178 processActivityResults(); 179 } 180 testVideoCodecReclaim(boolean highResolution, String mimeType)181 public void testVideoCodecReclaim(boolean highResolution, String mimeType) 182 throws InterruptedException { 183 Thread thread = new Thread() { 184 @Override 185 public void run() { 186 try { 187 Context context = getApplicationContext(); 188 189 // Start the transcoding activity first. 190 Log.d(TAG, "Starting ResourceManagerCodecActivity"); 191 Intent decoders = new Intent(context, ResourceManagerCodecActivity.class); 192 decoders.putExtra("high-resolution", highResolution); 193 decoders.putExtra("mime", mimeType); 194 startActivityForResult(decoders, mRequestCodes[0]); 195 // wait for ResourceManagerCodecActivity to launch and allocate all codecs. 196 Thread.sleep(5000); 197 198 Log.d(TAG, "Starting ResourceManagerRecorderActivity"); 199 // Start the Camera Recording next. 200 Intent recorder = new Intent(context, ResourceManagerRecorderActivity.class); 201 recorder.putExtra("high-resolution", highResolution); 202 recorder.putExtra("mime", mimeType); 203 startActivityForResult(recorder, mRequestCodes[1]); 204 205 waitForActivitiesToComplete(); 206 } catch (Exception e) { 207 Log.d(TAG, "testVideoCodecReclaim got exception " + e.toString()); 208 } 209 } 210 }; 211 212 thread.start(); 213 Log.i(TAG, "Started and waiting for Activities"); 214 thread.join(); 215 Log.i(TAG, "Activities completed"); 216 217 processActivityResults(); 218 } 219 doTestReclaimResource(String codecName, String mimeType, int width, int height)220 public void doTestReclaimResource(String codecName, String mimeType, int width, int height) 221 throws InterruptedException { 222 mWaitForReclaim = true; 223 Thread thread = new Thread() { 224 @Override 225 public void run() { 226 try { 227 Context context = getApplicationContext(); 228 Intent intent1 = new Intent(context, ResourceManagerTestActivity1.class); 229 intent1.putExtra("test-type", mType1); 230 intent1.putExtra("wait-for-reclaim", mWaitForReclaim); 231 intent1.putExtra("name", codecName); 232 intent1.putExtra("mime", mimeType); 233 intent1.putExtra("width", width); 234 intent1.putExtra("height", height); 235 startActivityForResult(intent1, mRequestCodes[0]); 236 Thread.sleep(5000); // wait for process to launch and allocate all codecs. 237 238 Intent intent2 = new Intent(context, ResourceManagerTestActivity2.class); 239 intent2.putExtra("test-type", mType2); 240 intent2.putExtra("name", codecName); 241 intent2.putExtra("mime", mimeType); 242 intent2.putExtra("width", width); 243 intent2.putExtra("height", height); 244 startActivityForResult(intent2, mRequestCodes[1]); 245 246 waitForActivitiesToComplete(); 247 } catch (Exception e) { 248 Log.d(TAG, "doTestReclaimResource got exception " + e.toString()); 249 } 250 } 251 }; 252 253 thread.start(); 254 Log.i(TAG, "Started and waiting for Activities"); 255 thread.join(); 256 Log.i(TAG, "Activities completed"); 257 258 processActivityResults(); 259 } 260 261 /** 262 * creates allowable number of decoders at given resolution. 263 * All the codecs are configured with the default importance (highest) 264 * But, when we get a INSUFFICIENT_RESOURCE, we lower the importance of the 265 * first codec so that we can create/start one more codec by reclaiming the 266 * first codec (that has lower importance now) 267 */ doTestCodecImportanceReclaimResource( String codecName, String mimeType, int width, int height, boolean highResolution, boolean changeImportanceAtConfig)268 public void doTestCodecImportanceReclaimResource( 269 String codecName, String mimeType, int width, int height, 270 boolean highResolution, boolean changeImportanceAtConfig) 271 throws InterruptedException { 272 mWaitForReclaim = true; 273 Thread thread = new Thread() { 274 @Override 275 public void run() { 276 try { 277 Context context = getApplicationContext(); 278 Intent intent = new Intent(context, ResourceManagerTestActivity2.class); 279 intent.putExtra("test-type", mType1); 280 intent.putExtra("wait-for-reclaim", mWaitForReclaim); 281 intent.putExtra("name", codecName); 282 intent.putExtra("mime", mimeType); 283 if (width == 0 || height == 0) { 284 intent.putExtra("high-resolution", highResolution); 285 } else { 286 intent.putExtra("width", width); 287 intent.putExtra("height", height); 288 } 289 if (changeImportanceAtConfig) { 290 intent.putExtra("codec-importance-at-config", true); 291 } else { 292 intent.putExtra("codec-importance-later", true); 293 } 294 mStartedOnlyOneActivity = true; 295 startActivityForResult(intent, mRequestCodes[0]); 296 waitForOneActivityToComplete(); 297 } catch (Exception e) { 298 Log.d(TAG, "doTestCodecImportanceReclaimResource got exception " 299 + e.toString()); 300 } 301 } 302 }; 303 304 thread.start(); 305 Log.i(TAG, "Started and waiting for Activities"); 306 thread.join(); 307 Log.i(TAG, "Activities completed"); 308 309 // Since we have started one activity, set the other activity code to success. 310 mResults[1] = RESULT_OK; 311 processActivityResults(); 312 } 313 } 314