blob: c9126f0684a6b1b2c374dacd0fa4771aefcea790 [file] [log] [blame]
nxpandroid34627bd2016-05-27 15:52:30 +05301/*
2 * Copyright (C) 2015 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 */
16package com.android.nfc.cardemulation;
17
18import java.io.FileDescriptor;
19import java.io.PrintWriter;
20
21import com.android.nfc.ForegroundUtils;
22
23import android.app.ActivityManager;
24import android.content.ComponentName;
25import android.content.Context;
26import android.nfc.cardemulation.NfcFServiceInfo;
27import android.os.Handler;
28import android.os.Looper;
29import android.util.Log;
nxf500513a018e72019-04-23 17:11:41 +053030import android.os.SystemProperties;
nxpandroid34627bd2016-05-27 15:52:30 +053031
32public class EnabledNfcFServices implements com.android.nfc.ForegroundUtils.Callback {
33 static final String TAG = "EnabledNfcFCardEmulationServices";
nxf500513a018e72019-04-23 17:11:41 +053034 static final boolean DBG = ((SystemProperties.get("persist.nfc.ce_debug").equals("1")) ? true : false);
nxpandroid34627bd2016-05-27 15:52:30 +053035
36 final Context mContext;
37 final RegisteredNfcFServicesCache mNfcFServiceCache;
38 final RegisteredT3tIdentifiersCache mT3tIdentifiersCache;
39 final Callback mCallback;
40 final ForegroundUtils mForegroundUtils = ForegroundUtils.getInstance();
41 final Handler mHandler = new Handler(Looper.getMainLooper());
42
43 final Object mLock = new Object();
44 // Variables below synchronized on mLock
45 ComponentName mForegroundComponent = null; // The computed enabled foreground component
46 ComponentName mForegroundRequested = null; // The component requested to be enabled by fg app
47 int mForegroundUid = -1; // The UID of the fg app, or -1 if fg app didn't request
48
49 boolean mComputeFgRequested = false;
50 boolean mActivated = false;
51
52 public interface Callback {
53 void onEnabledForegroundNfcFServiceChanged(ComponentName service);
54 }
55
56 public EnabledNfcFServices(Context context,
57 RegisteredNfcFServicesCache nfcFServiceCache,
58 RegisteredT3tIdentifiersCache t3tIdentifiersCache, Callback callback) {
59 if (DBG) Log.d(TAG, "EnabledNfcFServices");
60 mContext = context;
61 mNfcFServiceCache = nfcFServiceCache;
62 mT3tIdentifiersCache = t3tIdentifiersCache;
63 mCallback = callback;
64 }
65
66 void computeEnabledForegroundService() {
67 if (DBG) Log.d(TAG, "computeEnabledForegroundService");
68 ComponentName foregroundRequested = null;
69 boolean changed = false;
70 synchronized (mLock) {
71 if (mActivated) {
72 Log.d(TAG, "configuration will be postponed until deactivation");
73 mComputeFgRequested = true;
74 return;
75 }
76 mComputeFgRequested = false;
77 foregroundRequested = mForegroundRequested;
78 if (mForegroundRequested != null &&
79 (mForegroundComponent == null ||
80 !mForegroundRequested.equals(mForegroundComponent))) {
81 mForegroundComponent = mForegroundRequested;
82 changed = true;
83 } else if (mForegroundRequested == null && mForegroundComponent != null){
84 mForegroundComponent = mForegroundRequested;
85 changed = true;
86 }
87 }
88 // Notify if anything changed
89 if (changed) {
90 mCallback.onEnabledForegroundNfcFServiceChanged(foregroundRequested);
91 }
92 }
93
94 public void onServicesUpdated() {
95 if (DBG) Log.d(TAG, "onServicesUpdated");
96 // If enabled foreground service is set, remove it
97 boolean changed = false;
98 synchronized (mLock) {
99 if (mForegroundComponent != null) {
100 Log.d(TAG, "Removing foreground enabled service because of service update.");
101 mForegroundRequested = null;
102 mForegroundUid = -1;
103 changed = true;
104 }
105 }
106 if (changed) {
107 computeEnabledForegroundService();
108 }
109 }
110
111 public boolean registerEnabledForegroundService(ComponentName service, int callingUid) {
112 if (DBG) Log.d(TAG, "registerEnabledForegroundService");
113 boolean success = false;
114 synchronized (mLock) {
115 NfcFServiceInfo serviceInfo = mNfcFServiceCache.getService(
116 ActivityManager.getCurrentUser(), service);
117 if (serviceInfo == null) {
118 return false;
119 } else {
120 if (serviceInfo.getSystemCode().equalsIgnoreCase("NULL") ||
nxpandroid6fd9cdb2017-07-12 18:25:41 +0530121 serviceInfo.getNfcid2().equalsIgnoreCase("NULL") ||
122 serviceInfo.getT3tPmm().equalsIgnoreCase("NULL")) {
nxpandroid34627bd2016-05-27 15:52:30 +0530123 return false;
124 }
125 }
126 if (service.equals(mForegroundRequested)) {
127 Log.e(TAG, "The servcie is already requested to the foreground service.");
128 return true;
129 }
130 if (mForegroundUtils.registerUidToBackgroundCallback(this, callingUid)) {
131 mForegroundRequested = service;
132 mForegroundUid = callingUid;
133 success = true;
134 } else {
135 Log.e(TAG, "Calling UID is not in the foreground, ignorning!");
136 }
137 }
138 if (success) {
139 computeEnabledForegroundService();
140 }
141 return success;
142 }
143
144 boolean unregisterForegroundService(int uid) {
145 if (DBG) Log.d(TAG, "unregisterForegroundService");
146 boolean success = false;
147 synchronized (mLock) {
148 if (mForegroundUid == uid) {
149 mForegroundRequested = null;
150 mForegroundUid = -1;
151 success = true;
152 } // else, other UID in foreground
153 }
154 if (success) {
155 computeEnabledForegroundService();
156 }
157 return success;
158 }
159
160 public boolean unregisteredEnabledForegroundService(int callingUid) {
161 if (DBG) Log.d(TAG, "unregisterEnabledForegroundService");
162 // Verify the calling UID is in the foreground
163 if (mForegroundUtils.isInForeground(callingUid)) {
164 return unregisterForegroundService(callingUid);
165 } else {
166 Log.e(TAG, "Calling UID is not in the foreground, ignorning!");
167 return false;
168 }
169 }
170
171 @Override
172 public void onUidToBackground(int uid) {
173 if (DBG) Log.d(TAG, "onUidToBackground");
174 unregisterForegroundService(uid);
175 }
176
177 public void onHostEmulationActivated() {
178 if (DBG) Log.d(TAG, "onHostEmulationActivated");
179 synchronized (mLock) {
180 mActivated = true;
181 }
182 }
183
184 public void onHostEmulationDeactivated() {
185 if (DBG) Log.d(TAG, "onHostEmulationDeactivated");
186 boolean needComputeFg = false;
187 synchronized (mLock) {
188 mActivated = false;
189 if (mComputeFgRequested) {
190 needComputeFg = true;
191 }
192 }
193 if (needComputeFg) {
194 Log.d(TAG, "do postponed configuration");
195 computeEnabledForegroundService();
196 }
197 }
198
199 public void onNfcDisabled() {
200 synchronized (mLock) {
201 mForegroundComponent = null;
202 mForegroundRequested = null;
203 mActivated = false;
204 mComputeFgRequested = false;
205 mForegroundUid = -1;
206 }
207 }
208
209 public void onUserSwitched(int userId) {
210 synchronized (mLock) {
211 mForegroundComponent = null;
212 mForegroundRequested = null;
213 mActivated = false;
214 mComputeFgRequested = false;
215 mForegroundUid = -1;
216 }
217 }
218
219 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
220 }
221}