Home | History | Annotate | Download | only in verifier
      1 // Copyright 2013 Google Inc. All Rights Reserved.
      2 
      3 package com.android.cts.verifier;
      4 
      5 import android.app.AlertDialog;
      6 import android.content.ActivityNotFoundException;
      7 import android.content.Intent;
      8 import android.os.Bundle;
      9 import android.os.Parcel;
     10 import android.os.Parcelable;
     11 import android.util.Log;
     12 import android.view.View;
     13 import android.view.View.OnClickListener;
     14 import android.view.ViewGroup;
     15 import android.widget.Button;
     16 import android.widget.TextView;
     17 
     18 /**
     19  *  A generic activity for intent based tests.
     20  *
     21  *  This activity can be reused for various tests that are intent based. The activity consists of a
     22  *  text view containing instructions and one or more buttons that trigger intents.
     23  *  Each button can send one or more intenrs as startActivity() calls.
     24  *
     25  *  The intents can either be generated statically and passed as an extra to the intent that started
     26  *  this activity or in some cases where the intent needs to be based on dynamic data (for example
     27  *  time of day), an {@link IntentFactory} class name can be passed instead. This intent factory
     28  *  will dynamically create the intent when the button is clicked based on the test id and the
     29  *  button that was clicked.
     30  */
     31 public class IntentDrivenTestActivity extends PassFailButtons.Activity implements OnClickListener {
     32     private static final String TAG = "IntentDrivenTestActivity";
     33 
     34     public static final String EXTRA_ID = "id";
     35     public static final String EXTRA_TITLE = "title";
     36     public static final String EXTRA_INFO = "info";
     37     public static final String EXTRA_BUTTONS = "buttons";
     38 
     39     private String mTestId;
     40     private ButtonInfo[] mButtonInfos;
     41 
     42 
     43     @Override
     44     protected void onCreate(Bundle savedInstanceState) {
     45         super.onCreate(savedInstanceState);
     46         setContentView(R.layout.intent_driven_test);
     47         setPassFailButtonClickListeners();
     48 
     49         final Intent intent = getIntent();
     50         if (!intent.hasExtra(EXTRA_ID)
     51                 || !intent.hasExtra(EXTRA_TITLE)
     52                 || !intent.hasExtra(EXTRA_INFO)
     53                 || !intent.hasExtra(EXTRA_BUTTONS)) {
     54             throw new IllegalArgumentException(
     55                     "Intent must have EXTRA_ID, EXTRA_TITLE, EXTRA_INFO & EXTRA_BUTTONS");
     56         }
     57 
     58         mTestId = intent.getStringExtra(EXTRA_ID);
     59         setTitle(intent.getIntExtra(EXTRA_TITLE, -1));
     60 
     61         final TextView info = (TextView) findViewById(R.id.info);
     62         info.setText(intent.getIntExtra(EXTRA_INFO, -1));
     63 
     64         final ViewGroup buttons = (ViewGroup) findViewById(R.id.buttons);
     65         final Parcelable[] parcelables = intent.getParcelableArrayExtra(EXTRA_BUTTONS);
     66         mButtonInfos = new ButtonInfo[parcelables.length];
     67         for (int i = 0; i < parcelables.length; i++) {
     68             final ButtonInfo buttonInfo = (ButtonInfo) parcelables[i];
     69             mButtonInfos[i] = buttonInfo;
     70             final Button button = new Button(this);
     71             buttons.addView(button);
     72             button.setText(buttonInfo.mButtonText);
     73             button.setTag(i);
     74             button.setOnClickListener(this);
     75         }
     76     }
     77 
     78     @Override
     79     protected void onResume() {
     80         super.onResume();
     81         setResult(RESULT_CANCELED);
     82     }
     83 
     84     @Override
     85     public void onClick(View v) {
     86         final ButtonInfo buttonInfo = mButtonInfos[(Integer) v.getTag()];
     87         final Intent[] intents = buttonInfo.getIntents();
     88         try {
     89             if (intents != null) {
     90                 for (Parcelable intent : intents) {
     91                     startActivity((Intent) intent);
     92                 }
     93             } else {
     94                 final Class<?> factoryClass;
     95                 final String className = buttonInfo.getIntentFactoryClassName();
     96                 try {
     97                     factoryClass = Thread.currentThread().getContextClassLoader().loadClass(className);
     98                 } catch (ClassNotFoundException e) {
     99                     throw new IllegalArgumentException("Factory not found: " + className, e);
    100                 }
    101                 final IntentFactory factory;
    102                 try {
    103                     factory = (IntentFactory) factoryClass.newInstance();
    104                 } catch (InstantiationException e) {
    105                     throw new IllegalArgumentException("Can't create factory: " + className, e);
    106                 } catch (IllegalAccessException e) {
    107                     throw new IllegalArgumentException("Can't create factory: " + className, e);
    108                 }
    109 
    110                 for (Intent intent : factory.createIntents(mTestId, buttonInfo.getButtonText())) {
    111                     startActivity(intent);
    112                 }
    113             }
    114         } catch (ActivityNotFoundException e) {
    115             // Instead of crashing, log and alert the user of that the Intent couldn't be resolved.
    116             Log.w(TAG, "Could not resolve Intent.", e);
    117             showFailedIntentResolution(e.getMessage());
    118         }
    119     }
    120 
    121     private void showFailedIntentResolution(String message) {
    122         new AlertDialog.Builder(this)
    123                 .setTitle(R.string.intent_not_resolved)
    124                 .setMessage(getString(R.string.intent_not_resolved_info, message))
    125                 .show();
    126     }
    127 
    128     @Override
    129     public String getTestId() {
    130         return mTestId;
    131     }
    132 
    133     public static class TestInfo {
    134         private final String mTestId;
    135         private final int mTitle;
    136         private final int mInfoText;
    137         private final ButtonInfo[] mButtons;
    138 
    139         public TestInfo(String testId,  int title, int infoText, ButtonInfo... buttons) {
    140             /** The Intent Driven Test layout {@link R.layout.intent_driven_test} is designed for
    141              *  up to 2 buttons and won't render well with more buttons on small screen devices.
    142              *  If you need more than 2 buttons, please change the layout so it can properly render
    143              *  them even on the smallest devices.
    144              */
    145             if (buttons.length > 2) {
    146                 throw new RuntimeException("Too many buttons");
    147             }
    148             mTestId = testId;
    149             mTitle = title;
    150             mInfoText = infoText;
    151             mButtons = buttons;
    152         }
    153 
    154         public String getTestId() {
    155             return mTestId;
    156         }
    157 
    158         public int getTitle() {
    159             return mTitle;
    160         }
    161 
    162         public int getInfoText() {
    163             return mInfoText;
    164         }
    165 
    166         public ButtonInfo[] getButtons() {
    167             return mButtons;
    168         }
    169     }
    170 
    171     public static class ButtonInfo implements Parcelable {
    172         private final int mButtonText;
    173         private final Intent[] mIntents;
    174         private final String mIntentFactoryClassName;
    175 
    176         public ButtonInfo(int buttonText, Intent... intents) {
    177             mButtonText = buttonText;
    178             mIntents = intents;
    179             mIntentFactoryClassName = null;
    180         }
    181 
    182         public ButtonInfo(int buttonText, String intentFactoryClassName) {
    183             mButtonText = buttonText;
    184             mIntents = null;
    185             mIntentFactoryClassName = intentFactoryClassName;
    186         }
    187 
    188         public ButtonInfo(Parcel source) {
    189             mButtonText = source.readInt();
    190             final Parcelable[] parcelables = source.readParcelableArray(null);
    191             if (parcelables != null) {
    192                 mIntents = new Intent[parcelables.length];
    193                 for (int i = 0, parcelablesLength = parcelables.length; i < parcelablesLength; i++) {
    194                     mIntents[i] = (Intent) parcelables[i];
    195                 }
    196             } else {
    197                 mIntents = null;
    198             }
    199             mIntentFactoryClassName = source.readString();
    200         }
    201 
    202         public int getButtonText() {
    203             return mButtonText;
    204         }
    205 
    206         public Intent[] getIntents() {
    207             return mIntents;
    208         }
    209 
    210         public String getIntentFactoryClassName() {
    211             return mIntentFactoryClassName;
    212         }
    213 
    214         @Override
    215         public int describeContents() {
    216             return 0;
    217         }
    218 
    219         @Override
    220         public void writeToParcel(Parcel dest, int flags) {
    221             dest.writeInt(mButtonText);
    222             dest.writeParcelableArray(mIntents, 0);
    223             dest.writeString(mIntentFactoryClassName);
    224         }
    225 
    226         public static final Creator<ButtonInfo> CREATOR = new Creator<ButtonInfo>() {
    227             public ButtonInfo createFromParcel(Parcel source) {
    228                 return new ButtonInfo(source);
    229             }
    230 
    231             public ButtonInfo[] newArray(int size) {
    232                 return new ButtonInfo[size];
    233             }
    234         };
    235 
    236     }
    237 
    238     public interface IntentFactory {
    239         Intent[] createIntents(String testId, int buttonText);
    240     }
    241 }
    242