175f63db568f953e935e62cb3046d167b881979c8Martijn Coenen/*
275f63db568f953e935e62cb3046d167b881979c8Martijn Coenen * Copyright (C) 2013 The Android Open Source Project
375f63db568f953e935e62cb3046d167b881979c8Martijn Coenen *
475f63db568f953e935e62cb3046d167b881979c8Martijn Coenen * Licensed under the Apache License, Version 2.0 (the "License");
575f63db568f953e935e62cb3046d167b881979c8Martijn Coenen * you may not use this file except in compliance with the License.
675f63db568f953e935e62cb3046d167b881979c8Martijn Coenen * You may obtain a copy of the License at
775f63db568f953e935e62cb3046d167b881979c8Martijn Coenen *
875f63db568f953e935e62cb3046d167b881979c8Martijn Coenen *      http://www.apache.org/licenses/LICENSE-2.0
975f63db568f953e935e62cb3046d167b881979c8Martijn Coenen *
1075f63db568f953e935e62cb3046d167b881979c8Martijn Coenen * Unless required by applicable law or agreed to in writing, software
1175f63db568f953e935e62cb3046d167b881979c8Martijn Coenen * distributed under the License is distributed on an "AS IS" BASIS,
1275f63db568f953e935e62cb3046d167b881979c8Martijn Coenen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1375f63db568f953e935e62cb3046d167b881979c8Martijn Coenen * See the License for the specific language governing permissions and
1475f63db568f953e935e62cb3046d167b881979c8Martijn Coenen * limitations under the License.
1575f63db568f953e935e62cb3046d167b881979c8Martijn Coenen */
1675f63db568f953e935e62cb3046d167b881979c8Martijn Coenen
1775f63db568f953e935e62cb3046d167b881979c8Martijn Coenenpackage com.android.nfc.cardemulation;
1875f63db568f953e935e62cb3046d167b881979c8Martijn Coenen
1975f63db568f953e935e62cb3046d167b881979c8Martijn Coenenimport com.android.internal.R;
2075f63db568f953e935e62cb3046d167b881979c8Martijn Coenenimport com.android.internal.app.AlertActivity;
2175f63db568f953e935e62cb3046d167b881979c8Martijn Coenenimport com.android.internal.app.AlertController;
2275f63db568f953e935e62cb3046d167b881979c8Martijn Coenen
2375f63db568f953e935e62cb3046d167b881979c8Martijn Coenenimport java.util.ArrayList;
2475f63db568f953e935e62cb3046d167b881979c8Martijn Coenenimport java.util.List;
2575f63db568f953e935e62cb3046d167b881979c8Martijn Coenen
2675f63db568f953e935e62cb3046d167b881979c8Martijn Coenenimport android.app.ActivityManager;
27dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenenimport android.content.BroadcastReceiver;
2875f63db568f953e935e62cb3046d167b881979c8Martijn Coenenimport android.content.ComponentName;
2975f63db568f953e935e62cb3046d167b881979c8Martijn Coenenimport android.content.Context;
3075f63db568f953e935e62cb3046d167b881979c8Martijn Coenenimport android.content.Intent;
31dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenenimport android.content.IntentFilter;
3275f63db568f953e935e62cb3046d167b881979c8Martijn Coenenimport android.content.pm.ApplicationInfo;
3375f63db568f953e935e62cb3046d167b881979c8Martijn Coenenimport android.content.pm.PackageManager;
3475f63db568f953e935e62cb3046d167b881979c8Martijn Coenenimport android.content.pm.PackageManager.NameNotFoundException;
3575f63db568f953e935e62cb3046d167b881979c8Martijn Coenenimport android.graphics.drawable.Drawable;
3675f63db568f953e935e62cb3046d167b881979c8Martijn Coenenimport android.nfc.NfcAdapter;
37dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenenimport android.nfc.cardemulation.ApduServiceInfo;
38f5cd84c3a7ffb66196ab3c0745569da937d7533bMartijn Coenenimport android.nfc.cardemulation.CardEmulation;
3975f63db568f953e935e62cb3046d167b881979c8Martijn Coenenimport android.os.Bundle;
4075f63db568f953e935e62cb3046d167b881979c8Martijn Coenenimport android.util.Log;
4175f63db568f953e935e62cb3046d167b881979c8Martijn Coenenimport android.view.LayoutInflater;
4275f63db568f953e935e62cb3046d167b881979c8Martijn Coenenimport android.view.View;
4375f63db568f953e935e62cb3046d167b881979c8Martijn Coenenimport android.view.ViewGroup;
44451ba48faa87d78bfbec0597ff06af1747cf6acbMartijn Coenenimport android.view.Window;
45451ba48faa87d78bfbec0597ff06af1747cf6acbMartijn Coenenimport android.view.WindowManager;
4675f63db568f953e935e62cb3046d167b881979c8Martijn Coenenimport android.widget.AdapterView;
4775f63db568f953e935e62cb3046d167b881979c8Martijn Coenenimport android.widget.BaseAdapter;
4875f63db568f953e935e62cb3046d167b881979c8Martijn Coenenimport android.widget.ImageView;
4975f63db568f953e935e62cb3046d167b881979c8Martijn Coenenimport android.widget.ListView;
5075f63db568f953e935e62cb3046d167b881979c8Martijn Coenenimport android.widget.TextView;
5175f63db568f953e935e62cb3046d167b881979c8Martijn Coenen
5275f63db568f953e935e62cb3046d167b881979c8Martijn Coenenpublic class AppChooserActivity extends AlertActivity
5375f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        implements AdapterView.OnItemClickListener {
5475f63db568f953e935e62cb3046d167b881979c8Martijn Coenen
5575f63db568f953e935e62cb3046d167b881979c8Martijn Coenen    static final String TAG = "AppChooserActivity";
5675f63db568f953e935e62cb3046d167b881979c8Martijn Coenen
57dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen    public static final String EXTRA_APDU_SERVICES = "services";
5875f63db568f953e935e62cb3046d167b881979c8Martijn Coenen    public static final String EXTRA_CATEGORY = "category";
5978976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen    public static final String EXTRA_FAILED_COMPONENT = "failed_component";
6075f63db568f953e935e62cb3046d167b881979c8Martijn Coenen
6175f63db568f953e935e62cb3046d167b881979c8Martijn Coenen    private int mIconSize;
6275f63db568f953e935e62cb3046d167b881979c8Martijn Coenen    private ListView mListView;
6375f63db568f953e935e62cb3046d167b881979c8Martijn Coenen    private ListAdapter mListAdapter;
64f5cd84c3a7ffb66196ab3c0745569da937d7533bMartijn Coenen    private CardEmulation mCardEmuManager;
6575f63db568f953e935e62cb3046d167b881979c8Martijn Coenen    private String mCategory;
6675f63db568f953e935e62cb3046d167b881979c8Martijn Coenen
67dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen    final BroadcastReceiver mReceiver = new BroadcastReceiver() {
68dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen        @Override
69dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen        public void onReceive(Context context, Intent intent) {
70dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen            finish();
71dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen        }
72dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen    };
73dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen
74dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen    @Override
75dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen    protected void onDestroy() {
76dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen        super.onDestroy();
77dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen        unregisterReceiver(mReceiver);
78dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen    }
79dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen
8075f63db568f953e935e62cb3046d167b881979c8Martijn Coenen    protected void onCreate(Bundle savedInstanceState, String category,
81dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen            ArrayList<ApduServiceInfo> options, ComponentName failedComponent) {
8275f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        super.onCreate(savedInstanceState);
83451ba48faa87d78bfbec0597ff06af1747cf6acbMartijn Coenen        setTheme(R.style.Theme_DeviceDefault_Light_Dialog_Alert);
8475f63db568f953e935e62cb3046d167b881979c8Martijn Coenen
85dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen        IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
86dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen        registerReceiver(mReceiver, filter);
87dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen
8878976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen        if ((options == null || options.size() == 0) && failedComponent == null) {
8975f63db568f953e935e62cb3046d167b881979c8Martijn Coenen            Log.e(TAG, "No components passed in.");
9075f63db568f953e935e62cb3046d167b881979c8Martijn Coenen            finish();
9175f63db568f953e935e62cb3046d167b881979c8Martijn Coenen            return;
9275f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        }
9375f63db568f953e935e62cb3046d167b881979c8Martijn Coenen
9475f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        mCategory = category;
95dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen        boolean isPayment = CardEmulation.CATEGORY_PAYMENT.equals(mCategory);
9675f63db568f953e935e62cb3046d167b881979c8Martijn Coenen
9775f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        final NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this);
98f5cd84c3a7ffb66196ab3c0745569da937d7533bMartijn Coenen        mCardEmuManager = CardEmulation.getInstance(adapter);
9975f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        AlertController.AlertParams ap = mAlertParams;
10075f63db568f953e935e62cb3046d167b881979c8Martijn Coenen
10175f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        final ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
10275f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        mIconSize = am.getLauncherLargeIconSize();
10375f63db568f953e935e62cb3046d167b881979c8Martijn Coenen
10478976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen        // Three cases:
10578976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen        // 1. Failed component and no alternatives: just an OK box
10678976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen        // 2. Failed component and alternatives: pick alternative
10778976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen        // 3. No failed component and alternatives: pick alternative
10878976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen        PackageManager pm = getPackageManager();
10975f63db568f953e935e62cb3046d167b881979c8Martijn Coenen
11078976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen        CharSequence applicationLabel = "unknown";
11178976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen        if (failedComponent != null) {
11278976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen            try {
11378976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen                ApplicationInfo info = pm.getApplicationInfo(failedComponent.getPackageName(), 0);
11478976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen                applicationLabel = info.loadLabel(pm);
11578976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen            } catch (NameNotFoundException e) {
11678976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen            }
11778976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen
11878976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen        }
11978976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen        if (options.size() == 0 && failedComponent != null) {
120dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen            String formatString = getString(com.android.nfc.R.string.transaction_failure);
12178976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen            ap.mTitle = "";
122dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen            ap.mMessage = String.format(formatString, applicationLabel);
123dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen            ap.mPositiveButtonText = getString(R.string.ok);
12478976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen            setupAlert();
12575f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        } else {
12678976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen            mListAdapter = new ListAdapter(this, options);
12778976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen            if (failedComponent != null) {
128dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen                String formatString = getString(com.android.nfc.R.string.could_not_use_app);
129dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen                ap.mTitle = String.format(formatString, applicationLabel);
130dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen                ap.mNegativeButtonText = getString(R.string.cancel);
13178976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen            } else {
132f5cd84c3a7ffb66196ab3c0745569da937d7533bMartijn Coenen                if (CardEmulation.CATEGORY_PAYMENT.equals(category)) {
133dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen                    ap.mTitle = getString(com.android.nfc.R.string.pay_with);
13478976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen                } else {
135dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen                    ap.mTitle = getString(com.android.nfc.R.string.complete_with);
13678976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen                }
13778976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen            }
13878976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen            ap.mView = getLayoutInflater().inflate(com.android.nfc.R.layout.cardemu_resolver, null);
13978976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen
14078976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen            mListView = (ListView) ap.mView.findViewById(com.android.nfc.R.id.resolver_list);
141dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen            if (isPayment) {
142a3b2c7944266cbd02afc08ce48ce8259d8a65019Martijn Coenen                mListView.setDivider(getResources().getDrawable(android.R.color.transparent));
143a3b2c7944266cbd02afc08ce48ce8259d8a65019Martijn Coenen                int height = (int) (getResources().getDisplayMetrics().density * 16);
144a3b2c7944266cbd02afc08ce48ce8259d8a65019Martijn Coenen                mListView.setDividerHeight(height);
145dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen            } else {
146dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen                mListView.setPadding(0, 0, 0, 0);
147dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen            }
14878976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen            mListView.setAdapter(mListAdapter);
14978976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen            mListView.setOnItemClickListener(this);
15078976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen
15178976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen            setupAlert();
15275f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        }
153451ba48faa87d78bfbec0597ff06af1747cf6acbMartijn Coenen        Window window = getWindow();
154451ba48faa87d78bfbec0597ff06af1747cf6acbMartijn Coenen        window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
15575f63db568f953e935e62cb3046d167b881979c8Martijn Coenen    }
15675f63db568f953e935e62cb3046d167b881979c8Martijn Coenen
15775f63db568f953e935e62cb3046d167b881979c8Martijn Coenen    @Override
15875f63db568f953e935e62cb3046d167b881979c8Martijn Coenen    protected void onCreate(Bundle savedInstanceState) {
15975f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        Intent intent = getIntent();
160dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen        ArrayList<ApduServiceInfo> services = intent.getParcelableArrayListExtra(EXTRA_APDU_SERVICES);
16175f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        String category = intent.getStringExtra(EXTRA_CATEGORY);
16278976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen        ComponentName failedComponent = intent.getParcelableExtra(EXTRA_FAILED_COMPONENT);
163dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen        onCreate(savedInstanceState, category, services, failedComponent);
16475f63db568f953e935e62cb3046d167b881979c8Martijn Coenen    }
16575f63db568f953e935e62cb3046d167b881979c8Martijn Coenen
16675f63db568f953e935e62cb3046d167b881979c8Martijn Coenen    @Override
16775f63db568f953e935e62cb3046d167b881979c8Martijn Coenen    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
16875f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        DisplayAppInfo info = (DisplayAppInfo) mListAdapter.getItem(position);
169a3b2c7944266cbd02afc08ce48ce8259d8a65019Martijn Coenen        mCardEmuManager.setDefaultForNextTap(info.serviceInfo.getComponent());
17075f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        Intent dialogIntent = new Intent(this, TapAgainDialog.class);
17175f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        dialogIntent.putExtra(TapAgainDialog.EXTRA_CATEGORY, mCategory);
172a3b2c7944266cbd02afc08ce48ce8259d8a65019Martijn Coenen        dialogIntent.putExtra(TapAgainDialog.EXTRA_APDU_SERVICE, info.serviceInfo);
17375f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        startActivity(dialogIntent);
17475f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        finish();
17575f63db568f953e935e62cb3046d167b881979c8Martijn Coenen    }
17675f63db568f953e935e62cb3046d167b881979c8Martijn Coenen
17775f63db568f953e935e62cb3046d167b881979c8Martijn Coenen    final class DisplayAppInfo {
178a3b2c7944266cbd02afc08ce48ce8259d8a65019Martijn Coenen        ApduServiceInfo serviceInfo;
17975f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        CharSequence displayLabel;
18075f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        Drawable displayIcon;
181dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen        Drawable displayBanner;
18275f63db568f953e935e62cb3046d167b881979c8Martijn Coenen
183a3b2c7944266cbd02afc08ce48ce8259d8a65019Martijn Coenen        public DisplayAppInfo(ApduServiceInfo serviceInfo, CharSequence label, Drawable icon,
184dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen                Drawable banner) {
185a3b2c7944266cbd02afc08ce48ce8259d8a65019Martijn Coenen            this.serviceInfo = serviceInfo;
18675f63db568f953e935e62cb3046d167b881979c8Martijn Coenen            displayIcon = icon;
18775f63db568f953e935e62cb3046d167b881979c8Martijn Coenen            displayLabel = label;
188dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen            displayBanner = banner;
18975f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        }
19075f63db568f953e935e62cb3046d167b881979c8Martijn Coenen    }
19175f63db568f953e935e62cb3046d167b881979c8Martijn Coenen
19275f63db568f953e935e62cb3046d167b881979c8Martijn Coenen    final class ListAdapter extends BaseAdapter {
19375f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        private final LayoutInflater mInflater;
194dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen        private final boolean mIsPayment;
19575f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        private List<DisplayAppInfo> mList;
19675f63db568f953e935e62cb3046d167b881979c8Martijn Coenen
197dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen        public ListAdapter(Context context, ArrayList<ApduServiceInfo> services) {
19875f63db568f953e935e62cb3046d167b881979c8Martijn Coenen            mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
19975f63db568f953e935e62cb3046d167b881979c8Martijn Coenen            // For each component, get the corresponding app name and icon
20075f63db568f953e935e62cb3046d167b881979c8Martijn Coenen            PackageManager pm = getPackageManager();
20175f63db568f953e935e62cb3046d167b881979c8Martijn Coenen            mList = new ArrayList<DisplayAppInfo>();
202dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen            mIsPayment = CardEmulation.CATEGORY_PAYMENT.equals(mCategory);
203dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen            for (ApduServiceInfo service : services) {
204a3b2c7944266cbd02afc08ce48ce8259d8a65019Martijn Coenen                CharSequence label = service.getDescription();
205a3b2c7944266cbd02afc08ce48ce8259d8a65019Martijn Coenen                if (label == null) label = service.loadLabel(pm);
206dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen                Drawable icon = service.loadIcon(pm);
207dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen                Drawable banner = null;
208dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen                if (mIsPayment) {
209dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen                    banner = service.loadBanner(pm);
210dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen                    if (banner == null) {
211dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen                        Log.e(TAG, "Not showing " + label + " because no banner specified.");
212dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen                        continue;
213dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen                    }
21475f63db568f953e935e62cb3046d167b881979c8Martijn Coenen                }
215a3b2c7944266cbd02afc08ce48ce8259d8a65019Martijn Coenen                DisplayAppInfo info = new DisplayAppInfo(service, label, icon, banner);
216dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen                mList.add(info);
21775f63db568f953e935e62cb3046d167b881979c8Martijn Coenen            }
21875f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        }
21975f63db568f953e935e62cb3046d167b881979c8Martijn Coenen
22075f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        @Override
22175f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        public int getCount() {
22275f63db568f953e935e62cb3046d167b881979c8Martijn Coenen            return mList.size();
22375f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        }
22475f63db568f953e935e62cb3046d167b881979c8Martijn Coenen
22575f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        @Override
22675f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        public Object getItem(int position) {
22775f63db568f953e935e62cb3046d167b881979c8Martijn Coenen            return mList.get(position);
22875f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        }
22975f63db568f953e935e62cb3046d167b881979c8Martijn Coenen
23075f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        @Override
23175f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        public long getItemId(int position) {
23275f63db568f953e935e62cb3046d167b881979c8Martijn Coenen            return position;
23375f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        }
23475f63db568f953e935e62cb3046d167b881979c8Martijn Coenen
23575f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        @Override
23675f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        public View getView(int position, View convertView, ViewGroup parent) {
23775f63db568f953e935e62cb3046d167b881979c8Martijn Coenen            View view;
23875f63db568f953e935e62cb3046d167b881979c8Martijn Coenen            if (convertView == null) {
239dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen                if (mIsPayment) {
240dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen                    view = mInflater.inflate(
241dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen                            com.android.nfc.R.layout.cardemu_payment_item, parent, false);
242dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen                } else {
243dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen                    view = mInflater.inflate(
244dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen                            com.android.nfc.R.layout.cardemu_item, parent, false);
245dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen                }
24675f63db568f953e935e62cb3046d167b881979c8Martijn Coenen                final ViewHolder holder = new ViewHolder(view);
24775f63db568f953e935e62cb3046d167b881979c8Martijn Coenen                view.setTag(holder);
24875f63db568f953e935e62cb3046d167b881979c8Martijn Coenen
24975f63db568f953e935e62cb3046d167b881979c8Martijn Coenen            } else {
25075f63db568f953e935e62cb3046d167b881979c8Martijn Coenen                view = convertView;
25175f63db568f953e935e62cb3046d167b881979c8Martijn Coenen            }
25275f63db568f953e935e62cb3046d167b881979c8Martijn Coenen
25375f63db568f953e935e62cb3046d167b881979c8Martijn Coenen            final ViewHolder holder = (ViewHolder) view.getTag();
25475f63db568f953e935e62cb3046d167b881979c8Martijn Coenen            DisplayAppInfo appInfo = mList.get(position);
255dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen            if (mIsPayment) {
256dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen                holder.banner.setImageDrawable(appInfo.displayBanner);
257dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen            } else {
258dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen                ViewGroup.LayoutParams lp = holder.icon.getLayoutParams();
259dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen                lp.width = lp.height = mIconSize;
260dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen                holder.icon.setImageDrawable(appInfo.displayIcon);
261dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen                holder.text.setText(appInfo.displayLabel);
262dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen            }
26375f63db568f953e935e62cb3046d167b881979c8Martijn Coenen            return view;
26475f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        }
26575f63db568f953e935e62cb3046d167b881979c8Martijn Coenen    }
26675f63db568f953e935e62cb3046d167b881979c8Martijn Coenen
26775f63db568f953e935e62cb3046d167b881979c8Martijn Coenen    static class ViewHolder {
26875f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        public TextView text;
26975f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        public ImageView icon;
270dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen        public ImageView banner;
27175f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        public ViewHolder(View view) {
27275f63db568f953e935e62cb3046d167b881979c8Martijn Coenen            text = (TextView) view.findViewById(com.android.nfc.R.id.applabel);
27375f63db568f953e935e62cb3046d167b881979c8Martijn Coenen            icon = (ImageView) view.findViewById(com.android.nfc.R.id.appicon);
274dc304dadda013e383fdd1348b2a24bc6b3c9acacMartijn Coenen            banner = (ImageView) view.findViewById(com.android.nfc.R.id.banner);
27575f63db568f953e935e62cb3046d167b881979c8Martijn Coenen        }
27675f63db568f953e935e62cb3046d167b881979c8Martijn Coenen    }
27775f63db568f953e935e62cb3046d167b881979c8Martijn Coenen}