Home | History | Annotate | Download | only in nfc
      1 /*
      2  * Copyright (C) 2013 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.settings.nfc;
     18 
     19 import android.content.ComponentName;
     20 import android.content.Context;
     21 import android.content.pm.PackageManager;
     22 import android.content.res.Resources;
     23 import android.graphics.drawable.Drawable;
     24 import android.nfc.NfcAdapter;
     25 import android.nfc.cardemulation.ApduServiceInfo;
     26 import android.nfc.cardemulation.CardEmulation;
     27 import android.os.Handler;
     28 import android.os.Message;
     29 import android.provider.Settings;
     30 import android.provider.Settings.SettingNotFoundException;
     31 
     32 import com.android.internal.content.PackageMonitor;
     33 
     34 import java.util.ArrayList;
     35 import java.util.List;
     36 
     37 public class PaymentBackend {
     38     public static final String TAG = "Settings.PaymentBackend";
     39 
     40     public interface Callback {
     41         void onPaymentAppsChanged();
     42     }
     43 
     44     public static class PaymentAppInfo {
     45         public CharSequence label;
     46         CharSequence description;
     47         Drawable banner;
     48         boolean isDefault;
     49         public ComponentName componentName;
     50         public ComponentName settingsComponent;
     51     }
     52 
     53     private final Context mContext;
     54     private final NfcAdapter mAdapter;
     55     private final CardEmulation mCardEmuManager;
     56     private final PackageMonitor mSettingsPackageMonitor = new SettingsPackageMonitor();
     57     // Fields below only modified on UI thread
     58     private ArrayList<PaymentAppInfo> mAppInfos;
     59     private PaymentAppInfo mDefaultAppInfo;
     60     private ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
     61 
     62     public PaymentBackend(Context context) {
     63         mContext = context;
     64 
     65         mAdapter = NfcAdapter.getDefaultAdapter(context);
     66         mCardEmuManager = CardEmulation.getInstance(mAdapter);
     67         refresh();
     68     }
     69 
     70     public void onPause() {
     71         mSettingsPackageMonitor.unregister();
     72     }
     73 
     74     public void onResume() {
     75         mSettingsPackageMonitor.register(mContext, mContext.getMainLooper(), false);
     76         refresh();
     77     }
     78 
     79     public void refresh() {
     80         PackageManager pm = mContext.getPackageManager();
     81         List<ApduServiceInfo> serviceInfos =
     82                 mCardEmuManager.getServices(CardEmulation.CATEGORY_PAYMENT);
     83         ArrayList<PaymentAppInfo> appInfos = new ArrayList<PaymentAppInfo>();
     84 
     85         if (serviceInfos == null) {
     86             makeCallbacks();
     87             return;
     88         }
     89 
     90         ComponentName defaultAppName = getDefaultPaymentApp();
     91         PaymentAppInfo foundDefaultApp = null;
     92         for (ApduServiceInfo service : serviceInfos) {
     93             PaymentAppInfo appInfo = new PaymentAppInfo();
     94             appInfo.label = service.loadLabel(pm);
     95             if (appInfo.label == null) {
     96                 appInfo.label = service.loadAppLabel(pm);
     97             }
     98             appInfo.isDefault = service.getComponent().equals(defaultAppName);
     99             if (appInfo.isDefault) {
    100                 foundDefaultApp = appInfo;
    101             }
    102             appInfo.componentName = service.getComponent();
    103             String settingsActivity = service.getSettingsActivityName();
    104             if (settingsActivity != null) {
    105                 appInfo.settingsComponent = new ComponentName(appInfo.componentName.getPackageName(),
    106                         settingsActivity);
    107             } else {
    108                 appInfo.settingsComponent = null;
    109             }
    110             appInfo.description = service.getDescription();
    111             appInfo.banner = service.loadBanner(pm);
    112             appInfos.add(appInfo);
    113         }
    114         mAppInfos = appInfos;
    115         mDefaultAppInfo = foundDefaultApp;
    116         makeCallbacks();
    117     }
    118 
    119     public void registerCallback(Callback callback) {
    120         mCallbacks.add(callback);
    121     }
    122 
    123     public void unregisterCallback(Callback callback) {
    124         mCallbacks.remove(callback);
    125     }
    126 
    127     public List<PaymentAppInfo> getPaymentAppInfos() {
    128         return mAppInfos;
    129     }
    130 
    131     public PaymentAppInfo getDefaultApp() {
    132         return mDefaultAppInfo;
    133     }
    134 
    135     void makeCallbacks() {
    136         for (Callback callback : mCallbacks) {
    137             callback.onPaymentAppsChanged();
    138         }
    139     }
    140 
    141     Drawable loadDrawableForPackage(String pkgName, int drawableResId) {
    142         PackageManager pm = mContext.getPackageManager();
    143         try {
    144             Resources res = pm.getResourcesForApplication(pkgName);
    145             Drawable banner = res.getDrawable(drawableResId);
    146             return banner;
    147         } catch (Resources.NotFoundException e) {
    148             return null;
    149         } catch (PackageManager.NameNotFoundException e) {
    150             return null;
    151         }
    152     }
    153 
    154     boolean isForegroundMode() {
    155         try {
    156             return Settings.Secure.getInt(mContext.getContentResolver(),
    157                     Settings.Secure.NFC_PAYMENT_FOREGROUND) != 0;
    158         } catch (SettingNotFoundException e) {
    159             return false;
    160         }
    161     }
    162 
    163     void setForegroundMode(boolean foreground) {
    164         Settings.Secure.putInt(mContext.getContentResolver(),
    165                 Settings.Secure.NFC_PAYMENT_FOREGROUND, foreground ? 1 : 0) ;
    166     }
    167 
    168     ComponentName getDefaultPaymentApp() {
    169         String componentString = Settings.Secure.getString(mContext.getContentResolver(),
    170                 Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT);
    171         if (componentString != null) {
    172             return ComponentName.unflattenFromString(componentString);
    173         } else {
    174             return null;
    175         }
    176     }
    177 
    178     public void setDefaultPaymentApp(ComponentName app) {
    179         Settings.Secure.putString(mContext.getContentResolver(),
    180                 Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT,
    181                 app != null ? app.flattenToString() : null);
    182         refresh();
    183     }
    184 
    185     private final Handler mHandler = new Handler() {
    186         @Override
    187         public void dispatchMessage(Message msg) {
    188             refresh();
    189         }
    190     };
    191 
    192     private class SettingsPackageMonitor extends PackageMonitor {
    193         @Override
    194         public void onPackageAdded(String packageName, int uid) {
    195             mHandler.obtainMessage().sendToTarget();
    196         }
    197 
    198         @Override
    199         public void onPackageAppeared(String packageName, int reason) {
    200             mHandler.obtainMessage().sendToTarget();
    201         }
    202 
    203         @Override
    204         public void onPackageDisappeared(String packageName, int reason) {
    205             mHandler.obtainMessage().sendToTarget();
    206         }
    207 
    208         @Override
    209         public void onPackageRemoved(String packageName, int uid) {
    210             mHandler.obtainMessage().sendToTarget();
    211         }
    212     }
    213 }
    214