1 /* 2 * Copyright (C) 2014 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; 18 19 import android.content.Context; 20 import android.location.GnssNavigationMessage; 21 import android.location.IGnssNavigationMessageListener; 22 import android.os.Handler; 23 import android.os.RemoteException; 24 import android.util.Log; 25 26 import com.android.internal.annotations.VisibleForTesting; 27 28 /** 29 * An base implementation for GPS navigation messages provider. 30 * It abstracts out the responsibility of handling listeners, while still allowing technology 31 * specific implementations to be built. 32 * 33 * @hide 34 */ 35 public abstract class GnssNavigationMessageProvider 36 extends RemoteListenerHelper<IGnssNavigationMessageListener> { 37 private static final String TAG = "GnssNavigationMessageProvider"; 38 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 39 40 private final GnssNavigationMessageProviderNative mNative; 41 private boolean mCollectionStarted; 42 GnssNavigationMessageProvider(Context context, Handler handler)43 protected GnssNavigationMessageProvider(Context context, Handler handler) { 44 this(context, handler, new GnssNavigationMessageProviderNative()); 45 } 46 47 @VisibleForTesting GnssNavigationMessageProvider(Context context, Handler handler, GnssNavigationMessageProviderNative aNative)48 GnssNavigationMessageProvider(Context context, Handler handler, 49 GnssNavigationMessageProviderNative aNative) { 50 super(context, handler, TAG); 51 mNative = aNative; 52 } 53 resumeIfStarted()54 void resumeIfStarted() { 55 if (DEBUG) { 56 Log.d(TAG, "resumeIfStarted"); 57 } 58 if (mCollectionStarted) { 59 mNative.startNavigationMessageCollection(); 60 } 61 } 62 63 @Override isAvailableInPlatform()64 protected boolean isAvailableInPlatform() { 65 return mNative.isNavigationMessageSupported(); 66 } 67 68 @Override registerWithService()69 protected int registerWithService() { 70 boolean result = mNative.startNavigationMessageCollection(); 71 if (result) { 72 mCollectionStarted = true; 73 return RemoteListenerHelper.RESULT_SUCCESS; 74 } else { 75 return RemoteListenerHelper.RESULT_INTERNAL_ERROR; 76 } 77 } 78 79 @Override unregisterFromService()80 protected void unregisterFromService() { 81 boolean stopped = mNative.stopNavigationMessageCollection(); 82 if (stopped) { 83 mCollectionStarted = false; 84 } 85 } 86 onNavigationMessageAvailable(final GnssNavigationMessage event)87 public void onNavigationMessageAvailable(final GnssNavigationMessage event) { 88 foreach((IGnssNavigationMessageListener listener, CallerIdentity callerIdentity) -> { 89 listener.onGnssNavigationMessageReceived(event); 90 } 91 ); 92 } 93 94 /** Handle GNSS capabilities update from the GNSS HAL implementation */ onCapabilitiesUpdated(boolean isGnssNavigationMessageSupported)95 public void onCapabilitiesUpdated(boolean isGnssNavigationMessageSupported) { 96 setSupported(isGnssNavigationMessageSupported); 97 updateResult(); 98 } 99 onGpsEnabledChanged()100 public void onGpsEnabledChanged() { 101 tryUpdateRegistrationWithService(); 102 updateResult(); 103 } 104 105 @Override getHandlerOperation(int result)106 protected ListenerOperation<IGnssNavigationMessageListener> getHandlerOperation(int result) { 107 int status; 108 switch (result) { 109 case RESULT_SUCCESS: 110 status = GnssNavigationMessage.Callback.STATUS_READY; 111 break; 112 case RESULT_NOT_AVAILABLE: 113 case RESULT_NOT_SUPPORTED: 114 case RESULT_INTERNAL_ERROR: 115 status = GnssNavigationMessage.Callback.STATUS_NOT_SUPPORTED; 116 break; 117 case RESULT_GPS_LOCATION_DISABLED: 118 status = GnssNavigationMessage.Callback.STATUS_LOCATION_DISABLED; 119 break; 120 case RESULT_UNKNOWN: 121 return null; 122 default: 123 Log.v(TAG, "Unhandled addListener result: " + result); 124 return null; 125 } 126 return new StatusChangedOperation(status); 127 } 128 129 private static class StatusChangedOperation 130 implements ListenerOperation<IGnssNavigationMessageListener> { 131 private final int mStatus; 132 StatusChangedOperation(int status)133 public StatusChangedOperation(int status) { 134 mStatus = status; 135 } 136 137 @Override execute(IGnssNavigationMessageListener listener, CallerIdentity callerIdentity)138 public void execute(IGnssNavigationMessageListener listener, 139 CallerIdentity callerIdentity) throws RemoteException { 140 listener.onStatusChanged(mStatus); 141 } 142 } 143 144 @VisibleForTesting 145 static class GnssNavigationMessageProviderNative { isNavigationMessageSupported()146 public boolean isNavigationMessageSupported() { 147 return native_is_navigation_message_supported(); 148 } 149 startNavigationMessageCollection()150 public boolean startNavigationMessageCollection() { 151 return native_start_navigation_message_collection(); 152 } 153 stopNavigationMessageCollection()154 public boolean stopNavigationMessageCollection() { 155 return native_stop_navigation_message_collection(); 156 } 157 } 158 native_is_navigation_message_supported()159 private static native boolean native_is_navigation_message_supported(); 160 native_start_navigation_message_collection()161 private static native boolean native_start_navigation_message_collection(); 162 native_stop_navigation_message_collection()163 private static native boolean native_stop_navigation_message_collection(); 164 } 165