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