Home | History | Annotate | Download | only in location
      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.GnssMeasurementsEvent;
     21 import android.location.IGnssMeasurementsListener;
     22 import android.os.Handler;
     23 import android.os.RemoteException;
     24 import android.provider.Settings;
     25 import android.util.Log;
     26 
     27 import com.android.internal.annotations.VisibleForTesting;
     28 
     29 /**
     30  * An base implementation for GPS measurements provider.
     31  * It abstracts out the responsibility of handling listeners, while still allowing technology
     32  * specific implementations to be built.
     33  *
     34  * @hide
     35  */
     36 public abstract class GnssMeasurementsProvider extends
     37         RemoteListenerHelper<IGnssMeasurementsListener> {
     38     private static final String TAG = "GnssMeasurementsProvider";
     39     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     40 
     41     private final Context mContext;
     42     private final GnssMeasurementProviderNative mNative;
     43 
     44     private boolean mIsCollectionStarted;
     45     private boolean mEnableFullTracking;
     46 
     47     protected GnssMeasurementsProvider(Context context, Handler handler) {
     48         this(context, handler, new GnssMeasurementProviderNative());
     49     }
     50 
     51     @VisibleForTesting
     52     GnssMeasurementsProvider(Context context, Handler handler,
     53             GnssMeasurementProviderNative aNative) {
     54         super(handler, TAG);
     55         mContext = context;
     56         mNative = aNative;
     57     }
     58 
     59     // TODO(b/37460011): Use this with death recovery logic.
     60     void resumeIfStarted() {
     61         if (DEBUG) {
     62             Log.d(TAG, "resumeIfStarted");
     63         }
     64         if (mIsCollectionStarted) {
     65             mNative.startMeasurementCollection(mEnableFullTracking);
     66         }
     67     }
     68 
     69     @Override
     70     public boolean isAvailableInPlatform() {
     71         return mNative.isMeasurementSupported();
     72     }
     73 
     74     @Override
     75     protected int registerWithService() {
     76         int devOptions = Settings.Secure.getInt(mContext.getContentResolver(),
     77                 Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0);
     78         int fullTrackingToggled = Settings.Global.getInt(mContext.getContentResolver(),
     79                 Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING, 0);
     80         boolean enableFullTracking = (devOptions == 1 /* Developer Mode enabled */)
     81                 && (fullTrackingToggled == 1 /* Raw Measurements Full Tracking enabled */);
     82         boolean result = mNative.startMeasurementCollection(enableFullTracking);
     83         if (result) {
     84             mIsCollectionStarted = true;
     85             mEnableFullTracking = enableFullTracking;
     86             return RemoteListenerHelper.RESULT_SUCCESS;
     87         } else {
     88             return RemoteListenerHelper.RESULT_INTERNAL_ERROR;
     89         }
     90     }
     91 
     92     @Override
     93     protected void unregisterFromService() {
     94         boolean stopped = mNative.stopMeasurementCollection();
     95         if (stopped) {
     96             mIsCollectionStarted = false;
     97         }
     98     }
     99 
    100     public void onMeasurementsAvailable(final GnssMeasurementsEvent event) {
    101         ListenerOperation<IGnssMeasurementsListener> operation =
    102                 listener -> listener.onGnssMeasurementsReceived(event);
    103         foreach(operation);
    104     }
    105 
    106     public void onCapabilitiesUpdated(boolean isGnssMeasurementsSupported) {
    107         setSupported(isGnssMeasurementsSupported);
    108         updateResult();
    109     }
    110 
    111     public void onGpsEnabledChanged() {
    112         tryUpdateRegistrationWithService();
    113         updateResult();
    114     }
    115 
    116     @Override
    117     protected ListenerOperation<IGnssMeasurementsListener> getHandlerOperation(int result) {
    118         int status;
    119         switch (result) {
    120             case RESULT_SUCCESS:
    121                 status = GnssMeasurementsEvent.Callback.STATUS_READY;
    122                 break;
    123             case RESULT_NOT_AVAILABLE:
    124             case RESULT_NOT_SUPPORTED:
    125             case RESULT_INTERNAL_ERROR:
    126                 status = GnssMeasurementsEvent.Callback.STATUS_NOT_SUPPORTED;
    127                 break;
    128             case RESULT_NOT_ALLOWED:
    129                 status = GnssMeasurementsEvent.Callback.STATUS_NOT_ALLOWED;
    130                 break;
    131             case RESULT_GPS_LOCATION_DISABLED:
    132                 status = GnssMeasurementsEvent.Callback.STATUS_LOCATION_DISABLED;
    133                 break;
    134             case RESULT_UNKNOWN:
    135                 return null;
    136             default:
    137                 Log.v(TAG, "Unhandled addListener result: " + result);
    138                 return null;
    139         }
    140         return new StatusChangedOperation(status);
    141     }
    142 
    143     private static class StatusChangedOperation
    144             implements ListenerOperation<IGnssMeasurementsListener> {
    145         private final int mStatus;
    146 
    147         public StatusChangedOperation(int status) {
    148             mStatus = status;
    149         }
    150 
    151         @Override
    152         public void execute(IGnssMeasurementsListener listener) throws RemoteException {
    153             listener.onStatusChanged(mStatus);
    154         }
    155     }
    156 
    157     @VisibleForTesting
    158     static class GnssMeasurementProviderNative {
    159         public boolean isMeasurementSupported() {
    160             return native_is_measurement_supported();
    161         }
    162 
    163         public boolean startMeasurementCollection(boolean enableFullTracking) {
    164             return native_start_measurement_collection(enableFullTracking);
    165         }
    166 
    167         public boolean stopMeasurementCollection() {
    168             return native_stop_measurement_collection();
    169         }
    170     }
    171 
    172     private static native boolean native_is_measurement_supported();
    173 
    174     private static native boolean native_start_measurement_collection(boolean enableFullTracking);
    175 
    176     private static native boolean native_stop_measurement_collection();
    177 }
    178