blob: 075858dd7e68a17ee4303368b72c6339dd567aa6 [file] [log] [blame]
nxf500513a018e72019-04-23 17:11:41 +05301/*
nxpandroid64fd68c2015-09-23 16:45:15 +05302 * Copyright (C) 2010 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/******************************************************************************
nxf500513a018e72019-04-23 17:11:41 +053017*
18* The original Work has been changed by NXP.
19*
20* Licensed under the Apache License, Version 2.0 (the "License");
21* you may not use this file except in compliance with the License.
22* You may obtain a copy of the License at
23*
24* http://www.apache.org/licenses/LICENSE-2.0
25*
26* Unless required by applicable law or agreed to in writing, software
27* distributed under the License is distributed on an "AS IS" BASIS,
28* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29* See the License for the specific language governing permissions and
30* limitations under the License.
31*
32* Copyright 2018-2019 NXP
33*
34******************************************************************************/
nxpandroid64fd68c2015-09-23 16:45:15 +053035package com.android.nfc;
36
37import android.app.ActivityManager;
38import android.app.Application;
nxpandroid6fd9cdb2017-07-12 18:25:41 +053039import android.app.backup.BackupManager;
nxpandroid64fd68c2015-09-23 16:45:15 +053040import android.app.KeyguardManager;
41import android.app.PendingIntent;
42import android.app.admin.DevicePolicyManager;
43import android.content.BroadcastReceiver;
44import android.content.ComponentName;
45import android.content.ContentResolver;
46import android.content.Context;
47import android.content.Intent;
48import android.content.IntentFilter;
49import android.content.SharedPreferences;
Suhas Sureshca6584b2018-04-27 17:17:22 +053050import android.content.pm.ApplicationInfo;
nxpandroid64fd68c2015-09-23 16:45:15 +053051import android.content.pm.IPackageManager;
52import android.content.pm.PackageInfo;
nxpandroid64fd68c2015-09-23 16:45:15 +053053import android.content.pm.PackageManager;
54import android.content.pm.UserInfo;
55import android.content.res.Resources.NotFoundException;
56import android.media.AudioManager;
57import android.media.SoundPool;
58import android.net.Uri;
59import android.nfc.BeamShareData;
60import android.nfc.ErrorCodes;
61import android.nfc.FormatException;
62import android.nfc.IAppCallback;
63import android.nfc.INfcAdapter;
64import android.nfc.INfcAdapterExtras;
65import android.nfc.INfcCardEmulation;
nxf500513a018e72019-04-23 17:11:41 +053066import android.nfc.INfcDta;
nxpandroid34627bd2016-05-27 15:52:30 +053067import android.nfc.INfcFCardEmulation;
nxpandroid64fd68c2015-09-23 16:45:15 +053068import android.nfc.INfcTag;
69import android.nfc.INfcUnlockHandler;
nxpandroid281eb922016-08-25 20:27:46 +053070import android.nfc.ITagRemovedCallback;
nxpandroid64fd68c2015-09-23 16:45:15 +053071import android.nfc.NdefMessage;
72import android.nfc.NfcAdapter;
73import android.nfc.Tag;
74import android.nfc.TechListParcel;
75import android.nfc.TransceiveResult;
76import android.nfc.tech.Ndef;
77import android.nfc.tech.TagTechnology;
78import android.os.AsyncTask;
79import android.os.Binder;
nxf500513a018e72019-04-23 17:11:41 +053080import android.os.HwBinder;
nxpandroid64fd68c2015-09-23 16:45:15 +053081import android.os.Build;
82import android.os.Bundle;
83import android.os.Handler;
84import android.os.IBinder;
85import android.os.Message;
86import android.os.PowerManager;
87import android.os.Process;
88import android.os.RemoteException;
89import android.os.ServiceManager;
90import android.os.SystemClock;
Nikhil Chhabraa9e399a2018-01-09 11:47:13 +053091import android.os.SystemProperties;
nxpandroid64fd68c2015-09-23 16:45:15 +053092import android.os.UserHandle;
93import android.os.UserManager;
Suhas Suresh6e05ee02018-04-25 12:19:35 +053094import android.os.VibrationEffect;
95import android.os.Vibrator;
nxpandroid64fd68c2015-09-23 16:45:15 +053096import android.provider.Settings;
Nikhil Chhabrafc8f3f62018-01-08 20:48:49 +053097import android.service.vr.IVrManager;
98import android.service.vr.IVrStateCallbacks;
nxf500513a018e72019-04-23 17:11:41 +053099import android.text.TextUtils;
nxpandroid64fd68c2015-09-23 16:45:15 +0530100import android.util.Log;
Ganesh Deva1835f102019-07-12 11:22:03 +0530101import android.widget.Toast;
nxpandroid64fd68c2015-09-23 16:45:15 +0530102
nxpandroid6fd9cdb2017-07-12 18:25:41 +0530103import com.android.internal.logging.MetricsLogger;
nxf500513a018e72019-04-23 17:11:41 +0530104import com.android.internal.util.ArrayUtils;
nxpandroid64fd68c2015-09-23 16:45:15 +0530105import com.android.nfc.DeviceHost.DeviceHostListener;
106import com.android.nfc.DeviceHost.LlcpConnectionlessSocket;
107import com.android.nfc.DeviceHost.LlcpServerSocket;
108import com.android.nfc.DeviceHost.LlcpSocket;
109import com.android.nfc.DeviceHost.NfcDepEndpoint;
110import com.android.nfc.DeviceHost.TagEndpoint;
nxpandroid64fd68c2015-09-23 16:45:15 +0530111import com.android.nfc.cardemulation.CardEmulationManager;
nxpandroid64fd68c2015-09-23 16:45:15 +0530112import com.android.nfc.dhimpl.NativeNfcManager;
113import com.android.nfc.handover.HandoverDataParser;
nxf500513a018e72019-04-23 17:11:41 +0530114import com.android.nfc.dhimpl.NativeNfcSecureElement;
nxpandroid64fd68c2015-09-23 16:45:15 +0530115import java.io.FileDescriptor;
116import java.io.PrintWriter;
Suhas Suresh061c9b02018-05-15 17:45:06 +0530117import java.io.UnsupportedEncodingException;
nxpandroid64fd68c2015-09-23 16:45:15 +0530118import java.io.InputStream;
119import java.io.OutputStream;
120import java.io.FileInputStream;
121import java.io.FileOutputStream;
122import java.io.File;
nxpandroid281eb922016-08-25 20:27:46 +0530123import java.io.FileWriter;
nxpandroid64fd68c2015-09-23 16:45:15 +0530124import java.io.BufferedReader;
125import java.io.FileReader;
nxf500513a018e72019-04-23 17:11:41 +0530126import java.io.FileNotFoundException;
127import java.nio.ByteBuffer;
128import java.util.concurrent.atomic.AtomicInteger;
nxpandroid64fd68c2015-09-23 16:45:15 +0530129import java.util.Arrays;
130import java.util.ArrayList;
131import java.util.HashMap;
132import java.util.List;
133import java.util.Map;
134import java.util.NoSuchElementException;
Pratap Reddy49abbe32018-03-27 16:51:59 +0530135import java.util.TimerTask;
136import java.util.Timer;
nxpandroid64fd68c2015-09-23 16:45:15 +0530137import java.io.IOException;
nxf500513a018e72019-04-23 17:11:41 +0530138import android.widget.Toast;
139import com.nxp.nfc.INxpNfcAdapter;
140import com.nxp.nfc.INxpNfcAdapterExtras;
141import java.util.HashSet;
142import com.android.nfc.cardemulation.AidRoutingManager;
143import com.android.nfc.cardemulation.RegisteredAidCache;
144import com.nxp.nfc.NfcConstants;
145import android.se.omapi.ISecureElementService;
Ganesh Devaf550e962018-07-24 11:59:09 +0530146import java.lang.reflect.Field;
147import java.lang.reflect.Method;
148import java.lang.reflect.InvocationTargetException;
nxf500513a018e72019-04-23 17:11:41 +0530149import java.lang.reflect.Constructor;
150import com.nxp.nfc.NfcAidServiceInfo;
Ganesh Devac90b32d2019-07-12 11:53:10 +0530151import android.util.StatsLog;
Shashank vimal83779082018-02-06 18:10:31 +0530152
nxpandroid64fd68c2015-09-23 16:45:15 +0530153public class NfcService implements DeviceHostListener {
nxpandroid64fd68c2015-09-23 16:45:15 +0530154 static final boolean DBG = true;
155 static final String TAG = "NfcService";
156
157 public static final String SERVICE_NAME = "nfc";
nxpandroida9a68ba2016-01-14 21:12:17 +0530158 public static final String NXP_PREF = "NfcServiceNxpPrefs";
nxf500513a018e72019-04-23 17:11:41 +0530159 public static final String PREF = "NfcServicePrefs";
160 private static final String PREF_CUR_SELECTED_UICC_ID = "current_selected_uicc_id";
161 private int SECURE_ELEMENT_UICC_SLOT_DEFAULT = 1;
162 static final int UICC_CONFIGURED = 0x00;
163 static final int UICC_NOT_CONFIGURED = 0x01;
nxpandroid64fd68c2015-09-23 16:45:15 +0530164 static final String PREF_NFC_ON = "nfc_on";
165 static final boolean NFC_ON_DEFAULT = true;
166 static final String PREF_NDEF_PUSH_ON = "ndef_push_on";
167 static final boolean NDEF_PUSH_ON_DEFAULT = true;
nxf500513a018e72019-04-23 17:11:41 +0530168 static final String PREF_SECURE_NFC_ON = "secure_nfc_on";
Ganesh Deva09f89062019-04-30 15:16:01 +0530169 static final boolean SECURE_NFC_ON_DEFAULT = false;
nxpandroid64fd68c2015-09-23 16:45:15 +0530170 static final String PREF_FIRST_BEAM = "first_beam";
171 static final String PREF_FIRST_BOOT = "first_boot";
nxpandroid6fd9cdb2017-07-12 18:25:41 +0530172 public static final int ROUTE_LOC_MASK=8;
173 public static final int TECH_TYPE_MASK=11;
nxpandroid6fd9cdb2017-07-12 18:25:41 +0530174 static final String TRON_NFC_CE = "nfc_ce";
175 static final String TRON_NFC_P2P = "nfc_p2p";
176 static final String TRON_NFC_TAG = "nfc_tag";
nxf500513a018e72019-04-23 17:11:41 +0530177 static final int TECH_TYPE_A= 0x01;
nxpandroid64fd68c2015-09-23 16:45:15 +0530178 static final int MSG_NDEF_TAG = 0;
nxf500513a018e72019-04-23 17:11:41 +0530179 private boolean ETSI_STOP_CONFIG = false;
180 static final int MSG_LLCP_LINK_ACTIVATION = 1;
181 static final int MSG_LLCP_LINK_DEACTIVATED = 2;
182 static final int MSG_MOCK_NDEF = 3;
183 static final int MSG_LLCP_LINK_FIRST_PACKET = 4;
184 static final int MSG_ROUTE_AID = 5;
185 static final int MSG_UNROUTE_AID = 6;
186 static final int MSG_COMMIT_ROUTING = 7;
187 static final int MSG_INVOKE_BEAM = 8;
188 static final int MSG_RF_FIELD_ACTIVATED = 9;
189 static final int MSG_RF_FIELD_DEACTIVATED = 10;
190 static final int MSG_RESUME_POLLING = 11;
191 static final int MSG_REGISTER_T3T_IDENTIFIER = 12;
192 static final int MSG_DEREGISTER_T3T_IDENTIFIER = 13;
193 static final int MSG_TAG_DEBOUNCE = 14;
194 static final int MSG_UPDATE_STATS = 15;
195 static final int MSG_APPLY_SCREEN_STATE = 16;
196 static final int MSG_TRANSACTION_EVENT = 17;
197 static final int MSG_CARD_EMULATION = 21;
198 static final int MSG_SWP_READER_REQUESTED = 18;
199 static final int MSG_SWP_READER_DEACTIVATED = 19;
200 static final int MSG_SWP_READER_REQUESTED_FAIL =20 ;
nxpandroid64fd68c2015-09-23 16:45:15 +0530201 static final int MSG_ETSI_START_CONFIG = 48;
202 static final int MSG_ETSI_STOP_CONFIG = 49;
203 static final int MSG_ETSI_SWP_TIMEOUT = 50;
Pratap Reddy7e57f0d2018-03-15 16:54:33 +0530204 static final int MSG_SWP_READER_RESTART = 58;
nxf500513a018e72019-04-23 17:11:41 +0530205 static final int MSG_SE_INIT = 59;
nxf500513a018e72019-04-23 17:11:41 +0530206 static final int MSG_CLEAR_ROUTING = 62;
207 static final int MSG_INIT_WIREDSE = 63;
208 static final int MSG_COMPUTE_ROUTING_PARAMS = 64;
Suhas Sureshbe2ba092019-05-15 17:26:23 +0530209 static final int MSG_RESET_AND_UPDATE_ROUTING_PARAMS = 65;
Ganesh Deva1ad7d6f2019-06-17 11:46:02 +0530210 static final int MSG_DEINIT_WIREDSE = 66;
nxpandroid6fd9cdb2017-07-12 18:25:41 +0530211 // Update stats every 4 hours
212 static final long STATS_UPDATE_INTERVAL_MS = 4 * 60 * 60 * 1000;
nxpandroid64fd68c2015-09-23 16:45:15 +0530213 static final long MAX_POLLING_PAUSE_TIMEOUT = 40000;
nxf500513a018e72019-04-23 17:11:41 +0530214
nxpandroid64fd68c2015-09-23 16:45:15 +0530215 static final int TASK_ENABLE = 1;
216 static final int TASK_DISABLE = 2;
217 static final int TASK_BOOT = 3;
nxpandroid64fd68c2015-09-23 16:45:15 +0530218
nxf500513a018e72019-04-23 17:11:41 +0530219 // Listen Protocol
220 public static final int NFC_LISTEN_PROTO_ISO_DEP = 0x01; // This values is need to move from this to CardEmulationManager
221 public static final int NFC_LISTEN_PROTO_NFC_DEP = 0x02; // This values is need to move from this to CardEmulationManager
222 public static final int NFC_LISTEN_PROTO_T3T = 0x04;
Suhas Suresh14c42612019-05-10 17:18:24 +0530223 public static final int NFC_LISTEN_PROTO_ISO7816 = 0x20;
nxf500513a018e72019-04-23 17:11:41 +0530224
225 public static final int NFC_LISTEN_TECH_A = 0x01; // This values is need to move from this to CardEmulationManager
226 public static final int NFC_LISTEN_TECH_B = 0x02; // This values is need to move from this to CardEmulationManager
227 public static final int NFC_LISTEN_TECH_F = 0x04; // This values is need to move from this to CardEmulationManager
228
229
230 // Polling technology masks
231 static final int NFC_POLL_A = 0x01;
232 static final int NFC_POLL_B = 0x02;
233 static final int NFC_POLL_F = 0x04;
234 static final int NFC_POLL_V = 0x08;
235 static final int NFC_POLL_B_PRIME = 0x10;
236 static final int NFC_POLL_KOVIO = 0x20;
nxpandroid64fd68c2015-09-23 16:45:15 +0530237
238 // Return values from NfcEe.open() - these are 1:1 mapped
239 // to the thrown EE_EXCEPTION_ exceptions in nfc-extras.
240 static final int EE_ERROR_IO = -1;
241 static final int EE_ERROR_ALREADY_OPEN = -2;
242 static final int EE_ERROR_INIT = -3;
243 static final int EE_ERROR_LISTEN_MODE = -4;
244 static final int EE_ERROR_EXT_FIELD = -5;
245 static final int EE_ERROR_NFC_DISABLED = -6;
246
nxf500513a018e72019-04-23 17:11:41 +0530247 static final public int TECH_ENTRY = 1;
248 static final public int PROTOCOL_ENTRY = 2;
249 static final public int AID_ENTRY = 4; // it is dummy values;
nxpandroid64fd68c2015-09-23 16:45:15 +0530250
251 // minimum screen state that enables NFC polling
252 static final int NFC_POLLING_MODE = ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED;
253
254 // Time to wait for NFC controller to initialize before watchdog
255 // goes off. This time is chosen large, because firmware download
256 // may be a part of initialization.
257 static final int INIT_WATCHDOG_MS = 90000;
nxf500513a018e72019-04-23 17:11:41 +0530258
nxpandroid64fd68c2015-09-23 16:45:15 +0530259 // Time to wait for routing to be applied before watchdog
260 // goes off
261 static final int ROUTING_WATCHDOG_MS = 10000;
262
nxpandroid64fd68c2015-09-23 16:45:15 +0530263 // Default delay used for presence checks
264 static final int DEFAULT_PRESENCE_CHECK_DELAY = 125;
265
nxpandroid64fd68c2015-09-23 16:45:15 +0530266 // The amount of time we wait before manually launching
267 // the Beam animation when called through the share menu.
268 static final int INVOKE_BEAM_DELAY_MS = 1000;
nxf500513a018e72019-04-23 17:11:41 +0530269
270 // RF field events as defined in NFC extras
271 public static final String ACTION_RF_FIELD_ON_DETECTED =
272 "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED";
273 public static final String ACTION_RF_FIELD_OFF_DETECTED =
274 "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED";
275
276 public static boolean sIsShortRecordLayout = false;
Pratap Reddy49abbe32018-03-27 16:51:59 +0530277 // Default delay used for presence checks in ETSI mode
278 static final int ETSI_PRESENCE_CHECK_DELAY = 1000;
nxpandroid64fd68c2015-09-23 16:45:15 +0530279 // for use with playSound()
280 public static final int SOUND_START = 0;
281 public static final int SOUND_END = 1;
282 public static final int SOUND_ERROR = 2;
283
nxpandroide66eb092017-07-12 21:36:08 +0530284 public static final int NCI_VERSION_2_0 = 0x20;
285
286 public static final int NCI_VERSION_1_0 = 0x10;
nxf500513a018e72019-04-23 17:11:41 +0530287
288 public static final String ACTION_LLCP_UP =
289 "com.android.nfc.action.LLCP_UP";
290
291 public static final String ACTION_LLCP_DOWN =
292 "com.android.nfc.action.LLCP_DOWN";
nxpandroid64fd68c2015-09-23 16:45:15 +0530293 //ETSI Reader Events
Pratap Reddy49abbe32018-03-27 16:51:59 +0530294 public static final int ETSI_READER_START_SUCCESS = 0;
Pratap Reddy7e57f0d2018-03-15 16:54:33 +0530295 public static final int ETSI_READER_START_FAIL = 1;
296 public static final int ETSI_READER_ACTIVATED = 2;
297 public static final int ETSI_READER_STOP = 3;
nxpandroid64fd68c2015-09-23 16:45:15 +0530298
299 //ETSI Reader Req States
300 public static final int STATE_SE_RDR_MODE_INVALID = 0x00;
301 public static final int STATE_SE_RDR_MODE_START_CONFIG = 0x01;
302 public static final int STATE_SE_RDR_MODE_START_IN_PROGRESS = 0x02;
303 public static final int STATE_SE_RDR_MODE_STARTED = 0x03;
304 public static final int STATE_SE_RDR_MODE_ACTIVATED = 0x04;
305 public static final int STATE_SE_RDR_MODE_STOP_CONFIG = 0x05;
306 public static final int STATE_SE_RDR_MODE_STOP_IN_PROGRESS = 0x06;
307 public static final int STATE_SE_RDR_MODE_STOPPED = 0x07;
308
nxpandroid281eb922016-08-25 20:27:46 +0530309 //Transit setconfig status
310 public static final int TRANSIT_SETCONFIG_STAT_SUCCESS = 0x00;
311 public static final int TRANSIT_SETCONFIG_STAT_FAILED = 0xFF;
312
nxf500513a018e72019-04-23 17:11:41 +0530313 // Timeout to re-apply routing if a tag was present and we postponed it
314 private static final int APPLY_ROUTING_RETRY_TIMEOUT_MS = 5000;
nxpandroid64fd68c2015-09-23 16:45:15 +0530315
Ganesh Devaf18df212019-06-25 11:02:30 +0530316 // these states are for making enable and disable nfc atomic
317 private int NXP_NFC_STATE_OFF = 0;
318 private int NXP_NFC_STATE_TURNING_ON = 1;
319 private int NXP_NFC_STATE_ON = 2;
320 private int NXP_NFC_STATE_TURNING_OFF = 3;
321
nxf500513a018e72019-04-23 17:11:41 +0530322 // eSE handle
323 public static final int EE_HANDLE_0xF3 = 0x4C0;
nxpandroid64fd68c2015-09-23 16:45:15 +0530324
nxpandroid64fd68c2015-09-23 16:45:15 +0530325 /**
326 * SMART MX ID to be able to select it as the default Secure Element
327 */
328 public static final int SMART_MX_ID_TYPE = 1;
329
330 /**
331 * UICC ID to be able to select it as the default Secure Element
332 */
333 public static final int UICC_ID_TYPE = 2;
334
335 /**
nxpandroid7d44e572016-08-01 19:11:04 +0530336 * UICC2 ID to be able to select it as the default Secure Element
337 */
338 public static final int UICC2_ID_TYPE = 4;
nxpandroid64fd68c2015-09-23 16:45:15 +0530339
nxf500513a018e72019-04-23 17:11:41 +0530340 public boolean mIsRouteForced;
Nikhil Chhabrad6957c72018-03-09 11:44:48 +0530341
nxpandroid64fd68c2015-09-23 16:45:15 +0530342 private final UserManager mUserManager;
nxf500513a018e72019-04-23 17:11:41 +0530343
nxpandroide66eb092017-07-12 21:36:08 +0530344 private static int nci_version = NCI_VERSION_1_0;
nxpandroid64fd68c2015-09-23 16:45:15 +0530345 // NFC Execution Environment
346 // fields below are protected by this
Ganesh Devaf550e962018-07-24 11:59:09 +0530347 public NativeNfcSecureElement mSecureElement;
nxf500513a018e72019-04-23 17:11:41 +0530348 public boolean isWiredOpen = false;
nxpandroid64fd68c2015-09-23 16:45:15 +0530349 private final ReaderModeDeathRecipient mReaderModeDeathRecipient =
350 new ReaderModeDeathRecipient();
351 private final NfcUnlockManager mNfcUnlockManager;
352
nxf500513a018e72019-04-23 17:11:41 +0530353
354 private final BackupManager mBackupManager;
Suhas Sureshca6584b2018-04-27 17:17:22 +0530355 // cached version of installed packages requesting Android.permission.NFC_TRANSACTION_EVENTS
Suhas Suresh140f7ac2018-05-15 14:59:11 +0530356 List<String> mNfcEventInstalledPackages = new ArrayList<String>();
nxpandroid64fd68c2015-09-23 16:45:15 +0530357
nxpandroid64fd68c2015-09-23 16:45:15 +0530358 // fields below are used in multiple threads and protected by synchronized(this)
359 final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>();
nxpandroid64fd68c2015-09-23 16:45:15 +0530360 HashSet<String> mSePackages = new HashSet<String>();
361 int mScreenState;
362 boolean mInProvisionMode; // whether we're in setup wizard and enabled NFC provisioning
363 boolean mIsNdefPushEnabled;
nxf500513a018e72019-04-23 17:11:41 +0530364 boolean mIsSecureNfcEnabled;
nxpandroid64fd68c2015-09-23 16:45:15 +0530365 NfcDiscoveryParameters mCurrentDiscoveryParameters =
366 NfcDiscoveryParameters.getNfcOffParameters();
nxf500513a018e72019-04-23 17:11:41 +0530367
nxpandroid64fd68c2015-09-23 16:45:15 +0530368 ReaderModeParams mReaderModeParams;
nxf500513a018e72019-04-23 17:11:41 +0530369
nxpandroid281eb922016-08-25 20:27:46 +0530370 private int mUserId;
371 boolean mPollingPaused;
372
Nikhil Chhabra1b2368f2018-01-09 18:34:21 +0530373 static final int INVALID_NATIVE_HANDLE = -1;
nxf500513a018e72019-04-23 17:11:41 +0530374 byte mDebounceTagUid[];
nxpandroid281eb922016-08-25 20:27:46 +0530375 int mDebounceTagDebounceMs;
Nikhil Chhabra1b2368f2018-01-09 18:34:21 +0530376 int mDebounceTagNativeHandle = INVALID_NATIVE_HANDLE;
nxpandroid281eb922016-08-25 20:27:46 +0530377 ITagRemovedCallback mDebounceTagRemovedCallback;
nxpandroid64fd68c2015-09-23 16:45:15 +0530378
nxpandroid6fd9cdb2017-07-12 18:25:41 +0530379 // Only accessed on one thread so doesn't need locking
380 NdefMessage mLastReadNdefMessage;
381
382 // Metrics
383 AtomicInteger mNumTagsDetected;
384 AtomicInteger mNumP2pDetected;
385 AtomicInteger mNumHceDetected;
nxf500513a018e72019-04-23 17:11:41 +0530386 ToastHandler mToastHandler;
nxpandroid64fd68c2015-09-23 16:45:15 +0530387 // mState is protected by this, however it is only modified in onCreate()
388 // and the default AsyncTask thread so it is read unprotected from that
389 // thread
390 int mState; // one of NfcAdapter.STATE_ON, STATE_TURNING_ON, etc
Ganesh Devaf18df212019-06-25 11:02:30 +0530391 int mNxpNfcState = NXP_NFC_STATE_OFF;
392
nxpandroid64fd68c2015-09-23 16:45:15 +0530393 // fields below are final after onCreate()
394 Context mContext;
395 private DeviceHost mDeviceHost;
396 private SharedPreferences mPrefs;
397 private SharedPreferences.Editor mPrefsEditor;
398 private PowerManager.WakeLock mRoutingWakeLock;
399 private PowerManager.WakeLock mEeWakeLock;
nxf500513a018e72019-04-23 17:11:41 +0530400 private SharedPreferences.Editor mNxpPrefsEditor;
401 private SharedPreferences mNxpPrefs;
nxpandroid64fd68c2015-09-23 16:45:15 +0530402 int mStartSound;
403 int mEndSound;
404 int mErrorSound;
405 SoundPool mSoundPool; // playback synchronized on this
406 P2pLinkManager mP2pLinkManager;
407 TagService mNfcTagService;
nxf500513a018e72019-04-23 17:11:41 +0530408 boolean mIsSecureElementOpened = false;
409 boolean mSEClientAccessState = false;
nxpandroid64fd68c2015-09-23 16:45:15 +0530410 NfcAdapterService mNfcAdapter;
nxf500513a018e72019-04-23 17:11:41 +0530411 NfcDtaService mNfcDtaService;
412 NxpNfcAdapterExtrasService mNxpExtrasService;
nxpandroid64fd68c2015-09-23 16:45:15 +0530413 NxpNfcAdapterService mNxpNfcAdapter;
nxpandroid64fd68c2015-09-23 16:45:15 +0530414 boolean mIsDebugBuild;
415 boolean mIsHceCapable;
nxpandroid34627bd2016-05-27 15:52:30 +0530416 boolean mIsHceFCapable;
nxf500513a018e72019-04-23 17:11:41 +0530417 boolean mIsBeamCapable;
418 boolean mIsSecureNfcCapable;
nxpandroid64fd68c2015-09-23 16:45:15 +0530419
nxpandroid64fd68c2015-09-23 16:45:15 +0530420 private NfcDispatcher mNfcDispatcher;
421 private PowerManager mPowerManager;
422 private KeyguardManager mKeyguard;
nxpandroid64fd68c2015-09-23 16:45:15 +0530423 private HandoverDataParser mHandoverDataParser;
424 private ContentResolver mContentResolver;
nxpandroid64fd68c2015-09-23 16:45:15 +0530425 private CardEmulationManager mCardEmulationManager;
nxf500513a018e72019-04-23 17:11:41 +0530426 private AidRoutingManager mAidRoutingManager;
427 private RegisteredAidCache mAidCache;
Suhas Suresh6e05ee02018-04-25 12:19:35 +0530428 private Vibrator mVibrator;
429 private VibrationEffect mVibrationEffect;
nxf500513a018e72019-04-23 17:11:41 +0530430
nxpandroid64fd68c2015-09-23 16:45:15 +0530431 private ScreenStateHelper mScreenStateHelper;
432 private ForegroundUtils mForegroundUtils;
nxpandroid64fd68c2015-09-23 16:45:15 +0530433
nxpandroid64fd68c2015-09-23 16:45:15 +0530434 private static NfcService sService;
Ganesh Deva65fa8112019-07-12 12:00:29 +0530435 private static Toast mToast;
nxf500513a018e72019-04-23 17:11:41 +0530436 public static boolean sIsDtaMode = false;
nxpandroid6fd9cdb2017-07-12 18:25:41 +0530437
Nikhil Chhabrafc8f3f62018-01-08 20:48:49 +0530438 private IVrManager vrManager;
439 boolean mIsVrModeEnabled;
nxf500513a018e72019-04-23 17:11:41 +0530440 private ISecureElementService mSEService;
441 /* WiredSe attributes */
442 Class mWiredSeClass;
443 Method mWiredSeInitMethod, mWiredSeDeInitMethod;
444 Object mWiredSeObj;
Ganesh Deva1ad7d6f2019-06-17 11:46:02 +0530445 Class mNfcExtnsClass;
446 Object mNfcExtnsObj;
nxf500513a018e72019-04-23 17:11:41 +0530447 Class mNfcExtraClass;
448 Object mNfcExtraObj;
449
450 private int ROUTE_ID_HOST = 0x00;
451 private int ROUTE_ID_SMX = 0x01;
452 private int ROUTE_ID_UICC = 0x02;
453 private int ROUTE_ID_UICC2 = 0x04;
454 private int DEFAULT_ROUTE_ID_DEFAULT = 0x00;
Nikhil Chhabrafc8f3f62018-01-08 20:48:49 +0530455
nxpandroid64fd68c2015-09-23 16:45:15 +0530456 public static NfcService getInstance() {
457 return sService;
458 }
459
nxpandroid64fd68c2015-09-23 16:45:15 +0530460 public int getRemainingAidTableSize() {
461 return mDeviceHost.getRemainingAidTableSize();
462 }
463
nxf500513a018e72019-04-23 17:11:41 +0530464
nxpandroidebf53fb2016-12-22 18:48:59 +0530465 public boolean getLastCommitRoutingStatus() {
466 return mAidRoutingManager.getLastCommitRoutingStatus();
467 }
468
nxf500513a018e72019-04-23 17:11:41 +0530469 public AidRoutingManager getAidRoutingCache() {
470 return mAidRoutingManager;
nxpandroid64fd68c2015-09-23 16:45:15 +0530471 }
472
473 @Override
nxf500513a018e72019-04-23 17:11:41 +0530474 public void onRemoteEndpointDiscovered(TagEndpoint tag) {
475 sendMessage(NfcService.MSG_NDEF_TAG, tag);
nxpandroid64fd68c2015-09-23 16:45:15 +0530476 }
477
478 /**
479 * Notifies transaction
480 */
481 @Override
nxpandroid34627bd2016-05-27 15:52:30 +0530482 public void onHostCardEmulationActivated(int technology) {
nxpandroid64fd68c2015-09-23 16:45:15 +0530483 if (mCardEmulationManager != null) {
nxpandroid34627bd2016-05-27 15:52:30 +0530484 mCardEmulationManager.onHostCardEmulationActivated(technology);
nxpandroid64fd68c2015-09-23 16:45:15 +0530485 }
486 }
nxpandroid64fd68c2015-09-23 16:45:15 +0530487 @Override
nxf500513a018e72019-04-23 17:11:41 +0530488 public void onSeListenActivated() {
nxpandroid64fd68c2015-09-23 16:45:15 +0530489 if (mIsHceCapable) {
nxf500513a018e72019-04-23 17:11:41 +0530490 mCardEmulationManager.onHostCardEmulationActivated(TagTechnology.NFC_A);
nxpandroid64fd68c2015-09-23 16:45:15 +0530491 }
492 }
493
494 @Override
nxf500513a018e72019-04-23 17:11:41 +0530495 public void onSeListenDeactivated() {
496 if( mIsHceCapable) {
497 mCardEmulationManager.onHostCardEmulationDeactivated(TagTechnology.NFC_A);
498 }
nxpandroid5d64ce92016-11-18 19:48:53 +0530499 }
nxpandroid5d64ce92016-11-18 19:48:53 +0530500 @Override
nxpandroid34627bd2016-05-27 15:52:30 +0530501 public void onHostCardEmulationData(int technology, byte[] data) {
nxpandroid64fd68c2015-09-23 16:45:15 +0530502 if (mCardEmulationManager != null) {
nxpandroid34627bd2016-05-27 15:52:30 +0530503 mCardEmulationManager.onHostCardEmulationData(technology, data);
nxpandroid64fd68c2015-09-23 16:45:15 +0530504 }
505 }
506
507 @Override
nxpandroid34627bd2016-05-27 15:52:30 +0530508 public void onHostCardEmulationDeactivated(int technology) {
nxpandroid64fd68c2015-09-23 16:45:15 +0530509 if (mCardEmulationManager != null) {
nxpandroid6fd9cdb2017-07-12 18:25:41 +0530510 // Do metrics here so we don't slow the CE path down
511 mNumHceDetected.incrementAndGet();
nxpandroid34627bd2016-05-27 15:52:30 +0530512 mCardEmulationManager.onHostCardEmulationDeactivated(technology);
nxpandroid64fd68c2015-09-23 16:45:15 +0530513 }
514 }
515
516 /**
517 * Notifies P2P Device detected, to activate LLCP link
518 */
519 @Override
520 public void onLlcpLinkActivated(NfcDepEndpoint device) {
nxf500513a018e72019-04-23 17:11:41 +0530521 if (!mIsBeamCapable) return;
nxpandroid64fd68c2015-09-23 16:45:15 +0530522 sendMessage(NfcService.MSG_LLCP_LINK_ACTIVATION, device);
523 }
524
525 /**
526 * Notifies P2P Device detected, to activate LLCP link
527 */
528 @Override
529 public void onLlcpLinkDeactivated(NfcDepEndpoint device) {
nxf500513a018e72019-04-23 17:11:41 +0530530 if (!mIsBeamCapable) return;
nxpandroid64fd68c2015-09-23 16:45:15 +0530531 sendMessage(NfcService.MSG_LLCP_LINK_DEACTIVATED, device);
532 }
533
534 /**
535 * Notifies P2P Device detected, first packet received over LLCP link
536 */
537 @Override
538 public void onLlcpFirstPacketReceived(NfcDepEndpoint device) {
nxf500513a018e72019-04-23 17:11:41 +0530539 if (!mIsBeamCapable) return;
nxpandroid6fd9cdb2017-07-12 18:25:41 +0530540 mNumP2pDetected.incrementAndGet();
nxpandroid64fd68c2015-09-23 16:45:15 +0530541 sendMessage(NfcService.MSG_LLCP_LINK_FIRST_PACKET, device);
542 }
543
544 @Override
545 public void onRemoteFieldActivated() {
nxf500513a018e72019-04-23 17:11:41 +0530546 sendMessage(NfcService.MSG_RF_FIELD_ACTIVATED, null);
nxpandroid64fd68c2015-09-23 16:45:15 +0530547 }
548
549 @Override
550 public void onRemoteFieldDeactivated() {
nxf500513a018e72019-04-23 17:11:41 +0530551 sendMessage(NfcService.MSG_RF_FIELD_DEACTIVATED, null);
nxpandroid64fd68c2015-09-23 16:45:15 +0530552 }
553
554 @Override
nxf500513a018e72019-04-23 17:11:41 +0530555 public void onSeInitialized() {
556 sendMessage(NfcService.MSG_SE_INIT, null);
nxpandroid64fd68c2015-09-23 16:45:15 +0530557 }
558
559 @Override
Pratap Reddy7e57f0d2018-03-15 16:54:33 +0530560 public void onETSIReaderRequestedEvent(boolean istechA, boolean istechB)
nxpandroid64fd68c2015-09-23 16:45:15 +0530561 {
562 int size=0;
563 ArrayList<Integer> techList = new ArrayList<Integer>();
564 if(istechA)
565 techList.add(TagTechnology.NFC_A);
566 if(istechB)
567 techList.add(TagTechnology.NFC_B);
568
569 sendMessage(NfcService.MSG_SWP_READER_REQUESTED , techList);
570 }
571
572 @Override
nxf500513a018e72019-04-23 17:11:41 +0530573 public void onNfcTransactionEvent(byte[] aid, byte[] data, String seName) {
574 byte[][] dataObj = {aid, data, seName.getBytes()};
575 sendMessage(NfcService.MSG_TRANSACTION_EVENT, dataObj);
Ganesh Devac90b32d2019-07-12 11:53:10 +0530576 StatsLog.write(StatsLog.NFC_CARDEMULATION_OCCURRED, StatsLog.NFC_CARDEMULATION_OCCURRED__CATEGORY__OFFHOST, seName);
nxf500513a018e72019-04-23 17:11:41 +0530577 }
578 @Override
Pratap Reddy7e57f0d2018-03-15 16:54:33 +0530579 public void onETSIReaderRequestedFail(int FailCause)
nxpandroid64fd68c2015-09-23 16:45:15 +0530580 {
581 sendMessage(NfcService.MSG_SWP_READER_REQUESTED_FAIL , FailCause);
582 }
583
584 @Override
nxpandroid64fd68c2015-09-23 16:45:15 +0530585 public void onETSIReaderModeStartConfig(int eeHandle)
586 {
Pratap Reddy49abbe32018-03-27 16:51:59 +0530587 // Check if NFC is enabled
588 if (!isNfcEnabled()) {
589 return;
590 }
nxpandroid64fd68c2015-09-23 16:45:15 +0530591 ArrayList<Integer> configList = new ArrayList<Integer>();
592 configList.add(eeHandle);
593 sendMessage(NfcService.MSG_ETSI_START_CONFIG, configList);
594 }
595
596 @Override
597 public void onETSIReaderModeStopConfig(int disc_ntf_timeout)
598 {
Pratap Reddy49abbe32018-03-27 16:51:59 +0530599 // Check if NFC is enabled
600 if (!isNfcEnabled()) {
601 return;
602 }
603 EtsiStopConfigTask task = new EtsiStopConfigTask();
604 task.execute(disc_ntf_timeout);
605
nxpandroid64fd68c2015-09-23 16:45:15 +0530606 }
607
608 @Override
609 public void onETSIReaderModeSwpTimeout(int disc_ntf_timeout)
610 {
611 sendMessage(NfcService.MSG_ETSI_SWP_TIMEOUT, disc_ntf_timeout);
612 }
613
Pratap Reddy7e57f0d2018-03-15 16:54:33 +0530614 @Override
615 public void onETSIReaderModeRestart() {
616 sendMessage(NfcService.MSG_SWP_READER_RESTART, null);
617 }
nxpandroid64fd68c2015-09-23 16:45:15 +0530618 final class ReaderModeParams {
619 public int flags;
620 public IAppCallback callback;
621 public int presenceCheckDelay;
622 }
623
624 public NfcService(Application nfcApplication) {
625 mUserId = ActivityManager.getCurrentUser();
626 mContext = nfcApplication;
627
628 mNfcTagService = new TagService();
629 mNfcAdapter = new NfcAdapterService();
nxf500513a018e72019-04-23 17:11:41 +0530630
nxpandroid64fd68c2015-09-23 16:45:15 +0530631 mNxpNfcAdapter = new NxpNfcAdapterService();
nxf500513a018e72019-04-23 17:11:41 +0530632 mNxpExtrasService = new NxpNfcAdapterExtrasService();
633 Log.i(TAG, "Starting NFC service");
nxpandroid64fd68c2015-09-23 16:45:15 +0530634
Ganesh Devaf550e962018-07-24 11:59:09 +0530635 try {
636 mWiredSeClass = Class.forName("com.android.nfc.WiredSeService");
637 mWiredSeObj = mWiredSeClass.newInstance();
638 } catch (ClassNotFoundException | IllegalAccessException e){
639 Log.e(TAG, "WiredSeService Class not found");
640 } catch (InstantiationException e) {
641 Log.e(TAG, "WiredSeService object Instantiation failed");
642 }
nxpandroid64fd68c2015-09-23 16:45:15 +0530643 sService = this;
644
645 mScreenStateHelper = new ScreenStateHelper(mContext);
646 mContentResolver = mContext.getContentResolver();
647 mDeviceHost = new NativeNfcManager(mContext, this);
648
Ganesh Deva1ad7d6f2019-06-17 11:46:02 +0530649 try {
650 Object[] objargs = new Object[] {mContext};
651 mNfcExtnsClass = Class.forName("com.android.nfc.NfcExtnsService");
652 Constructor mNfcConstr = mNfcExtnsClass.getDeclaredConstructor(Context.class);
653 mNfcExtnsObj = mNfcConstr.newInstance(objargs);
654 } catch(ClassNotFoundException | IllegalAccessException e) {
655 Log.d(TAG, "NfcExtnsService not found");
656 } catch (InstantiationException e) {
657 Log.e(TAG, "NfcExtnsService object Instantaiation failed");
658 } catch (NoSuchMethodException e ) {
659 Log.e(TAG, " NoSuchMethodException");
660 } catch (InvocationTargetException e) {
661 Log.e(TAG, " InvocationTargetException");
662 }
nxf500513a018e72019-04-23 17:11:41 +0530663 Object[] args = new Object[] {mDeviceHost, mContext};
664 try {
665 mNfcExtraClass = Class.forName("com.android.nfc.NfcAdapterExtrasService");
666 Constructor mNfcExtraConstr = mNfcExtraClass.getDeclaredConstructor(DeviceHost.class, Context.class);
667 mNfcExtraObj = mNfcExtraConstr.newInstance(args);
668 } catch (NoSuchMethodException e ) {
669 Log.e(TAG, "NfcAdapterExtrasService NoSuchMethodException");
670 e.printStackTrace();
671 } catch (InvocationTargetException e) {
672 Log.e(TAG, "NfcAdapterExtrasService InvocationTargetException");
673 e.printStackTrace();
674 } catch (ClassNotFoundException | IllegalAccessException e){
675 Log.e(TAG, "NfcAdapterExtrasService Class not found");
676 e.printStackTrace();
677 } catch (InstantiationException e) {
678 Log.e(TAG, "NfcAdapterExtrasService object Instantiation failed");
679 e.printStackTrace();
680 }
681
nxpandroid64fd68c2015-09-23 16:45:15 +0530682 mNfcUnlockManager = NfcUnlockManager.getInstance();
683
684 mHandoverDataParser = new HandoverDataParser();
685 boolean isNfcProvisioningEnabled = false;
686 try {
687 isNfcProvisioningEnabled = mContext.getResources().getBoolean(
688 R.bool.enable_nfc_provisioning);
689 } catch (NotFoundException e) {
690 }
691
692 if (isNfcProvisioningEnabled) {
693 mInProvisionMode = Settings.Secure.getInt(mContentResolver,
694 Settings.Global.DEVICE_PROVISIONED, 0) == 0;
695 } else {
696 mInProvisionMode = false;
697 }
698
nxf500513a018e72019-04-23 17:11:41 +0530699 mNfcDispatcher = new NfcDispatcher(mContext, mHandoverDataParser, mInProvisionMode);
nxpandroid64fd68c2015-09-23 16:45:15 +0530700
701 mSecureElement = new NativeNfcSecureElement(mContext);
nxpandroid64fd68c2015-09-23 16:45:15 +0530702 mToastHandler = new ToastHandler(mContext);
nxpandroid64fd68c2015-09-23 16:45:15 +0530703 mPrefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
704 mPrefsEditor = mPrefs.edit();
nxpandroida9a68ba2016-01-14 21:12:17 +0530705 mNxpPrefs = mContext.getSharedPreferences(NXP_PREF, Context.MODE_PRIVATE);
706 mNxpPrefsEditor = mNxpPrefs.edit();
nxpandroid64fd68c2015-09-23 16:45:15 +0530707
708 mState = NfcAdapter.STATE_OFF;
nxpandroid64fd68c2015-09-23 16:45:15 +0530709
710 mIsDebugBuild = "userdebug".equals(Build.TYPE) || "eng".equals(Build.TYPE);
711
712 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
713
714 mRoutingWakeLock = mPowerManager.newWakeLock(
nxf500513a018e72019-04-23 17:11:41 +0530715 PowerManager.PARTIAL_WAKE_LOCK, "NfcService:mRoutingWakeLock");
nxpandroid64fd68c2015-09-23 16:45:15 +0530716 mEeWakeLock = mPowerManager.newWakeLock(
nxf500513a018e72019-04-23 17:11:41 +0530717 PowerManager.PARTIAL_WAKE_LOCK, "NfcService:mEeWakeLock");
nxpandroid64fd68c2015-09-23 16:45:15 +0530718 mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
719 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
Suhas Suresh6e05ee02018-04-25 12:19:35 +0530720 mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
721 mVibrationEffect = VibrationEffect.createOneShot(200, VibrationEffect.DEFAULT_AMPLITUDE);
nxpandroid64fd68c2015-09-23 16:45:15 +0530722
723 mScreenState = mScreenStateHelper.checkScreenState();
724
nxpandroid6fd9cdb2017-07-12 18:25:41 +0530725 mNumTagsDetected = new AtomicInteger();
726 mNumP2pDetected = new AtomicInteger();
727 mNumHceDetected = new AtomicInteger();
728
729 mBackupManager = new BackupManager(mContext);
730
nxpandroid64fd68c2015-09-23 16:45:15 +0530731 // Intents for all users
nxf500513a018e72019-04-23 17:11:41 +0530732 IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
nxpandroid64fd68c2015-09-23 16:45:15 +0530733 filter.addAction(Intent.ACTION_SCREEN_ON);
734 filter.addAction(Intent.ACTION_USER_PRESENT);
735 filter.addAction(Intent.ACTION_USER_SWITCHED);
nxpandroid64fd68c2015-09-23 16:45:15 +0530736 mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null);
737
738 IntentFilter ownerFilter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
739 ownerFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
Suhas Sureshc9772c82018-04-27 15:41:19 +0530740 ownerFilter.addAction(Intent.ACTION_SHUTDOWN);
nxpandroid64fd68c2015-09-23 16:45:15 +0530741 mContext.registerReceiver(mOwnerReceiver, ownerFilter);
742
743 ownerFilter = new IntentFilter();
744 ownerFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
745 ownerFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
746 ownerFilter.addDataScheme("package");
747 mContext.registerReceiver(mOwnerReceiver, ownerFilter);
748
nxpandroid64fd68c2015-09-23 16:45:15 +0530749 IntentFilter policyFilter = new IntentFilter(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
750 mContext.registerReceiverAsUser(mPolicyReceiver, UserHandle.ALL, policyFilter, null, null);
751
752 updatePackageCache();
753
754 PackageManager pm = mContext.getPackageManager();
nxf500513a018e72019-04-23 17:11:41 +0530755 mIsBeamCapable = pm.hasSystemFeature(PackageManager.FEATURE_NFC_BEAM);
756 mIsNdefPushEnabled =
757 mPrefs.getBoolean(PREF_NDEF_PUSH_ON, NDEF_PUSH_ON_DEFAULT) &&
758 mIsBeamCapable;
759 if (mIsBeamCapable) {
760 mP2pLinkManager = new P2pLinkManager(
761 mContext, mHandoverDataParser, mDeviceHost.getDefaultLlcpMiu(),
762 mDeviceHost.getDefaultLlcpRwSize());
763 }
764 enforceBeamShareActivityPolicy(mContext, new UserHandle(mUserId));
765
nxpandroid34627bd2016-05-27 15:52:30 +0530766 mIsHceCapable =
767 pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION) ||
768 pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF);
769 mIsHceFCapable =
770 pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF);
nxpandroid64fd68c2015-09-23 16:45:15 +0530771 if (mIsHceCapable) {
772 mAidRoutingManager = new AidRoutingManager();
nxf500513a018e72019-04-23 17:11:41 +0530773 mCardEmulationManager = new CardEmulationManager(mContext);
nxpandroid1680a6d2017-01-13 19:13:14 +0530774 mAidCache = mCardEmulationManager.getRegisteredAidCache();
nxpandroid64fd68c2015-09-23 16:45:15 +0530775 }
nxpandroid64fd68c2015-09-23 16:45:15 +0530776 mForegroundUtils = ForegroundUtils.getInstance();
nxpandroid281eb922016-08-25 20:27:46 +0530777
nxf500513a018e72019-04-23 17:11:41 +0530778 mIsSecureNfcCapable = mNfcAdapter.deviceSupportsNfcSecure();
779 mIsSecureNfcEnabled =
780 // To be reverted once device support added for secure NFC.
781 //mPrefs.getBoolean(PREF_SECURE_NFC_ON, SECURE_NFC_ON_DEFAULT) &&
782 //mIsSecureNfcCapable;
783 mPrefs.getBoolean(PREF_SECURE_NFC_ON, SECURE_NFC_ON_DEFAULT);
784 mDeviceHost.setNfcSecure(mIsSecureNfcEnabled);
785
nxpandroid281eb922016-08-25 20:27:46 +0530786 // Make sure this is only called when object construction is complete.
787 ServiceManager.addService(SERVICE_NAME, mNfcAdapter);
nxf500513a018e72019-04-23 17:11:41 +0530788 new EnableDisableTask().execute(TASK_BOOT); // do blocking boot tasks
nxpandroid6fd9cdb2017-07-12 18:25:41 +0530789
790 mHandler.sendEmptyMessageDelayed(MSG_UPDATE_STATS, STATS_UPDATE_INTERVAL_MS);
Nikhil Chhabrafc8f3f62018-01-08 20:48:49 +0530791
792 IVrManager mVrManager = IVrManager.Stub.asInterface(ServiceManager.getService(
793 mContext.VR_SERVICE));
794 if (mVrManager != null) {
795 try {
796 mVrManager.registerListener(mVrStateCallbacks);
797 mIsVrModeEnabled = mVrManager.getVrModeState();
798 } catch (RemoteException e) {
799 Log.e(TAG, "Failed to register VR mode state listener: " + e);
800 }
801 }
Suhas Sureshca6584b2018-04-27 17:17:22 +0530802 mSEService = ISecureElementService.Stub.asInterface(ServiceManager.getService(
803 Context.SECURE_ELEMENT_SERVICE));
nxpandroid64fd68c2015-09-23 16:45:15 +0530804 }
805
Ganesh Deva272ad052018-07-09 15:56:45 +0530806 private boolean isSEServiceAvailable() {
807 if (mSEService == null) {
808 mSEService = ISecureElementService.Stub.asInterface(ServiceManager.getService(
809 Context.SECURE_ELEMENT_SERVICE));
810 }
811 return (mSEService != null);
812 }
813
nxpandroid64fd68c2015-09-23 16:45:15 +0530814 void initSoundPool() {
nxf500513a018e72019-04-23 17:11:41 +0530815 synchronized (this) {
nxpandroid64fd68c2015-09-23 16:45:15 +0530816 if (mSoundPool == null) {
817 mSoundPool = new SoundPool(1, AudioManager.STREAM_NOTIFICATION, 0);
818 mStartSound = mSoundPool.load(mContext, R.raw.start, 1);
819 mEndSound = mSoundPool.load(mContext, R.raw.end, 1);
820 mErrorSound = mSoundPool.load(mContext, R.raw.error, 1);
821 }
822 }
823 }
824
825 void releaseSoundPool() {
826 synchronized (this) {
827 if (mSoundPool != null) {
828 mSoundPool.release();
829 mSoundPool = null;
830 }
831 }
832 }
833
nxpandroid64fd68c2015-09-23 16:45:15 +0530834 void updatePackageCache() {
835 PackageManager pm = mContext.getPackageManager();
Suhas Sureshca6584b2018-04-27 17:17:22 +0530836 List<PackageInfo> packagesNfcEvents = pm.getPackagesHoldingPermissions(
837 new String[] {android.Manifest.permission.NFC_TRANSACTION_EVENT},
838 PackageManager.GET_ACTIVITIES);
nxpandroid64fd68c2015-09-23 16:45:15 +0530839 synchronized (this) {
Suhas Suresh140f7ac2018-05-15 14:59:11 +0530840 mNfcEventInstalledPackages.clear();
841 for (int i = 0; i < packagesNfcEvents.size(); i++) {
nxf382935cedb182019-02-01 11:48:15 +0530842 mNfcEventInstalledPackages.add(packagesNfcEvents.get(i).packageName);
Suhas Suresh140f7ac2018-05-15 14:59:11 +0530843 }
nxpandroid64fd68c2015-09-23 16:45:15 +0530844 }
845 }
846
nxf500513a018e72019-04-23 17:11:41 +0530847 int doOpenSecureElementConnection() {
nxpandroid64fd68c2015-09-23 16:45:15 +0530848 mEeWakeLock.acquire();
849 try {
nxf500513a018e72019-04-23 17:11:41 +0530850 return mSecureElement.doOpenSecureElementConnection();
nxpandroid64fd68c2015-09-23 16:45:15 +0530851 } finally {
852 mEeWakeLock.release();
853 }
854 }
855
nxpandroid64fd68c2015-09-23 16:45:15 +0530856 void doDisconnect(int handle) {
857 mEeWakeLock.acquire();
858 try {
859 mSecureElement.doDisconnect(handle);
860 } finally {
861 mEeWakeLock.release();
862 }
863 }
864
nxf500513a018e72019-04-23 17:11:41 +0530865 byte[] doTransceive(int handle, byte[] cmd) {
866 mEeWakeLock.acquire();
867 try {
868 return doTransceiveNoLock(handle, cmd);
869 } finally {
870 mEeWakeLock.release();
871 }
nxpandroid64fd68c2015-09-23 16:45:15 +0530872 }
873
nxf500513a018e72019-04-23 17:11:41 +0530874 byte[] doTransceiveNoLock(int handle, byte[] cmd) {
875 return mSecureElement.doTransceive(handle, cmd);
nxpandroid64fd68c2015-09-23 16:45:15 +0530876 }
877
nxpandroid64fd68c2015-09-23 16:45:15 +0530878 /**
879 * Manages tasks that involve turning on/off the NFC controller.
880 * <p/>
881 * <p>All work that might turn the NFC adapter on or off must be done
882 * through this task, to keep the handling of mState simple.
883 * In other words, mState is only modified in these tasks (and we
884 * don't need a lock to read it in these tasks).
885 * <p/>
886 * <p>These tasks are all done on the same AsyncTask background
887 * thread, so they are serialized. Each task may temporarily transition
888 * mState to STATE_TURNING_OFF or STATE_TURNING_ON, but must exit in
889 * either STATE_ON or STATE_OFF. This way each task can be guaranteed
890 * of starting in either STATE_OFF or STATE_ON, without needing to hold
891 * NfcService.this for the entire task.
892 * <p/>
893 * <p>AsyncTask's are also implicitly queued. This is useful for corner
894 * cases like turning airplane mode on while TASK_ENABLE is in progress.
895 * The TASK_DISABLE triggered by airplane mode will be correctly executed
896 * immediately after TASK_ENABLE is complete. This seems like the most sane
897 * way to deal with these situations.
898 * <p/>
899 * <p>{@link #TASK_ENABLE} enables the NFC adapter, without changing
900 * preferences
901 * <p>{@link #TASK_DISABLE} disables the NFC adapter, without changing
902 * preferences
903 * <p>{@link #TASK_BOOT} does first boot work and may enable NFC
904 */
905 class EnableDisableTask extends AsyncTask<Integer, Void, Void> {
906 @Override
907 protected Void doInBackground(Integer... params) {
908 // Sanity check mState
909 switch (mState) {
910 case NfcAdapter.STATE_TURNING_OFF:
911 case NfcAdapter.STATE_TURNING_ON:
912 Log.e(TAG, "Processing EnableDisable task " + params[0] + " from bad state " +
913 mState);
914 return null;
915 }
916
917 /* AsyncTask sets this thread to THREAD_PRIORITY_BACKGROUND,
918 * override with the default. THREAD_PRIORITY_BACKGROUND causes
919 * us to service software I2C too slow for firmware download
920 * with the NXP PN544.
921 * TODO: move this to the DAL I2C layer in libnfc-nxp, since this
922 * problem only occurs on I2C platforms using PN544
923 */
924 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
925
926 switch (params[0].intValue()) {
927 case TASK_ENABLE:
928 enableInternal();
929 break;
930 case TASK_DISABLE:
931 disableInternal();
932 break;
933 case TASK_BOOT:
nxf500513a018e72019-04-23 17:11:41 +0530934 boolean initialized;
935 if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) {
Suhas Suresh1fe09dc2018-05-07 11:55:06 +0530936 Log.i(TAG, "First Boot");
937 mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false);
938 mPrefsEditor.apply();
939 mDeviceHost.factoryReset();
940 }
nxpandroid64fd68c2015-09-23 16:45:15 +0530941 Log.d(TAG, "checking on firmware download");
nxpandroid7d44e572016-08-01 19:11:04 +0530942 if (mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT)) {
nxpandroid64fd68c2015-09-23 16:45:15 +0530943 Log.d(TAG, "NFC is on. Doing normal stuff");
nxf500513a018e72019-04-23 17:11:41 +0530944 initialized = enableInternal();
nxpandroid64fd68c2015-09-23 16:45:15 +0530945 } else {
946 Log.d(TAG, "NFC is off. Checking firmware version");
nxf500513a018e72019-04-23 17:11:41 +0530947 initialized = mDeviceHost.checkFirmware();
nxpandroid64fd68c2015-09-23 16:45:15 +0530948 }
nxf500513a018e72019-04-23 17:11:41 +0530949 if (initialized) {
950 SystemProperties.set("nfc.initialized", "true");
951 }
nxpandroid64fd68c2015-09-23 16:45:15 +0530952 break;
953 }
954
955 // Restore default AsyncTask priority
956 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
957 return null;
958 }
959
nxpandroid64fd68c2015-09-23 16:45:15 +0530960 /**
961 * Enable NFC adapter functions.
962 * Does not toggle preferences.
963 */
964 boolean enableInternal() {
965 if (mState == NfcAdapter.STATE_ON) {
966 return true;
967 }
968 Log.i(TAG, "Enabling NFC");
Ganesh Devac90b32d2019-07-12 11:53:10 +0530969 StatsLog.write(StatsLog.NFC_STATE_CHANGED, StatsLog.NFC_STATE_CHANGED__STATE__ON);
nxpandroid64fd68c2015-09-23 16:45:15 +0530970 updateState(NfcAdapter.STATE_TURNING_ON);
nxf500513a018e72019-04-23 17:11:41 +0530971
972 WatchDogThread watchDog = new WatchDogThread("enableInternal", INIT_WATCHDOG_MS);
nxpandroid64fd68c2015-09-23 16:45:15 +0530973 watchDog.start();
974 try {
975 mRoutingWakeLock.acquire();
976 try {
977 if (!mDeviceHost.initialize()) {
978 Log.w(TAG, "Error enabling NFC");
979 updateState(NfcAdapter.STATE_OFF);
980 return false;
981 }
982 } finally {
983 mRoutingWakeLock.release();
984 }
985 } finally {
986 watchDog.cancel();
987 }
nxf500513a018e72019-04-23 17:11:41 +0530988 int uiccSlot = 0;
989 uiccSlot = mPrefs.getInt(PREF_CUR_SELECTED_UICC_ID, SECURE_ELEMENT_UICC_SLOT_DEFAULT);
990 mDeviceHost.setPreferredSimSlot(uiccSlot);
Suhas Suresh89d0d612019-05-13 18:34:25 +0530991 nci_version = getNciVersion();
992 Log.d(TAG, "NCI_Version: " + nci_version);
Ganesh Deva49fde922019-05-21 15:07:33 +0530993 mNxpPrefsEditor.remove("PREF_SET_DEFAULT_ROUTE_ID").commit();
nxpandroid64fd68c2015-09-23 16:45:15 +0530994 if (mIsHceCapable) {
995 // Generate the initial card emulation routing table
nxpandroid64fd68c2015-09-23 16:45:15 +0530996 mCardEmulationManager.onNfcEnabled();
nxf500513a018e72019-04-23 17:11:41 +0530997 computeRoutingParameters();
nxpandroid64fd68c2015-09-23 16:45:15 +0530998 }
nxf500513a018e72019-04-23 17:11:41 +0530999
nxpandroid64fd68c2015-09-23 16:45:15 +05301000 synchronized (NfcService.this) {
1001 mObjectMap.clear();
nxf500513a018e72019-04-23 17:11:41 +05301002 if (mIsBeamCapable) {
1003 mP2pLinkManager.enableDisable(mIsNdefPushEnabled, true);
1004 }
1005 updateState(NfcAdapter.STATE_ON);
nxpandroid64fd68c2015-09-23 16:45:15 +05301006 }
1007
nxf500513a018e72019-04-23 17:11:41 +05301008 initSoundPool();
1009
nxpandroid64fd68c2015-09-23 16:45:15 +05301010 mScreenState = mScreenStateHelper.checkScreenState();
nxpandroide66eb092017-07-12 21:36:08 +05301011 int screen_state_mask = (mNfcUnlockManager.isLockscreenPollingEnabled()) ?
1012 (ScreenStateHelper.SCREEN_POLLING_TAG_MASK | mScreenState) : mScreenState;
1013
1014 if(mNfcUnlockManager.isLockscreenPollingEnabled())
1015 applyRouting(false);
1016
nxf500513a018e72019-04-23 17:11:41 +05301017 mDeviceHost.doSetScreenState(screen_state_mask);
1018
1019 /* Start polling loop */
nxpandroid64fd68c2015-09-23 16:45:15 +05301020 applyRouting(true);
nxf500513a018e72019-04-23 17:11:41 +05301021 commitRouting();
1022 /* WiredSe Init after ESE is discovered and initialised */
1023 initWiredSe();
Ganesh Devaf18df212019-06-25 11:02:30 +05301024 synchronized (NfcService.this) {
1025 mNxpNfcState = NXP_NFC_STATE_ON;
1026 }
nxpandroid64fd68c2015-09-23 16:45:15 +05301027 return true;
1028 }
1029
1030 /**
1031 * Disable all NFC adapter functions.
1032 * Does not toggle preferences.
1033 */
1034 boolean disableInternal() {
1035 if (mState == NfcAdapter.STATE_OFF) {
1036 return true;
1037 }
1038 Log.i(TAG, "Disabling NFC");
Ganesh Devac90b32d2019-07-12 11:53:10 +05301039 StatsLog.write(StatsLog.NFC_STATE_CHANGED, StatsLog.NFC_STATE_CHANGED__STATE__OFF);
nxpandroid64fd68c2015-09-23 16:45:15 +05301040 updateState(NfcAdapter.STATE_TURNING_OFF);
Ganesh Deva1ad7d6f2019-06-17 11:46:02 +05301041 deInitWiredSe();
nxpandroid64fd68c2015-09-23 16:45:15 +05301042 /* Sometimes mDeviceHost.deinitialize() hangs, use a watch-dog.
1043 * Implemented with a new thread (instead of a Handler or AsyncTask),
1044 * because the UI Thread and AsyncTask thread-pools can also get hung
1045 * when the NFC controller stops responding */
nxf500513a018e72019-04-23 17:11:41 +05301046 WatchDogThread watchDog = new WatchDogThread("disableInternal", ROUTING_WATCHDOG_MS);
1047 Log.d(TAG, "New Watchdog: WatchDog Thread ID is "+ watchDog.getId());
1048 watchDog.start();
nxpandroid64fd68c2015-09-23 16:45:15 +05301049
1050 if (mIsHceCapable) {
1051 mCardEmulationManager.onNfcDisabled();
1052 }
1053
nxf500513a018e72019-04-23 17:11:41 +05301054 if (mIsBeamCapable) {
1055 mP2pLinkManager.enableDisable(false, false);
nxpandroid64fd68c2015-09-23 16:45:15 +05301056 }
1057
1058 // Stop watchdog if tag present
1059 // A convenient way to stop the watchdog properly consists of
1060 // disconnecting the tag. The polling loop shall be stopped before
1061 // to avoid the tag being discovered again.
1062 maybeDisconnectTarget();
1063
1064 mNfcDispatcher.setForegroundDispatch(null, null, null);
1065
nxf500513a018e72019-04-23 17:11:41 +05301066
nxpandroid64fd68c2015-09-23 16:45:15 +05301067 boolean result = mDeviceHost.deinitialize();
1068 if (DBG) Log.d(TAG, "mDeviceHost.deinitialize() = " + result);
nxf500513a018e72019-04-23 17:11:41 +05301069 isWiredOpen = false;
1070 watchDog.cancel();
nxpandroid64fd68c2015-09-23 16:45:15 +05301071
1072 synchronized (NfcService.this) {
1073 mCurrentDiscoveryParameters = NfcDiscoveryParameters.getNfcOffParameters();
1074 updateState(NfcAdapter.STATE_OFF);
Ganesh Devaf18df212019-06-25 11:02:30 +05301075 mNxpNfcState = NXP_NFC_STATE_OFF;
nxpandroid64fd68c2015-09-23 16:45:15 +05301076 }
nxf500513a018e72019-04-23 17:11:41 +05301077 releaseSoundPool();
nxpandroid1680a6d2017-01-13 19:13:14 +05301078 return result;
1079 }
1080
nxpandroid64fd68c2015-09-23 16:45:15 +05301081 void updateState(int newState) {
1082 synchronized (NfcService.this) {
1083 if (newState == mState) {
1084 return;
1085 }
nxpandroid64fd68c2015-09-23 16:45:15 +05301086 mState = newState;
1087 Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
1088 intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1089 intent.putExtra(NfcAdapter.EXTRA_ADAPTER_STATE, mState);
1090 mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
1091 }
1092 }
1093 }
1094
1095 void saveNfcOnSetting(boolean on) {
1096 synchronized (NfcService.this) {
1097 mPrefsEditor.putBoolean(PREF_NFC_ON, on);
1098 mPrefsEditor.apply();
nxpandroid6fd9cdb2017-07-12 18:25:41 +05301099 mBackupManager.dataChanged();
nxpandroid64fd68c2015-09-23 16:45:15 +05301100 }
1101 }
1102
1103 public void playSound(int sound) {
1104 synchronized (this) {
1105 if (mSoundPool == null) {
1106 Log.w(TAG, "Not playing sound when NFC is disabled");
1107 return;
1108 }
Nikhil Chhabrafc8f3f62018-01-08 20:48:49 +05301109
1110 if (mIsVrModeEnabled) {
1111 Log.d(TAG, "Not playing NFC sound when Vr Mode is enabled");
1112 return;
1113 }
nxpandroid64fd68c2015-09-23 16:45:15 +05301114 switch (sound) {
1115 case SOUND_START:
1116 mSoundPool.play(mStartSound, 1.0f, 1.0f, 0, 0, 1.0f);
1117 break;
1118 case SOUND_END:
1119 mSoundPool.play(mEndSound, 1.0f, 1.0f, 0, 0, 1.0f);
1120 break;
1121 case SOUND_ERROR:
1122 mSoundPool.play(mErrorSound, 1.0f, 1.0f, 0, 0, 1.0f);
1123 break;
1124 }
1125 }
1126 }
1127
1128 synchronized int getUserId() {
1129 return mUserId;
1130 }
1131
Suhas Suresha18dee02018-04-27 15:28:04 +05301132 void enforceBeamShareActivityPolicy(Context context, UserHandle uh) {
nxpandroid64fd68c2015-09-23 16:45:15 +05301133 UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
1134 IPackageManager mIpm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
Suhas Suresha18dee02018-04-27 15:28:04 +05301135 boolean isGlobalEnabled = mIsNdefPushEnabled;
nxpandroid64fd68c2015-09-23 16:45:15 +05301136 boolean isActiveForUser =
nxf500513a018e72019-04-23 17:11:41 +05301137 (!um.hasUserRestriction(UserManager.DISALLOW_OUTGOING_BEAM, uh)) &&
1138 isGlobalEnabled && mIsBeamCapable;
Suhas Sureshe2a2ff02018-04-27 12:21:19 +05301139 if (DBG) {
Suhas Suresha18dee02018-04-27 15:28:04 +05301140 Log.d(TAG, "Enforcing a policy change on user: " + uh.toString() +
nxpandroid64fd68c2015-09-23 16:45:15 +05301141 ", isActiveForUser = " + isActiveForUser);
1142 }
1143 try {
1144 mIpm.setComponentEnabledSetting(new ComponentName(
1145 BeamShareActivity.class.getPackageName$(),
1146 BeamShareActivity.class.getName()),
1147 isActiveForUser ?
1148 PackageManager.COMPONENT_ENABLED_STATE_ENABLED :
1149 PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
1150 PackageManager.DONT_KILL_APP,
nxf500513a018e72019-04-23 17:11:41 +05301151 uh.getIdentifier());
nxpandroid64fd68c2015-09-23 16:45:15 +05301152 } catch (RemoteException e) {
1153 Log.w(TAG, "Unable to change Beam status for user " + uh);
1154 }
1155 }
1156
1157 final class NfcAdapterService extends INfcAdapter.Stub {
1158 @Override
1159 public boolean enable() throws RemoteException {
Ganesh Devaf18df212019-06-25 11:02:30 +05301160 synchronized (NfcService.this) {
1161 if (mNxpNfcState != NXP_NFC_STATE_OFF) {
1162 Log.e(TAG, "mNxpNfcStateis not equal to NXP_NFC_STATE_OFF."
1163 + " Enable NFC Rejected.");
1164 return false;
1165 }
1166 mNxpNfcState = NXP_NFC_STATE_TURNING_ON;
1167 }
nxf38293dcc67462018-08-31 15:57:08 +05301168 NfcPermissions.enforceAdminPermissions(mContext);
nxpandroid64fd68c2015-09-23 16:45:15 +05301169
1170 saveNfcOnSetting(true);
1171
nxpandroid64fd68c2015-09-23 16:45:15 +05301172 new EnableDisableTask().execute(TASK_ENABLE);
1173
1174 return true;
1175 }
1176
Ganesh Deva1ad7d6f2019-06-17 11:46:02 +05301177 public void resonantFrequency(int isResonantFreq)
1178 {
1179 Log.d(TAG, "resonantFrequency");
1180 if(0x00 != isResonantFreq)
1181 mDeviceHost.doResonantFrequency(true);
1182 else
1183 mDeviceHost.doResonantFrequency(false);
1184 }
nxpandroid64fd68c2015-09-23 16:45:15 +05301185 @Override
1186 public boolean disable(boolean saveState) throws RemoteException {
Ganesh Devaf18df212019-06-25 11:02:30 +05301187 synchronized (NfcService.this) {
1188 if (mNxpNfcState != NXP_NFC_STATE_ON) {
1189 Log.e(TAG, "mNxpNfcStateis not equal to NXP_NFC_STATE_ON."
1190 + " Disable NFC Rejected.");
1191 return false;
1192 }
1193 mNxpNfcState = NXP_NFC_STATE_TURNING_OFF;
1194 }
nxf500513a018e72019-04-23 17:11:41 +05301195 NfcPermissions.enforceAdminPermissions(mContext);
Nikhil Chhabrad6957c72018-03-09 11:44:48 +05301196
nxf500513a018e72019-04-23 17:11:41 +05301197 if (saveState) {
1198 saveNfcOnSetting(false);
1199 }
Nikhil Chhabrad6957c72018-03-09 11:44:48 +05301200
nxf500513a018e72019-04-23 17:11:41 +05301201 new EnableDisableTask().execute(TASK_DISABLE);
nxpandroid64fd68c2015-09-23 16:45:15 +05301202
nxf500513a018e72019-04-23 17:11:41 +05301203 return true;
nxpandroid64fd68c2015-09-23 16:45:15 +05301204 }
1205
1206 @Override
1207 public void pausePolling(int timeoutInMs) {
1208 NfcPermissions.enforceAdminPermissions(mContext);
1209
1210 if (timeoutInMs <= 0 || timeoutInMs > MAX_POLLING_PAUSE_TIMEOUT) {
1211 Log.e(TAG, "Refusing to pause polling for " + timeoutInMs + "ms.");
1212 return;
1213 }
1214
1215 synchronized (NfcService.this) {
1216 mPollingPaused = true;
1217 mDeviceHost.disableDiscovery();
1218 mHandler.sendMessageDelayed(
1219 mHandler.obtainMessage(MSG_RESUME_POLLING), timeoutInMs);
1220 }
1221 }
1222
1223 @Override
1224 public void resumePolling() {
1225 NfcPermissions.enforceAdminPermissions(mContext);
1226
1227 synchronized (NfcService.this) {
1228 if (!mPollingPaused) {
1229 return;
1230 }
1231
1232 mHandler.removeMessages(MSG_RESUME_POLLING);
1233 mPollingPaused = false;
1234 new ApplyRoutingTask().execute();
1235 }
1236 }
1237
1238 @Override
1239 public boolean isNdefPushEnabled() throws RemoteException {
1240 synchronized (NfcService.this) {
1241 return mState == NfcAdapter.STATE_ON && mIsNdefPushEnabled;
1242 }
1243 }
1244
1245 @Override
1246 public boolean enableNdefPush() throws RemoteException {
1247 NfcPermissions.enforceAdminPermissions(mContext);
1248 synchronized (NfcService.this) {
nxf500513a018e72019-04-23 17:11:41 +05301249 if (mIsNdefPushEnabled || !mIsBeamCapable) {
nxpandroid64fd68c2015-09-23 16:45:15 +05301250 return true;
1251 }
1252 Log.i(TAG, "enabling NDEF Push");
1253 mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, true);
1254 mPrefsEditor.apply();
1255 mIsNdefPushEnabled = true;
Ganesh Devab1498762019-04-30 15:13:22 +05301256 // Propagate the state change to all user profiles
1257 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1258 List <UserHandle> luh = um.getUserProfiles();
1259 for (UserHandle uh : luh){
1260 enforceBeamShareActivityPolicy(mContext, uh);
1261 }
Suhas Suresha18dee02018-04-27 15:28:04 +05301262 enforceBeamShareActivityPolicy(mContext, new UserHandle(mUserId));
nxpandroid64fd68c2015-09-23 16:45:15 +05301263 if (isNfcEnabled()) {
1264 mP2pLinkManager.enableDisable(true, true);
1265 }
nxpandroid6fd9cdb2017-07-12 18:25:41 +05301266 mBackupManager.dataChanged();
nxpandroid64fd68c2015-09-23 16:45:15 +05301267 }
1268 return true;
1269 }
1270
nxf500513a018e72019-04-23 17:11:41 +05301271 @Override
1272 public boolean isNfcSecureEnabled() throws RemoteException {
1273 synchronized (NfcService.this) {
1274 return mIsSecureNfcEnabled;
1275 }
1276 }
1277
1278 @Override
1279 public boolean setNfcSecure(boolean enable) {
1280 NfcPermissions.enforceAdminPermissions(mContext);
Ganesh Deva77866362019-07-12 11:58:49 +05301281 if(mKeyguard.isKeyguardLocked() && !enable) {
1282 Log.i(TAG, "KeyGuard need to be unlocked before setting Secure NFC OFF");
1283 return false;
1284 }
1285
nxf500513a018e72019-04-23 17:11:41 +05301286 synchronized (NfcService.this) {
1287 Log.i(TAG, "setting Secure NFC " + enable);
1288 mPrefsEditor.putBoolean(PREF_SECURE_NFC_ON, enable);
1289 mPrefsEditor.apply();
1290 mIsSecureNfcEnabled = enable;
1291 mBackupManager.dataChanged();
1292 mDeviceHost.setNfcSecure(enable);
1293 computeAndSetRoutingParameters();
1294 }
1295 if (mIsHceCapable) {
1296 mCardEmulationManager.onSecureNfcToggled();
1297 }
Ganesh Devafc5ab6f2019-07-12 11:55:25 +05301298 if (enable)
1299 StatsLog.write(StatsLog.NFC_STATE_CHANGED, StatsLog.NFC_STATE_CHANGED__STATE__ON_LOCKED);
1300 else
1301 StatsLog.write(StatsLog.NFC_STATE_CHANGED, StatsLog.NFC_STATE_CHANGED__STATE__ON);
nxf500513a018e72019-04-23 17:11:41 +05301302 return true;
1303 }
1304
nxpandroid64fd68c2015-09-23 16:45:15 +05301305 @Override
1306 public boolean disableNdefPush() throws RemoteException {
1307 NfcPermissions.enforceAdminPermissions(mContext);
1308 synchronized (NfcService.this) {
nxf500513a018e72019-04-23 17:11:41 +05301309 if (!mIsNdefPushEnabled || !mIsBeamCapable) {
nxpandroid64fd68c2015-09-23 16:45:15 +05301310 return true;
1311 }
1312 Log.i(TAG, "disabling NDEF Push");
1313 mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, false);
1314 mPrefsEditor.apply();
1315 mIsNdefPushEnabled = false;
Ganesh Devab1498762019-04-30 15:13:22 +05301316 // Propagate the state change to all user profiles
1317 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1318 List <UserHandle> luh = um.getUserProfiles();
1319 for (UserHandle uh : luh){
1320 enforceBeamShareActivityPolicy(mContext, uh);
1321 }
Suhas Suresha18dee02018-04-27 15:28:04 +05301322 enforceBeamShareActivityPolicy(mContext, new UserHandle(mUserId));
nxpandroid64fd68c2015-09-23 16:45:15 +05301323 if (isNfcEnabled()) {
1324 mP2pLinkManager.enableDisable(false, true);
1325 }
nxpandroid6fd9cdb2017-07-12 18:25:41 +05301326 mBackupManager.dataChanged();
nxpandroid64fd68c2015-09-23 16:45:15 +05301327 }
1328 return true;
1329 }
1330
1331 @Override
1332 public void setForegroundDispatch(PendingIntent intent,
1333 IntentFilter[] filters, TechListParcel techListsParcel) {
1334 NfcPermissions.enforceUserPermissions(mContext);
nxpandroid281eb922016-08-25 20:27:46 +05301335 if (!mForegroundUtils.isInForeground(Binder.getCallingUid())) {
1336 Log.e(TAG, "setForegroundDispatch: Caller not in foreground.");
1337 return;
1338 }
nxpandroid64fd68c2015-09-23 16:45:15 +05301339 // Short-cut the disable path
1340 if (intent == null && filters == null && techListsParcel == null) {
1341 mNfcDispatcher.setForegroundDispatch(null, null, null);
1342 return;
1343 }
1344
1345 // Validate the IntentFilters
1346 if (filters != null) {
1347 if (filters.length == 0) {
1348 filters = null;
1349 } else {
1350 for (IntentFilter filter : filters) {
1351 if (filter == null) {
1352 throw new IllegalArgumentException("null IntentFilter");
1353 }
1354 }
1355 }
1356 }
1357
1358 // Validate the tech lists
1359 String[][] techLists = null;
1360 if (techListsParcel != null) {
1361 techLists = techListsParcel.getTechLists();
1362 }
1363
1364 mNfcDispatcher.setForegroundDispatch(intent, filters, techLists);
1365 }
1366
nxf500513a018e72019-04-23 17:11:41 +05301367
nxpandroid64fd68c2015-09-23 16:45:15 +05301368 @Override
1369 public void setAppCallback(IAppCallback callback) {
1370 NfcPermissions.enforceUserPermissions(mContext);
1371
1372 // don't allow Beam for managed profiles, or devices with a device owner or policy owner
1373 UserInfo userInfo = mUserManager.getUserInfo(UserHandle.getCallingUserId());
nxf500513a018e72019-04-23 17:11:41 +05301374 if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_OUTGOING_BEAM,
1375 userInfo.getUserHandle()) &&
1376 mIsBeamCapable) {
nxpandroid64fd68c2015-09-23 16:45:15 +05301377 mP2pLinkManager.setNdefCallback(callback, Binder.getCallingUid());
1378 } else if (DBG) {
1379 Log.d(TAG, "Disabling default Beam behavior");
1380 }
1381 }
1382
1383 @Override
nxpandroid281eb922016-08-25 20:27:46 +05301384 public boolean ignore(int nativeHandle, int debounceMs, ITagRemovedCallback callback)
1385 throws RemoteException {
1386 NfcPermissions.enforceUserPermissions(mContext);
1387
Nikhil Chhabra1b2368f2018-01-09 18:34:21 +05301388 if (debounceMs == 0 && mDebounceTagNativeHandle != INVALID_NATIVE_HANDLE
1389 && nativeHandle == mDebounceTagNativeHandle) {
1390 // Remove any previous messages and immediately debounce.
1391 mHandler.removeMessages(MSG_TAG_DEBOUNCE);
1392 mHandler.sendEmptyMessage(MSG_TAG_DEBOUNCE);
1393 return true;
1394 }
1395
nxpandroid281eb922016-08-25 20:27:46 +05301396 TagEndpoint tag = (TagEndpoint) findAndRemoveObject(nativeHandle);
1397 if (tag != null) {
1398 // Store UID and params
1399 int uidLength = tag.getUid().length;
1400 synchronized (NfcService.this) {
1401 mDebounceTagDebounceMs = debounceMs;
Nikhil Chhabra1b2368f2018-01-09 18:34:21 +05301402 mDebounceTagNativeHandle = nativeHandle;
nxpandroid281eb922016-08-25 20:27:46 +05301403 mDebounceTagUid = new byte[uidLength];
1404 mDebounceTagRemovedCallback = callback;
1405 System.arraycopy(tag.getUid(), 0, mDebounceTagUid, 0, uidLength);
1406 }
1407
1408 // Disconnect from this tag; this should resume the normal
1409 // polling loop (and enter listen mode for a while), before
1410 // we pick up any tags again.
1411 tag.disconnect();
1412 mHandler.sendEmptyMessageDelayed(MSG_TAG_DEBOUNCE, debounceMs);
1413 return true;
1414 } else {
1415 return false;
1416 }
1417 }
1418
nxf500513a018e72019-04-23 17:11:41 +05301419 @Override
nxpandroid64fd68c2015-09-23 16:45:15 +05301420 public void verifyNfcPermission() {
1421 NfcPermissions.enforceUserPermissions(mContext);
1422 }
1423
1424 @Override
1425 public void invokeBeam() {
nxf500513a018e72019-04-23 17:11:41 +05301426 if (!mIsBeamCapable) {
1427 return;
1428 }
nxpandroid64fd68c2015-09-23 16:45:15 +05301429 NfcPermissions.enforceUserPermissions(mContext);
1430
1431 if (mForegroundUtils.isInForeground(Binder.getCallingUid())) {
1432 mP2pLinkManager.onManualBeamInvoke(null);
1433 } else {
1434 Log.e(TAG, "Calling activity not in foreground.");
1435 }
1436 }
1437
1438 @Override
1439 public void invokeBeamInternal(BeamShareData shareData) {
1440 NfcPermissions.enforceAdminPermissions(mContext);
1441 Message msg = Message.obtain();
1442 msg.what = MSG_INVOKE_BEAM;
1443 msg.obj = shareData;
1444 // We have to send this message delayed for two reasons:
1445 // 1) This is an IPC call from BeamShareActivity, which is
1446 // running when the user has invoked Beam through the
1447 // share menu. As soon as BeamShareActivity closes, the UI
1448 // will need some time to rebuild the original Activity.
1449 // Waiting here for a while gives a better chance of the UI
1450 // having been rebuilt, which means the screenshot that the
1451 // Beam animation is using will be more accurate.
1452 // 2) Similarly, because the Activity that launched BeamShareActivity
1453 // with an ACTION_SEND intent is now in paused state, the NDEF
1454 // callbacks that it has registered may no longer be valid.
1455 // Allowing the original Activity to resume will make sure we
1456 // it has a chance to re-register the NDEF message / callback,
1457 // so we share the right data.
1458 //
1459 // Note that this is somewhat of a hack because the delay may not actually
1460 // be long enough for 2) on very slow devices, but there's no better
1461 // way to do this right now without additional framework changes.
1462 mHandler.sendMessageDelayed(msg, INVOKE_BEAM_DELAY_MS);
1463 }
1464
1465 @Override
1466 public INfcTag getNfcTagInterface() throws RemoteException {
1467 return mNfcTagService;
1468 }
1469
1470 @Override
1471 public INfcCardEmulation getNfcCardEmulationInterface() {
1472 if (mIsHceCapable) {
1473 return mCardEmulationManager.getNfcCardEmulationInterface();
1474 } else {
1475 return null;
1476 }
1477 }
1478
nxpandroid34627bd2016-05-27 15:52:30 +05301479 @Override
1480 public INfcFCardEmulation getNfcFCardEmulationInterface() {
1481 if (mIsHceFCapable) {
1482 return mCardEmulationManager.getNfcFCardEmulationInterface();
1483 } else {
1484 return null;
1485 }
nxf500513a018e72019-04-23 17:11:41 +05301486 }
nxpandroid64fd68c2015-09-23 16:45:15 +05301487
1488 @Override
1489 public int getState() throws RemoteException {
1490 synchronized (NfcService.this) {
1491 return mState;
1492 }
1493 }
1494
1495 @Override
1496 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1497 NfcService.this.dump(fd, pw, args);
1498 }
1499
1500 @Override
1501 public void dispatch(Tag tag) throws RemoteException {
1502 NfcPermissions.enforceAdminPermissions(mContext);
1503 mNfcDispatcher.dispatchTag(tag);
1504 }
1505
1506 @Override
1507 public void setP2pModes(int initiatorModes, int targetModes) throws RemoteException {
1508 NfcPermissions.enforceAdminPermissions(mContext);
1509 mDeviceHost.setP2pInitiatorModes(initiatorModes);
1510 mDeviceHost.setP2pTargetModes(targetModes);
1511 applyRouting(true);
1512 }
1513
1514 @Override
1515 public void setReaderMode(IBinder binder, IAppCallback callback, int flags, Bundle extras)
1516 throws RemoteException {
nxpandroid281eb922016-08-25 20:27:46 +05301517 int callingUid = Binder.getCallingUid();
1518 if (callingUid != Process.SYSTEM_UID && !mForegroundUtils.isInForeground(callingUid)) {
1519 Log.e(TAG, "setReaderMode: Caller is not in foreground and is not system process.");
1520 return;
1521 }
nxpandroid64fd68c2015-09-23 16:45:15 +05301522 synchronized (NfcService.this) {
nxpandroid34627bd2016-05-27 15:52:30 +05301523 if (!isNfcEnabled()) {
1524 Log.e(TAG, "setReaderMode() called while NFC is not enabled.");
1525 return;
1526 }
nxpandroid64fd68c2015-09-23 16:45:15 +05301527 if (flags != 0) {
1528 try {
1529 mReaderModeParams = new ReaderModeParams();
1530 mReaderModeParams.callback = callback;
1531 mReaderModeParams.flags = flags;
1532 mReaderModeParams.presenceCheckDelay = extras != null
1533 ? (extras.getInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY,
1534 DEFAULT_PRESENCE_CHECK_DELAY))
1535 : DEFAULT_PRESENCE_CHECK_DELAY;
1536 binder.linkToDeath(mReaderModeDeathRecipient, 0);
1537 } catch (RemoteException e) {
1538 Log.e(TAG, "Remote binder has already died.");
1539 return;
1540 }
1541 } else {
1542 try {
1543 mReaderModeParams = null;
Suhas Suresh5efc5432018-04-27 15:31:02 +05301544 StopPresenceChecking();
nxpandroid64fd68c2015-09-23 16:45:15 +05301545 binder.unlinkToDeath(mReaderModeDeathRecipient, 0);
1546 } catch (NoSuchElementException e) {
1547 Log.e(TAG, "Reader mode Binder was never registered.");
1548 }
1549 }
nxpandroid64fd68c2015-09-23 16:45:15 +05301550 applyRouting(false);
1551 }
1552 }
1553
nxf500513a018e72019-04-23 17:11:41 +05301554 @Override
1555 public INfcAdapterExtras getNfcAdapterExtrasInterface(String pkg) throws RemoteException {
1556 return (INfcAdapterExtras) mNfcExtraObj;
1557 }
1558
1559 @Override
1560 public INfcDta getNfcDtaInterface(String pkg) throws RemoteException {
1561 NfcPermissions.enforceAdminPermissions(mContext);
1562 if (mNfcDtaService == null) {
1563 mNfcDtaService = new NfcDtaService();
1564 }
1565 return mNfcDtaService;
1566 }
nxpandroid64fd68c2015-09-23 16:45:15 +05301567
1568 @Override
1569 public void addNfcUnlockHandler(INfcUnlockHandler unlockHandler, int[] techList) {
1570 NfcPermissions.enforceAdminPermissions(mContext);
1571
1572 int lockscreenPollMask = computeLockscreenPollMask(techList);
1573 synchronized (NfcService.this) {
1574 mNfcUnlockManager.addUnlockHandler(unlockHandler, lockscreenPollMask);
1575 }
1576
1577 applyRouting(false);
1578 }
1579
1580 @Override
1581 public void removeNfcUnlockHandler(INfcUnlockHandler token) throws RemoteException {
1582 synchronized (NfcService.this) {
1583 mNfcUnlockManager.removeUnlockHandler(token.asBinder());
1584 }
1585
1586 applyRouting(false);
1587 }
nxf500513a018e72019-04-23 17:11:41 +05301588
1589 @Override
1590 public boolean deviceSupportsNfcSecure() {
nxf50051e9931962019-05-16 11:52:10 +05301591 String skuList[] = mContext.getResources().getStringArray(
nxf500513a018e72019-04-23 17:11:41 +05301592 R.array.config_skuSupportsSecureNfc);
1593 String sku = SystemProperties.get("ro.boot.hardware.sku");
1594 if (TextUtils.isEmpty(sku) || !ArrayUtils.contains(skuList, sku)) {
1595 return false;
1596 }
nxf50051e9931962019-05-16 11:52:10 +05301597 return true;
nxf500513a018e72019-04-23 17:11:41 +05301598 }
1599
nxpandroid64fd68c2015-09-23 16:45:15 +05301600 private int computeLockscreenPollMask(int[] techList) {
1601
1602 Map<Integer, Integer> techCodeToMask = new HashMap<Integer, Integer>();
1603
1604 techCodeToMask.put(TagTechnology.NFC_A, NfcService.NFC_POLL_A);
1605 techCodeToMask.put(TagTechnology.NFC_B, NfcService.NFC_POLL_B);
Nikhil Chhabra288edb02018-01-10 19:36:21 +05301606 techCodeToMask.put(TagTechnology.NFC_V, NfcService.NFC_POLL_V);
nxpandroid64fd68c2015-09-23 16:45:15 +05301607 techCodeToMask.put(TagTechnology.NFC_F, NfcService.NFC_POLL_F);
1608 techCodeToMask.put(TagTechnology.NFC_BARCODE, NfcService.NFC_POLL_KOVIO);
nxpandroid64fd68c2015-09-23 16:45:15 +05301609
1610 int mask = 0;
1611
1612 for (int i = 0; i < techList.length; i++) {
1613 if (techCodeToMask.containsKey(techList[i])) {
1614 mask |= techCodeToMask.get(techList[i]).intValue();
1615 }
1616 }
1617
1618 return mask;
1619 }
nxpandroid6fd9cdb2017-07-12 18:25:41 +05301620 /**
1621 * An interface for nxp extensions
1622 */
nxpandroid64fd68c2015-09-23 16:45:15 +05301623 @Override
nxpandroid6fd9cdb2017-07-12 18:25:41 +05301624 public IBinder getNfcAdapterVendorInterface(String vendor) {
1625 if(vendor.equalsIgnoreCase("nxp")) {
1626 return (IBinder) mNxpNfcAdapter;
1627 } else {
1628 return null;
1629 }
nxpandroid64fd68c2015-09-23 16:45:15 +05301630 }
1631 }
nxf500513a018e72019-04-23 17:11:41 +05301632
nxpandroid64fd68c2015-09-23 16:45:15 +05301633 final class NxpNfcAdapterService extends INxpNfcAdapter.Stub {
nxpandroid64fd68c2015-09-23 16:45:15 +05301634 @Override
nxf500513a018e72019-04-23 17:11:41 +05301635 public INxpNfcAdapterExtras getNxpNfcAdapterExtrasInterface() throws RemoteException {
1636 return mNxpExtrasService;
nxpandroid64fd68c2015-09-23 16:45:15 +05301637 }
nxpandroid64fd68c2015-09-23 16:45:15 +05301638 @Override
nxf500513a018e72019-04-23 17:11:41 +05301639 public void MifareDesfireRouteSet(int routeLoc, boolean fullPower, boolean lowPower,
1640 boolean noPower) throws RemoteException {
1641 if (routeLoc == UICC2_ID_TYPE) {
1642 throw new RemoteException("UICC2 is not supported");
1643 }
1644 int protoRouteEntry = 0;
1645 /*UICC2 ID-4(fromApp) mapped to 3 (JNI)*/
1646 protoRouteEntry = ((routeLoc & 0x07) == 0x04) ? (0x03 << ROUTE_LOC_MASK) : /*UICC2*/
1647 ((routeLoc & 0x07) == 0x02) ? (0x02 << ROUTE_LOC_MASK) : /*UICC1*/
1648 ((routeLoc & 0x07) == 0x01) ? (0x01 << ROUTE_LOC_MASK) : /*eSE*/
1649 0x00;
1650 protoRouteEntry |=
1651 ((fullPower ? (mDeviceHost.getDefaultDesfirePowerState() & 0x1F) | 0x01 : 0)
1652 | (lowPower ? 0x01 << 1 : 0) | (noPower ? 0x01 << 2 : 0));
1653
1654 if (routeLoc == 0x00) {
1655 /*
1656 bit pos 1 = Power Off
1657 bit pos 2 = Battery Off
1658 bit pos 4 = Screen Off
1659 Set these bits to 0 because in case routeLoc = HOST it can not work on POWER_OFF,
1660 BATTERY_OFF and SCREEN_OFF*/
1661 protoRouteEntry &= 0xE9;
1662 }
1663
1664 Log.i(TAG, "MifareDesfireRouteSet : " + protoRouteEntry);
1665 mNxpPrefsEditor = mNxpPrefs.edit();
1666 mNxpPrefsEditor.putInt("PREF_MIFARE_DESFIRE_PROTO_ROUTE_ID", protoRouteEntry);
1667 mNxpPrefsEditor.commit();
1668 Log.i(TAG, "MifareDesfireRouteSet function in");
1669 commitRouting();
nxpandroid64fd68c2015-09-23 16:45:15 +05301670 }
nxpandroid64fd68c2015-09-23 16:45:15 +05301671 @Override
nxf500513a018e72019-04-23 17:11:41 +05301672 public void MifareCLTRouteSet(int routeLoc, boolean fullPower, boolean lowPower,
1673 boolean noPower) throws RemoteException {
1674 if (routeLoc == UICC2_ID_TYPE) {
1675 throw new RemoteException("UICC2 is not supported");
1676 }
1677
1678 int techRouteEntry = 0;
1679 techRouteEntry = ((routeLoc & 0x07) == 0x04) ? (0x03 << ROUTE_LOC_MASK) : /*UICC2*/
1680 ((routeLoc & 0x07) == 0x02) ? (0x02 << ROUTE_LOC_MASK) : /*UICC1*/
1681 ((routeLoc & 0x07) == 0x01) ? (0x01 << ROUTE_LOC_MASK) : /*eSE*/
1682 0x00;
1683 techRouteEntry |=
1684 ((fullPower ? (mDeviceHost.getDefaultMifareCLTPowerState() & 0x1F) | 0x01 : 0)
1685 | (lowPower ? 0x01 << 1 : 0) | (noPower ? 0x01 << 2 : 0));
1686 techRouteEntry |= (TECH_TYPE_A << TECH_TYPE_MASK);
1687
1688 Log.i(TAG, "MifareCLTRouteSet : " + techRouteEntry);
1689 mNxpPrefsEditor = mNxpPrefs.edit();
1690 mNxpPrefsEditor.putInt("PREF_MIFARE_CLT_ROUTE_ID", techRouteEntry);
1691 mNxpPrefsEditor.commit();
1692 commitRouting();
nxpandroid64fd68c2015-09-23 16:45:15 +05301693 }
1694
1695 @Override
nxpandroid64fd68c2015-09-23 16:45:15 +05301696 public int[] getActiveSecureElementList(String pkg) throws RemoteException {
nxf50051cd8d5822019-03-20 15:32:57 +05301697 int[] list = null;
1698 if (isNfcEnabled()) {
1699 list = mDeviceHost.doGetActiveSecureElementList();
nxf500513a018e72019-04-23 17:11:41 +05301700 }
1701 for (int i = 0; i < list.length; i++) {
1702 Log.d(TAG, "Active element = " + list[i]);
nxf50051cd8d5822019-03-20 15:32:57 +05301703 }
1704 return list;
nxpandroid64fd68c2015-09-23 16:45:15 +05301705 }
1706
nxpandroid64fd68c2015-09-23 16:45:15 +05301707 @Override
nxf500513a018e72019-04-23 17:11:41 +05301708 public int mPOSSetReaderMode (String pkg, boolean on) {
1709 // Check if NFC is enabled
1710 if (!isNfcEnabled()) {
1711 return NfcConstants.MPOS_STATUS_REJECTED;
Ganesh Devaee0da3a2018-11-27 20:29:40 +05301712 }
1713
nxf500513a018e72019-04-23 17:11:41 +05301714 synchronized(NfcService.this) {
1715 int status = mDeviceHost.mposSetReaderMode(on);
1716 if(!on) {
1717 if(nci_version != NCI_VERSION_2_0) {
1718 applyRouting(true);
1719 } else if(mScreenState == ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED
1720 || mNfcUnlockManager.isLockscreenPollingEnabled()) {
1721 applyRouting(false);
1722 }
1723 }
1724 return status;
1725 }
1726 }
1727
1728 @Override
1729 public boolean mPOSGetReaderMode (String pkg) {
1730 // Check if NFC is enabled
1731 if (!isNfcEnabled()) {
1732 return false;
1733 }
1734
1735 boolean status = false;
1736 synchronized(NfcService.this) {
1737 status = mDeviceHost.mposGetReaderMode();
1738 }
1739 return status;
1740 }
1741 @Override
1742 public void changeDiscoveryTech(IBinder binder, int pollTech, int listenTech)
1743 throws RemoteException {
1744
1745 synchronized (NfcService.this) {
1746 if (!(mState == NfcAdapter.STATE_ON)) {
1747 if (DBG) Log.d(TAG, "changeDiscoveryTech. NFC is not enabled");
1748 return;
1749 }
1750
1751 if (DBG) Log.d(TAG, "changeDiscoveryTech. pollTech : 0x" + Integer.toHexString(pollTech) + ", listenTech : 0x" + Integer.toHexString(listenTech));
1752
1753 //In case both parameters are set to 0xFF, which means that original poll, listen techs are applied.
1754 if (pollTech == 0xFF && listenTech == 0xFF) {
1755 //Recover to previous state.
1756 try {
1757 if (!mIsNdefPushEnabled) {
1758 if (DBG) Log.d(TAG, "changeDiscoveryTech. Android Beam was temporarily enabled, so disable this.");
1759 mP2pLinkManager.enableDisable(false, true);
1760 }
1761 mDeviceHost.doChangeDiscoveryTech(pollTech, listenTech);
1762 } catch(NoSuchElementException e) {
1763 Log.e(TAG, "Change Tech Binder was never registered.");
1764 }
1765 } else {
1766 //Change discovery tech.
1767 if (!mIsNdefPushEnabled) {
1768 if (DBG) Log.d(TAG, "changeDiscoveryTech. Android Beam is disabled, so enable this temporarily.");
1769 mP2pLinkManager.enableDisable(true, true);
1770 }
1771 mDeviceHost.doChangeDiscoveryTech(pollTech, listenTech);
1772 }
1773
1774 if (DBG) Log.d(TAG, "applyRouting #15");
1775 applyRouting(true);
1776 }
1777 }
1778
1779 @Override
1780 public void stopPoll(String pkg, int mode) {
1781 // Check if NFC is enabled
1782 if (!isNfcEnabled()) {
1783 return;
1784 }
1785
1786 synchronized(NfcService.this) {
1787 mDeviceHost.stopPoll(mode);
1788 }
1789 }
1790
1791 @Override
1792 public void startPoll(String pkg) {
1793 // Check if NFC is enabled
1794 if (!isNfcEnabled()) {
1795 return;
1796 }
1797
1798 synchronized(NfcService.this) {
1799 mDeviceHost.startPoll();
1800 }
Ganesh Devaee0da3a2018-11-27 20:29:40 +05301801 }
1802
1803 @Override
nxpandroid64fd68c2015-09-23 16:45:15 +05301804 public void DefaultRouteSet(int routeLoc, boolean fullPower, boolean lowPower, boolean noPower)
1805 throws RemoteException
1806 {
nxf500513a018e72019-04-23 17:11:41 +05301807 if(routeLoc == UICC2_ID_TYPE) {
anil.hiranniah3cb5a1f2018-02-07 19:29:55 +05301808 throw new RemoteException("UICC2 is not supported");
1809 }
nxpandroid64fd68c2015-09-23 16:45:15 +05301810 if (mIsHceCapable) {
1811 int protoRouteEntry = 0;
anil.hiranniah3cb5a1f2018-02-07 19:29:55 +05301812 protoRouteEntry=((routeLoc & 0x07) == 0x04) ? (0x03 << ROUTE_LOC_MASK) : /*UICC2*/
1813 ((routeLoc & 0x07) == 0x02) ? (0x02 << ROUTE_LOC_MASK) : /*UICC1*/
1814 ((routeLoc & 0x07) == 0x01) ? (0x01 << ROUTE_LOC_MASK) : /*eSE*/
1815 0x00;
nxf500513a018e72019-04-23 17:11:41 +05301816 protoRouteEntry |=
1817 ((fullPower ? (mDeviceHost.getDefaultAidPowerState() & 0x1F) | 0x01 : 0)
1818 | (lowPower ? 0x01 << 1 : 0) | (noPower ? 0x01 << 2 : 0));
nxpandroid8aecbf82016-09-16 20:21:47 +05301819
nxpandroid7d44e572016-08-01 19:11:04 +05301820 if(routeLoc == 0x00)
nxpandroid7d44e572016-08-01 19:11:04 +05301821 {
nxpandroid8aecbf82016-09-16 20:21:47 +05301822 /*
1823 bit pos 1 = Power Off
1824 bit pos 2 = Battery Off
nxf500513a018e72019-04-23 17:11:41 +05301825 bit pos 4 = Screen Off
1826 Set these bits to 0 because in case routeLoc = HOST it can not work on
1827 POWER_OFF, BATTERY_OFF and SCREEN_OFF*/
1828 protoRouteEntry &= 0xE9;
nxpandroid7d44e572016-08-01 19:11:04 +05301829 }
1830 Log.i(TAG,"DefaultRouteSet : " + protoRouteEntry);
nxpandroid64fd68c2015-09-23 16:45:15 +05301831 if(GetDefaultRouteLoc() != routeLoc)
1832 {
nxpandroida9a68ba2016-01-14 21:12:17 +05301833 mNxpPrefsEditor = mNxpPrefs.edit();
1834 mNxpPrefsEditor.putInt("PREF_SET_DEFAULT_ROUTE_ID", protoRouteEntry );
1835 mNxpPrefsEditor.commit();
nxpandroid64fd68c2015-09-23 16:45:15 +05301836 mIsRouteForced = true;
1837 if (mIsHceCapable) {
1838 mAidRoutingManager.onNfccRoutingTableCleared();
1839 mCardEmulationManager.onRoutingTableChanged();
1840 }
1841 mIsRouteForced = false;
nxpandroid64fd68c2015-09-23 16:45:15 +05301842 }
1843 }
1844 else{
1845 Log.i(TAG,"DefaultRoute can not be set. mIsHceCapable = flase");
1846 }
1847 }
1848
nxpandroid64fd68c2015-09-23 16:45:15 +05301849 @Override
1850 public byte[] getFWVersion()
1851 {
nxpandroid5d64ce92016-11-18 19:48:53 +05301852 byte[] buf = new byte[3];
nxpandroid64fd68c2015-09-23 16:45:15 +05301853 Log.i(TAG, "Starting getFwVersion");
1854 int fwver = mDeviceHost.getFWVersion();
1855 buf[0] = (byte)((fwver&0xFF00)>>8);
1856 buf[1] = (byte)((fwver&0xFF));
nxpandroid5d64ce92016-11-18 19:48:53 +05301857 buf[2] = (byte)((fwver&0xFF0000)>>16);
nxpandroid64fd68c2015-09-23 16:45:15 +05301858 Log.i(TAG, "Firmware version is 0x"+ buf[0]+" 0x"+buf[1]);
1859 return buf;
1860 }
1861
nxf500513a018e72019-04-23 17:11:41 +05301862 private void WaitForAdapterChange(int state) {
1863 while (true) {
1864 if(mState == state) {
1865 break;
1866 }
1867 try {
1868 Thread.sleep(100);
1869 } catch (Exception e) {
1870 e.printStackTrace();
1871 }
1872 }
1873 return;
1874 }
1875
nxpandroid64fd68c2015-09-23 16:45:15 +05301876 @Override
nxf3829316ee8ee2018-06-29 12:05:36 +05301877 public byte[] readerPassThruMode(byte status, byte modulationTyp)
1878 throws RemoteException {
1879
1880 Log.i(TAG, "Reader pass through mode request: 0x" + status +
1881 " with modulation: 0x" + modulationTyp);
1882 return mDeviceHost.readerPassThruMode(status, modulationTyp);
1883 }
1884
1885 @Override
1886 public byte[] transceiveAppData(byte[] data) throws RemoteException {
1887
1888 Log.i(TAG, "Transceive requested on reader pass through mode");
1889 return mDeviceHost.transceiveAppData(data);
1890 }
nxpandroid281eb922016-08-25 20:27:46 +05301891 @Override
1892 public int setConfig(String configs , String pkg) {
1893 Log.e(TAG, "Setting configs for Transit" );
1894 /*Check permissions*/
1895 NfcPermissions.enforceAdminPermissions(mContext);
1896 /*Check if any NFC transactions are ongoing*/
1897 if(mDeviceHost.isNfccBusy())
1898 {
1899 Log.e(TAG, "NFCC is busy.." );
1900 return TRANSIT_SETCONFIG_STAT_FAILED;
1901 }
1902 /*check if format of configs is fine*/
1903 /*Save configurations to file*/
1904 try {
Ganesh Deva382b1062018-07-27 23:09:03 +05301905 File newTextFile = new File("/data/nfc/libnfc-nxpTransit.conf");
nxpandroid281eb922016-08-25 20:27:46 +05301906 if(configs == null)
1907 {
1908 if(newTextFile.delete()){
1909 Log.e(TAG, "Removing transit config file. Taking default Value" );
1910 }else{
1911 System.out.println("Error taking defualt value");
1912 }
1913 }
1914 else
1915 {
1916 FileWriter fw = new FileWriter(newTextFile);
1917 fw.write(configs);
1918 fw.close();
1919 Log.e(TAG, "File Written to libnfc-nxpTransit.conf successfully" );
1920 }
Ganesh Deva382b1062018-07-27 23:09:03 +05301921 mDeviceHost.setTransitConfig(configs);
nxpandroid281eb922016-08-25 20:27:46 +05301922 } catch (Exception e) {
1923 e.printStackTrace();
1924 return TRANSIT_SETCONFIG_STAT_FAILED;
1925 }
1926
1927 /*restart NFC service*/
1928 try {
1929 mNfcAdapter.disable(true);
Ganesh Deva382b1062018-07-27 23:09:03 +05301930 WaitForAdapterChange(NfcAdapter.STATE_OFF);
nxpandroid281eb922016-08-25 20:27:46 +05301931 mNfcAdapter.enable();
Ganesh Deva382b1062018-07-27 23:09:03 +05301932 WaitForAdapterChange(NfcAdapter.STATE_ON);
nxpandroid281eb922016-08-25 20:27:46 +05301933 } catch (Exception e) {
1934 Log.e(TAG, "Unable to restart NFC Service");
1935 e.printStackTrace();
1936 return TRANSIT_SETCONFIG_STAT_FAILED;
1937 }
1938 return TRANSIT_SETCONFIG_STAT_SUCCESS;
1939 }
Pratap Reddy7e57f0d2018-03-15 16:54:33 +05301940
Ganesh Deva876c65b2018-06-01 18:51:30 +05301941 @Override
1942 public int selectUicc(int uiccSlot) throws RemoteException {
1943 synchronized(NfcService.this) {
1944 if (!isNfcEnabled()) {
1945 throw new RemoteException("NFC is not enabled");
1946 }
1947 int status = mDeviceHost.doselectUicc(uiccSlot);
1948 Log.i(TAG, "Update routing table");
1949 /*In case of UICC connected and Enabled or Removed ,
1950 *Reconfigure the routing table based on current UICC parameters
1951 **/
nxf500513a018e72019-04-23 17:11:41 +05301952 if((status == UICC_CONFIGURED)||(status == UICC_NOT_CONFIGURED))
Ganesh Deva876c65b2018-06-01 18:51:30 +05301953 {
1954 mPrefsEditor.putInt(PREF_CUR_SELECTED_UICC_ID, uiccSlot);
1955 mPrefsEditor.apply();
1956 if((mAidRoutingManager != null) && (mCardEmulationManager != null))
1957 {
1958 Log.i(TAG, "Update routing table");
1959 mAidRoutingManager.onNfccRoutingTableCleared();
nxf500513a018e72019-04-23 17:11:41 +05301960 mDeviceHost.clearRoutingEntry(AID_ENTRY);
1961 mDeviceHost.clearRoutingEntry(TECH_ENTRY);
1962 mDeviceHost.clearRoutingEntry(PROTOCOL_ENTRY);
Ganesh Deva876c65b2018-06-01 18:51:30 +05301963 mCardEmulationManager.onNfcEnabled();
nxf500513a018e72019-04-23 17:11:41 +05301964 computeRoutingParameters();
1965 commitRouting();
Ganesh Deva876c65b2018-06-01 18:51:30 +05301966 }
1967 else
1968 {
1969 Log.i(TAG, "Update only Mifare and Desfire route");
Ganesh Deva876c65b2018-06-01 18:51:30 +05301970 applyRouting(false);
1971 }
1972 }
1973 return status;
1974 }
1975 }
1976
nxf500513a018e72019-04-23 17:11:41 +05301977 @Override
1978 public List<NfcAidServiceInfo> getServicesAidInfo(int userId, String category){
1979 return mCardEmulationManager.getServicesAidInfo(userId, category);
1980 }
1981
1982 @Override
1983 public int updateServiceState(int userId , Map serviceState) {
1984 return mCardEmulationManager.updateServiceState(userId ,serviceState);
1985 }
1986
1987 @Override
1988 public int getMaxAidRoutingTableSize() throws RemoteException {
1989 NfcPermissions.enforceUserPermissions(mContext);
1990 return getAidRoutingTableSize();
1991 }
1992
1993 @Override
1994 public int getCommittedAidRoutingTableSize() throws RemoteException {
1995 NfcPermissions.enforceUserPermissions(mContext);
1996 return (getAidRoutingTableSize() - getRemainingAidTableSize());
1997 }
1998
1999 @Override
2000 public int getSelectedUicc() throws RemoteException {
2001 if (!isNfcEnabled()) {
2002 throw new RemoteException("NFC is not enabled");
2003 }
2004 return mDeviceHost.doGetSelectedUicc();
2005 }
Suhas Sureshf2aa04f2019-06-14 17:55:46 +05302006
2007 @Override
2008 public int setFieldDetectMode(boolean mode) {
2009 NfcPermissions.enforceUserPermissions(mContext);
2010 return mDeviceHost.doSetFieldDetectMode(mode);
2011 }
2012
2013 @Override
2014 public boolean isFieldDetectEnabled() {
2015 NfcPermissions.enforceUserPermissions(mContext);
2016 return mDeviceHost.isFieldDetectEnabled();
2017 }
nxf500513a018e72019-04-23 17:11:41 +05302018}
nxpandroid64fd68c2015-09-23 16:45:15 +05302019
2020 final class ReaderModeDeathRecipient implements IBinder.DeathRecipient {
2021 @Override
2022 public void binderDied() {
2023 synchronized (NfcService.this) {
2024 if (mReaderModeParams != null) {
2025 mReaderModeParams = null;
nxpandroid64fd68c2015-09-23 16:45:15 +05302026 applyRouting(false);
2027 }
2028 }
2029 }
2030 }
2031
2032 final class TagService extends INfcTag.Stub {
2033 @Override
nxpandroid64fd68c2015-09-23 16:45:15 +05302034 public int connect(int nativeHandle, int technology) throws RemoteException {
2035 NfcPermissions.enforceUserPermissions(mContext);
2036
2037 TagEndpoint tag = null;
2038
2039 if (!isNfcEnabled()) {
2040 return ErrorCodes.ERROR_NOT_INITIALIZED;
2041 }
2042
2043 /* find the tag in the hmap */
2044 tag = (TagEndpoint) findObject(nativeHandle);
2045 if (tag == null) {
2046 return ErrorCodes.ERROR_DISCONNECT;
2047 }
2048
2049 if (!tag.isPresent()) {
2050 return ErrorCodes.ERROR_DISCONNECT;
2051 }
2052
2053 // Note that on most tags, all technologies are behind a single
2054 // handle. This means that the connect at the lower levels
2055 // will do nothing, as the tag is already connected to that handle.
2056 if (tag.connect(technology)) {
2057 return ErrorCodes.SUCCESS;
2058 } else {
2059 return ErrorCodes.ERROR_DISCONNECT;
2060 }
2061 }
2062
2063 @Override
2064 public int reconnect(int nativeHandle) throws RemoteException {
2065 NfcPermissions.enforceUserPermissions(mContext);
2066
2067 TagEndpoint tag = null;
2068
2069 // Check if NFC is enabled
2070 if (!isNfcEnabled()) {
2071 return ErrorCodes.ERROR_NOT_INITIALIZED;
2072 }
2073
2074 /* find the tag in the hmap */
2075 tag = (TagEndpoint) findObject(nativeHandle);
2076 if (tag != null) {
2077 if (tag.reconnect()) {
2078 return ErrorCodes.SUCCESS;
2079 } else {
2080 return ErrorCodes.ERROR_DISCONNECT;
2081 }
2082 }
2083 return ErrorCodes.ERROR_DISCONNECT;
2084 }
2085
2086 @Override
2087 public int[] getTechList(int nativeHandle) throws RemoteException {
2088 NfcPermissions.enforceUserPermissions(mContext);
2089
2090 // Check if NFC is enabled
2091 if (!isNfcEnabled()) {
2092 return null;
2093 }
2094
2095 /* find the tag in the hmap */
2096 TagEndpoint tag = (TagEndpoint) findObject(nativeHandle);
2097 if (tag != null) {
2098 return tag.getTechList();
2099 }
2100 return null;
2101 }
2102
2103 @Override
2104 public boolean isPresent(int nativeHandle) throws RemoteException {
2105 TagEndpoint tag = null;
2106
2107 // Check if NFC is enabled
2108 if (!isNfcEnabled()) {
2109 return false;
2110 }
2111
2112 /* find the tag in the hmap */
2113 tag = (TagEndpoint) findObject(nativeHandle);
2114 if (tag == null) {
2115 return false;
2116 }
2117
2118 return tag.isPresent();
2119 }
2120
2121 @Override
2122 public boolean isNdef(int nativeHandle) throws RemoteException {
2123 NfcPermissions.enforceUserPermissions(mContext);
2124
2125 TagEndpoint tag = null;
2126
2127 // Check if NFC is enabled
2128 if (!isNfcEnabled()) {
2129 return false;
2130 }
2131
2132 /* find the tag in the hmap */
2133 tag = (TagEndpoint) findObject(nativeHandle);
2134 int[] ndefInfo = new int[2];
2135 if (tag == null) {
2136 return false;
2137 }
2138 return tag.checkNdef(ndefInfo);
2139 }
2140
2141 @Override
2142 public TransceiveResult transceive(int nativeHandle, byte[] data, boolean raw)
2143 throws RemoteException {
2144 NfcPermissions.enforceUserPermissions(mContext);
2145
2146 TagEndpoint tag = null;
2147 byte[] response;
2148
2149 // Check if NFC is enabled
2150 if (!isNfcEnabled()) {
2151 return null;
2152 }
2153
2154 /* find the tag in the hmap */
2155 tag = (TagEndpoint) findObject(nativeHandle);
2156 if (tag != null) {
2157 // Check if length is within limits
2158 if (data.length > getMaxTransceiveLength(tag.getConnectedTechnology())) {
2159 return new TransceiveResult(TransceiveResult.RESULT_EXCEEDED_LENGTH, null);
2160 }
2161 int[] targetLost = new int[1];
2162 response = tag.transceive(data, raw, targetLost);
2163 int result;
2164 if (response != null) {
2165 result = TransceiveResult.RESULT_SUCCESS;
2166 } else if (targetLost[0] == 1) {
2167 result = TransceiveResult.RESULT_TAGLOST;
2168 } else {
2169 result = TransceiveResult.RESULT_FAILURE;
2170 }
2171 return new TransceiveResult(result, response);
2172 }
2173 return null;
2174 }
2175
2176 @Override
2177 public NdefMessage ndefRead(int nativeHandle) throws RemoteException {
2178 NfcPermissions.enforceUserPermissions(mContext);
2179
2180 TagEndpoint tag;
2181
2182 // Check if NFC is enabled
2183 if (!isNfcEnabled()) {
2184 return null;
2185 }
2186
2187 /* find the tag in the hmap */
2188 tag = (TagEndpoint) findObject(nativeHandle);
2189 if (tag != null) {
2190 byte[] buf = tag.readNdef();
2191 if (buf == null) {
2192 return null;
2193 }
2194
2195 /* Create an NdefMessage */
2196 try {
2197 return new NdefMessage(buf);
2198 } catch (FormatException e) {
2199 return null;
2200 }
2201 }
2202 return null;
2203 }
2204
2205 @Override
2206 public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException {
2207 NfcPermissions.enforceUserPermissions(mContext);
2208
2209 TagEndpoint tag;
2210
2211 // Check if NFC is enabled
2212 if (!isNfcEnabled()) {
2213 return ErrorCodes.ERROR_NOT_INITIALIZED;
2214 }
2215
2216 /* find the tag in the hmap */
2217 tag = (TagEndpoint) findObject(nativeHandle);
2218 if (tag == null) {
2219 return ErrorCodes.ERROR_IO;
2220 }
2221
2222 if (msg == null) return ErrorCodes.ERROR_INVALID_PARAM;
2223
2224 if (tag.writeNdef(msg.toByteArray())) {
2225 return ErrorCodes.SUCCESS;
2226 } else {
2227 return ErrorCodes.ERROR_IO;
2228 }
2229
2230 }
2231
2232 @Override
2233 public boolean ndefIsWritable(int nativeHandle) throws RemoteException {
2234 throw new UnsupportedOperationException();
2235 }
2236
2237 @Override
2238 public int ndefMakeReadOnly(int nativeHandle) throws RemoteException {
2239 NfcPermissions.enforceUserPermissions(mContext);
2240
2241 TagEndpoint tag;
2242
2243 // Check if NFC is enabled
2244 if (!isNfcEnabled()) {
2245 return ErrorCodes.ERROR_NOT_INITIALIZED;
2246 }
2247
2248 /* find the tag in the hmap */
2249 tag = (TagEndpoint) findObject(nativeHandle);
2250 if (tag == null) {
2251 return ErrorCodes.ERROR_IO;
2252 }
2253
2254 if (tag.makeReadOnly()) {
2255 return ErrorCodes.SUCCESS;
2256 } else {
2257 return ErrorCodes.ERROR_IO;
2258 }
2259 }
2260
2261 @Override
2262 public int formatNdef(int nativeHandle, byte[] key) throws RemoteException {
2263 NfcPermissions.enforceUserPermissions(mContext);
2264
2265 TagEndpoint tag;
2266
2267 // Check if NFC is enabled
2268 if (!isNfcEnabled()) {
2269 return ErrorCodes.ERROR_NOT_INITIALIZED;
2270 }
2271
2272 /* find the tag in the hmap */
2273 tag = (TagEndpoint) findObject(nativeHandle);
2274 if (tag == null) {
2275 return ErrorCodes.ERROR_IO;
2276 }
2277
2278 if (tag.formatNdef(key)) {
2279 return ErrorCodes.SUCCESS;
2280 } else {
2281 return ErrorCodes.ERROR_IO;
2282 }
2283 }
2284
2285 @Override
2286 public Tag rediscover(int nativeHandle) throws RemoteException {
2287 NfcPermissions.enforceUserPermissions(mContext);
2288
2289 TagEndpoint tag = null;
2290
2291 // Check if NFC is enabled
2292 if (!isNfcEnabled()) {
2293 return null;
2294 }
2295
2296 /* find the tag in the hmap */
2297 tag = (TagEndpoint) findObject(nativeHandle);
2298 if (tag != null) {
2299 // For now the prime usecase for rediscover() is to be able
2300 // to access the NDEF technology after formatting without
2301 // having to remove the tag from the field, or similar
2302 // to have access to NdefFormatable in case low-level commands
2303 // were used to remove NDEF. So instead of doing a full stack
2304 // rediscover (which is poorly supported at the moment anyway),
2305 // we simply remove these two technologies and detect them
2306 // again.
2307 tag.removeTechnology(TagTechnology.NDEF);
2308 tag.removeTechnology(TagTechnology.NDEF_FORMATABLE);
2309 tag.findAndReadNdef();
2310 // Build a new Tag object to return
2311 Tag newTag = new Tag(tag.getUid(), tag.getTechList(),
2312 tag.getTechExtras(), tag.getHandle(), this);
2313 return newTag;
2314 }
2315 return null;
2316 }
2317
2318 @Override
2319 public int setTimeout(int tech, int timeout) throws RemoteException {
2320 NfcPermissions.enforceUserPermissions(mContext);
2321 boolean success = mDeviceHost.setTimeout(tech, timeout);
2322 if (success) {
2323 return ErrorCodes.SUCCESS;
2324 } else {
2325 return ErrorCodes.ERROR_INVALID_PARAM;
2326 }
2327 }
2328
2329 @Override
2330 public int getTimeout(int tech) throws RemoteException {
2331 NfcPermissions.enforceUserPermissions(mContext);
2332
2333 return mDeviceHost.getTimeout(tech);
2334 }
2335
2336 @Override
2337 public void resetTimeouts() throws RemoteException {
2338 NfcPermissions.enforceUserPermissions(mContext);
2339
2340 mDeviceHost.resetTimeouts();
2341 }
2342
2343 @Override
2344 public boolean canMakeReadOnly(int ndefType) throws RemoteException {
2345 return mDeviceHost.canMakeReadOnly(ndefType);
2346 }
2347
2348 @Override
2349 public int getMaxTransceiveLength(int tech) throws RemoteException {
2350 return mDeviceHost.getMaxTransceiveLength(tech);
2351 }
2352
2353 @Override
2354 public boolean getExtendedLengthApdusSupported() throws RemoteException {
2355 return mDeviceHost.getExtendedLengthApdusSupported();
2356 }
2357 }
2358
Bhupendra Pawar9f0c8382018-01-11 17:05:27 +05302359 final class NfcDtaService extends INfcDta.Stub {
2360 public void enableDta() throws RemoteException {
nxpandroid64fd68c2015-09-23 16:45:15 +05302361 NfcPermissions.enforceAdminPermissions(mContext);
Bhupendra Pawar9f0c8382018-01-11 17:05:27 +05302362 if(!sIsDtaMode) {
nxpandroid64fd68c2015-09-23 16:45:15 +05302363 mDeviceHost.enableDtaMode();
nxpandroid281eb922016-08-25 20:27:46 +05302364 sIsDtaMode = true;
nxpandroid64fd68c2015-09-23 16:45:15 +05302365 Log.d(TAG, "DTA Mode is Enabled ");
Bhupendra Pawar9f0c8382018-01-11 17:05:27 +05302366 }
2367 }
2368
2369 public void disableDta() throws RemoteException {
2370 NfcPermissions.enforceAdminPermissions(mContext);
2371 if(sIsDtaMode) {
nxpandroid64fd68c2015-09-23 16:45:15 +05302372 mDeviceHost.disableDtaMode();
nxpandroid281eb922016-08-25 20:27:46 +05302373 sIsDtaMode = false;
nxpandroid64fd68c2015-09-23 16:45:15 +05302374 }
Bhupendra Pawar9f0c8382018-01-11 17:05:27 +05302375 }
2376
2377 public boolean enableServer(String serviceName, int serviceSap, int miu,
2378 int rwSize,int testCaseId) throws RemoteException {
2379 NfcPermissions.enforceAdminPermissions(mContext);
2380
nxf500513a018e72019-04-23 17:11:41 +05302381 if (serviceName.equals(null) || !mIsBeamCapable)
Bhupendra Pawar9f0c8382018-01-11 17:05:27 +05302382 return false;
2383
2384 mP2pLinkManager.enableExtDtaSnepServer(serviceName, serviceSap, miu, rwSize,testCaseId);
nxpandroid64fd68c2015-09-23 16:45:15 +05302385 return true;
2386 }
2387
Bhupendra Pawar9f0c8382018-01-11 17:05:27 +05302388 public void disableServer() throws RemoteException {
nxf500513a018e72019-04-23 17:11:41 +05302389 if (!mIsBeamCapable)
2390 return;
Bhupendra Pawar9f0c8382018-01-11 17:05:27 +05302391 NfcPermissions.enforceAdminPermissions(mContext);
2392 mP2pLinkManager.disableExtDtaSnepServer();
2393 }
2394
2395 public boolean enableClient(String serviceName, int miu, int rwSize,
2396 int testCaseId) throws RemoteException {
2397 NfcPermissions.enforceAdminPermissions(mContext);
2398
nxf500513a018e72019-04-23 17:11:41 +05302399 if (testCaseId == 0 || !mIsBeamCapable)
Bhupendra Pawar9f0c8382018-01-11 17:05:27 +05302400 return false;
2401
2402 if (testCaseId>20){
2403 sIsShortRecordLayout=true;
2404 testCaseId=testCaseId-20;
2405 } else {
2406 sIsShortRecordLayout=false;
2407 }
2408 Log.d("testCaseId", ""+testCaseId);
2409 mP2pLinkManager.enableDtaSnepClient(serviceName, miu, rwSize, testCaseId);
2410 return true;
2411 }
2412
2413 public void disableClient() throws RemoteException {
nxf500513a018e72019-04-23 17:11:41 +05302414 if (!mIsBeamCapable)
2415 return;
2416 NfcPermissions.enforceAdminPermissions(mContext);
2417 mP2pLinkManager.disableDtaSnepClient();
Bhupendra Pawar9f0c8382018-01-11 17:05:27 +05302418 }
2419
2420 public boolean registerMessageService(String msgServiceName)
2421 throws RemoteException {
2422 NfcPermissions.enforceAdminPermissions(mContext);
2423 if(msgServiceName.equals(null))
2424 return false;
2425
2426 DtaServiceConnector.setMessageService(msgServiceName);
2427 return true;
nxpandroid64fd68c2015-09-23 16:45:15 +05302428 }
2429
2430 };
2431
nxf500513a018e72019-04-23 17:11:41 +05302432 final class NxpNfcAdapterExtrasService extends INxpNfcAdapterExtras.Stub {
2433 private Bundle writeNoException() {
2434 Bundle p = new Bundle();
2435 p.putInt("e", 0);
2436 return p;
2437 }
nxpandroid64fd68c2015-09-23 16:45:15 +05302438
nxf500513a018e72019-04-23 17:11:41 +05302439 private Bundle writeEeException(int exceptionType, String message) {
2440 Bundle p = new Bundle();
2441 p.putInt("e", exceptionType);
2442 p.putString("m", message);
2443 return p;
2444 }
2445 /*
2446 * Enable or disable eSE COS patch dedicated mode
2447 * @param mode 1:dedicated mode 0:normal mode
2448 * @return 0:success 1:SWP is already in use -1:error
2449 */
2450 @Override
Anil Hiranniahc1805912019-05-15 21:49:59 +05302451 public boolean accessControlForCOSU (int mode)
nxf500513a018e72019-04-23 17:11:41 +05302452 {
2453 return mDeviceHost.accessControlForCOSU(mode);
2454 }
nxpandroid64fd68c2015-09-23 16:45:15 +05302455
nxf500513a018e72019-04-23 17:11:41 +05302456 @Override
2457 public boolean reset(String pkg) throws RemoteException {
2458 Bundle result;
2459 boolean stat = false;
2460 try {
2461 stat = _nfcEeReset();
2462 result = writeNoException();
2463 } catch (IOException e) {
2464 result = writeEeException(EE_ERROR_IO, e.getMessage());
nxpandroid64fd68c2015-09-23 16:45:15 +05302465 }
nxf500513a018e72019-04-23 17:11:41 +05302466 Log.d(TAG,"reset" + stat);
2467 return stat;
nxpandroid64fd68c2015-09-23 16:45:15 +05302468 }
2469
2470 boolean _nfcEeReset() throws IOException {
nxf500513a018e72019-04-23 17:11:41 +05302471 synchronized (NfcService.this) {
2472 if (!isNfcEnabledOrShuttingDown()) {
2473 throw new IOException("NFC adapter is disabled");
2474 }
2475 return mSecureElement.doReset(EE_HANDLE_0xF3);
2476 }
2477 }
2478
2479 @Override
2480 public Bundle getAtr(String pkg) throws RemoteException {
2481
2482 Bundle result;
2483 byte[] out;
2484 try {
2485 out = _getAtr();
2486 result = writeNoException();
2487 result.putByteArray("out", out);
2488 } catch (IOException e) {
2489 result = writeEeException(EE_ERROR_IO, e.getMessage());
2490 }
2491 Log.d(TAG,"getAtr result " + result);
2492 return result;
nxpandroid64fd68c2015-09-23 16:45:15 +05302493 }
2494
nxf500513a018e72019-04-23 17:11:41 +05302495 private byte[] _getAtr() throws IOException {
2496 synchronized(NfcService.this) {
2497 if (!isNfcEnabled()) {
2498 throw new IOException("NFC is not enabled");
nxpandroid64fd68c2015-09-23 16:45:15 +05302499 }
2500 }
nxf500513a018e72019-04-23 17:11:41 +05302501 return mSecureElement.doGetAtr(EE_HANDLE_0xF3);
nxpandroid64fd68c2015-09-23 16:45:15 +05302502 }
nxpandroid64fd68c2015-09-23 16:45:15 +05302503
nxf500513a018e72019-04-23 17:11:41 +05302504}
nxpandroid64fd68c2015-09-23 16:45:15 +05302505
2506 boolean isNfcEnabledOrShuttingDown() {
2507 synchronized (this) {
2508 return (mState == NfcAdapter.STATE_ON || mState == NfcAdapter.STATE_TURNING_OFF);
2509 }
2510 }
2511
Suhas Suresh8cd37b32019-06-25 16:50:16 +05302512 public boolean isNfcEnabled() {
nxpandroid64fd68c2015-09-23 16:45:15 +05302513 synchronized (this) {
2514 return mState == NfcAdapter.STATE_ON;
2515 }
2516 }
2517
2518 class WatchDogThread extends Thread {
2519 final Object mCancelWaiter = new Object();
2520 final int mTimeout;
2521 boolean mCanceled = false;
2522
2523 public WatchDogThread(String threadName, int timeout) {
2524 super(threadName);
2525 mTimeout = timeout;
2526 }
2527
2528 @Override
2529 public void run() {
2530 try {
2531 synchronized (mCancelWaiter) {
2532 mCancelWaiter.wait(mTimeout);
2533 if (mCanceled) {
2534 return;
2535 }
2536 }
2537 } catch (InterruptedException e) {
2538 // Should not happen; fall-through to abort.
2539 Log.w(TAG, "Watchdog thread interruped.");
2540 interrupt();
2541 }
2542 Log.e(TAG, "Watchdog triggered, aborting.");
Ganesh Devac90b32d2019-07-12 11:53:10 +05302543 StatsLog.write(StatsLog.NFC_STATE_CHANGED, StatsLog.NFC_STATE_CHANGED__STATE__CRASH_RESTART);
nxpandroid6fd9cdb2017-07-12 18:25:41 +05302544 mDeviceHost.doAbort(getName());
nxpandroid64fd68c2015-09-23 16:45:15 +05302545 }
2546
2547 public synchronized void cancel() {
2548 synchronized (mCancelWaiter) {
2549 mCanceled = true;
2550 mCancelWaiter.notify();
2551 }
2552 }
2553 }
2554
nxpandroid64fd68c2015-09-23 16:45:15 +05302555 static byte[] hexStringToBytes(String s) {
2556 if (s == null || s.length() == 0) return null;
2557 int len = s.length();
2558 if (len % 2 != 0) {
2559 s = '0' + s;
2560 len++;
2561 }
2562 byte[] data = new byte[len / 2];
2563 for (int i = 0; i < len; i += 2) {
2564 data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
2565 + Character.digit(s.charAt(i + 1), 16));
2566 }
2567 return data;
2568 }
2569
nxpandroid64fd68c2015-09-23 16:45:15 +05302570 /**
2571 * Read mScreenState and apply NFC-C polling and NFC-EE routing
2572 */
2573 void applyRouting(boolean force) {
nxf500513a018e72019-04-23 17:11:41 +05302574 Log.d(TAG, "applyRouting enter");
2575 if (!isNfcEnabledOrShuttingDown()) {
2576 return;
2577 }
nxpandroid64fd68c2015-09-23 16:45:15 +05302578 synchronized (this) {
nxpandroid64fd68c2015-09-23 16:45:15 +05302579 WatchDogThread watchDog = new WatchDogThread("applyRouting", ROUTING_WATCHDOG_MS);
2580 if (mInProvisionMode) {
2581 mInProvisionMode = Settings.Secure.getInt(mContentResolver,
2582 Settings.Global.DEVICE_PROVISIONED, 0) == 0;
2583 if (!mInProvisionMode) {
2584 // Notify dispatcher it's fine to dispatch to any package now
2585 // and allow handover transfers.
2586 mNfcDispatcher.disableProvisioningMode();
2587 }
2588 }
2589 // Special case: if we're transitioning to unlocked state while
2590 // still talking to a tag, postpone re-configuration.
2591 if (mScreenState == ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED && isTagPresent()) {
2592 Log.d(TAG, "Not updating discovery parameters, tag connected.");
2593 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_RESUME_POLLING),
2594 APPLY_ROUTING_RETRY_TIMEOUT_MS);
2595 return;
2596 }
2597
2598 try {
2599 watchDog.start();
2600 // Compute new polling parameters
2601 NfcDiscoveryParameters newParams = computeDiscoveryParameters(mScreenState);
2602 if (force || !newParams.equals(mCurrentDiscoveryParameters)) {
2603 if (newParams.shouldEnableDiscovery()) {
2604 boolean shouldRestart = mCurrentDiscoveryParameters.shouldEnableDiscovery();
2605 mDeviceHost.enableDiscovery(newParams, shouldRestart);
2606 } else {
2607 mDeviceHost.disableDiscovery();
2608 }
2609 mCurrentDiscoveryParameters = newParams;
2610 } else {
2611 Log.d(TAG, "Discovery configuration equal, not updating.");
2612 }
2613 } finally {
2614 watchDog.cancel();
2615 }
2616 }
2617 }
2618
2619 private NfcDiscoveryParameters computeDiscoveryParameters(int screenState) {
2620 // Recompute discovery parameters based on screen state
2621 NfcDiscoveryParameters.Builder paramsBuilder = NfcDiscoveryParameters.newBuilder();
2622 // Polling
nxf500513a018e72019-04-23 17:11:41 +05302623 if (screenState >= NFC_POLLING_MODE) {
nxpandroid64fd68c2015-09-23 16:45:15 +05302624 // Check if reader-mode is enabled
2625 if (mReaderModeParams != null) {
2626 int techMask = 0;
2627 if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_A) != 0)
2628 techMask |= NFC_POLL_A;
2629 if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_B) != 0)
2630 techMask |= NFC_POLL_B;
2631 if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_F) != 0)
2632 techMask |= NFC_POLL_F;
2633 if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_V) != 0)
Nikhil Chhabra288edb02018-01-10 19:36:21 +05302634 techMask |= NFC_POLL_V;
nxpandroid64fd68c2015-09-23 16:45:15 +05302635 if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_BARCODE) != 0)
2636 techMask |= NFC_POLL_KOVIO;
2637
2638 paramsBuilder.setTechMask(techMask);
2639 paramsBuilder.setEnableReaderMode(true);
2640 } else {
2641 paramsBuilder.setTechMask(NfcDiscoveryParameters.NFC_POLL_DEFAULT);
nxf500513a018e72019-04-23 17:11:41 +05302642 paramsBuilder.setEnableP2p(mIsBeamCapable);
nxpandroid64fd68c2015-09-23 16:45:15 +05302643 }
nxf500513a018e72019-04-23 17:11:41 +05302644 } else if (screenState == ScreenStateHelper.SCREEN_STATE_ON_LOCKED && mInProvisionMode) {
nxpandroid64fd68c2015-09-23 16:45:15 +05302645 paramsBuilder.setTechMask(NfcDiscoveryParameters.NFC_POLL_DEFAULT);
2646 // enable P2P for MFM/EDU/Corp provisioning
nxf500513a018e72019-04-23 17:11:41 +05302647 paramsBuilder.setEnableP2p(mIsBeamCapable);
2648 } else if (screenState == ScreenStateHelper.SCREEN_STATE_ON_LOCKED &&
2649 mNfcUnlockManager.isLockscreenPollingEnabled()) {
nxpandroid6fd9cdb2017-07-12 18:25:41 +05302650 int techMask = 0;
nxpandroid6fd9cdb2017-07-12 18:25:41 +05302651 if (mNfcUnlockManager.isLockscreenPollingEnabled())
2652 techMask |= mNfcUnlockManager.getLockscreenPollMask();
2653 paramsBuilder.setTechMask(techMask);
nxpandroid64fd68c2015-09-23 16:45:15 +05302654 paramsBuilder.setEnableLowPowerDiscovery(false);
2655 paramsBuilder.setEnableP2p(false);
2656 }
2657
nxf500513a018e72019-04-23 17:11:41 +05302658 if (mIsHceCapable && mScreenState >= ScreenStateHelper.SCREEN_STATE_ON_LOCKED && mReaderModeParams == null) {
Nikhil Chhabrae1d07ba2018-01-10 11:33:17 +05302659 // Host routing is always enabled at lock screen or later, provided we aren't in reader mode
nxf500513a018e72019-04-23 17:11:41 +05302660 paramsBuilder.setEnableHostRouting(true);
nxpandroid64fd68c2015-09-23 16:45:15 +05302661 }
nxpandroid64fd68c2015-09-23 16:45:15 +05302662
nxpandroid64fd68c2015-09-23 16:45:15 +05302663 return paramsBuilder.build();
2664 }
2665
nxf500513a018e72019-04-23 17:11:41 +05302666 private void computeAndSetRoutingParameters()
2667 {
2668 int protoRoute = mNxpPrefs.getInt("PREF_MIFARE_DESFIRE_PROTO_ROUTE_ID", GetDefaultMifareDesfireRouteEntry());
2669 int defaultRoute=mNxpPrefs.getInt("PREF_SET_DEFAULT_ROUTE_ID", GetDefaultRouteEntry());
2670 int techRoute=mNxpPrefs.getInt("PREF_MIFARE_CLT_ROUTE_ID", GetDefaultMifateCLTRouteEntry());
2671 int techfRoute=mNxpPrefs.getInt("PREF_FELICA_CLT_ROUTE_ID", GetDefaultFelicaCLTRouteEntry());
2672 int TechSeId,TechFSeId;
2673 int TechRoute = 0x00;
2674 if (DBG) Log.d(TAG, "Set Routing Entry");
2675 /* Routing for Protocol */
Suhas Suresh14c42612019-05-10 17:18:24 +05302676 if (getNciVersion() == NCI_VERSION_1_0) {
2677 mDeviceHost.setRoutingEntry(
2678 PROTOCOL_ENTRY, NFC_LISTEN_PROTO_ISO7816, ((defaultRoute >> ROUTE_LOC_MASK) & 0x07), defaultRoute & 0x3F);
2679 mDeviceHost.setRoutingEntry(PROTOCOL_ENTRY, NFC_LISTEN_PROTO_T3T, 0x00, 0x01);
2680 }
nxf500513a018e72019-04-23 17:11:41 +05302681 mDeviceHost.setRoutingEntry(PROTOCOL_ENTRY, NFC_LISTEN_PROTO_ISO_DEP, ((protoRoute >> ROUTE_LOC_MASK) & 0x07), protoRoute & 0x3F);
2682 mDeviceHost.setRoutingEntry(PROTOCOL_ENTRY, NFC_LISTEN_PROTO_NFC_DEP, 0x00, 0x01);
2683
2684 /* Routing for Technology */
2685 TechSeId = (techRoute >> ROUTE_LOC_MASK);
2686 TechFSeId = (techfRoute >> ROUTE_LOC_MASK);
2687 /* Technology types are masked internally depending on the capability of SE */
Ganesh Devaa8c49ac2019-05-23 11:04:12 +05302688 if(techRoute == techfRoute)
nxf500513a018e72019-04-23 17:11:41 +05302689 {
2690 TechRoute = 0x07;
2691 mDeviceHost.setRoutingEntry(TECH_ENTRY,TechRoute, TechSeId, techRoute & 0x3F);
2692 }
2693 else {
2694 TechRoute = 0x03;
2695 mDeviceHost.setRoutingEntry(TECH_ENTRY,TechRoute, TechSeId, techRoute & 0x3F);
2696 TechRoute = 0x04;
2697 Log.d(TAG, "Set Routing Entry" + TechRoute + "" + TechFSeId + "" + techfRoute);
2698 mDeviceHost.setRoutingEntry(TECH_ENTRY,TechRoute, TechFSeId, techfRoute & 0x3F);
2699 }
2700 }
2701 public void computeRoutingParameters() {
2702 Log.d(TAG, "computeRoutingParameters >>>");
2703 mHandler.sendEmptyMessage(MSG_COMPUTE_ROUTING_PARAMS);
2704 }
nxpandroid64fd68c2015-09-23 16:45:15 +05302705 private boolean isTagPresent() {
2706 for (Object object : mObjectMap.values()) {
2707 if (object instanceof TagEndpoint) {
2708 return ((TagEndpoint) object).isPresent();
2709 }
2710 }
2711 return false;
2712 }
Suhas Suresh5efc5432018-04-27 15:31:02 +05302713
2714 private void StopPresenceChecking() {
2715 Object[] objectValues = mObjectMap.values().toArray();
2716 for (Object object : objectValues) {
2717 if (object instanceof TagEndpoint) {
2718 TagEndpoint tag = (TagEndpoint)object;
2719 ((TagEndpoint) object).stopPresenceChecking();
2720 }
2721 }
2722 }
2723
nxpandroid64fd68c2015-09-23 16:45:15 +05302724 /**
2725 * Disconnect any target if present
2726 */
2727 void maybeDisconnectTarget() {
2728 if (!isNfcEnabledOrShuttingDown()) {
2729 return;
2730 }
2731 Object[] objectsToDisconnect;
2732 synchronized (this) {
2733 Object[] objectValues = mObjectMap.values().toArray();
2734 // Copy the array before we clear mObjectMap,
2735 // just in case the HashMap values are backed by the same array
2736 objectsToDisconnect = Arrays.copyOf(objectValues, objectValues.length);
2737 mObjectMap.clear();
2738 }
2739 for (Object o : objectsToDisconnect) {
2740 if (DBG) Log.d(TAG, "disconnecting " + o.getClass().getName());
2741 if (o instanceof TagEndpoint) {
2742 // Disconnect from tags
2743 TagEndpoint tag = (TagEndpoint) o;
2744 tag.disconnect();
2745 } else if (o instanceof NfcDepEndpoint) {
2746 // Disconnect from P2P devices
2747 NfcDepEndpoint device = (NfcDepEndpoint) o;
2748 if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) {
2749 // Remote peer is target, request disconnection
2750 device.disconnect();
2751 } else {
2752 // Remote peer is initiator, we cannot disconnect
2753 // Just wait for field removal
2754 }
2755 }
2756 }
2757 }
2758
2759 Object findObject(int key) {
2760 synchronized (this) {
2761 Object device = mObjectMap.get(key);
2762 if (device == null) {
2763 Log.w(TAG, "Handle not found");
2764 }
2765 return device;
2766 }
2767 }
2768
nxpandroid281eb922016-08-25 20:27:46 +05302769 Object findAndRemoveObject(int handle) {
2770 synchronized (this) {
2771 Object device = mObjectMap.get(handle);
2772 if (device == null) {
2773 Log.w(TAG, "Handle not found");
2774 } else {
2775 mObjectMap.remove(handle);
2776 }
2777 return device;
2778 }
2779 }
2780
nxpandroid64fd68c2015-09-23 16:45:15 +05302781 void registerTagObject(TagEndpoint tag) {
2782 synchronized (this) {
2783 mObjectMap.put(tag.getHandle(), tag);
2784 }
2785 }
2786
2787 void unregisterObject(int handle) {
2788 synchronized (this) {
2789 mObjectMap.remove(handle);
2790 }
2791 }
2792
2793 /**
2794 * For use by code in this process
2795 */
2796 public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)
2797 throws LlcpException {
2798 return mDeviceHost.createLlcpSocket(sap, miu, rw, linearBufferLength);
2799 }
2800
2801 /**
2802 * For use by code in this process
2803 */
2804 public LlcpConnectionlessSocket createLlcpConnectionLessSocket(int sap, String sn)
2805 throws LlcpException {
2806 return mDeviceHost.createLlcpConnectionlessSocket(sap, sn);
2807 }
2808
2809 /**
2810 * For use by code in this process
2811 */
2812 public LlcpServerSocket createLlcpServerSocket(int sap, String sn, int miu, int rw,
2813 int linearBufferLength) throws LlcpException {
2814 return mDeviceHost.createLlcpServerSocket(sap, sn, miu, rw, linearBufferLength);
2815 }
2816
2817 public void sendMockNdefTag(NdefMessage msg) {
2818 sendMessage(MSG_MOCK_NDEF, msg);
2819 }
2820
2821 public void notifyRoutingTableFull()
2822 {
nxf2676386ae0fb2018-11-19 17:33:54 +05302823 mToastHandler.showToast("Last installed NFC Service is not enabled due to limited resources. To enable this service, " +
nxf500513a018e72019-04-23 17:11:41 +05302824 "please disable other servives in Settings Menu", 20);
2825 Log.d(TAG, "notify aid routing table full to the user here");
nxf2676386ae0fb2018-11-19 17:33:54 +05302826
nxf500513a018e72019-04-23 17:11:41 +05302827 mNxpPrefsEditor = mNxpPrefs.edit();
2828 mNxpPrefsEditor.putInt("PREF_SET_AID_ROUTING_TABLE_FULL",0x01);
2829 mNxpPrefsEditor.commit();
2830 //broadcast Aid Routing Table Full intent to the user
2831 Intent aidTableFull = new Intent();
2832 aidTableFull.setAction(NfcConstants.ACTION_ROUTING_TABLE_FULL);
2833 if (DBG) {
2834 Log.d(TAG, "notify aid routing table full to the user");
nxpandroid64fd68c2015-09-23 16:45:15 +05302835 }
nxf500513a018e72019-04-23 17:11:41 +05302836 mContext.sendBroadcastAsUser(aidTableFull, UserHandle.CURRENT);
nxpandroid64fd68c2015-09-23 16:45:15 +05302837 }
nxf500513a018e72019-04-23 17:11:41 +05302838
2839 public void routeAids(String aid, int route, int aidInfo, int power) {
2840 Message msg = mHandler.obtainMessage();
2841 msg.what = MSG_ROUTE_AID;
2842 msg.arg1 = route;
2843 msg.obj = aid;
2844 msg.arg2 = aidInfo;
2845 Bundle aidbundle = new Bundle();
2846 aidbundle.putInt("power",power);
2847 msg.setData(aidbundle);
2848 mHandler.sendMessage(msg);
2849 }
2850
2851 public int getAidRoutingTableSize ()
2852 {
2853 //return 18;
2854 return mDeviceHost.getAidTableSize();
2855 }
2856
nxpandroid64fd68c2015-09-23 16:45:15 +05302857 /**
2858 * set default Aid route entry in case application does not configure this route entry
2859 */
nxpandroidebf53fb2016-12-22 18:48:59 +05302860 public void setDefaultAidRouteLoc( int routeLoc)
nxpandroid64fd68c2015-09-23 16:45:15 +05302861 {
nxpandroida9a68ba2016-01-14 21:12:17 +05302862 mNxpPrefsEditor = mNxpPrefs.edit();
nxpandroidebf53fb2016-12-22 18:48:59 +05302863 Log.d(TAG, "writing to preferences setDefaultAidRouteLoc :" + routeLoc);
2864
nxf38293d7215c82019-03-18 09:42:50 +05302865 int defaultAidRoute = ((mDeviceHost.getDefaultAidPowerState() & 0x3F) | (routeLoc << ROUTE_LOC_MASK));
nxpandroidebf53fb2016-12-22 18:48:59 +05302866
2867 mNxpPrefsEditor.putInt("PREF_SET_DEFAULT_ROUTE_ID", defaultAidRoute);
nxpandroida9a68ba2016-01-14 21:12:17 +05302868 mNxpPrefsEditor.commit();
2869 int defaultRoute=mNxpPrefs.getInt("PREF_SET_DEFAULT_ROUTE_ID",0xFF);
nxpandroid64fd68c2015-09-23 16:45:15 +05302870 Log.d(TAG, "reading preferences from user :" + defaultRoute);
2871 }
2872
nxpandroid64fd68c2015-09-23 16:45:15 +05302873 public void unrouteAids(String aid) {
2874 sendMessage(MSG_UNROUTE_AID, aid);
2875 }
nxpandroida5fd6622017-07-31 16:15:18 +05302876
nxpandroide66eb092017-07-12 21:36:08 +05302877 public int getNciVersion() {
2878 return mDeviceHost.getNciVersion();
2879 }
nxf500513a018e72019-04-23 17:11:41 +05302880
nxpandroid6fd9cdb2017-07-12 18:25:41 +05302881 private byte[] getT3tIdentifierBytes(String systemCode, String nfcId2, String t3tPmm) {
nxf500513a018e72019-04-23 17:11:41 +05302882 ByteBuffer buffer = ByteBuffer.allocate(2 + 8 + 8); /* systemcode + nfcid2 + t3tpmm */
nxpandroid34627bd2016-05-27 15:52:30 +05302883 buffer.put(hexStringToBytes(systemCode));
2884 buffer.put(hexStringToBytes(nfcId2));
nxpandroid6fd9cdb2017-07-12 18:25:41 +05302885 buffer.put(hexStringToBytes(t3tPmm));
nxpandroid34627bd2016-05-27 15:52:30 +05302886 byte[] t3tIdBytes = new byte[buffer.position()];
2887 buffer.position(0);
2888 buffer.get(t3tIdBytes);
nxpandroid6fd9cdb2017-07-12 18:25:41 +05302889
nxpandroid34627bd2016-05-27 15:52:30 +05302890 return t3tIdBytes;
2891 }
2892
nxpandroid6fd9cdb2017-07-12 18:25:41 +05302893 public void registerT3tIdentifier(String systemCode, String nfcId2, String t3tPmm) {
2894 Log.d(TAG, "request to register LF_T3T_IDENTIFIER");
2895
2896 byte[] t3tIdentifier = getT3tIdentifierBytes(systemCode, nfcId2, t3tPmm);
nxpandroid34627bd2016-05-27 15:52:30 +05302897 sendMessage(MSG_REGISTER_T3T_IDENTIFIER, t3tIdentifier);
2898 }
2899
nxpandroid6fd9cdb2017-07-12 18:25:41 +05302900 public void deregisterT3tIdentifier(String systemCode, String nfcId2, String t3tPmm) {
2901 Log.d(TAG, "request to deregister LF_T3T_IDENTIFIER");
2902
2903 byte[] t3tIdentifier = getT3tIdentifierBytes(systemCode, nfcId2, t3tPmm);
nxpandroid34627bd2016-05-27 15:52:30 +05302904 sendMessage(MSG_DEREGISTER_T3T_IDENTIFIER, t3tIdentifier);
2905 }
2906
2907 public void clearT3tIdentifiersCache() {
nxpandroid6fd9cdb2017-07-12 18:25:41 +05302908 Log.d(TAG, "clear T3t Identifiers Cache");
nxpandroid34627bd2016-05-27 15:52:30 +05302909 mDeviceHost.clearT3tIdentifiersCache();
2910 }
2911
2912 public int getLfT3tMax() {
2913 return mDeviceHost.getLfT3tMax();
2914 }
nxpandroid64fd68c2015-09-23 16:45:15 +05302915
2916 public void commitRouting() {
nxf500513a018e72019-04-23 17:11:41 +05302917 Log.d(TAG, "commitRouting >>>");
2918 mHandler.sendEmptyMessage(MSG_COMMIT_ROUTING);
2919 }
2920 public void initWiredSe() {
2921 Log.d(TAG, "Init wired Se");
2922 mHandler.sendEmptyMessage(MSG_INIT_WIREDSE);
nxpandroid64fd68c2015-09-23 16:45:15 +05302923 }
Ganesh Deva1ad7d6f2019-06-17 11:46:02 +05302924 public void deInitWiredSe() {
2925 Log.d(TAG, "DeInit wired Se");
2926 mHandler.sendEmptyMessage(MSG_DEINIT_WIREDSE);
2927 }
nxpandroid64fd68c2015-09-23 16:45:15 +05302928 /**
2929 * get default Aid route entry in case application does not configure this route entry
2930 */
2931 public int GetDefaultRouteLoc()
2932 {
nxpandroida9a68ba2016-01-14 21:12:17 +05302933 int defaultRouteLoc = mNxpPrefs.getInt("PREF_SET_DEFAULT_ROUTE_ID", GetDefaultRouteEntry()) >> ROUTE_LOC_MASK;
nxpandroid64fd68c2015-09-23 16:45:15 +05302934 Log.d(TAG, "GetDefaultRouteLoc :" + defaultRouteLoc);
2935 return defaultRouteLoc ;
2936 }
nxpandroid64fd68c2015-09-23 16:45:15 +05302937 /**
2938 * get default MifareDesfireRoute route entry in case application does not configure this route entry
2939 */
2940 public int GetDefaultMifareDesfireRouteEntry()
2941 {
nxpandroid7d44e572016-08-01 19:11:04 +05302942 int routeLoc = mDeviceHost.getDefaultDesfireRoute();
nxpandroid6fd9cdb2017-07-12 18:25:41 +05302943 int defaultMifareDesfireRoute = ((mDeviceHost.getDefaultDesfirePowerState() & 0x3F) | (routeLoc << ROUTE_LOC_MASK));
nxpandroid7d44e572016-08-01 19:11:04 +05302944 if(routeLoc == 0x00)
2945 {
nxpandroid8aecbf82016-09-16 20:21:47 +05302946 /*
2947 bit pos 1 = Power Off
2948 bit pos 2 = Battery Off
nxf500513a018e72019-04-23 17:11:41 +05302949 bit pos 4 = Screen Off
nxpandroid8aecbf82016-09-16 20:21:47 +05302950 Set these bits to 0 because in case routeLoc = HOST it can not work on POWER_OFF, BATTERY_OFF and SCREEN_OFF*/
nxf500513a018e72019-04-23 17:11:41 +05302951 defaultMifareDesfireRoute &= 0xF9;
nxpandroid7d44e572016-08-01 19:11:04 +05302952 }
nxpandroid281eb922016-08-25 20:27:46 +05302953 if (DBG) Log.d(TAG, "defaultMifareDesfireRoute : " + defaultMifareDesfireRoute);
nxpandroid7d44e572016-08-01 19:11:04 +05302954 return defaultMifareDesfireRoute;
nxpandroid64fd68c2015-09-23 16:45:15 +05302955 }
2956 /**
2957 * set default Aid route entry in case application does not configure this route entry
2958 */
2959
2960 public int GetDefaultRouteEntry()
2961 {
nxpandroid7d44e572016-08-01 19:11:04 +05302962 int routeLoc = mDeviceHost.getDefaultAidRoute();
nxpandroid6fd9cdb2017-07-12 18:25:41 +05302963 int defaultAidRoute = ((mDeviceHost.getDefaultAidPowerState() & 0x3F) | (routeLoc << ROUTE_LOC_MASK));
nxpandroid7d44e572016-08-01 19:11:04 +05302964 if(routeLoc == 0x00)
2965 {
nxpandroid8aecbf82016-09-16 20:21:47 +05302966 /*
2967 bit pos 1 = Power Off
2968 bit pos 2 = Battery Off
nxf500513a018e72019-04-23 17:11:41 +05302969 bit pos 4 = Screen Off
nxpandroid8aecbf82016-09-16 20:21:47 +05302970 Set these bits to 0 because in case routeLoc = HOST it can not work on POWER_OFF, BATTERY_OFF and SCREEN_OFF*/
nxf500513a018e72019-04-23 17:11:41 +05302971 defaultAidRoute &= 0xF9;
nxpandroid7d44e572016-08-01 19:11:04 +05302972 }
nxpandroid281eb922016-08-25 20:27:46 +05302973 if (DBG) Log.d(TAG, "defaultAidRoute : " + defaultAidRoute);
nxpandroid64fd68c2015-09-23 16:45:15 +05302974 return defaultAidRoute;
2975 }
2976
2977 /**
2978 * get default MifateCLT route entry in case application does not configure this route entry
2979 */
2980 public int GetDefaultMifateCLTRouteEntry()
2981 {
nxpandroid7d44e572016-08-01 19:11:04 +05302982 int routeLoc = mDeviceHost.getDefaultMifareCLTRoute();
nxf500513a018e72019-04-23 17:11:41 +05302983 int defaultMifateCLTRoute = ((mDeviceHost.getDefaultMifareCLTPowerState() & 0x3F) | (mDeviceHost.getDefaultMifareCLTRoute() << ROUTE_LOC_MASK)) ;
nxpandroid281eb922016-08-25 20:27:46 +05302984 if (DBG) Log.d(TAG, "defaultMifateCLTRoute : " + defaultMifateCLTRoute);
nxpandroid7d44e572016-08-01 19:11:04 +05302985 return defaultMifateCLTRoute;
nxpandroid64fd68c2015-09-23 16:45:15 +05302986 }
nxf500513a018e72019-04-23 17:11:41 +05302987 /**
2988 * get default FelicaCLT route entry in case application does not configure this route entry
2989 */
2990 public int GetDefaultFelicaCLTRouteEntry()
2991 {
2992 int routeLoc = mDeviceHost.getDefaultFelicaCLTRoute();
2993 int defaultFelicaCLTRoute = ((mDeviceHost.getDefaultFelicaCLTPowerState() & 0x3F) | (mDeviceHost.getDefaultFelicaCLTRoute() << ROUTE_LOC_MASK)) ;
2994 if (DBG) Log.d(TAG, "defaultFelicaCLTRoute : " + defaultFelicaCLTRoute);
2995 return defaultFelicaCLTRoute;
nxpandroid64fd68c2015-09-23 16:45:15 +05302996 }
2997
nxf500513a018e72019-04-23 17:11:41 +05302998 public int getGsmaPwrState()
2999 {
3000 return mDeviceHost.getGsmaPwrState();
nxpandroid64fd68c2015-09-23 16:45:15 +05303001 }
3002
nxpandroida9a68ba2016-01-14 21:12:17 +05303003 public int getAidRoutingTableStatus() {
3004 int aidTableStatus = 0x00;
3005 aidTableStatus = mNxpPrefs.getInt("PREF_SET_AID_ROUTING_TABLE_FULL",0x00);
3006 return aidTableStatus;
3007 }
nxpandroid64fd68c2015-09-23 16:45:15 +05303008 public boolean sendData(byte[] data) {
3009 return mDeviceHost.sendRawFrame(data);
3010 }
3011
nxf500513a018e72019-04-23 17:11:41 +05303012 void sendMessage(int what, Object obj) {
3013 Message msg = mHandler.obtainMessage();
3014 msg.what = what;
3015 msg.obj = obj;
3016 mHandler.sendMessage(msg);
nxpandroid64fd68c2015-09-23 16:45:15 +05303017 }
3018
Pratap Reddy7e57f0d2018-03-15 16:54:33 +05303019 public void updateLastScreenState()
3020 {
3021 Log.d(TAG, "updateLastScreenState");
3022 int screen_state_mask = (mNfcUnlockManager.isLockscreenPollingEnabled()) ?
3023 (ScreenStateHelper.SCREEN_POLLING_TAG_MASK | mScreenState) : mScreenState;
nxf500513a018e72019-04-23 17:11:41 +05303024 mDeviceHost.doSetScreenState(screen_state_mask);
Pratap Reddy7e57f0d2018-03-15 16:54:33 +05303025 }
3026
nxpandroid64fd68c2015-09-23 16:45:15 +05303027 public void etsiStartConfig(int eeHandle) {
3028 Log.d(TAG, "etsiStartConfig Enter");
3029
3030 Log.d(TAG, "etsiStartConfig : etsiInitConfig");
3031 mDeviceHost.etsiInitConfig();
3032
3033 Log.d(TAG, "etsiStartConfig : disableDiscovery");
3034 mDeviceHost.disableDiscovery();
3035
3036 Log.d(TAG, "etsiStartConfig : etsiReaderConfig");
3037 mDeviceHost.etsiReaderConfig(eeHandle);
3038
3039 Log.d(TAG, "etsiStartConfig : notifyEEReaderEvent");
Pratap Reddy49abbe32018-03-27 16:51:59 +05303040 mDeviceHost.notifyEEReaderEvent(ETSI_READER_START_SUCCESS);
nxpandroid64fd68c2015-09-23 16:45:15 +05303041
3042 Log.d(TAG, "etsiStartConfig : setEtsiReaederState");
3043 mDeviceHost.setEtsiReaederState(STATE_SE_RDR_MODE_STARTED);
3044 //broadcast SWP_READER_ACTIVATED evt
nxpandroid5d64ce92016-11-18 19:48:53 +05303045 Intent swpReaderRequestedIntent = new Intent();
nxf500513a018e72019-04-23 17:11:41 +05303046 swpReaderRequestedIntent.setAction(NfcConstants.ACTION_NFC_MPOS_READER_MODE_START_SUCCESS);
nxpandroid64fd68c2015-09-23 16:45:15 +05303047 if (DBG) {
3048 Log.d(TAG, "SWP READER - Requested");
3049 }
nxpandroid5d64ce92016-11-18 19:48:53 +05303050 mContext.sendBroadcast(swpReaderRequestedIntent);
nxpandroid64fd68c2015-09-23 16:45:15 +05303051
3052 Log.d(TAG, "etsiStartConfig : enableDiscovery");
3053 mDeviceHost.enableDiscovery(mCurrentDiscoveryParameters, true);
3054
3055 Log.d(TAG, "etsiStartConfig Exit");
3056 }
3057
3058 public void etsiStopConfig(int discNtfTimeout) {
3059 Log.d(TAG, "etsiStopConfig Enter");
3060 if( mDeviceHost.getEtsiReaederState() == STATE_SE_RDR_MODE_STOP_IN_PROGRESS)
3061 {
3062 Log.d(TAG, "Attempting etsiStopConfig while STATE_SE_RDR_MODE_STOP_IN_PROGRESS. Returning..");
3063 return;
3064 }
3065 ETSI_STOP_CONFIG = true;
nxpandroid64fd68c2015-09-23 16:45:15 +05303066 Log.d(TAG, "etsiStopConfig : etsiInitConfig");
3067 mDeviceHost.etsiInitConfig();
3068
Pratap Reddy49abbe32018-03-27 16:51:59 +05303069 Timer mTimer = new Timer();
3070 TagRemoveTaskTimer tagRemoveTask = new TagRemoveTaskTimer();
3071 mTimer.schedule(tagRemoveTask, ETSI_PRESENCE_CHECK_DELAY, ETSI_PRESENCE_CHECK_DELAY);
3072
nxpandroid64fd68c2015-09-23 16:45:15 +05303073 Log.d(TAG, "etsiStopConfig : disableDiscovery");
nxf500513a018e72019-04-23 17:11:41 +05303074 mDeviceHost.stopPoll(NfcConstants.ULTRA_LOW_POWER);
Pratap Reddy49abbe32018-03-27 16:51:59 +05303075 mTimer.cancel();
nxpandroid64fd68c2015-09-23 16:45:15 +05303076
3077 if(mDeviceHost.getEtsiReaederState() == STATE_SE_RDR_MODE_STOPPED)
3078 {
3079 Log.d(TAG, "etsiStopConfig :etsi reader already Stopped. Returning..");
3080 ETSI_STOP_CONFIG = false;
3081 return;
3082 }
3083 Log.d(TAG, "etsiStopConfig : etsiResetReaderConfig");
3084 mDeviceHost.etsiResetReaderConfig();
3085
Suhas Sureshe8aa9cf2018-08-01 15:16:59 +05303086 Log.d(TAG, "etsiStopConfig : notifyEEReaderEvent");
3087 mDeviceHost.notifyEEReaderEvent(ETSI_READER_STOP);
3088
nxpandroid5d64ce92016-11-18 19:48:53 +05303089 Intent swpReaderDeActivatedIntent = new Intent();
nxpandroid64fd68c2015-09-23 16:45:15 +05303090
3091 //broadcast SWP_READER_DEACTIVATED evt
nxpandroid5d64ce92016-11-18 19:48:53 +05303092 swpReaderDeActivatedIntent
nxf500513a018e72019-04-23 17:11:41 +05303093 .setAction(NfcConstants.ACTION_NFC_MPOS_READER_MODE_STOP_SUCCESS);
nxpandroid64fd68c2015-09-23 16:45:15 +05303094 if (DBG) {
3095 Log.d(TAG, "SWP READER - DeActivated");
3096 }
nxpandroid5d64ce92016-11-18 19:48:53 +05303097 mContext.sendBroadcast(swpReaderDeActivatedIntent);
nxpandroid64fd68c2015-09-23 16:45:15 +05303098
3099 Log.d(TAG, "etsiStopConfig : setEtsiReaederState");
3100 mDeviceHost.setEtsiReaederState(STATE_SE_RDR_MODE_STOPPED);
3101
nxpandroid64fd68c2015-09-23 16:45:15 +05303102 ETSI_STOP_CONFIG = false;
Pratap Reddy7e57f0d2018-03-15 16:54:33 +05303103 updateLastScreenState();
nxpandroid64fd68c2015-09-23 16:45:15 +05303104
3105 Log.d(TAG, "etsiStopConfig Exit");
3106 }
nxpandroid64fd68c2015-09-23 16:45:15 +05303107 final class NfcServiceHandler extends Handler {
3108 @Override
3109 public void handleMessage(Message msg) {
3110 switch (msg.what) {
3111 case MSG_ROUTE_AID: {
nxf500513a018e72019-04-23 17:11:41 +05303112 int route = msg.arg1;
3113 int aidInfo = msg.arg2;
3114 int power = 0x00;
nxpandroidcbf24822017-07-12 21:37:17 +05303115 Bundle dataBundle = msg.getData();
3116 if (dataBundle != null)
nxf500513a018e72019-04-23 17:11:41 +05303117 power = dataBundle.getInt("power");
3118 String aid = (String) msg.obj;
3119 mDeviceHost.routeAid(hexStringToBytes(aid), route, aidInfo,power);
nxpandroid64fd68c2015-09-23 16:45:15 +05303120 // Restart polling config
3121 break;
3122 }
nxf500513a018e72019-04-23 17:11:41 +05303123 case MSG_UNROUTE_AID: {
3124 String aid = (String) msg.obj;
3125 mDeviceHost.unrouteAid(hexStringToBytes(aid));
3126 break;
3127 }
nxpandroid34627bd2016-05-27 15:52:30 +05303128 case MSG_REGISTER_T3T_IDENTIFIER: {
3129 Log.d(TAG, "message to register LF_T3T_IDENTIFIER");
3130 mDeviceHost.disableDiscovery();
3131
3132 byte[] t3tIdentifier = (byte[]) msg.obj;
3133 mDeviceHost.registerT3tIdentifier(t3tIdentifier);
3134
3135 NfcDiscoveryParameters params = computeDiscoveryParameters(mScreenState);
3136 boolean shouldRestart = mCurrentDiscoveryParameters.shouldEnableDiscovery();
3137 mDeviceHost.enableDiscovery(params, shouldRestart);
3138 break;
3139 }
3140 case MSG_DEREGISTER_T3T_IDENTIFIER: {
3141 Log.d(TAG, "message to deregister LF_T3T_IDENTIFIER");
3142 mDeviceHost.disableDiscovery();
3143
3144 byte[] t3tIdentifier = (byte[]) msg.obj;
3145 mDeviceHost.deregisterT3tIdentifier(t3tIdentifier);
3146
3147 NfcDiscoveryParameters params = computeDiscoveryParameters(mScreenState);
3148 boolean shouldRestart = mCurrentDiscoveryParameters.shouldEnableDiscovery();
3149 mDeviceHost.enableDiscovery(params, shouldRestart);
3150 break;
3151 }
nxpandroid64fd68c2015-09-23 16:45:15 +05303152 case MSG_INVOKE_BEAM: {
3153 mP2pLinkManager.onManualBeamInvoke((BeamShareData)msg.obj);
3154 break;
3155 }
nxpandroid64fd68c2015-09-23 16:45:15 +05303156 case MSG_COMMIT_ROUTING: {
nxf500513a018e72019-04-23 17:11:41 +05303157 Log.d(TAG, "commitRouting >>>");
Ganesh Deva1ad7d6f2019-06-17 11:46:02 +05303158 int defaultRoute=mNxpPrefs.getInt("PREF_SET_DEFAULT_ROUTE_ID", GetDefaultRouteEntry());
Ganesh Deva6d1c3d12019-05-30 15:12:46 +05303159 mDeviceHost.setEmptyAidRoute(defaultRoute >> ROUTE_LOC_MASK);
3160 mDeviceHost.commitRouting();
nxpandroid64fd68c2015-09-23 16:45:15 +05303161 break;
3162 }
Suhas Sureshbe2ba092019-05-15 17:26:23 +05303163 case MSG_RESET_AND_UPDATE_ROUTING_PARAMS: {
3164 mDeviceHost.clearRoutingEntry(TECH_ENTRY);
3165 mDeviceHost.clearRoutingEntry(PROTOCOL_ENTRY);
3166 }
3167 /*fallThrough to compute routing params*/
nxf500513a018e72019-04-23 17:11:41 +05303168 case MSG_COMPUTE_ROUTING_PARAMS:
3169 Log.d(TAG, "computeRoutingParameters >>>");
3170 synchronized (NfcService.this) {
3171 computeAndSetRoutingParameters();
nxpandroid64fd68c2015-09-23 16:45:15 +05303172 }
3173 break;
3174
3175 case MSG_MOCK_NDEF: {
3176 NdefMessage ndefMsg = (NdefMessage) msg.obj;
3177 Bundle extras = new Bundle();
3178 extras.putParcelable(Ndef.EXTRA_NDEF_MSG, ndefMsg);
3179 extras.putInt(Ndef.EXTRA_NDEF_MAXLENGTH, 0);
3180 extras.putInt(Ndef.EXTRA_NDEF_CARDSTATE, Ndef.NDEF_MODE_READ_ONLY);
3181 extras.putInt(Ndef.EXTRA_NDEF_TYPE, Ndef.TYPE_OTHER);
3182 Tag tag = Tag.createMockTag(new byte[]{0x00},
3183 new int[]{TagTechnology.NDEF},
3184 new Bundle[]{extras});
3185 Log.d(TAG, "mock NDEF tag, starting corresponding activity");
3186 Log.d(TAG, tag.toString());
3187 int dispatchStatus = mNfcDispatcher.dispatchTag(tag);
3188 if (dispatchStatus == NfcDispatcher.DISPATCH_SUCCESS) {
3189 playSound(SOUND_END);
3190 } else if (dispatchStatus == NfcDispatcher.DISPATCH_FAIL) {
3191 playSound(SOUND_ERROR);
3192 }
3193 break;
3194 }
3195
nxpandroid64fd68c2015-09-23 16:45:15 +05303196 case MSG_NDEF_TAG:
3197 if (DBG) Log.d(TAG, "Tag detected, notifying applications");
Suhas Suresh31963a02018-04-25 12:14:23 +05303198 mPowerManager.userActivity(SystemClock.uptimeMillis(),
3199 PowerManager.USER_ACTIVITY_EVENT_OTHER, 0);
nxpandroid6fd9cdb2017-07-12 18:25:41 +05303200 mNumTagsDetected.incrementAndGet();
nxpandroid64fd68c2015-09-23 16:45:15 +05303201 TagEndpoint tag = (TagEndpoint) msg.obj;
nxpandroid281eb922016-08-25 20:27:46 +05303202 byte[] debounceTagUid;
3203 int debounceTagMs;
3204 ITagRemovedCallback debounceTagRemovedCallback;
3205 synchronized (NfcService.this) {
3206 debounceTagUid = mDebounceTagUid;
3207 debounceTagMs = mDebounceTagDebounceMs;
3208 debounceTagRemovedCallback = mDebounceTagRemovedCallback;
3209 }
nxpandroid64fd68c2015-09-23 16:45:15 +05303210 ReaderModeParams readerParams = null;
3211 int presenceCheckDelay = DEFAULT_PRESENCE_CHECK_DELAY;
3212 DeviceHost.TagDisconnectedCallback callback =
3213 new DeviceHost.TagDisconnectedCallback() {
3214 @Override
3215 public void onTagDisconnected(long handle) {
nxf500513a018e72019-04-23 17:11:41 +05303216 applyRouting(false);
nxpandroid64fd68c2015-09-23 16:45:15 +05303217 }
3218 };
3219 synchronized (NfcService.this) {
3220 readerParams = mReaderModeParams;
3221 }
3222 if (readerParams != null) {
3223 presenceCheckDelay = readerParams.presenceCheckDelay;
3224 if ((readerParams.flags & NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK) != 0) {
3225 if (DBG) Log.d(TAG, "Skipping NDEF detection in reader mode");
3226 tag.startPresenceChecking(presenceCheckDelay, callback);
3227 dispatchTagEndpoint(tag, readerParams);
3228 break;
3229 }
3230 }
3231
nxpandroid64fd68c2015-09-23 16:45:15 +05303232 if (tag.getConnectedTechnology() == TagTechnology.NFC_BARCODE) {
3233 // When these tags start containing NDEF, they will require
3234 // the stack to deal with them in a different way, since
3235 // they are activated only really shortly.
3236 // For now, don't consider NDEF on these.
3237 if (DBG) Log.d(TAG, "Skipping NDEF detection for NFC Barcode");
3238 tag.startPresenceChecking(presenceCheckDelay, callback);
3239 dispatchTagEndpoint(tag, readerParams);
3240 break;
3241 }
3242 NdefMessage ndefMsg = tag.findAndReadNdef();
3243
nxpandroid6fd9cdb2017-07-12 18:25:41 +05303244 if (ndefMsg == null) {
3245 // First try to see if this was a bad tag read
3246 if (!tag.reconnect()) {
nxpandroid64fd68c2015-09-23 16:45:15 +05303247 tag.disconnect();
Ganesh Deva1835f102019-07-12 11:22:03 +05303248 if (mScreenState == ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED) {
Ganesh Deva65fa8112019-07-12 12:00:29 +05303249 if (mToast == null) {
3250 mToast = Toast.makeText(mContext,
3251 R.string.tag_read_error, Toast.LENGTH_SHORT);
3252 }
3253 mToast.setText(R.string.tag_read_error);
3254 mToast.show();
Ganesh Deva1835f102019-07-12 11:22:03 +05303255 }
nxpandroid6fd9cdb2017-07-12 18:25:41 +05303256 break;
nxpandroid64fd68c2015-09-23 16:45:15 +05303257 }
3258 }
nxpandroid6fd9cdb2017-07-12 18:25:41 +05303259
3260 if (debounceTagUid != null) {
3261 // If we're debouncing and the UID or the NDEF message of the tag match,
3262 // don't dispatch but drop it.
3263 if (Arrays.equals(debounceTagUid, tag.getUid()) ||
3264 (ndefMsg != null && ndefMsg.equals(mLastReadNdefMessage))) {
3265 mHandler.removeMessages(MSG_TAG_DEBOUNCE);
3266 mHandler.sendEmptyMessageDelayed(MSG_TAG_DEBOUNCE, debounceTagMs);
3267 tag.disconnect();
3268 return;
3269 } else {
3270 synchronized (NfcService.this) {
3271 mDebounceTagUid = null;
3272 mDebounceTagRemovedCallback = null;
Nikhil Chhabra1b2368f2018-01-09 18:34:21 +05303273 mDebounceTagNativeHandle = INVALID_NATIVE_HANDLE;
nxpandroid6fd9cdb2017-07-12 18:25:41 +05303274 }
3275 if (debounceTagRemovedCallback != null) {
3276 try {
3277 debounceTagRemovedCallback.onTagRemoved();
3278 } catch (RemoteException e) {
3279 // Ignore
3280 }
3281 }
3282 }
3283 }
3284
3285 mLastReadNdefMessage = ndefMsg;
3286
3287 tag.startPresenceChecking(presenceCheckDelay, callback);
3288 dispatchTagEndpoint(tag, readerParams);
nxpandroid64fd68c2015-09-23 16:45:15 +05303289 break;
nxpandroid64fd68c2015-09-23 16:45:15 +05303290 case MSG_LLCP_LINK_ACTIVATION:
Suhas Suresh31963a02018-04-25 12:14:23 +05303291 mPowerManager.userActivity(SystemClock.uptimeMillis(),
3292 PowerManager.USER_ACTIVITY_EVENT_OTHER, 0);
nxpandroid64fd68c2015-09-23 16:45:15 +05303293 if (mIsDebugBuild) {
3294 Intent actIntent = new Intent(ACTION_LLCP_UP);
3295 mContext.sendBroadcast(actIntent);
3296 }
3297 llcpActivated((NfcDepEndpoint) msg.obj);
3298 break;
3299
3300 case MSG_LLCP_LINK_DEACTIVATED:
3301 if (mIsDebugBuild) {
3302 Intent deactIntent = new Intent(ACTION_LLCP_DOWN);
3303 mContext.sendBroadcast(deactIntent);
3304 }
3305 NfcDepEndpoint device = (NfcDepEndpoint) msg.obj;
3306 boolean needsDisconnect = false;
3307
3308 Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop.");
3309 synchronized (NfcService.this) {
3310 /* Check if the device has been already unregistered */
3311 if (mObjectMap.remove(device.getHandle()) != null) {
3312 /* Disconnect if we are initiator */
3313 if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) {
3314 if (DBG) Log.d(TAG, "disconnecting from target");
3315 needsDisconnect = true;
3316 } else {
3317 if (DBG) Log.d(TAG, "not disconnecting from initiator");
3318 }
3319 }
3320 }
3321 if (needsDisconnect) {
3322 device.disconnect(); // restarts polling loop
3323 }
3324
3325 mP2pLinkManager.onLlcpDeactivated();
3326 break;
3327 case MSG_LLCP_LINK_FIRST_PACKET:
3328 mP2pLinkManager.onLlcpFirstPacketReceived();
3329 break;
nxf500513a018e72019-04-23 17:11:41 +05303330 case MSG_RF_FIELD_ACTIVATED:
3331 Intent fieldOnIntent = new Intent(ACTION_RF_FIELD_ON_DETECTED);
3332 sendNfcEeAccessProtectedBroadcast(fieldOnIntent);
nxpandroid64fd68c2015-09-23 16:45:15 +05303333 break;
nxf500513a018e72019-04-23 17:11:41 +05303334 case MSG_RF_FIELD_DEACTIVATED:
3335 Intent fieldOffIntent = new Intent(ACTION_RF_FIELD_OFF_DETECTED);
3336 sendNfcEeAccessProtectedBroadcast(fieldOffIntent);
nxpandroid64fd68c2015-09-23 16:45:15 +05303337 break;
nxpandroid64fd68c2015-09-23 16:45:15 +05303338 case MSG_RESUME_POLLING:
3339 mNfcAdapter.resumePolling();
3340 break;
nxf500513a018e72019-04-23 17:11:41 +05303341 case MSG_TAG_DEBOUNCE:
3342 // Didn't see the tag again, tag is gone
3343 ITagRemovedCallback tagRemovedCallback;
3344 synchronized (NfcService.this) {
3345 mDebounceTagUid = null;
3346 tagRemovedCallback = mDebounceTagRemovedCallback;
3347 mDebounceTagRemovedCallback = null;
3348 mDebounceTagNativeHandle = INVALID_NATIVE_HANDLE;
nxpandroid64fd68c2015-09-23 16:45:15 +05303349 }
nxf500513a018e72019-04-23 17:11:41 +05303350 if (tagRemovedCallback != null) {
3351 try {
3352 tagRemovedCallback.onTagRemoved();
3353 } catch (RemoteException e) {
3354 // Ignore
3355 }
nxpandroid64fd68c2015-09-23 16:45:15 +05303356 }
nxf500513a018e72019-04-23 17:11:41 +05303357 break;
3358 case MSG_UPDATE_STATS:
3359 if (mNumTagsDetected.get() > 0) {
3360 MetricsLogger.count(mContext, TRON_NFC_TAG, mNumTagsDetected.get());
3361 mNumTagsDetected.set(0);
3362 }
3363 if (mNumHceDetected.get() > 0) {
3364 MetricsLogger.count(mContext, TRON_NFC_CE, mNumHceDetected.get());
3365 mNumHceDetected.set(0);
3366 }
3367 if (mNumP2pDetected.get() > 0) {
3368 MetricsLogger.count(mContext, TRON_NFC_P2P, mNumP2pDetected.get());
3369 mNumP2pDetected.set(0);
3370 }
3371 removeMessages(MSG_UPDATE_STATS);
3372 sendEmptyMessageDelayed(MSG_UPDATE_STATS, STATS_UPDATE_INTERVAL_MS);
nxpandroid64fd68c2015-09-23 16:45:15 +05303373 break;
3374
nxf500513a018e72019-04-23 17:11:41 +05303375 case MSG_APPLY_SCREEN_STATE:
3376 mScreenState = (Integer)msg.obj;
3377 Log.d(TAG, "MSG_APPLY_SCREEN_STATE " + mScreenState);
3378
3379 // If NFC is turning off, we shouldn't need any changes here
3380 synchronized (NfcService.this) {
3381 if (mState == NfcAdapter.STATE_TURNING_OFF)
3382 return;
3383 }
3384
3385 if (mScreenState == ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED) {
3386 applyRouting(false);
3387 }
3388 int screen_state_mask = (mNfcUnlockManager.isLockscreenPollingEnabled()) ?
3389 (ScreenStateHelper.SCREEN_POLLING_TAG_MASK | mScreenState) : mScreenState;
3390
3391 if (mNfcUnlockManager.isLockscreenPollingEnabled())
3392 applyRouting(false);
3393
3394 mDeviceHost.doSetScreenState(screen_state_mask);
3395 break;
nxpandroid64fd68c2015-09-23 16:45:15 +05303396 case MSG_ETSI_START_CONFIG:
3397 {
3398 Log.d(TAG, "NfcServiceHandler - MSG_ETSI_START_CONFIG");
3399 ArrayList<Integer> configList = (ArrayList<Integer>) msg.obj;
3400 int eeHandle;
3401 if(configList.contains(0x402))
3402 {
3403 eeHandle = 0x402;
3404 }
3405 else{
3406 eeHandle = 0x4C0;
3407 }
Pratap Reddy49abbe32018-03-27 16:51:59 +05303408 synchronized (NfcService.this) {
3409 etsiStartConfig(eeHandle);
3410 }
nxpandroid64fd68c2015-09-23 16:45:15 +05303411 }
3412 break;
3413
3414 case MSG_ETSI_STOP_CONFIG:
3415
3416 Log.d(TAG, "NfcServiceHandler - MSG_ETSI_STOP_CONFIG");
3417
3418 etsiStopConfig((int)msg.obj);
3419 break;
3420
3421 case MSG_ETSI_SWP_TIMEOUT:
3422
3423 Log.d(TAG, "NfcServiceHandler - MSG_ETSI_SWP_TIMEOUT");
3424
Pratap Reddy7e57f0d2018-03-15 16:54:33 +05303425 /* Send broadcast ordered */
3426 Intent swpReaderTimeoutIntent = new Intent();
nxpandroid64fd68c2015-09-23 16:45:15 +05303427
Pratap Reddy7e57f0d2018-03-15 16:54:33 +05303428 swpReaderTimeoutIntent
nxf500513a018e72019-04-23 17:11:41 +05303429 .setAction(NfcConstants.ACTION_NFC_MPOS_READER_MODE_TIMEOUT);
Pratap Reddy7e57f0d2018-03-15 16:54:33 +05303430 if (DBG) {
3431 Log.d(TAG, "SWP READER - Timeout");
3432 }
3433 mContext.sendBroadcast(swpReaderTimeoutIntent);
nxpandroid64fd68c2015-09-23 16:45:15 +05303434 break;
Pratap Reddy7e57f0d2018-03-15 16:54:33 +05303435
3436 case MSG_SWP_READER_RESTART:
3437
3438 Log.d(TAG, "NfcServiceHandler - MSG_SWP_READER_RESTART");
3439
3440 /* Send broadcast ordered */
3441 Intent swpReaderRestartIntent = new Intent();
3442
3443 swpReaderRestartIntent
nxf500513a018e72019-04-23 17:11:41 +05303444 .setAction(NfcConstants.ACTION_NFC_MPOS_READER_MODE_RESTART);
Pratap Reddy7e57f0d2018-03-15 16:54:33 +05303445 if (DBG) {
3446 Log.d(TAG, "SWP READER - RESTART");
3447 }
3448 mContext.sendBroadcast(swpReaderRestartIntent);
3449 break;
nxf500513a018e72019-04-23 17:11:41 +05303450 case MSG_TRANSACTION_EVENT:
3451 if (mCardEmulationManager != null) {
3452 mCardEmulationManager.onOffHostAidSelected();
Nikhil Chhabra20be8d92018-01-09 18:32:58 +05303453 }
nxf500513a018e72019-04-23 17:11:41 +05303454 byte[][] data = (byte[][]) msg.obj;
3455 sendOffHostTransactionEvent(data[0], data[1], data[2]);
nxpandroid64fd68c2015-09-23 16:45:15 +05303456 break;
nxf500513a018e72019-04-23 17:11:41 +05303457 case MSG_SE_INIT:
3458 Log.e(TAG, "msg se init");
nxpandroida5fd6622017-07-31 16:15:18 +05303459
nxf500513a018e72019-04-23 17:11:41 +05303460 try {
3461 if (mIsHceCapable) {
3462 // Generate the initial card emulation routing table
3463 computeRoutingParameters();
3464 }
3465
3466 /* TODO Call WiredSe HAL to notify */
3467
3468 } catch (Exception e) {
3469 Log.e(TAG, "mSecureElementclientCallback.onStateChange");
3470 }
3471
3472 break;
Suhas Suresh0162e8e2019-06-19 16:02:47 +05303473
nxf500513a018e72019-04-23 17:11:41 +05303474 case MSG_INIT_WIREDSE: {
3475 try {
3476 mWiredSeInitMethod = mWiredSeClass.getDeclaredMethod("wiredSeInitialize");
3477 mWiredSeInitMethod.invoke(mWiredSeObj);
3478 } catch (NoSuchElementException | NoSuchMethodException e) {
3479 Log.i(TAG, "No such Method WiredSeInitialize");
3480 } catch (RuntimeException | IllegalAccessException | InvocationTargetException e) {
3481 Log.e(TAG, "Error in invoking wiredSeInitialize invocation");
3482 } catch (Exception e) {
3483 Log.e(TAG, "caught Exception during wiredSeInitialize");
3484 e.printStackTrace();
3485 }
Suhas Suresh061c9b02018-05-15 17:45:06 +05303486 break;
nxf500513a018e72019-04-23 17:11:41 +05303487 }
Ganesh Deva1ad7d6f2019-06-17 11:46:02 +05303488 case MSG_DEINIT_WIREDSE: {
3489 try {
3490 mWiredSeInitMethod = mWiredSeClass.getDeclaredMethod("wiredSeDeInitialize");
3491 mWiredSeInitMethod.invoke(mWiredSeObj);
3492 } catch (NoSuchElementException | NoSuchMethodException e) {
3493 Log.i(TAG, "No such Method wiredSeDeInitialize");
3494 } catch (RuntimeException | IllegalAccessException | InvocationTargetException e) {
3495 Log.e(TAG, "Error in invoking wiredSeDeInitialize invocation");
3496 } catch (Exception e) {
3497 Log.e(TAG, "caught Exception during wiredSeDeInitialize");
3498 e.printStackTrace();
3499 }
3500 break;
3501 }
nxpandroid64fd68c2015-09-23 16:45:15 +05303502 default:
3503 Log.e(TAG, "Unknown message received");
3504 break;
3505 }
3506 }
3507
Suhas Suresh061c9b02018-05-15 17:45:06 +05303508 private void sendOffHostTransactionEvent(byte[] aid, byte[] data, byte[] readerByteArray) {
Ganesh Deva272ad052018-07-09 15:56:45 +05303509 if (!isSEServiceAvailable() || mNfcEventInstalledPackages.isEmpty()) {
Suhas Sureshca6584b2018-04-27 17:17:22 +05303510 return;
3511 }
nxf500513a018e72019-04-23 17:11:41 +05303512
Suhas Sureshca6584b2018-04-27 17:17:22 +05303513 try {
Suhas Suresh061c9b02018-05-15 17:45:06 +05303514 String reader = new String(readerByteArray, "UTF-8");
3515 String[] installedPackages = new String[mNfcEventInstalledPackages.size()];
Suhas Sureshca6584b2018-04-27 17:17:22 +05303516 boolean[] nfcAccess = mSEService.isNFCEventAllowed(reader, aid,
3517 mNfcEventInstalledPackages.toArray(installedPackages));
3518 if (nfcAccess == null) {
3519 return;
3520 }
3521 ArrayList<String> packages = new ArrayList<String>();
nxf38293fa39fab2018-07-23 15:50:08 +05303522 Intent intent = new Intent(NfcAdapter.ACTION_TRANSACTION_DETECTED);
Suhas Sureshca6584b2018-04-27 17:17:22 +05303523 intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
Suhas Suresh061c9b02018-05-15 17:45:06 +05303524 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
nxf38293fa39fab2018-07-23 15:50:08 +05303525 intent.putExtra(NfcAdapter.EXTRA_AID, aid);
3526 intent.putExtra(NfcAdapter.EXTRA_DATA, data);
Ganesh Deva2c027052018-08-07 15:18:32 +05303527 intent.putExtra(NfcAdapter.EXTRA_SECURE_ELEMENT_NAME, reader);
Suhas Suresh061c9b02018-05-15 17:45:06 +05303528 StringBuilder aidString = new StringBuilder(aid.length);
3529 for (byte b : aid) {
3530 aidString.append(String.format("%02X", b));
3531 }
3532 String url = new String ("nfc://secure:0/" + reader + "/" + aidString.toString());
3533 intent.setData(Uri.parse(url));
Suhas Sureshca6584b2018-04-27 17:17:22 +05303534 for (int i = 0; i < nfcAccess.length; i++) {
3535 if (nfcAccess[i]) {
Suhas Suresh140f7ac2018-05-15 14:59:11 +05303536 intent.setPackage(mNfcEventInstalledPackages.get(i));
Suhas Sureshca6584b2018-04-27 17:17:22 +05303537 mContext.sendBroadcast(intent);
3538 }
3539 }
3540 } catch (RemoteException e) {
3541 Log.e(TAG, "Error in isNFCEventAllowed() " + e);
Suhas Suresh061c9b02018-05-15 17:45:06 +05303542 } catch (UnsupportedEncodingException e) {
3543 Log.e(TAG, "Incorrect format for Secure Element name" + e);
Suhas Sureshca6584b2018-04-27 17:17:22 +05303544 }
3545 }
3546
3547 /* Returns the list of packages that have access to NFC Events on any SE */
3548 private ArrayList<String> getSEAccessAllowedPackages() {
Ganesh Deva272ad052018-07-09 15:56:45 +05303549 if (!isSEServiceAvailable() || mNfcEventInstalledPackages.isEmpty()) {
Suhas Sureshca6584b2018-04-27 17:17:22 +05303550 return null;
3551 }
3552 String[] readers = null;
3553 try {
3554 readers = mSEService.getReaders();
3555 } catch (RemoteException e) {
3556 Log.e(TAG, "Error in getReaders() " + e);
3557 return null;
3558 }
3559
3560 if (readers == null || readers.length == 0) {
3561 return null;
3562 }
3563 boolean[] nfcAccessFinal = null;
3564 String[] installedPackages = new String[mNfcEventInstalledPackages.size()];
3565 for (String reader : readers) {
3566 try {
3567 boolean[] accessList = mSEService.isNFCEventAllowed(reader, null,
3568 mNfcEventInstalledPackages.toArray(installedPackages));
3569 if (accessList == null) {
3570 continue;
3571 }
3572 if (nfcAccessFinal == null) {
3573 nfcAccessFinal = accessList;
3574 }
3575 for (int i = 0; i < accessList.length; i++) {
3576 if (accessList[i]) {
3577 nfcAccessFinal[i] = true;
3578 }
3579 }
3580 } catch (RemoteException e) {
3581 Log.e(TAG, "Error in isNFCEventAllowed() " + e);
3582 }
3583 }
3584 if (nfcAccessFinal == null) {
3585 return null;
3586 }
3587 ArrayList<String> packages = new ArrayList<String>();
3588 for (int i = 0; i < nfcAccessFinal.length; i++) {
3589 if (nfcAccessFinal[i]) {
Suhas Suresh140f7ac2018-05-15 14:59:11 +05303590 packages.add(mNfcEventInstalledPackages.get(i));
Suhas Sureshca6584b2018-04-27 17:17:22 +05303591 }
3592 }
3593 return packages;
3594 }
3595
nxf500513a018e72019-04-23 17:11:41 +05303596 private void sendNfcEeAccessProtectedBroadcast(Intent intent) {
nxpandroid64fd68c2015-09-23 16:45:15 +05303597 intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
3598 // Resume app switches so the receivers can start activites without delay
3599 mNfcDispatcher.resumeAppSwitches();
nxf500513a018e72019-04-23 17:11:41 +05303600 ArrayList<String> matchingPackages = new ArrayList<String>();
3601 ArrayList<String> preferredPackages = new ArrayList<String>();
3602 synchronized (this) {
Suhas Sureshca6584b2018-04-27 17:17:22 +05303603 ArrayList<String> SEPackages = getSEAccessAllowedPackages();
3604 if (SEPackages!= null && !SEPackages.isEmpty()) {
3605 for (String packageName : SEPackages) {
nxpandroid64fd68c2015-09-23 16:45:15 +05303606 intent.setPackage(packageName);
3607 mContext.sendBroadcast(intent);
3608 }
Suhas Sureshca6584b2018-04-27 17:17:22 +05303609 }
Suhas Suresh140f7ac2018-05-15 14:59:11 +05303610 PackageManager pm = mContext.getPackageManager();
3611 for (String packageName : mNfcEventInstalledPackages) {
3612 try {
3613 PackageInfo info = pm.getPackageInfo(packageName, 0);
3614 if (SEPackages != null && SEPackages.contains(packageName)) {
3615 continue;
3616 }
3617 if (info.applicationInfo != null &&
3618 ((info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 ||
3619 (info.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0)) {
3620 intent.setPackage(packageName);
3621 mContext.sendBroadcast(intent);
3622 }
3623 } catch (Exception e) {
3624 Log.e(TAG, "Exception in getPackageInfo " + e);
nxpandroid64fd68c2015-09-23 16:45:15 +05303625 }
3626 }
3627 }
3628 }
3629
nxpandroid64fd68c2015-09-23 16:45:15 +05303630 private boolean llcpActivated(NfcDepEndpoint device) {
3631 Log.d(TAG, "LLCP Activation message");
3632
3633 if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) {
3634 if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET");
3635 if (device.connect()) {
nxf500513a018e72019-04-23 17:11:41 +05303636 /* Check LLCP compliancy */
nxpandroid64fd68c2015-09-23 16:45:15 +05303637 if (mDeviceHost.doCheckLlcp()) {
3638 /* Activate LLCP Link */
3639 if (mDeviceHost.doActivateLlcp()) {
3640 if (DBG) Log.d(TAG, "Initiator Activate LLCP OK");
3641 synchronized (NfcService.this) {
3642 // Register P2P device
3643 mObjectMap.put(device.getHandle(), device);
3644 }
nxpandroid1153eb32015-11-06 18:46:58 +05303645 mP2pLinkManager.onLlcpActivated(device.getLlcpVersion());
nxpandroid64fd68c2015-09-23 16:45:15 +05303646 return true;
3647 } else {
3648 /* should not happen */
3649 Log.w(TAG, "Initiator LLCP activation failed. Disconnect.");
3650 device.disconnect();
3651 }
3652 } else {
3653 if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect.");
3654 device.disconnect();
3655 }
3656 } else {
3657 if (DBG) Log.d(TAG, "Cannot connect remote Target. Polling loop restarted.");
3658 /*
3659 * The polling loop should have been restarted in failing
3660 * doConnect
3661 */
3662 }
3663 } else if (device.getMode() == NfcDepEndpoint.MODE_P2P_INITIATOR) {
3664 if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR");
3665 /* Check LLCP compliancy */
3666 if (mDeviceHost.doCheckLlcp()) {
3667 /* Activate LLCP Link */
3668 if (mDeviceHost.doActivateLlcp()) {
3669 if (DBG) Log.d(TAG, "Target Activate LLCP OK");
3670 synchronized (NfcService.this) {
3671 // Register P2P device
3672 mObjectMap.put(device.getHandle(), device);
3673 }
nxpandroid1153eb32015-11-06 18:46:58 +05303674 mP2pLinkManager.onLlcpActivated(device.getLlcpVersion());
nxpandroid64fd68c2015-09-23 16:45:15 +05303675 return true;
3676 }
3677 } else {
3678 Log.w(TAG, "checkLlcp failed");
3679 }
3680 }
3681
3682 return false;
3683 }
3684
3685 private void dispatchTagEndpoint(TagEndpoint tagEndpoint, ReaderModeParams readerParams) {
3686 Tag tag = new Tag(tagEndpoint.getUid(), tagEndpoint.getTechList(),
3687 tagEndpoint.getTechExtras(), tagEndpoint.getHandle(), mNfcTagService);
3688 registerTagObject(tagEndpoint);
3689 if (readerParams != null) {
3690 try {
3691 if ((readerParams.flags & NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS) == 0) {
Suhas Suresh6e05ee02018-04-25 12:19:35 +05303692 mVibrator.vibrate(mVibrationEffect);
nxpandroid64fd68c2015-09-23 16:45:15 +05303693 playSound(SOUND_END);
3694 }
3695 if (readerParams.callback != null) {
3696 readerParams.callback.onTagDiscovered(tag);
3697 return;
3698 } else {
3699 // Follow normal dispatch below
3700 }
3701 } catch (RemoteException e) {
3702 Log.e(TAG, "Reader mode remote has died, falling back.", e);
3703 // Intentional fall-through
3704 } catch (Exception e) {
3705 // Catch any other exception
3706 Log.e(TAG, "App exception, not dispatching.", e);
3707 return;
3708 }
3709 }
3710 int dispatchResult = mNfcDispatcher.dispatchTag(tag);
nxf500513a018e72019-04-23 17:11:41 +05303711 if (dispatchResult == NfcDispatcher.DISPATCH_FAIL && !mInProvisionMode) {
nxpandroid64fd68c2015-09-23 16:45:15 +05303712 unregisterObject(tagEndpoint.getHandle());
Ganesh Deva1835f102019-07-12 11:22:03 +05303713 if (mScreenState == ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED) {
Ganesh Deva65fa8112019-07-12 12:00:29 +05303714 if (mToast == null) {
3715 mToast = Toast.makeText(mContext,
3716 R.string.tag_dispatch_failed, Toast.LENGTH_SHORT);
3717 }
3718 mToast.setText(R.string.tag_dispatch_failed);
3719 mToast.show();
Ganesh Deva1835f102019-07-12 11:22:03 +05303720 }
nxpandroid64fd68c2015-09-23 16:45:15 +05303721 playSound(SOUND_ERROR);
3722 } else if (dispatchResult == NfcDispatcher.DISPATCH_SUCCESS) {
Suhas Suresh6e05ee02018-04-25 12:19:35 +05303723 mVibrator.vibrate(mVibrationEffect);
nxpandroid64fd68c2015-09-23 16:45:15 +05303724 playSound(SOUND_END);
3725 }
3726 }
3727 }
3728
nxf500513a018e72019-04-23 17:11:41 +05303729 /* For Toast from background process*/
3730
3731 public class ToastHandler
3732 {
3733 // General attributes
3734 private Context mContext;
3735 private Handler mHandler;
3736
3737 public ToastHandler(Context _context)
3738 {
3739 this.mContext = _context;
3740 this.mHandler = new Handler();
3741 }
3742
3743 /**
3744 * Runs the <code>Runnable</code> in a separate <code>Thread</code>.
3745 *
3746 * @param _runnable
3747 * The <code>Runnable</code> containing the <code>Toast</code>
3748 */
3749 private void runRunnable(final Runnable _runnable)
3750 {
3751 Thread thread = new Thread()
3752 {
3753 public void run()
3754 {
3755 mHandler.post(_runnable);
3756 }
3757 };
3758
3759 thread.start();
3760 thread.interrupt();
3761 thread = null;
3762 }
3763
3764 public void showToast(final CharSequence _text, final int _duration)
3765 {
3766 final Runnable runnable = new Runnable()
3767 {
3768 @Override
3769 public void run()
3770 {
3771 Toast.makeText(mContext, _text, _duration).show();
3772 }
3773 };
3774
3775 runRunnable(runnable);
3776 }
3777 }
3778
nxpandroid64fd68c2015-09-23 16:45:15 +05303779 private NfcServiceHandler mHandler = new NfcServiceHandler();
3780
3781 class ApplyRoutingTask extends AsyncTask<Integer, Void, Void> {
3782 @Override
3783 protected Void doInBackground(Integer... params) {
3784 synchronized (NfcService.this) {
3785 if (params == null || params.length != 1) {
3786 // force apply current routing
nxpandroid64fd68c2015-09-23 16:45:15 +05303787 applyRouting(true);
3788 return null;
3789 }
3790 mScreenState = params[0].intValue();
nxf500513a018e72019-04-23 17:11:41 +05303791
nxpandroid64fd68c2015-09-23 16:45:15 +05303792 mRoutingWakeLock.acquire();
3793 try {
nxpandroid64fd68c2015-09-23 16:45:15 +05303794 applyRouting(false);
3795 } finally {
3796 mRoutingWakeLock.release();
3797 }
3798 return null;
3799 }
3800 }
3801 }
3802
nxf500513a018e72019-04-23 17:11:41 +05303803 class TagRemoveTaskTimer extends TimerTask {
3804 public void run()
3805 {
3806 Intent swpReaderTagRemoveIntent = new Intent();
3807 swpReaderTagRemoveIntent.setAction(NfcConstants.ACTION_NFC_MPOS_READER_MODE_REMOVE_CARD);
3808 if (DBG) {
3809 Log.d(TAG, "SWP READER - Tag Remove");
3810 }
3811 mContext.sendBroadcast(swpReaderTagRemoveIntent);
3812 }
3813 }
Pratap Reddy49abbe32018-03-27 16:51:59 +05303814 class EtsiStopConfigTask extends AsyncTask<Integer, Void, Void> {
nxpandroid64fd68c2015-09-23 16:45:15 +05303815 @Override
3816 protected Void doInBackground(Integer... params) {
Pratap Reddy49abbe32018-03-27 16:51:59 +05303817 synchronized (NfcService.this) {
3818 etsiStopConfig(params[0].intValue());
nxpandroid64fd68c2015-09-23 16:45:15 +05303819 return null;
Pratap Reddy49abbe32018-03-27 16:51:59 +05303820 }
3821 }
3822 }
nxpandroid64fd68c2015-09-23 16:45:15 +05303823 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
3824 @Override
3825 public void onReceive(Context context, Intent intent) {
3826 String action = intent.getAction();
nxf500513a018e72019-04-23 17:11:41 +05303827 if (action.equals(Intent.ACTION_SCREEN_ON)
nxpandroid64fd68c2015-09-23 16:45:15 +05303828 || action.equals(Intent.ACTION_SCREEN_OFF)
nxf500513a018e72019-04-23 17:11:41 +05303829 || action.equals(Intent.ACTION_USER_PRESENT)) {
nxpandroid64fd68c2015-09-23 16:45:15 +05303830 // Perform applyRouting() in AsyncTask to serialize blocking calls
nxpandroid6fd9cdb2017-07-12 18:25:41 +05303831 int screenState = mScreenStateHelper.checkScreenState();
nxpandroid64fd68c2015-09-23 16:45:15 +05303832 if (action.equals(Intent.ACTION_SCREEN_OFF)) {
nxf500513a018e72019-04-23 17:11:41 +05303833 if (mScreenState != ScreenStateHelper.SCREEN_STATE_OFF_LOCKED) {
nxpandroid6fd9cdb2017-07-12 18:25:41 +05303834 screenState = mKeyguard.isKeyguardLocked() ?
nxf500513a018e72019-04-23 17:11:41 +05303835 ScreenStateHelper.SCREEN_STATE_OFF_LOCKED : ScreenStateHelper.SCREEN_STATE_OFF_UNLOCKED;
3836 }
nxpandroid64fd68c2015-09-23 16:45:15 +05303837 } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
nxf500513a018e72019-04-23 17:11:41 +05303838 screenState = mKeyguard.isKeyguardLocked()
3839 ? ScreenStateHelper.SCREEN_STATE_ON_LOCKED
3840 : ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED;
nxpandroid64fd68c2015-09-23 16:45:15 +05303841 } else if (action.equals(Intent.ACTION_USER_PRESENT)) {
nxf500513a018e72019-04-23 17:11:41 +05303842 screenState = ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED;
nxpandroid64fd68c2015-09-23 16:45:15 +05303843 }
nxf500513a018e72019-04-23 17:11:41 +05303844 if (nci_version != NCI_VERSION_2_0) {
nxpandroide66eb092017-07-12 21:36:08 +05303845 new ApplyRoutingTask().execute(Integer.valueOf(screenState));
Pratap Reddy7e57f0d2018-03-15 16:54:33 +05303846 }
nxf500513a018e72019-04-23 17:11:41 +05303847 sendMessage(NfcService.MSG_APPLY_SCREEN_STATE, screenState);
nxpandroid64fd68c2015-09-23 16:45:15 +05303848 } else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
nxpandroid64fd68c2015-09-23 16:45:15 +05303849 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
nxf500513a018e72019-04-23 17:11:41 +05303850 if (mIsBeamCapable) {
3851 int beamSetting =
3852 PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
3853 try {
3854 IPackageManager mIpm = IPackageManager.Stub.asInterface(
3855 ServiceManager.getService("package"));
3856 beamSetting = mIpm.getComponentEnabledSetting(new ComponentName(
3857 BeamShareActivity.class.getPackageName$(),
3858 BeamShareActivity.class.getName()),
3859 userId);
3860 } catch(RemoteException e) {
3861 Log.e(TAG, "Error int getComponentEnabledSetting for BeamShareActivity");
Suhas Sureshe2a2ff02018-04-27 12:21:19 +05303862 }
nxf500513a018e72019-04-23 17:11:41 +05303863 synchronized (this) {
3864 mUserId = userId;
3865 if (beamSetting == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
3866 mIsNdefPushEnabled = false;
3867 } else {
3868 mIsNdefPushEnabled = true;
Ganesh Devab1498762019-04-30 15:13:22 +05303869 } // Propagate the state change to all user profiles
3870 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
3871 List <UserHandle> luh = um.getUserProfiles();
3872 for (UserHandle uh : luh){
3873 enforceBeamShareActivityPolicy(mContext, uh);
nxf500513a018e72019-04-23 17:11:41 +05303874 }
Ganesh Devab1498762019-04-30 15:13:22 +05303875 enforceBeamShareActivityPolicy(mContext, new UserHandle(mUserId));
nxf500513a018e72019-04-23 17:11:41 +05303876 }
3877 mP2pLinkManager.onUserSwitched(getUserId());
nxpandroid64fd68c2015-09-23 16:45:15 +05303878 }
nxpandroid64fd68c2015-09-23 16:45:15 +05303879 if (mIsHceCapable) {
3880 mCardEmulationManager.onUserSwitched(getUserId());
3881 }
nxf500513a018e72019-04-23 17:11:41 +05303882 int screenState = mScreenStateHelper.checkScreenState();
3883 if (screenState != mScreenState) {
3884 new ApplyRoutingTask().execute(Integer.valueOf(screenState));
3885 }
nxpandroid64fd68c2015-09-23 16:45:15 +05303886 }
3887 }
3888 };
3889
nxf500513a018e72019-04-23 17:11:41 +05303890
nxpandroid64fd68c2015-09-23 16:45:15 +05303891 private final BroadcastReceiver mOwnerReceiver = new BroadcastReceiver() {
3892 @Override
3893 public void onReceive(Context context, Intent intent) {
3894 String action = intent.getAction();
3895 if (action.equals(Intent.ACTION_PACKAGE_REMOVED) ||
3896 action.equals(Intent.ACTION_PACKAGE_ADDED) ||
3897 action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE) ||
3898 action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
3899 updatePackageCache();
nxf500513a018e72019-04-23 17:11:41 +05303900 } else if (action.equals(Intent.ACTION_SHUTDOWN)) {
3901 if (DBG) Log.d(TAG, "Device is shutting down.");
Suhas Suresh9139dc22018-05-09 15:48:37 +05303902 if (isNfcEnabled()) {
3903 mDeviceHost.shutdown();
3904 }
nxpandroid64fd68c2015-09-23 16:45:15 +05303905 }
3906 }
3907 };
3908
nxpandroid64fd68c2015-09-23 16:45:15 +05303909 private final BroadcastReceiver mPolicyReceiver = new BroadcastReceiver() {
3910 @Override
3911 public void onReceive(Context context, Intent intent){
3912 String action = intent.getAction();
3913 if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
nxf500513a018e72019-04-23 17:11:41 +05303914 .equals(action) &&
3915 mIsBeamCapable) {
3916 enforceBeamShareActivityPolicy(
3917 context, new UserHandle(getSendingUserId()));
nxpandroid64fd68c2015-09-23 16:45:15 +05303918 }
3919 }
3920 };
3921
Nikhil Chhabrafc8f3f62018-01-08 20:48:49 +05303922 private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
3923 @Override
3924 public void onVrStateChanged(boolean enabled) {
3925 synchronized (this) {
3926 mIsVrModeEnabled = enabled;
3927 }
3928 }
3929 };
3930
nxpandroid64fd68c2015-09-23 16:45:15 +05303931 /**
nxpandroid64fd68c2015-09-23 16:45:15 +05303932 * for debugging only - no i18n
3933 */
3934 static String stateToString(int state) {
3935 switch (state) {
3936 case NfcAdapter.STATE_OFF:
3937 return "off";
3938 case NfcAdapter.STATE_TURNING_ON:
3939 return "turning on";
3940 case NfcAdapter.STATE_ON:
3941 return "on";
3942 case NfcAdapter.STATE_TURNING_OFF:
3943 return "turning off";
3944 default:
3945 return "<error>";
3946 }
3947 }
3948
3949 void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
3950 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
3951 != PackageManager.PERMISSION_GRANTED) {
3952 pw.println("Permission Denial: can't dump nfc from from pid="
3953 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
3954 + " without permission " + android.Manifest.permission.DUMP);
3955 return;
3956 }
3957
3958 synchronized (this) {
3959 pw.println("mState=" + stateToString(mState));
3960 pw.println("mIsZeroClickRequested=" + mIsNdefPushEnabled);
3961 pw.println("mScreenState=" + ScreenStateHelper.screenStateToString(mScreenState));
Ganesh Devab5def972019-07-12 11:59:43 +05303962 pw.println("mIsSecureNfcEnabled=" + mIsSecureNfcEnabled);
nxpandroid64fd68c2015-09-23 16:45:15 +05303963 pw.println(mCurrentDiscoveryParameters);
nxf500513a018e72019-04-23 17:11:41 +05303964 if (mIsBeamCapable)
3965 mP2pLinkManager.dump(fd, pw, args);
nxpandroid64fd68c2015-09-23 16:45:15 +05303966 if (mIsHceCapable) {
3967 mCardEmulationManager.dump(fd, pw, args);
3968 }
nxpandroid64fd68c2015-09-23 16:45:15 +05303969 mNfcDispatcher.dump(fd, pw, args);
Nikhil Chhabra9645ab62018-01-09 18:44:05 +05303970 pw.flush();
Nikhil Chhabra1e1ac462018-01-10 12:53:43 +05303971 mDeviceHost.dump(fd);
nxpandroid64fd68c2015-09-23 16:45:15 +05303972 }
3973 }
Suhas Suresh14c42612019-05-10 17:18:24 +05303974
Ganesh Deva49fde922019-05-21 15:07:33 +05303975 public void updateDefaultAidRoute(int routeLoc) {
Suhas Suresh14c42612019-05-10 17:18:24 +05303976 mNxpPrefsEditor = mNxpPrefs.edit();
3977 Log.d(TAG, "writing to preferences setDefaultAidRouteLoc :" + routeLoc);
Suhas Suresha1fa17e2019-05-15 13:06:10 +05303978 if (mNxpPrefs.getInt("PREF_SET_DEFAULT_ROUTE_ID", 0xFF) == routeLoc) {
3979 Log.d(TAG, "DefaultRoute :" + routeLoc + " is not changed. Returning.");
3980 return;
3981 }
Suhas Suresh14c42612019-05-10 17:18:24 +05303982 int defaultAidRoute =
3983 ((mDeviceHost.getDefaultAidPowerState() & 0x3F) | (routeLoc << ROUTE_LOC_MASK));
3984 if (routeLoc == 0x00) {
3985 /*
3986 bit pos 1 = Power Off
3987 bit pos 2 = Battery Off
Ganesh Deva0fed5b52019-05-15 10:40:11 +05303988 bit pos 3 = Screen Off
Suhas Suresh14c42612019-05-10 17:18:24 +05303989 Set these bits to 0 because in case routeLoc = HOST it can not work on POWER_OFF,
3990 BATTERY_OFF and SCREEN_OFF*/
3991
Ganesh Deva0fed5b52019-05-15 10:40:11 +05303992 defaultAidRoute &= 0x11;
Suhas Suresh14c42612019-05-10 17:18:24 +05303993 }
3994 mNxpPrefsEditor.putInt("PREF_SET_DEFAULT_ROUTE_ID", defaultAidRoute);
3995 mNxpPrefsEditor.commit();
3996 int defaultRoute = mNxpPrefs.getInt("PREF_SET_DEFAULT_ROUTE_ID", 0xFF);
3997 Log.d(TAG, "Reading updated preference :" + defaultRoute);
Suhas Sureshbe2ba092019-05-15 17:26:23 +05303998 mHandler.sendEmptyMessage(MSG_RESET_AND_UPDATE_ROUTING_PARAMS);
Suhas Suresh14c42612019-05-10 17:18:24 +05303999 }
nxpandroid64fd68c2015-09-23 16:45:15 +05304000}