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