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