1 package com.android.cts.verifier.nfc.hce;
2 
3 import android.annotation.TargetApi;
4 import android.app.Activity;
5 import android.app.AlertDialog;
6 import android.app.ProgressDialog;
7 import android.content.BroadcastReceiver;
8 import android.content.ComponentName;
9 import android.content.Context;
10 import android.content.DialogInterface;
11 import android.content.Intent;
12 import android.content.IntentFilter;
13 import android.nfc.NfcAdapter;
14 import android.nfc.cardemulation.CardEmulation;
15 import android.os.AsyncTask;
16 import android.os.Bundle;
17 import android.util.Log;
18 
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.List;
22 
23 import com.android.cts.verifier.PassFailButtons;
24 import com.android.cts.verifier.R;
25 
26 @TargetApi(19)
27 public abstract class BaseEmulatorActivity extends PassFailButtons.Activity {
28     static final String TAG = "BaseEmulatorActivity";
29     NfcAdapter mAdapter;
30     CardEmulation mCardEmulation;
31     ProgressDialog mSetupDialog;
32     ComponentName mMakingDefault;
33 
34     final ArrayList<ComponentName> SERVICES = new ArrayList<ComponentName>(
35             Arrays.asList(
36             PaymentService1.COMPONENT,
37             PaymentService2.COMPONENT,
38             TransportService1.COMPONENT,
39             TransportService2.COMPONENT,
40             AccessService.COMPONENT,
41             ThroughputService.COMPONENT,
42             OffHostService.COMPONENT,
43             PaymentServiceDynamicAids.COMPONENT,
44             PrefixPaymentService1.COMPONENT,
45             PrefixPaymentService2.COMPONENT,
46             PrefixTransportService1.COMPONENT,
47             PrefixTransportService2.COMPONENT,
48             PrefixAccessService.COMPONENT,
49             LargeNumAidsService.COMPONENT)
50     );
51 
52     @Override
onCreate(Bundle savedInstanceState)53     protected void onCreate(Bundle savedInstanceState) {
54         super.onCreate(savedInstanceState);
55 
56         mAdapter = NfcAdapter.getDefaultAdapter(this);
57         mCardEmulation = CardEmulation.getInstance(mAdapter);
58         IntentFilter filter = new IntentFilter(HceUtils.ACTION_APDU_SEQUENCE_COMPLETE);
59         registerReceiver(mReceiver, filter);
60     }
61 
onServicesSetup(boolean result)62     abstract void onServicesSetup(boolean result);
63 
onApduSequenceComplete(ComponentName component, long duration)64     abstract void onApduSequenceComplete(ComponentName component, long duration);
65 
onApduSequenceError()66     void onApduSequenceError() {
67 
68     }
69 
70     @Override
onStop()71     protected void onStop() {
72         super.onStop();
73     }
74 
75     @Override
onDestroy()76     protected void onDestroy() {
77         super.onDestroy();
78         unregisterReceiver(mReceiver);
79     }
80 
81     @Override
onPause()82     protected void onPause() {
83         super.onPause();
84     }
85 
86     @Override
onResume()87     protected void onResume() {
88         super.onResume();
89     }
90 
setupServices(Context context, ComponentName... components)91     final void setupServices(Context context, ComponentName... components) {
92         mSetupDialog = new ProgressDialog(context);
93         new SetupServicesTask().execute(components);
94     }
95 
makePaymentDefault(final ComponentName defaultComponent, int stringId)96     final boolean makePaymentDefault(final ComponentName defaultComponent, int stringId) {
97         if (!mCardEmulation.isDefaultServiceForCategory(defaultComponent,
98                 CardEmulation.CATEGORY_PAYMENT)) {
99             AlertDialog.Builder builder = new AlertDialog.Builder(this);
100             builder.setTitle("Note");
101             builder.setMessage(stringId);
102             mMakingDefault = defaultComponent;
103             builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
104                 @Override
105                 public void onClick(DialogInterface dialog, int which) {
106                 Intent changeDefault = new Intent(CardEmulation.ACTION_CHANGE_DEFAULT);
107                 changeDefault.putExtra(CardEmulation.EXTRA_CATEGORY, CardEmulation.CATEGORY_PAYMENT);
108                 changeDefault.putExtra(CardEmulation.EXTRA_SERVICE_COMPONENT, defaultComponent);
109                 startActivityForResult(changeDefault, 0);
110                 }
111             });
112             builder.show();
113             return true;
114         } else {
115             return false;
116         }
117     }
118 
119     final BroadcastReceiver mReceiver = new BroadcastReceiver() {
120         @Override
121         public void onReceive(Context context, Intent intent) {
122             String action = intent.getAction();
123             if (HceUtils.ACTION_APDU_SEQUENCE_COMPLETE.equals(action)) {
124                 // Get component whose sequence was completed
125                 ComponentName component = intent.getParcelableExtra(HceUtils.EXTRA_COMPONENT);
126                 long duration = intent.getLongExtra(HceUtils.EXTRA_DURATION, 0);
127                 if (component != null) {
128                     onApduSequenceComplete(component, duration);
129                 }
130             } else if (HceUtils.ACTION_APDU_SEQUENCE_ERROR.equals(action)) {
131                 onApduSequenceError();
132             }
133         }
134     };
135 
136     private class SetupServicesTask extends AsyncTask<ComponentName, Void, Boolean> {
137         @Override
onPostExecute(Boolean result)138         protected void onPostExecute(Boolean result) {
139             super.onPostExecute(result);
140             mSetupDialog.dismiss();
141             onServicesSetup(result);
142         }
143 
144         @Override
onPreExecute()145         protected void onPreExecute() {
146             super.onPreExecute();
147             mSetupDialog.setTitle(R.string.nfc_hce_please_wait);
148             mSetupDialog.setMessage(getString(R.string.nfc_hce_setting_up));
149             mSetupDialog.setCancelable(false);
150             mSetupDialog.show();
151         }
152 
153         @Override
doInBackground(ComponentName... components)154         protected Boolean doInBackground(ComponentName... components) {
155             List<ComponentName> enableComponents = Arrays.asList(components);
156             for (ComponentName component : SERVICES) {
157                 if (enableComponents.contains(component)) {
158                     Log.d(TAG, "Enabling component " + component);
159                     HceUtils.enableComponent(getPackageManager(), component);
160                 } else {
161                     Log.d(TAG, "Disabling component " + component);
162                     HceUtils.disableComponent(getPackageManager(), component);
163                 }
164             }
165             // This is a trick to invalidate the HCE cache and avoid
166             // having to wait for PackageManager broadcasts to NFCService.
167             ComponentName bogusComponent = new ComponentName("com.android.cts.verifier",
168                     "com.android.cts.verifier.nfc.hce.BogusService");
169             mCardEmulation.isDefaultServiceForCategory(bogusComponent,
170                     CardEmulation.CATEGORY_PAYMENT);
171             return true;
172         }
173     }
174 
175     @Override
onActivityResult(int requestCode, int resultCode, Intent data)176     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
177         super.onActivityResult(requestCode, resultCode, data);
178         if (resultCode == Activity.RESULT_OK) {
179             // Verify it's default
180             if (!mCardEmulation.isDefaultServiceForCategory(mMakingDefault,
181                     CardEmulation.CATEGORY_PAYMENT)) {
182                 // Popup dialog-box
183                 AlertDialog.Builder builder = new AlertDialog.Builder(this);
184                 builder.setTitle("Test failed.");
185                 builder.setMessage("The service was not made the default service according " +
186                         "to CardEmulation.getDefaultServiceForCategory(), verify the make " +
187                         "default implementation is correct.");
188                 builder.setPositiveButton("OK", null);
189                 builder.show();
190                 onPaymentDefaultResult(mMakingDefault, false);
191             } else {
192                 onPaymentDefaultResult(mMakingDefault, true);
193             }
194         } else {
195             AlertDialog.Builder builder = new AlertDialog.Builder(this);
196             builder.setTitle("Test failed.");
197             builder.setMessage("You clicked no.");
198             builder.setPositiveButton("OK", null);
199             builder.show();
200             onPaymentDefaultResult(mMakingDefault, false);
201         }
202     }
203 
onPaymentDefaultResult(ComponentName component, boolean success)204     void onPaymentDefaultResult(ComponentName component, boolean success) {
205 
206     };
207 }
208