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 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 } 77 78 public void refresh() { 79 PackageManager pm = mContext.getPackageManager(); 80 List<ApduServiceInfo> serviceInfos = 81 mCardEmuManager.getServices(CardEmulation.CATEGORY_PAYMENT); 82 ArrayList<PaymentAppInfo> appInfos = new ArrayList<PaymentAppInfo>(); 83 84 if (serviceInfos == null) { 85 makeCallbacks(); 86 return; 87 } 88 89 ComponentName defaultAppName = getDefaultPaymentApp(); 90 PaymentAppInfo foundDefaultApp = null; 91 for (ApduServiceInfo service : serviceInfos) { 92 PaymentAppInfo appInfo = new PaymentAppInfo(); 93 appInfo.label = service.loadLabel(pm); 94 if (appInfo.label == null) { 95 appInfo.label = service.loadAppLabel(pm); 96 } 97 appInfo.isDefault = service.getComponent().equals(defaultAppName); 98 if (appInfo.isDefault) { 99 foundDefaultApp = appInfo; 100 } 101 appInfo.componentName = service.getComponent(); 102 String settingsActivity = service.getSettingsActivityName(); 103 if (settingsActivity != null) { 104 appInfo.settingsComponent = new ComponentName(appInfo.componentName.getPackageName(), 105 settingsActivity); 106 } else { 107 appInfo.settingsComponent = null; 108 } 109 appInfo.description = service.getDescription(); 110 appInfo.banner = service.loadBanner(pm); 111 appInfos.add(appInfo); 112 } 113 mAppInfos = appInfos; 114 mDefaultAppInfo = foundDefaultApp; 115 makeCallbacks(); 116 } 117 118 public void registerCallback(Callback callback) { 119 mCallbacks.add(callback); 120 } 121 122 public void unregisterCallback(Callback callback) { 123 mCallbacks.remove(callback); 124 } 125 126 public List<PaymentAppInfo> getPaymentAppInfos() { 127 return mAppInfos; 128 } 129 130 public PaymentAppInfo getDefaultApp() { 131 return mDefaultAppInfo; 132 } 133 134 void makeCallbacks() { 135 for (Callback callback : mCallbacks) { 136 callback.onPaymentAppsChanged(); 137 } 138 } 139 140 Drawable loadDrawableForPackage(String pkgName, int drawableResId) { 141 PackageManager pm = mContext.getPackageManager(); 142 try { 143 Resources res = pm.getResourcesForApplication(pkgName); 144 Drawable banner = res.getDrawable(drawableResId); 145 return banner; 146 } catch (Resources.NotFoundException e) { 147 return null; 148 } catch (PackageManager.NameNotFoundException e) { 149 return null; 150 } 151 } 152 153 boolean isForegroundMode() { 154 try { 155 return Settings.Secure.getInt(mContext.getContentResolver(), 156 Settings.Secure.NFC_PAYMENT_FOREGROUND) != 0; 157 } catch (SettingNotFoundException e) { 158 return false; 159 } 160 } 161 162 void setForegroundMode(boolean foreground) { 163 Settings.Secure.putInt(mContext.getContentResolver(), 164 Settings.Secure.NFC_PAYMENT_FOREGROUND, foreground ? 1 : 0) ; 165 } 166 167 ComponentName getDefaultPaymentApp() { 168 String componentString = Settings.Secure.getString(mContext.getContentResolver(), 169 Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT); 170 if (componentString != null) { 171 return ComponentName.unflattenFromString(componentString); 172 } else { 173 return null; 174 } 175 } 176 177 public void setDefaultPaymentApp(ComponentName app) { 178 Settings.Secure.putString(mContext.getContentResolver(), 179 Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT, 180 app != null ? app.flattenToString() : null); 181 refresh(); 182 } 183 184 private final Handler mHandler = new Handler() { 185 @Override 186 public void dispatchMessage(Message msg) { 187 refresh(); 188 } 189 }; 190 191 private class SettingsPackageMonitor extends PackageMonitor { 192 @Override 193 public void onPackageAdded(String packageName, int uid) { 194 mHandler.obtainMessage().sendToTarget(); 195 } 196 197 @Override 198 public void onPackageAppeared(String packageName, int reason) { 199 mHandler.obtainMessage().sendToTarget(); 200 } 201 202 @Override 203 public void onPackageDisappeared(String packageName, int reason) { 204 mHandler.obtainMessage().sendToTarget(); 205 } 206 207 @Override 208 public void onPackageRemoved(String packageName, int uid) { 209 mHandler.obtainMessage().sendToTarget(); 210 } 211 } 212 } 213