• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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