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