Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4257db35 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Refactor GnssBatchingProvider" into pi-dev

parents fd5166dd 3557cc71
Loading
Loading
Loading
Loading
+3 −2
Original line number Original line Diff line number Diff line
@@ -86,6 +86,7 @@ import com.android.server.location.ActivityRecognitionProxy;
import com.android.server.location.GeocoderProxy;
import com.android.server.location.GeocoderProxy;
import com.android.server.location.GeofenceManager;
import com.android.server.location.GeofenceManager;
import com.android.server.location.GeofenceProxy;
import com.android.server.location.GeofenceProxy;
import com.android.server.location.GnssBatchingProvider;
import com.android.server.location.GnssLocationProvider;
import com.android.server.location.GnssLocationProvider;
import com.android.server.location.GnssMeasurementsProvider;
import com.android.server.location.GnssMeasurementsProvider;
import com.android.server.location.GnssNavigationMessageProvider;
import com.android.server.location.GnssNavigationMessageProvider;
@@ -244,7 +245,7 @@ public class LocationManagerService extends ILocationManager.Stub {


    private GnssLocationProvider.GnssMetricsProvider mGnssMetricsProvider;
    private GnssLocationProvider.GnssMetricsProvider mGnssMetricsProvider;


    private GnssLocationProvider.GnssBatchingProvider mGnssBatchingProvider;
    private GnssBatchingProvider mGnssBatchingProvider;
    private IBatchedLocationCallback mGnssBatchingCallback;
    private IBatchedLocationCallback mGnssBatchingCallback;
    private LinkedCallback mGnssBatchingDeathCallback;
    private LinkedCallback mGnssBatchingDeathCallback;
    private boolean mGnssBatchingInProgress = false;
    private boolean mGnssBatchingInProgress = false;
@@ -1176,7 +1177,7 @@ public class LocationManagerService extends ILocationManager.Stub {
                "Location Hardware permission not granted to access hardware batching");
                "Location Hardware permission not granted to access hardware batching");


        if (hasGnssPermissions(packageName) && mGnssBatchingProvider != null) {
        if (hasGnssPermissions(packageName) && mGnssBatchingProvider != null) {
            return mGnssBatchingProvider.getSize();
            return mGnssBatchingProvider.getBatchSize();
        } else {
        } else {
            return 0;
            return 0;
        }
        }
+145 −0
Original line number Original line Diff line number Diff line
package com.android.server.location;

import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;

/**
 * Manages GNSS Batching operations.
 *
 * <p>This class is not thread safe (It's client's responsibility to make sure calls happen on
 * the same thread).
 */
public class GnssBatchingProvider {

    private static final String TAG = "GnssBatchingProvider";
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);

    private final GnssBatchingProviderNative mNative;
    private boolean mEnabled;
    private boolean mStarted;
    private long mPeriodNanos;
    private boolean mWakeOnFifoFull;

    GnssBatchingProvider() {
        this(new GnssBatchingProviderNative());
    }

    @VisibleForTesting
    GnssBatchingProvider(GnssBatchingProviderNative gnssBatchingProviderNative) {
        mNative = gnssBatchingProviderNative;
    }

    /**
     * Returns the GNSS batching size
     */
    public int getBatchSize() {
        return mNative.getBatchSize();
    }

    /** Enable GNSS batching. */
    public void enable() {
        mEnabled = mNative.initBatching();
        if (!mEnabled) {
            Log.e(TAG, "Failed to initialize GNSS batching");
        }
    }

    /**
     * Starts the hardware batching operation
     */
    public boolean start(long periodNanos, boolean wakeOnFifoFull) {
        if (!mEnabled) {
            throw new IllegalStateException();
        }
        if (periodNanos <= 0) {
            Log.e(TAG, "Invalid periodNanos " + periodNanos +
                    " in batching request, not started");
            return false;
        }
        mStarted = mNative.startBatch(periodNanos, wakeOnFifoFull);
        if (mStarted) {
            mPeriodNanos = periodNanos;
            mWakeOnFifoFull = wakeOnFifoFull;
        }
        return mStarted;
    }

    /**
     * Forces a flush of existing locations from the hardware batching
     */
    public void flush() {
        if (!mStarted) {
            Log.w(TAG, "Cannot flush since GNSS batching has not started.");
            return;
        }
        mNative.flushBatch();
    }

    /**
     * Stops the batching operation
     */
    public boolean stop() {
        boolean stopped = mNative.stopBatch();
        if (stopped) {
            mStarted = false;
        }
        return stopped;
    }

    /** Disable GNSS batching. */
    public void disable() {
        stop();
        mNative.cleanupBatching();
        mEnabled = false;
    }

    // TODO(b/37460011): Use this with death recovery logic.
    void resumeIfStarted() {
        if (DEBUG) {
            Log.d(TAG, "resumeIfStarted");
        }
        if (mStarted) {
            mNative.startBatch(mPeriodNanos, mWakeOnFifoFull);
        }
    }

    @VisibleForTesting
    static class GnssBatchingProviderNative {
        public int getBatchSize() {
            return native_get_batch_size();
        }

        public boolean startBatch(long periodNanos, boolean wakeOnFifoFull) {
            return native_start_batch(periodNanos, wakeOnFifoFull);
        }

        public void flushBatch() {
            native_flush_batch();
        }

        public boolean stopBatch() {
            return native_stop_batch();
        }

        public boolean initBatching() {
            return native_init_batching();
        }

        public void cleanupBatching() {
            native_cleanup_batching();
        }
    }

    private static native int native_get_batch_size();

    private static native boolean native_start_batch(long periodNanos, boolean wakeOnFifoFull);

    private static native void native_flush_batch();

    private static native boolean native_stop_batch();

    private static native boolean native_init_batching();

    private static native void native_cleanup_batching();
}
+5 −81
Original line number Original line Diff line number Diff line
@@ -418,6 +418,7 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
    private final LocationChangeListener mNetworkLocationListener = new NetworkLocationListener();
    private final LocationChangeListener mNetworkLocationListener = new NetworkLocationListener();
    private final LocationChangeListener mFusedLocationListener = new FusedLocationListener();
    private final LocationChangeListener mFusedLocationListener = new FusedLocationListener();
    private final NtpTimeHelper mNtpTimeHelper;
    private final NtpTimeHelper mNtpTimeHelper;
    private final GnssBatchingProvider mGnssBatchingProvider;


    // Handler for processing events
    // Handler for processing events
    private Handler mHandler;
    private Handler mHandler;
@@ -885,6 +886,7 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
        mGnssSatelliteBlacklistHelper = new GnssSatelliteBlacklistHelper(mContext,
        mGnssSatelliteBlacklistHelper = new GnssSatelliteBlacklistHelper(mContext,
                looper, this);
                looper, this);
        mHandler.post(mGnssSatelliteBlacklistHelper::updateSatelliteBlacklist);
        mHandler.post(mGnssSatelliteBlacklistHelper::updateSatelliteBlacklist);
        mGnssBatchingProvider = new GnssBatchingProvider();
    }
    }


    /**
    /**
@@ -1267,7 +1269,7 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt


            mGnssMeasurementsProvider.onGpsEnabledChanged();
            mGnssMeasurementsProvider.onGpsEnabledChanged();
            mGnssNavigationMessageProvider.onGpsEnabledChanged();
            mGnssNavigationMessageProvider.onGpsEnabledChanged();
            enableBatching();
            mGnssBatchingProvider.enable();
        } else {
        } else {
            synchronized (mLock) {
            synchronized (mLock) {
                mEnabled = false;
                mEnabled = false;
@@ -1299,7 +1301,7 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
        mAlarmManager.cancel(mWakeupIntent);
        mAlarmManager.cancel(mWakeupIntent);
        mAlarmManager.cancel(mTimeoutIntent);
        mAlarmManager.cancel(mTimeoutIntent);


        disableBatching();
        mGnssBatchingProvider.disable();
        // do this before releasing wakelock
        // do this before releasing wakelock
        native_cleanup();
        native_cleanup();


@@ -2001,58 +2003,11 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
        };
        };
    }
    }


    public interface GnssBatchingProvider {
        /**
         * Returns the GNSS batching size
         */
        int getSize();

        /**
         * Starts the hardware batching operation
         */
        boolean start(long periodNanos, boolean wakeOnFifoFull);

        /**
         * Forces a flush of existing locations from the hardware batching
         */
        void flush();

        /**
         * Stops the batching operation
         */
        boolean stop();
    }

    /**
    /**
     * @hide
     * @hide
     */
     */
    public GnssBatchingProvider getGnssBatchingProvider() {
    public GnssBatchingProvider getGnssBatchingProvider() {
        return new GnssBatchingProvider() {
        return mGnssBatchingProvider;
            @Override
            public int getSize() {
                return native_get_batch_size();
            }

            @Override
            public boolean start(long periodNanos, boolean wakeOnFifoFull) {
                if (periodNanos <= 0) {
                    Log.e(TAG, "Invalid periodNanos " + periodNanos +
                            "in batching request, not started");
                    return false;
                }
                return native_start_batch(periodNanos, wakeOnFifoFull);
            }

            @Override
            public void flush() {
                native_flush_batch();
            }

            @Override
            public boolean stop() {
                return native_stop_batch();
            }
        };
    }
    }


    public interface GnssMetricsProvider {
    public interface GnssMetricsProvider {
@@ -2074,23 +2029,6 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
        };
        };
    }
    }


    /**
     * Initialize Batching if enabled
     */
    private void enableBatching() {
        if (!native_init_batching()) {
            Log.e(TAG, "Failed to initialize GNSS batching");
        }
    }

    /**
     * Disable batching
     */
    private void disableBatching() {
        native_stop_batch();
        native_cleanup_batching();
    }

    /**
    /**
     * called from native code - GNSS location batch callback
     * called from native code - GNSS location batch callback
     */
     */
@@ -2912,19 +2850,5 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
    private static native boolean native_set_emergency_supl_pdn(int emergencySuplPdn);
    private static native boolean native_set_emergency_supl_pdn(int emergencySuplPdn);


    private static native boolean native_set_satellite_blacklist(int[] constellations, int[] svIds);
    private static native boolean native_set_satellite_blacklist(int[] constellations, int[] svIds);

    // GNSS Batching
    private static native int native_get_batch_size();

    private static native boolean native_start_batch(long periodNanos, boolean wakeOnFifoFull);

    private static native void native_flush_batch();

    private static native boolean native_stop_batch();

    private static native boolean native_init_batching();

    private static native void native_cleanup_batching();

}
}
+21 −15
Original line number Original line Diff line number Diff line
@@ -2050,7 +2050,7 @@ static jboolean android_location_GnssLocationProvider_set_satellite_blacklist(
}
}




static jint android_location_GnssLocationProvider_get_batch_size(JNIEnv*, jclass) {
static jint android_location_GnssBatchingProvider_get_batch_size(JNIEnv*, jclass) {
    if (gnssBatchingIface == nullptr) {
    if (gnssBatchingIface == nullptr) {
        return 0; // batching not supported, size = 0
        return 0; // batching not supported, size = 0
    }
    }
@@ -2062,7 +2062,7 @@ static jint android_location_GnssLocationProvider_get_batch_size(JNIEnv*, jclass
    }
    }
}
}


static jboolean android_location_GnssLocationProvider_init_batching(JNIEnv*, jclass) {
static jboolean android_location_GnssBatchingProvider_init_batching(JNIEnv*, jclass) {
    if (gnssBatchingIface == nullptr) {
    if (gnssBatchingIface == nullptr) {
        return JNI_FALSE; // batching not supported
        return JNI_FALSE; // batching not supported
    }
    }
@@ -2071,14 +2071,14 @@ static jboolean android_location_GnssLocationProvider_init_batching(JNIEnv*, jcl
    return static_cast<jboolean>(gnssBatchingIface->init(gnssBatchingCbIface));
    return static_cast<jboolean>(gnssBatchingIface->init(gnssBatchingCbIface));
}
}


static void android_location_GnssLocationProvider_cleanup_batching(JNIEnv*, jclass) {
static void android_location_GnssBatchingProvider_cleanup_batching(JNIEnv*, jclass) {
    if (gnssBatchingIface == nullptr) {
    if (gnssBatchingIface == nullptr) {
        return; // batching not supported
        return; // batching not supported
    }
    }
    gnssBatchingIface->cleanup();
    gnssBatchingIface->cleanup();
}
}


static jboolean android_location_GnssLocationProvider_start_batch(JNIEnv*, jclass,
static jboolean android_location_GnssBatchingProvider_start_batch(JNIEnv*, jclass,
        jlong periodNanos, jboolean wakeOnFifoFull) {
        jlong periodNanos, jboolean wakeOnFifoFull) {
    if (gnssBatchingIface == nullptr) {
    if (gnssBatchingIface == nullptr) {
        return JNI_FALSE; // batching not supported
        return JNI_FALSE; // batching not supported
@@ -2095,7 +2095,7 @@ static jboolean android_location_GnssLocationProvider_start_batch(JNIEnv*, jclas
    return static_cast<jboolean>(gnssBatchingIface->start(options));
    return static_cast<jboolean>(gnssBatchingIface->start(options));
}
}


static void android_location_GnssLocationProvider_flush_batch(JNIEnv*, jclass) {
static void android_location_GnssBatchingProvider_flush_batch(JNIEnv*, jclass) {
    if (gnssBatchingIface == nullptr) {
    if (gnssBatchingIface == nullptr) {
        return; // batching not supported
        return; // batching not supported
    }
    }
@@ -2103,7 +2103,7 @@ static void android_location_GnssLocationProvider_flush_batch(JNIEnv*, jclass) {
    gnssBatchingIface->flush();
    gnssBatchingIface->flush();
}
}


static jboolean android_location_GnssLocationProvider_stop_batch(JNIEnv*, jclass) {
static jboolean android_location_GnssBatchingProvider_stop_batch(JNIEnv*, jclass) {
    if (gnssBatchingIface == nullptr) {
    if (gnssBatchingIface == nullptr) {
        return JNI_FALSE; // batching not supported
        return JNI_FALSE; // batching not supported
    }
    }
@@ -2241,30 +2241,36 @@ static const JNINativeMethod sMethods[] = {
    {"native_set_satellite_blacklist",
    {"native_set_satellite_blacklist",
            "([I[I)Z",
            "([I[I)Z",
            reinterpret_cast<void *>(android_location_GnssLocationProvider_set_satellite_blacklist)},
            reinterpret_cast<void *>(android_location_GnssLocationProvider_set_satellite_blacklist)},
};

static const JNINativeMethod sMethodsBatching[] = {
     /* name, signature, funcPtr */
    {"native_get_batch_size",
    {"native_get_batch_size",
            "()I",
            "()I",
            reinterpret_cast<void *>(android_location_GnssLocationProvider_get_batch_size)},
            reinterpret_cast<void *>(android_location_GnssBatchingProvider_get_batch_size)},
    {"native_init_batching",
            "()Z",
            reinterpret_cast<void *>(android_location_GnssLocationProvider_init_batching)},
    {"native_start_batch",
    {"native_start_batch",
            "(JZ)Z",
            "(JZ)Z",
            reinterpret_cast<void *>(android_location_GnssLocationProvider_start_batch)},
            reinterpret_cast<void *>(android_location_GnssBatchingProvider_start_batch)},
    {"native_flush_batch",
    {"native_flush_batch",
            "()V",
            "()V",
            reinterpret_cast<void *>(android_location_GnssLocationProvider_flush_batch)},
            reinterpret_cast<void *>(android_location_GnssBatchingProvider_flush_batch)},
    {"native_stop_batch",
    {"native_stop_batch",
            "()Z",
            "()Z",
            reinterpret_cast<void *>(android_location_GnssLocationProvider_stop_batch)},
            reinterpret_cast<void *>(android_location_GnssBatchingProvider_stop_batch)},
    {"native_init_batching",
    {"native_init_batching",
            "()Z",
            "()Z",
            reinterpret_cast<void *>(android_location_GnssLocationProvider_init_batching)},
            reinterpret_cast<void *>(android_location_GnssBatchingProvider_init_batching)},
    {"native_cleanup_batching",
    {"native_cleanup_batching",
            "()V",
            "()V",
            reinterpret_cast<void *>(android_location_GnssLocationProvider_cleanup_batching)},
            reinterpret_cast<void *>(android_location_GnssBatchingProvider_cleanup_batching)},
};
};


int register_android_server_location_GnssLocationProvider(JNIEnv* env) {
int register_android_server_location_GnssLocationProvider(JNIEnv* env) {
    jniRegisterNativeMethods(
            env,
            "com/android/server/location/GnssBatchingProvider",
            sMethodsBatching,
            NELEM(sMethodsBatching));
    return jniRegisterNativeMethods(
    return jniRegisterNativeMethods(
            env,
            env,
            "com/android/server/location/GnssLocationProvider",
            "com/android/server/location/GnssLocationProvider",
+91 −0
Original line number Original line Diff line number Diff line
package com.android.server.location;

import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.platform.test.annotations.Presubmit;

import com.android.server.location.GnssBatchingProvider.GnssBatchingProviderNative;
import com.android.server.testing.FrameworkRobolectricTestRunner;
import com.android.server.testing.SystemLoaderPackages;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;

/**
 * Unit tests for {@link GnssBatchingProvider}.
 */
@RunWith(FrameworkRobolectricTestRunner.class)
@Config(
        manifest = Config.NONE,
        shadows = {
        },
        sdk = 27
)
@SystemLoaderPackages({"com.android.server.location"})
@Presubmit
public class GnssBatchingProviderTest {

    private static final long PERIOD_NANOS = (long) 1e9;
    private static final boolean WAKE_ON_FIFO_FULL = true;
    private static final int BATCH_SIZE = 3;
    @Mock
    private GnssBatchingProviderNative mMockNative;
    private GnssBatchingProvider mTestProvider;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        when(mMockNative.initBatching()).thenReturn(true);
        when(mMockNative.startBatch(anyLong(), anyBoolean())).thenReturn(true);
        when(mMockNative.stopBatch()).thenReturn(true);
        when(mMockNative.getBatchSize()).thenReturn(BATCH_SIZE);
        mTestProvider = new GnssBatchingProvider(mMockNative);
        mTestProvider.enable();
        mTestProvider.start(PERIOD_NANOS, WAKE_ON_FIFO_FULL);
    }

    @Test
    public void start_nativeStarted() {
        verify(mMockNative).startBatch(eq(PERIOD_NANOS), eq(WAKE_ON_FIFO_FULL));
    }

    @Test
    public void stop_nativeStopped() {
        mTestProvider.stop();
        verify(mMockNative).stopBatch();
    }

    @Test
    public void flush_nativeFlushed() {
        mTestProvider.flush();
        verify(mMockNative).flushBatch();
    }

    @Test
    public void getBatchSize_nativeGetBatchSize() {
        assertThat(mTestProvider.getBatchSize()).isEqualTo(BATCH_SIZE);
    }

    @Test
    public void started_resume_started() {
        mTestProvider.resumeIfStarted();
        verify(mMockNative, times(2)).startBatch(eq(PERIOD_NANOS), eq(WAKE_ON_FIFO_FULL));
    }

    @Test
    public void stopped_resume_notStarted() {
        mTestProvider.stop();
        mTestProvider.resumeIfStarted();
        verify(mMockNative, times(1)).startBatch(eq(PERIOD_NANOS), eq(WAKE_ON_FIFO_FULL));
    }
}