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