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.util.Log;
20 
21 import com.android.internal.annotations.VisibleForTesting;
22 
23 /**
24  * Manages GNSS Batching operations.
25  *
26  * <p>This class is not thread safe (It's client's responsibility to make sure calls happen on
27  * the same thread).
28  */
29 public class GnssBatchingProvider {
30 
31     private static final String TAG = "GnssBatchingProvider";
32     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
33 
34     private final GnssBatchingProviderNative mNative;
35     private boolean mEnabled;
36     private boolean mStarted;
37     private long mPeriodNanos;
38     private boolean mWakeOnFifoFull;
39 
GnssBatchingProvider()40     GnssBatchingProvider() {
41         this(new GnssBatchingProviderNative());
42     }
43 
44     @VisibleForTesting
GnssBatchingProvider(GnssBatchingProviderNative gnssBatchingProviderNative)45     GnssBatchingProvider(GnssBatchingProviderNative gnssBatchingProviderNative) {
46         mNative = gnssBatchingProviderNative;
47     }
48 
49     /**
50      * Returns the GNSS batching size
51      */
getBatchSize()52     public int getBatchSize() {
53         return mNative.getBatchSize();
54     }
55 
56     /** Enable GNSS batching. */
enable()57     public void enable() {
58         mEnabled = mNative.initBatching();
59         if (!mEnabled) {
60             Log.e(TAG, "Failed to initialize GNSS batching");
61         }
62     }
63 
64     /**
65      * Starts the hardware batching operation
66      */
start(long periodNanos, boolean wakeOnFifoFull)67     public boolean start(long periodNanos, boolean wakeOnFifoFull) {
68         if (!mEnabled) {
69             throw new IllegalStateException();
70         }
71         if (periodNanos <= 0) {
72             Log.e(TAG, "Invalid periodNanos " + periodNanos +
73                     " in batching request, not started");
74             return false;
75         }
76         mStarted = mNative.startBatch(periodNanos, wakeOnFifoFull);
77         if (mStarted) {
78             mPeriodNanos = periodNanos;
79             mWakeOnFifoFull = wakeOnFifoFull;
80         }
81         return mStarted;
82     }
83 
84     /**
85      * Forces a flush of existing locations from the hardware batching
86      */
flush()87     public void flush() {
88         if (!mStarted) {
89             Log.w(TAG, "Cannot flush since GNSS batching has not started.");
90             return;
91         }
92         mNative.flushBatch();
93     }
94 
95     /**
96      * Stops the batching operation
97      */
stop()98     public boolean stop() {
99         boolean stopped = mNative.stopBatch();
100         if (stopped) {
101             mStarted = false;
102         }
103         return stopped;
104     }
105 
106     /** Disable GNSS batching. */
disable()107     public void disable() {
108         stop();
109         mNative.cleanupBatching();
110         mEnabled = false;
111     }
112 
113     // TODO(b/37460011): Use this with death recovery logic.
resumeIfStarted()114     void resumeIfStarted() {
115         if (DEBUG) {
116             Log.d(TAG, "resumeIfStarted");
117         }
118         if (mStarted) {
119             mNative.startBatch(mPeriodNanos, mWakeOnFifoFull);
120         }
121     }
122 
123     @VisibleForTesting
124     static class GnssBatchingProviderNative {
getBatchSize()125         public int getBatchSize() {
126             return native_get_batch_size();
127         }
128 
startBatch(long periodNanos, boolean wakeOnFifoFull)129         public boolean startBatch(long periodNanos, boolean wakeOnFifoFull) {
130             return native_start_batch(periodNanos, wakeOnFifoFull);
131         }
132 
flushBatch()133         public void flushBatch() {
134             native_flush_batch();
135         }
136 
stopBatch()137         public boolean stopBatch() {
138             return native_stop_batch();
139         }
140 
initBatching()141         public boolean initBatching() {
142             return native_init_batching();
143         }
144 
cleanupBatching()145         public void cleanupBatching() {
146             native_cleanup_batching();
147         }
148     }
149 
native_get_batch_size()150     private static native int native_get_batch_size();
151 
native_start_batch(long periodNanos, boolean wakeOnFifoFull)152     private static native boolean native_start_batch(long periodNanos, boolean wakeOnFifoFull);
153 
native_flush_batch()154     private static native void native_flush_batch();
155 
native_stop_batch()156     private static native boolean native_stop_batch();
157 
native_init_batching()158     private static native boolean native_init_batching();
159 
native_cleanup_batching()160     private static native void native_cleanup_batching();
161 }
162