1 /*
2  * Copyright (C) 2020 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.server.location.gnss;
18 
19 import android.content.Context;
20 import android.location.GnssAntennaInfo;
21 import android.location.IGnssAntennaInfoListener;
22 import android.os.Handler;
23 import android.util.Log;
24 
25 import com.android.internal.annotations.VisibleForTesting;
26 import com.android.server.location.CallerIdentity;
27 import com.android.server.location.RemoteListenerHelper;
28 
29 import java.util.List;
30 
31 /**
32  * An base implementation for GNSS antenna info provider. It abstracts out the responsibility of
33  * handling listeners, while still allowing technology specific implementations to be built.
34  *
35  * @hide
36  */
37 public abstract class GnssAntennaInfoProvider
38         extends RemoteListenerHelper<Void, IGnssAntennaInfoListener> {
39     private static final String TAG = "GnssAntennaInfoProvider";
40     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
41 
42     private final GnssAntennaInfoProviderNative mNative;
43 
44     private boolean mIsListeningStarted;
45 
GnssAntennaInfoProvider(Context context, Handler handler)46     protected GnssAntennaInfoProvider(Context context, Handler handler) {
47         this(context, handler, new GnssAntennaInfoProviderNative());
48     }
49 
50     @VisibleForTesting
GnssAntennaInfoProvider( Context context, Handler handler, GnssAntennaInfoProviderNative aNative)51     public GnssAntennaInfoProvider(
52             Context context, Handler handler, GnssAntennaInfoProviderNative aNative) {
53         super(context, handler, TAG);
54         mNative = aNative;
55     }
56 
resumeIfStarted()57     void resumeIfStarted() {
58         if (DEBUG) {
59             Log.d(TAG, "resumeIfStarted");
60         }
61         if (mIsListeningStarted) {
62             mNative.startAntennaInfoListening();
63         }
64     }
65 
66 
67     @Override
isAvailableInPlatform()68     public boolean isAvailableInPlatform() {
69         return mNative.isAntennaInfoSupported();
70     }
71 
72     @Override
registerWithService()73     protected int registerWithService() {
74         boolean started = mNative.startAntennaInfoListening();
75         if (started) {
76             mIsListeningStarted = true;
77             return RemoteListenerHelper.RESULT_SUCCESS;
78         }
79         return RemoteListenerHelper.RESULT_INTERNAL_ERROR;
80     }
81 
82     @Override
unregisterFromService()83     protected void unregisterFromService() {
84         boolean stopped = mNative.stopAntennaInfoListening();
85         if (stopped) {
86             mIsListeningStarted = false;
87         }
88     }
89 
90     /** Handle GNSS capabilities update from the GNSS HAL implementation. */
onCapabilitiesUpdated(boolean isAntennaInfoSupported)91     public void onCapabilitiesUpdated(boolean isAntennaInfoSupported) {
92         setSupported(isAntennaInfoSupported);
93         updateResult();
94     }
95 
96     /** Handle GNSS enabled changes.*/
onGpsEnabledChanged()97     public void onGpsEnabledChanged() {
98         tryUpdateRegistrationWithService();
99         updateResult();
100     }
101 
102     @Override
getHandlerOperation(int result)103     protected ListenerOperation<IGnssAntennaInfoListener> getHandlerOperation(int result) {
104         return (IGnssAntennaInfoListener listener,
105                 CallerIdentity callerIdentity) -> {
106                 // Do nothing, as GnssAntennaInfo.Callback does not have an onStatusChanged method.
107         };
108     }
109 
110     /** Handle Gnss Antenna Info report. */
onGnssAntennaInfoAvailable(final List<GnssAntennaInfo> gnssAntennaInfos)111     public void onGnssAntennaInfoAvailable(final List<GnssAntennaInfo> gnssAntennaInfos) {
112         foreach((IGnssAntennaInfoListener listener, CallerIdentity callerIdentity) -> {
113             if (!hasPermission(mContext, callerIdentity)) {
114                 logPermissionDisabledEventNotReported(
115                         TAG, callerIdentity.packageName, "GNSS antenna info");
116                 return;
117             }
118             listener.onGnssAntennaInfoReceived(gnssAntennaInfos);
119         });
120     }
121 
122     /**
123      * Wrapper class for native methods. This is mocked for testing.
124      */
125     @VisibleForTesting
126     public static class GnssAntennaInfoProviderNative {
127 
isAntennaInfoSupported()128         public boolean isAntennaInfoSupported() {
129             return native_is_antenna_info_supported();
130         }
131 
132         /** Start antenna info listening. */
startAntennaInfoListening()133         public boolean startAntennaInfoListening() {
134             return native_start_antenna_info_listening();
135         }
136 
137         /** Stop antenna info listening. */
stopAntennaInfoListening()138         public boolean stopAntennaInfoListening() {
139             return native_stop_antenna_info_listening();
140         }
141     }
142 
native_is_antenna_info_supported()143     private static native boolean native_is_antenna_info_supported();
144 
native_start_antenna_info_listening()145     private static native boolean native_start_antenna_info_listening();
146 
native_stop_antenna_info_listening()147     private static native boolean native_stop_antenna_info_listening();
148 }
149