1 /* 2 * Copyright (C) 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 17 package com.android.shell; 18 19 import java.util.concurrent.BlockingQueue; 20 import java.util.concurrent.SynchronousQueue; 21 import java.util.concurrent.TimeUnit; 22 23 import android.app.Activity; 24 import android.content.BroadcastReceiver; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.content.IntentFilter; 28 import android.os.Bundle; 29 30 /** 31 * Activity responsible for handling ACTION_SEND_MULTIPLE intents and passing them back to the test 32 * case class (through a {@link CustomActionSendMultipleListener}). 33 */ 34 public class ActionSendMultipleConsumerActivity extends Activity { 35 36 private static final String CUSTOM_ACTION_SEND_MULTIPLE_INTENT = 37 "com.android.shell.tests.CUSTOM_ACTION_SEND_MULTIPLE"; 38 39 private static CustomActionSendMultipleListener sListener; 40 41 static final String UI_NAME = "ActionSendMultipleConsumer"; 42 43 @Override onCreate(Bundle savedInstanceState)44 protected void onCreate(Bundle savedInstanceState) { 45 super.onCreate(savedInstanceState); 46 47 // The original intent cannot be broadcasted, it will fail due to security violations. 48 // Since the test case is only interested in the extras, we need to create a new custom 49 // intent with just them. 50 final Intent intent = getIntent(); 51 final Intent customIntent = new Intent(CUSTOM_ACTION_SEND_MULTIPLE_INTENT); 52 customIntent.putExtras(intent.getExtras()); 53 54 getApplicationContext().sendBroadcast(customIntent); 55 } 56 57 @Override onResume()58 protected void onResume() { 59 super.onResume(); 60 /* 61 * TODO: if finish() is not called, app will crash with an exception such as: 62 * AndroidRuntime: java.lang.RuntimeException: Unable to resume activity 63 * {com.android.shell.tests/com.android.shell.SendMultipleActivity}: 64 * java.lang.IllegalStateException: Activity 65 * {com.android.shell.tests/com.android.shell.SendMultipleActivity} did not call finish() 66 * prior to onResume() completing. That seems to be a problem on M: 67 * https://code.google.com/p/android-developer-preview/issues/detail?id=2353 68 */ 69 finish(); 70 } 71 72 /** 73 * Gets the {@link CustomActionSendMultipleListener} singleton. 74 */ getListener(Context context)75 static CustomActionSendMultipleListener getListener(Context context) { 76 synchronized (ActionSendMultipleConsumerActivity.class) { 77 if (sListener == null) { 78 sListener = new CustomActionSendMultipleListener(context); 79 } 80 } 81 return sListener; 82 } 83 84 /** 85 * Listener of custom ACTION_SEND_MULTIPLE_INTENTS. 86 */ 87 static class CustomActionSendMultipleListener { 88 89 private static final int TIMEOUT = 10; 90 private final BlockingQueue<Bundle> mQueue = new SynchronousQueue<>(); 91 CustomActionSendMultipleListener(Context context)92 public CustomActionSendMultipleListener(Context context) { 93 BroadcastReceiver receiver = new BroadcastReceiver() { 94 95 @Override 96 public void onReceive(Context context, Intent intent) { 97 try { 98 mQueue.put(intent.getExtras()); 99 } catch (InterruptedException e) { 100 Thread.currentThread().interrupt(); 101 } 102 } 103 }; 104 105 final IntentFilter filter = new IntentFilter(); 106 filter.addAction(CUSTOM_ACTION_SEND_MULTIPLE_INTENT); 107 context.registerReceiver(receiver, filter); 108 } 109 110 /** 111 * Gets the extras from the custom intent, blocking until it's received. 112 */ getExtras()113 Bundle getExtras() { 114 Bundle bundle = null; 115 try { 116 // UI operations can be slower the very first time the tests are run due 117 // because ActionSendMultipleConsumer is not the default activity chosen. 118 bundle = mQueue.poll(2 * TIMEOUT, TimeUnit.SECONDS); 119 } catch (InterruptedException e) { 120 Thread.currentThread().interrupt(); 121 } 122 if (bundle == null) { 123 throw new IllegalStateException("Intent not received after " + TIMEOUT + "s"); 124 } 125 return bundle; 126 } 127 } 128 } 129