1 /* 2 * Copyright (C) 2023 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.internal.telephony.satellite; 18 19 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE; 20 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.app.ActivityManager; 24 import android.content.ActivityNotFoundException; 25 import android.content.ComponentName; 26 import android.content.Context; 27 import android.content.Intent; 28 import android.content.pm.PackageManager; 29 import android.os.AsyncResult; 30 import android.os.Build; 31 import android.os.Handler; 32 import android.os.IBinder; 33 import android.os.Looper; 34 import android.os.Message; 35 import android.os.RemoteException; 36 import android.os.SystemProperties; 37 import android.os.UserHandle; 38 import android.telephony.PersistentLogger; 39 import android.telephony.SubscriptionManager; 40 import android.telephony.satellite.ISatelliteTransmissionUpdateCallback; 41 import android.telephony.satellite.PointingInfo; 42 import android.telephony.satellite.SatelliteManager; 43 import android.text.TextUtils; 44 import android.util.Log; 45 46 import com.android.internal.R; 47 import com.android.internal.annotations.GuardedBy; 48 import com.android.internal.annotations.VisibleForTesting; 49 import com.android.internal.telephony.flags.FeatureFlags; 50 51 import java.util.ArrayList; 52 import java.util.Arrays; 53 import java.util.List; 54 import java.util.concurrent.ConcurrentHashMap; 55 import java.util.function.Consumer; 56 57 /** 58 * PointingApp controller to manage interactions with PointingUI app. 59 */ 60 public class PointingAppController { 61 private static final String TAG = "PointingAppController"; 62 private static final String ALLOW_MOCK_MODEM_PROPERTY = "persist.radio.allow_mock_modem"; 63 private static final boolean DEBUG = !"user".equals(Build.TYPE); 64 65 @NonNull 66 private static PointingAppController sInstance; 67 @NonNull private final Context mContext; 68 @NonNull private final FeatureFlags mFeatureFlags; 69 private boolean mStartedSatelliteTransmissionUpdates; 70 private boolean mLastNeedFullScreenPointingUI; 71 private boolean mLastIsDemoMode; 72 private boolean mLastIsEmergency; 73 74 private final Object mListenerForPointingUIRegisteredLock = new Object(); 75 @GuardedBy("mListenerForPointingUIRegisteredLock") 76 private boolean mListenerForPointingUIRegistered; 77 @NonNull private String mPointingUiPackageName = ""; 78 @NonNull private String mPointingUiClassName = ""; 79 @NonNull private ActivityManager mActivityManager; 80 @NonNull public UidImportanceListener mUidImportanceListener = new UidImportanceListener(); 81 /** 82 * Map key: subId, value: SatelliteTransmissionUpdateHandler to notify registrants. 83 */ 84 private final ConcurrentHashMap<Integer, SatelliteTransmissionUpdateHandler> 85 mSatelliteTransmissionUpdateHandlers = new ConcurrentHashMap<>(); 86 @Nullable private PersistentLogger mPersistentLogger = null; 87 88 /** 89 * @return The singleton instance of PointingAppController. 90 */ getInstance()91 public static PointingAppController getInstance() { 92 if (sInstance == null) { 93 loge("PointingAppController was not yet initialized."); 94 } 95 return sInstance; 96 } 97 98 /** 99 * Create the PointingAppController singleton instance. 100 * @param context The Context to use to create the PointingAppController. 101 * @param featureFlags The telephony feature flags. 102 * @return The singleton instance of PointingAppController. 103 */ make(@onNull Context context, @NonNull FeatureFlags featureFlags)104 public static PointingAppController make(@NonNull Context context, 105 @NonNull FeatureFlags featureFlags) { 106 if (sInstance == null) { 107 sInstance = new PointingAppController(context, featureFlags); 108 } 109 return sInstance; 110 } 111 112 /** 113 * Create a PointingAppController to manage interactions with PointingUI app. 114 * 115 * @param context The Context for the PointingUIController. 116 */ 117 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) PointingAppController(@onNull Context context, @NonNull FeatureFlags featureFlags)118 public PointingAppController(@NonNull Context context, 119 @NonNull FeatureFlags featureFlags) { 120 mContext = context; 121 mFeatureFlags = featureFlags; 122 mStartedSatelliteTransmissionUpdates = false; 123 mLastNeedFullScreenPointingUI = false; 124 mLastIsDemoMode = false; 125 mLastIsEmergency = false; 126 mListenerForPointingUIRegistered = false; 127 mActivityManager = mContext.getSystemService(ActivityManager.class); 128 mPersistentLogger = SatelliteServiceUtils.getPersistentLogger(context); 129 } 130 131 /** 132 * Set the flag mStartedSatelliteTransmissionUpdates to true or false based on the state of 133 * transmission updates 134 * @param startedSatelliteTransmissionUpdates boolean to set the flag 135 */ 136 @VisibleForTesting setStartedSatelliteTransmissionUpdates( boolean startedSatelliteTransmissionUpdates)137 public void setStartedSatelliteTransmissionUpdates( 138 boolean startedSatelliteTransmissionUpdates) { 139 mStartedSatelliteTransmissionUpdates = startedSatelliteTransmissionUpdates; 140 } 141 142 /** 143 * Get the flag mStartedSatelliteTransmissionUpdates 144 * @return returns mStartedSatelliteTransmissionUpdates 145 */ 146 @VisibleForTesting getStartedSatelliteTransmissionUpdates()147 public boolean getStartedSatelliteTransmissionUpdates() { 148 return mStartedSatelliteTransmissionUpdates; 149 } 150 151 /** 152 * Listener for handling pointing UI App in the event of crash 153 */ 154 @VisibleForTesting 155 public class UidImportanceListener implements ActivityManager.OnUidImportanceListener { 156 @Override onUidImportance(int uid, int importance)157 public void onUidImportance(int uid, int importance) { 158 if (importance != IMPORTANCE_GONE) return; 159 final PackageManager pm = mContext.getPackageManager(); 160 final String[] callerPackages = pm.getPackagesForUid(uid); 161 String pointingUiPackage = getPointingUiPackageName(); 162 163 if (callerPackages != null) { 164 if (Arrays.stream(callerPackages).anyMatch(pointingUiPackage::contains)) { 165 plogd("Restarting pointingUI"); 166 startPointingUI(mLastNeedFullScreenPointingUI, mLastIsDemoMode, 167 mLastIsEmergency); 168 } 169 } 170 } 171 } 172 173 private static final class DatagramTransferStateHandlerRequest { 174 public int datagramType; 175 public int datagramTransferState; 176 public int pendingCount; 177 public int errorCode; 178 DatagramTransferStateHandlerRequest(int datagramType, int datagramTransferState, int pendingCount, int errorCode)179 DatagramTransferStateHandlerRequest(int datagramType, int datagramTransferState, 180 int pendingCount, int errorCode) { 181 this.datagramType = datagramType; 182 this.datagramTransferState = datagramTransferState; 183 this.pendingCount = pendingCount; 184 this.errorCode = errorCode; 185 } 186 } 187 188 189 private static final class SatelliteTransmissionUpdateHandler extends Handler { 190 public static final int EVENT_POSITION_INFO_CHANGED = 1; 191 public static final int EVENT_SEND_DATAGRAM_STATE_CHANGED = 2; 192 public static final int EVENT_RECEIVE_DATAGRAM_STATE_CHANGED = 3; 193 public static final int EVENT_DATAGRAM_TRANSFER_STATE_CHANGED = 4; 194 public static final int EVENT_SEND_DATAGRAM_REQUESTED = 5; 195 196 private final ConcurrentHashMap<IBinder, ISatelliteTransmissionUpdateCallback> mListeners; 197 SatelliteTransmissionUpdateHandler(Looper looper)198 SatelliteTransmissionUpdateHandler(Looper looper) { 199 super(looper); 200 mListeners = new ConcurrentHashMap<>(); 201 } 202 addListener(ISatelliteTransmissionUpdateCallback listener)203 public void addListener(ISatelliteTransmissionUpdateCallback listener) { 204 mListeners.put(listener.asBinder(), listener); 205 } 206 removeListener(ISatelliteTransmissionUpdateCallback listener)207 public void removeListener(ISatelliteTransmissionUpdateCallback listener) { 208 mListeners.remove(listener.asBinder()); 209 } 210 hasListeners()211 public boolean hasListeners() { 212 return !mListeners.isEmpty(); 213 } 214 215 @Override handleMessage(@onNull Message msg)216 public void handleMessage(@NonNull Message msg) { 217 switch (msg.what) { 218 case EVENT_POSITION_INFO_CHANGED: { 219 AsyncResult ar = (AsyncResult) msg.obj; 220 PointingInfo pointingInfo = (PointingInfo) ar.result; 221 List<IBinder> toBeRemoved = new ArrayList<>(); 222 mListeners.values().forEach(listener -> { 223 try { 224 listener.onSatellitePositionChanged(pointingInfo); 225 } catch (RemoteException e) { 226 logd("EVENT_POSITION_INFO_CHANGED RemoteException: " + e); 227 toBeRemoved.add(listener.asBinder()); 228 } 229 }); 230 toBeRemoved.forEach(listener -> { 231 mListeners.remove(listener); 232 }); 233 break; 234 } 235 236 case EVENT_DATAGRAM_TRANSFER_STATE_CHANGED: { 237 AsyncResult ar = (AsyncResult) msg.obj; 238 logd("Receive EVENT_DATAGRAM_TRANSFER_STATE_CHANGED state=" + (int) ar.result); 239 break; 240 } 241 242 case EVENT_SEND_DATAGRAM_STATE_CHANGED: { 243 logd("Received EVENT_SEND_DATAGRAM_STATE_CHANGED"); 244 DatagramTransferStateHandlerRequest request = 245 (DatagramTransferStateHandlerRequest) msg.obj; 246 List<IBinder> toBeRemoved = new ArrayList<>(); 247 mListeners.values().forEach(listener -> { 248 try { 249 listener.onSendDatagramStateChanged(request.datagramType, 250 request.datagramTransferState, request.pendingCount, 251 request.errorCode); 252 } catch (RemoteException e) { 253 logd("EVENT_SEND_DATAGRAM_STATE_CHANGED RemoteException: " + e); 254 toBeRemoved.add(listener.asBinder()); 255 } 256 }); 257 toBeRemoved.forEach(listener -> { 258 mListeners.remove(listener); 259 }); 260 break; 261 } 262 263 case EVENT_RECEIVE_DATAGRAM_STATE_CHANGED: { 264 logd("Received EVENT_RECEIVE_DATAGRAM_STATE_CHANGED"); 265 DatagramTransferStateHandlerRequest request = 266 (DatagramTransferStateHandlerRequest) msg.obj; 267 List<IBinder> toBeRemoved = new ArrayList<>(); 268 mListeners.values().forEach(listener -> { 269 try { 270 listener.onReceiveDatagramStateChanged(request.datagramTransferState, 271 request.pendingCount, request.errorCode); 272 } catch (RemoteException e) { 273 logd("EVENT_RECEIVE_DATAGRAM_STATE_CHANGED RemoteException: " + e); 274 toBeRemoved.add(listener.asBinder()); 275 } 276 }); 277 toBeRemoved.forEach(listener -> { 278 mListeners.remove(listener); 279 }); 280 break; 281 } 282 283 case EVENT_SEND_DATAGRAM_REQUESTED: { 284 logd("Received EVENT_SEND_DATAGRAM_REQUESTED"); 285 int datagramType = (int) msg.obj; 286 List<IBinder> toBeRemoved = new ArrayList<>(); 287 mListeners.values().forEach(listener -> { 288 try { 289 listener.onSendDatagramRequested(datagramType); 290 } catch (RemoteException e) { 291 logd("EVENT_SEND_DATAGRAM_REQUESTED RemoteException: " + e); 292 toBeRemoved.add(listener.asBinder()); 293 } 294 }); 295 toBeRemoved.forEach(listener -> { 296 mListeners.remove(listener); 297 }); 298 break; 299 } 300 301 default: 302 loge("SatelliteTransmissionUpdateHandler unknown event: " + msg.what); 303 } 304 } 305 } 306 307 /** 308 * Register to start receiving updates for satellite position and datagram transfer state 309 * @param subId The subId of the subscription to register for receiving the updates. 310 * @param callback The callback to notify of satellite transmission updates. 311 */ registerForSatelliteTransmissionUpdates(int subId, ISatelliteTransmissionUpdateCallback callback)312 public void registerForSatelliteTransmissionUpdates(int subId, 313 ISatelliteTransmissionUpdateCallback callback) { 314 subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID; 315 SatelliteTransmissionUpdateHandler handler = 316 mSatelliteTransmissionUpdateHandlers.get(subId); 317 if (handler != null) { 318 handler.addListener(callback); 319 } else { 320 handler = new SatelliteTransmissionUpdateHandler(Looper.getMainLooper()); 321 handler.addListener(callback); 322 mSatelliteTransmissionUpdateHandlers.put(subId, handler); 323 SatelliteModemInterface.getInstance().registerForSatellitePositionInfoChanged( 324 handler, SatelliteTransmissionUpdateHandler.EVENT_POSITION_INFO_CHANGED, 325 null); 326 SatelliteModemInterface.getInstance().registerForDatagramTransferStateChanged( 327 handler, 328 SatelliteTransmissionUpdateHandler.EVENT_DATAGRAM_TRANSFER_STATE_CHANGED, 329 null); 330 } 331 } 332 333 /** 334 * Unregister to stop receiving updates on satellite position and datagram transfer state 335 * If the callback was not registered before, it is ignored 336 * @param subId The subId of the subscription to unregister for receiving the updates. 337 * @param result The callback to get the error code in case of failure 338 * @param callback The callback that was passed to {@link 339 * #registerForSatelliteTransmissionUpdates(int, ISatelliteTransmissionUpdateCallback)}. 340 */ unregisterForSatelliteTransmissionUpdates(int subId, Consumer<Integer> result, ISatelliteTransmissionUpdateCallback callback)341 public void unregisterForSatelliteTransmissionUpdates(int subId, Consumer<Integer> result, 342 ISatelliteTransmissionUpdateCallback callback) { 343 subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID; 344 SatelliteTransmissionUpdateHandler handler = 345 mSatelliteTransmissionUpdateHandlers.get(subId); 346 if (handler != null) { 347 handler.removeListener(callback); 348 if (handler.hasListeners()) { 349 result.accept(SatelliteManager.SATELLITE_RESULT_SUCCESS); 350 return; 351 } 352 mSatelliteTransmissionUpdateHandlers.remove(subId); 353 354 SatelliteModemInterface satelliteModemInterface = SatelliteModemInterface.getInstance(); 355 satelliteModemInterface.unregisterForSatellitePositionInfoChanged(handler); 356 satelliteModemInterface.unregisterForDatagramTransferStateChanged(handler); 357 } 358 } 359 360 /** 361 * Start receiving satellite trasmission updates. 362 * This can be called by the pointing UI when the user starts pointing to the satellite. 363 * Modem should continue to report the pointing input as the device or satellite moves. 364 * The transmission updates will be received via 365 * {@link android.telephony.satellite.SatelliteTransmissionUpdateCallback 366 * #onSatellitePositionChanged(pointingInfo)}. 367 */ startSatelliteTransmissionUpdates(@onNull Message message)368 public void startSatelliteTransmissionUpdates(@NonNull Message message) { 369 if (mStartedSatelliteTransmissionUpdates) { 370 plogd("startSatelliteTransmissionUpdates: already started"); 371 AsyncResult.forMessage(message, null, new SatelliteManager.SatelliteException( 372 SatelliteManager.SATELLITE_RESULT_SUCCESS)); 373 message.sendToTarget(); 374 return; 375 } 376 SatelliteModemInterface.getInstance().startSendingSatellitePointingInfo(message); 377 mStartedSatelliteTransmissionUpdates = true; 378 } 379 380 /** 381 * Stop receiving satellite transmission updates. 382 * Reset the flag mStartedSatelliteTransmissionUpdates 383 * This can be called by the pointing UI when the user stops pointing to the satellite. 384 */ stopSatelliteTransmissionUpdates(@onNull Message message)385 public void stopSatelliteTransmissionUpdates(@NonNull Message message) { 386 setStartedSatelliteTransmissionUpdates(false); 387 SatelliteModemInterface.getInstance().stopSendingSatellitePointingInfo(message); 388 } 389 390 /** 391 * Check if Pointing is needed and Launch Pointing UI 392 * @param needFullScreenPointingUI if pointing UI has to be launchd with Full screen 393 */ startPointingUI(boolean needFullScreenPointingUI, boolean isDemoMode, boolean isEmergency)394 public void startPointingUI(boolean needFullScreenPointingUI, boolean isDemoMode, 395 boolean isEmergency) { 396 String packageName = getPointingUiPackageName(); 397 if (TextUtils.isEmpty(packageName)) { 398 plogd("startPointingUI: config_pointing_ui_package is not set. Ignore the request"); 399 return; 400 } 401 402 Intent launchIntent; 403 String className = getPointingUiClassName(); 404 if (!TextUtils.isEmpty(className)) { 405 launchIntent = new Intent() 406 .setComponent(new ComponentName(packageName, className)) 407 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 408 } else { 409 launchIntent = mContext.getPackageManager().getLaunchIntentForPackage(packageName); 410 } 411 if (launchIntent == null) { 412 ploge("startPointingUI: launchIntent is null"); 413 return; 414 } 415 plogd("startPointingUI: needFullScreenPointingUI: " + needFullScreenPointingUI 416 + ", isDemoMode: " + isDemoMode + ", isEmergency: " + isEmergency); 417 launchIntent.putExtra("needFullScreen", needFullScreenPointingUI); 418 launchIntent.putExtra("isDemoMode", isDemoMode); 419 launchIntent.putExtra("isEmergency", isEmergency); 420 421 try { 422 synchronized (mListenerForPointingUIRegisteredLock) { 423 if (!mListenerForPointingUIRegistered) { 424 mActivityManager.addOnUidImportanceListener(mUidImportanceListener, 425 IMPORTANCE_GONE); 426 mListenerForPointingUIRegistered = true; 427 } 428 } 429 mLastNeedFullScreenPointingUI = needFullScreenPointingUI; 430 mLastIsDemoMode = isDemoMode; 431 mLastIsEmergency = isEmergency; 432 mContext.startActivityAsUser(launchIntent, UserHandle.CURRENT); 433 } catch (ActivityNotFoundException | IllegalArgumentException ex) { 434 ploge("startPointingUI: Unable to start Pointing UI activity due to an exception, ex=" 435 + ex); 436 } 437 } 438 439 /** 440 * Remove the Importance Listener For Pointing UI App once the satellite is disabled 441 */ removeListenerForPointingUI()442 public void removeListenerForPointingUI() { 443 synchronized (mListenerForPointingUIRegisteredLock) { 444 if (mListenerForPointingUIRegistered) { 445 mActivityManager.removeOnUidImportanceListener(mUidImportanceListener); 446 mListenerForPointingUIRegistered = false; 447 } 448 } 449 } 450 updateSendDatagramTransferState(int subId, @SatelliteManager.DatagramType int datagramType, @SatelliteManager.SatelliteDatagramTransferState int datagramTransferState, int sendPendingCount, int errorCode)451 public void updateSendDatagramTransferState(int subId, 452 @SatelliteManager.DatagramType int datagramType, 453 @SatelliteManager.SatelliteDatagramTransferState int datagramTransferState, 454 int sendPendingCount, int errorCode) { 455 DatagramTransferStateHandlerRequest request = new DatagramTransferStateHandlerRequest( 456 datagramType, datagramTransferState, sendPendingCount, errorCode); 457 subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID; 458 SatelliteTransmissionUpdateHandler handler = 459 mSatelliteTransmissionUpdateHandlers.get(subId); 460 461 if (handler != null) { 462 Message msg = handler.obtainMessage( 463 SatelliteTransmissionUpdateHandler.EVENT_SEND_DATAGRAM_STATE_CHANGED, 464 request); 465 msg.sendToTarget(); 466 } else { 467 ploge("SatelliteTransmissionUpdateHandler not found for subId: " + subId); 468 } 469 } 470 471 /** 472 * This API is used to notify PointingAppController that a send datagram has just been 473 * requested. 474 */ onSendDatagramRequested( int subId, @SatelliteManager.DatagramType int datagramType)475 public void onSendDatagramRequested( 476 int subId, @SatelliteManager.DatagramType int datagramType) { 477 subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID; 478 SatelliteTransmissionUpdateHandler handler = 479 mSatelliteTransmissionUpdateHandlers.get(subId); 480 if (handler != null) { 481 Message msg = handler.obtainMessage( 482 SatelliteTransmissionUpdateHandler.EVENT_SEND_DATAGRAM_REQUESTED, 483 datagramType); 484 msg.sendToTarget(); 485 } else { 486 ploge("SatelliteTransmissionUpdateHandler not found for subId: " + subId); 487 } 488 } 489 updateReceiveDatagramTransferState(int subId, @SatelliteManager.SatelliteDatagramTransferState int datagramTransferState, int receivePendingCount, int errorCode)490 public void updateReceiveDatagramTransferState(int subId, 491 @SatelliteManager.SatelliteDatagramTransferState int datagramTransferState, 492 int receivePendingCount, int errorCode) { 493 DatagramTransferStateHandlerRequest request = new DatagramTransferStateHandlerRequest( 494 SatelliteManager.DATAGRAM_TYPE_UNKNOWN, datagramTransferState, receivePendingCount, 495 errorCode); 496 subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID; 497 SatelliteTransmissionUpdateHandler handler = 498 mSatelliteTransmissionUpdateHandlers.get(subId); 499 500 if (handler != null) { 501 Message msg = handler.obtainMessage( 502 SatelliteTransmissionUpdateHandler.EVENT_RECEIVE_DATAGRAM_STATE_CHANGED, 503 request); 504 msg.sendToTarget(); 505 } else { 506 ploge(" SatelliteTransmissionUpdateHandler not found for subId: " + subId); 507 } 508 } 509 510 /** 511 * This API can be used by only CTS to update satellite pointing UI app package and class names. 512 * 513 * @param packageName The package name of the satellite pointing UI app. 514 * @param className The class name of the satellite pointing UI app. 515 * @return {@code true} if the satellite pointing UI app package and class is set successfully, 516 * {@code false} otherwise. 517 */ setSatellitePointingUiClassName( @ullable String packageName, @Nullable String className)518 boolean setSatellitePointingUiClassName( 519 @Nullable String packageName, @Nullable String className) { 520 if (!isMockModemAllowed()) { 521 ploge("setSatellitePointingUiClassName: modifying satellite pointing UI package and " 522 + "class name is not allowed"); 523 return false; 524 } 525 526 plogd("setSatellitePointingUiClassName: config_pointing_ui_package is updated, new " 527 + "packageName=" + packageName 528 + ", config_pointing_ui_class new className=" + className); 529 530 if (packageName == null || packageName.equals("null")) { 531 mPointingUiPackageName = ""; 532 mPointingUiClassName = ""; 533 } else { 534 mPointingUiPackageName = packageName; 535 if (className == null || className.equals("null")) { 536 mPointingUiClassName = ""; 537 } else { 538 mPointingUiClassName = className; 539 } 540 } 541 542 return true; 543 } 544 getPointingUiPackageName()545 @NonNull private String getPointingUiPackageName() { 546 if (!TextUtils.isEmpty(mPointingUiPackageName)) { 547 return mPointingUiPackageName; 548 } 549 return TextUtils.emptyIfNull(mContext.getResources().getString( 550 R.string.config_pointing_ui_package)); 551 } 552 getPointingUiClassName()553 @NonNull private String getPointingUiClassName() { 554 if (!TextUtils.isEmpty(mPointingUiClassName)) { 555 return mPointingUiClassName; 556 } 557 return TextUtils.emptyIfNull(mContext.getResources().getString( 558 R.string.config_pointing_ui_class)); 559 } 560 isMockModemAllowed()561 private boolean isMockModemAllowed() { 562 return (DEBUG || SystemProperties.getBoolean(ALLOW_MOCK_MODEM_PROPERTY, false)); 563 } 564 logd(@onNull String log)565 private static void logd(@NonNull String log) { 566 Log.d(TAG, log); 567 } 568 loge(@onNull String log)569 private static void loge(@NonNull String log) { 570 Log.e(TAG, log); 571 } 572 plogd(@onNull String log)573 private void plogd(@NonNull String log) { 574 Log.d(TAG, log); 575 if (mPersistentLogger != null) { 576 mPersistentLogger.debug(TAG, log); 577 } 578 } 579 ploge(@onNull String log)580 private void ploge(@NonNull String log) { 581 Log.e(TAG, log); 582 if (mPersistentLogger != null) { 583 mPersistentLogger.error(TAG, log); 584 } 585 } 586 /** 587 * TODO: The following needs to be added in this class: 588 * - check if pointingUI crashes - then restart it 589 */ 590 } 591