• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.nfc;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.app.ActivityManager;
22 import android.app.KeyguardManager;
23 import android.app.backup.BackupManager;
24 import android.content.ApexEnvironment;
25 import android.content.Context;
26 import android.content.pm.PackageManager;
27 import android.content.res.Resources;
28 import android.nfc.Constants;
29 import android.nfc.NfcFrameworkInitializer;
30 import android.nfc.NfcServiceManager;
31 import android.os.Handler;
32 import android.os.HandlerThread;
33 import android.os.Looper;
34 import android.os.Process;
35 import android.os.RemoteException;
36 import android.os.SystemClock;
37 import android.os.SystemProperties;
38 import android.os.VibrationEffect;
39 import android.provider.Settings;
40 import android.se.omapi.ISecureElementService;
41 import android.se.omapi.SeFrameworkInitializer;
42 import android.se.omapi.SeServiceManager;
43 import android.util.AtomicFile;
44 import android.util.Log;
45 
46 import com.android.nfc.cardemulation.CardEmulationManager;
47 import com.android.nfc.cardemulation.util.StatsdUtils;
48 import com.android.nfc.cardemulation.util.StatsdUtilsContext;
49 import com.android.nfc.dhimpl.NativeNfcManager;
50 import com.android.nfc.flags.FeatureFlags;
51 import com.android.nfc.flags.Flags;
52 import com.android.nfc.handover.HandoverDataParser;
53 import com.android.nfc.wlc.NfcCharging;
54 
55 import java.io.File;
56 import java.time.LocalDateTime;
57 import java.util.concurrent.atomic.AtomicBoolean;
58 
59 /**
60  * To be used for dependency injection (especially helps mocking static dependencies).
61  * TODO: Migrate more classes to injector to resolve circular dependencies in the NFC stack.
62  */
63 public class NfcInjector {
64     private static final String TAG = "NfcInjector";
65     private static final String APEX_NAME = "com.android.nfcservices";
66     private static final String NFC_DATA_DIR = "/data/nfc";
67     private static final String EVENT_LOG_FILE_NAME = "event_log.binpb";
68 
69     private final Context mContext;
70     private final Looper mMainLooper;
71     private final NfcEventLog mNfcEventLog;
72     private final RoutingTableParser mRoutingTableParser;
73     private final ScreenStateHelper mScreenStateHelper;
74     private final NfcUnlockManager mNfcUnlockManager;
75     private final HandoverDataParser mHandoverDataParser;
76     private final DeviceConfigFacade mDeviceConfigFacade;
77     private final NfcDispatcher mNfcDispatcher;
78     private final VibrationEffect mVibrationEffect;
79     private final BackupManager mBackupManager;
80     private final FeatureFlags mFeatureFlags;
81     @Nullable
82     private final StatsdUtils mStatsdUtils;
83     @Nullable
84     private final StatsdUtilsContext mStatsdUtilsContext;
85     private final ForegroundUtils mForegroundUtils;
86     private final NfcDiagnostics mNfcDiagnostics;
87     private final NfcServiceManager.ServiceRegisterer mNfcManagerRegisterer;
88     private final NfcWatchdog mNfcWatchdog;
89     private final KeyguardManager mKeyguardManager;
90     private static NfcInjector sInstance;
91     private CardEmulationManager mCardEmulationManager;
92 
getInstance()93     public static NfcInjector getInstance() {
94         if (sInstance == null) throw new IllegalStateException("Nfc injector instance null");
95         return sInstance;
96     }
97 
setNfcInjector(NfcInjector nfcInjector)98     static void setNfcInjector(NfcInjector nfcInjector) {
99         sInstance = nfcInjector;
100     }
101 
102 
NfcInjector(@onNull Context context, @NonNull Looper mainLooper)103     public NfcInjector(@NonNull Context context, @NonNull Looper mainLooper) {
104         if (sInstance != null) throw new IllegalStateException("Nfc injector instance not null");
105 
106         mContext = context;
107         mMainLooper = mainLooper;
108         mRoutingTableParser = new RoutingTableParser();
109         mScreenStateHelper = new ScreenStateHelper(mContext);
110         mNfcUnlockManager = NfcUnlockManager.getInstance();
111         mHandoverDataParser = new HandoverDataParser();
112         mDeviceConfigFacade = new DeviceConfigFacade(mContext, new Handler(mainLooper));
113         mNfcDispatcher =
114             new NfcDispatcher(mContext, mHandoverDataParser, this,
115                     isInProvisionMode(), mDeviceConfigFacade);
116         mVibrationEffect = VibrationEffect.createOneShot(200, VibrationEffect.DEFAULT_AMPLITUDE);
117         mBackupManager = new BackupManager(mContext);
118         mFeatureFlags = new com.android.nfc.flags.FeatureFlagsImpl();
119         mStatsdUtilsContext = mFeatureFlags.statsdCeEventsFlag() ? new StatsdUtilsContext() : null;
120         mStatsdUtils = mFeatureFlags.statsdCeEventsFlag() ?
121             new StatsdUtils(mStatsdUtilsContext) : null;
122         mForegroundUtils =
123                 ForegroundUtils.getInstance(mContext.getSystemService(ActivityManager.class));
124         mNfcDiagnostics = new NfcDiagnostics(mContext);
125 
126         NfcServiceManager manager = NfcFrameworkInitializer.getNfcServiceManager();
127         if (manager == null) {
128             Log.e(TAG, "NfcServiceManager is null");
129             throw new UnsupportedOperationException();
130         }
131         mNfcManagerRegisterer = manager.getNfcManagerServiceRegisterer();
132 
133         // Create UWB event log thread.
134         HandlerThread eventLogThread = new HandlerThread("NfcEventLog");
135         eventLogThread.start();
136         mNfcEventLog = new NfcEventLog(mContext, this, eventLogThread.getLooper(),
137                 new AtomicFile(new File(NFC_DATA_DIR, EVENT_LOG_FILE_NAME)));
138         mNfcWatchdog = new NfcWatchdog(mContext);
139         mKeyguardManager = mContext.getSystemService(KeyguardManager.class);
140         sInstance = this;
141     }
142 
getCardEmulationManager()143     public CardEmulationManager getCardEmulationManager() {
144         if (mCardEmulationManager == null) {
145             mCardEmulationManager = new CardEmulationManager(mContext, sInstance, mDeviceConfigFacade);
146         }
147         return mCardEmulationManager;
148     }
149 
getNfcCharging(DeviceHost deviceHost)150     public NfcCharging getNfcCharging(DeviceHost deviceHost) {
151         return new NfcCharging(mContext, deviceHost);
152     }
153 
getContext()154     public Context getContext() {
155         return mContext;
156     }
157 
getMainLooper()158     public Looper getMainLooper() {
159         return mMainLooper;
160     }
161 
getNfcEventLog()162     public NfcEventLog getNfcEventLog() {
163         return mNfcEventLog;
164     }
165 
getScreenStateHelper()166     public ScreenStateHelper getScreenStateHelper() {
167         return mScreenStateHelper;
168     }
169 
getRoutingTableParser()170     public RoutingTableParser getRoutingTableParser() {
171         return mRoutingTableParser;
172     }
173 
getNfcUnlockManager()174     public NfcUnlockManager getNfcUnlockManager() {
175         return mNfcUnlockManager;
176     }
177 
getHandoverDataParser()178     public HandoverDataParser getHandoverDataParser() {
179         return mHandoverDataParser;
180     }
181 
getDeviceConfigFacade()182     public DeviceConfigFacade getDeviceConfigFacade() {
183         return mDeviceConfigFacade;
184     }
185 
getNfcDispatcher()186     public NfcDispatcher getNfcDispatcher() {
187         return mNfcDispatcher;
188     }
189 
getVibrationEffect()190     public VibrationEffect getVibrationEffect() {
191         return mVibrationEffect;
192     }
193 
getBackupManager()194     public BackupManager getBackupManager() {
195         return mBackupManager;
196     }
197 
getFeatureFlags()198     public FeatureFlags getFeatureFlags() {
199         return mFeatureFlags;
200     }
201 
202     @Nullable
getStatsdUtils()203     public StatsdUtils getStatsdUtils() {
204         return mStatsdUtils;
205     }
206 
207     @Nullable
getStatsdUtilsContext()208     public StatsdUtilsContext getStatsdUtilsContext() {
209         return mStatsdUtilsContext;
210     }
211 
getForegroundUtils()212     public ForegroundUtils getForegroundUtils() {
213         return mForegroundUtils;
214     }
215 
getNfcDiagnostics()216     public NfcDiagnostics getNfcDiagnostics() {
217         return mNfcDiagnostics;
218     }
219 
getNfcManagerRegisterer()220     public NfcServiceManager.ServiceRegisterer getNfcManagerRegisterer() {
221         return mNfcManagerRegisterer;
222     }
223 
getNfcWatchdog()224     public NfcWatchdog getNfcWatchdog() {
225         return mNfcWatchdog;
226     }
227 
makeDeviceHost(DeviceHost.DeviceHostListener listener)228     public DeviceHost makeDeviceHost(DeviceHost.DeviceHostListener listener) {
229         return new NativeNfcManager(mContext, listener);
230     }
231 
232     /**
233      * NFC apex DE folder.
234      */
getDeviceProtectedDataDir()235     public static File getDeviceProtectedDataDir() {
236         return ApexEnvironment.getApexEnvironment(APEX_NAME)
237                 .getDeviceProtectedDataDir();
238     }
239 
getLocalDateTime()240     public LocalDateTime getLocalDateTime() {
241         return LocalDateTime.now();
242     }
243 
getNfcPackageName()244     public String getNfcPackageName() {
245         return mContext.getPackageName();
246     }
247 
isInProvisionMode()248     public boolean isInProvisionMode() {
249         boolean isNfcProvisioningEnabled = false;
250         try {
251             isNfcProvisioningEnabled = mContext.getResources().getBoolean(
252                     R.bool.enable_nfc_provisioning);
253         } catch (Resources.NotFoundException e) {
254         }
255 
256         if (isNfcProvisioningEnabled) {
257             return Settings.Global.getInt(mContext.getContentResolver(),
258                     Settings.Global.DEVICE_PROVISIONED, 0) == 0;
259         } else {
260             return false;
261         }
262     }
263 
connectToSeService()264     public ISecureElementService connectToSeService() throws RemoteException {
265         SeServiceManager manager = SeFrameworkInitializer.getSeServiceManager();
266         if (manager == null) {
267             Log.e(TAG, "SEServiceManager is null");
268             return null;
269         }
270         return ISecureElementService.Stub.asInterface(
271                 manager.getSeManagerServiceRegisterer().get());
272     }
273 
274     /**
275      * Kill the NFC stack.
276      */
killNfcStack()277     public void killNfcStack() {
278         System.exit(0);
279     }
280 
isSatelliteModeSensitive()281     public boolean isSatelliteModeSensitive() {
282         final String satelliteRadios =
283                 Settings.Global.getString(mContext.getContentResolver(),
284                         Constants.SETTINGS_SATELLITE_MODE_RADIOS);
285         return satelliteRadios == null || satelliteRadios.contains(Settings.Global.RADIO_NFC);
286     }
287 
288     /** Returns true if satellite mode is turned on. */
isSatelliteModeOn()289     public boolean isSatelliteModeOn() {
290         if (!isSatelliteModeSensitive()) return false;
291         return Settings.Global.getInt(
292                 mContext.getContentResolver(), Constants.SETTINGS_SATELLITE_MODE_ENABLED, 0) == 1;
293     }
294 
isPrivileged(int callingUid)295     public static boolean isPrivileged(int callingUid) {
296         // Check for root uid to help invoking privileged APIs from rooted shell only.
297         return callingUid == Process.SYSTEM_UID || callingUid == Process.NFC_UID
298                 || callingUid == Process.ROOT_UID;
299     }
300 
301     /**
302      * Get the current time of the clock in milliseconds.
303      *
304      * @return Current time in milliseconds.
305      */
getWallClockMillis()306     public long getWallClockMillis() {
307         return System.currentTimeMillis();
308     }
309 
310     /**
311      * Returns milliseconds since boot, including time spent in sleep.
312      *
313      * @return Current time since boot in milliseconds.
314      */
getElapsedSinceBootMillis()315     public long getElapsedSinceBootMillis() {
316         return SystemClock.elapsedRealtime();
317     }
318 
319     /**
320      * Returns nanoseconds since boot, including time spent in sleep.
321      *
322      * @return Current time since boot in milliseconds.
323      */
getElapsedSinceBootNanos()324     public long getElapsedSinceBootNanos() {
325         return SystemClock.elapsedRealtimeNanos();
326     }
327 
328     /**
329      * Ensure that the watchdog is monitoring the NFC process.
330      */
ensureWatchdogMonitoring()331     public void ensureWatchdogMonitoring() {
332         mNfcWatchdog.ensureWatchdogMonitoring();
333     }
334 
createAtomicBoolean()335     public AtomicBoolean createAtomicBoolean() {
336         return new AtomicBoolean();
337     }
338 
339     /**
340      * Temporary location to store nfc properties being added in Android 16 for OEM convergence.
341      * Will move all of these together to libsysprop later to avoid multiple rounds of API reviews.
342      */
343     public static final class NfcProperties {
344         private static final String NFC_EUICC_SUPPORTED_PROP_KEY = "ro.nfc.euicc_supported";
345 
isEuiccSupported()346         public static boolean isEuiccSupported() {
347             return SystemProperties.getBoolean(NFC_EUICC_SUPPORTED_PROP_KEY, true);
348         }
349 
350     }
351 
352     /**
353      * Returns whether the device unlocked or not.
354      */
isDeviceLocked()355     public boolean isDeviceLocked() {
356         return (isInProvisionMode()
357             || (android.app.Flags.deviceUnlockListener() && Flags.useDeviceLockListener()))
358                             ? mKeyguardManager.isDeviceLocked()
359                             : mKeyguardManager.isKeyguardLocked();
360     }
361 
362     /**
363      * Returns whether boot completed or not (used to detect if NFC stack crashed and came back up).
364      * @return
365      */
isBootCompleted()366     public boolean isBootCompleted() {
367         return "1".equals(SystemProperties.get("sys.boot_completed"));
368     }
369 
370     /**
371      * Returns whether the uid is signed with the same key as the platform.
372      */
isSignedWithPlatformKey(int uid)373     public boolean isSignedWithPlatformKey(int uid) {
374         return mContext.getPackageManager().checkSignatures(uid, Process.SYSTEM_UID)
375                 == PackageManager.SIGNATURE_MATCH;
376     }
377 }
378