summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Chad Brubaker <cbrubaker@google.com> 2019-03-15 14:13:59 -0700
committer Chad Brubaker <cbrubaker@google.com> 2019-03-20 16:10:08 -0700
commitf113333b98385fcea5a7f5e596d2cd34ada05f1d (patch)
treeed420778b0802cb8f37cd06a1c3a07cc7496ec4a
parent72aa96ffb26fa264083a94e96828468225f1b6a0 (diff)
Add location backed system clock
This provides a permissionless way to use the location (e.g. GNSS) provided time data for more accurate time keeping. Test: atest LocationManagerTest#testGnssProvidedClock Bug: 123530510 Change-Id: Ifbc45997868040abbb3e1399a8649911afb0af05
-rw-r--r--api/current.txt1
-rw-r--r--core/java/android/os/SystemClock.java31
-rw-r--r--location/java/android/location/ILocationManager.aidl2
-rw-r--r--location/java/android/location/LocationTime.aidl19
-rw-r--r--location/java/android/location/LocationTime.java73
-rw-r--r--services/core/java/com/android/server/LocationManagerService.java14
6 files changed, 140 insertions, 0 deletions
diff --git a/api/current.txt b/api/current.txt
index 6fdf9c34ea5b..5f240256c87e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -35419,6 +35419,7 @@ package android.os {
}
public final class SystemClock {
+ method @NonNull public static java.time.Clock currentGnssTimeClock();
method public static long currentThreadTimeMillis();
method public static long elapsedRealtime();
method public static long elapsedRealtimeNanos();
diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java
index b254166303bc..a1432e602d75 100644
--- a/core/java/android/os/SystemClock.java
+++ b/core/java/android/os/SystemClock.java
@@ -19,6 +19,8 @@ package android.os;
import android.annotation.NonNull;
import android.app.IAlarmManager;
import android.content.Context;
+import android.location.ILocationManager;
+import android.location.LocationTime;
import android.util.Slog;
import dalvik.annotation.optimization.CriticalNative;
@@ -313,4 +315,33 @@ public final class SystemClock {
}
};
}
+
+ /**
+ * Returns a {@link Clock} that starts at January 1, 1970 00:00:00.0 UTC,
+ * synchronized using the device's location provider.
+ *
+ * @throws DateTimeException when the location provider has not had a location fix since boot.
+ */
+ public static @NonNull Clock currentGnssTimeClock() {
+ return new SimpleClock(ZoneOffset.UTC) {
+ private final ILocationManager mMgr = ILocationManager.Stub
+ .asInterface(ServiceManager.getService(Context.LOCATION_SERVICE));
+ @Override
+ public long millis() {
+ LocationTime time;
+ try {
+ time = mMgr.getGnssTimeMillis();
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ return 0;
+ }
+ if (time == null) {
+ throw new DateTimeException("Gnss based time is not available.");
+ }
+ long currentNanos = elapsedRealtimeNanos();
+ long deltaMs = (currentNanos - time.getElapsedRealtimeNanos()) / 1000000L;
+ return time.getTime() + deltaMs;
+ }
+ };
+ }
}
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index c371c5fa0448..ad1218b6922b 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -29,6 +29,7 @@ import android.location.IGnssNavigationMessageListener;
import android.location.ILocationListener;
import android.location.Location;
import android.location.LocationRequest;
+import android.location.LocationTime;
import android.os.Bundle;
import com.android.internal.location.ProviderProperties;
@@ -104,6 +105,7 @@ interface ILocationManager
void setTestProviderLocation(String provider, in Location loc, String opPackageName);
void setTestProviderEnabled(String provider, boolean enabled, String opPackageName);
List<LocationRequest> getTestProviderCurrentRequests(String provider, String opPackageName);
+ LocationTime getGnssTimeMillis();
// --- deprecated ---
void setTestProviderStatus(String provider, int status, in Bundle extras, long updateTime,
diff --git a/location/java/android/location/LocationTime.aidl b/location/java/android/location/LocationTime.aidl
new file mode 100644
index 000000000000..f6263637bb33
--- /dev/null
+++ b/location/java/android/location/LocationTime.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.location;
+
+parcelable LocationTime;
diff --git a/location/java/android/location/LocationTime.java b/location/java/android/location/LocationTime.java
new file mode 100644
index 000000000000..e5535d192776
--- /dev/null
+++ b/location/java/android/location/LocationTime.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.location;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Data class for passing location derived time.
+ * @hide
+ */
+public final class LocationTime implements Parcelable {
+
+ private final long mTime;
+ private final long mElapsedRealtimeNanos;
+
+ public LocationTime(long time, long elapsedRealtimeNanos) {
+ mTime = time;
+ mElapsedRealtimeNanos = elapsedRealtimeNanos;
+ }
+
+ /**
+ * The current time, according to the Gnss location provider. */
+ public long getTime() {
+ return mTime;
+ }
+
+ /**
+ * The elapsed nanos since boot {@link #getTime} was computed at.
+ */
+ public long getElapsedRealtimeNanos() {
+ return mElapsedRealtimeNanos;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeLong(mTime);
+ out.writeLong(mElapsedRealtimeNanos);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final @NonNull Parcelable.Creator<LocationTime> CREATOR =
+ new Parcelable.Creator<LocationTime>() {
+ public LocationTime createFromParcel(Parcel in) {
+ long time = in.readLong();
+ long elapsedRealtimeNanos = in.readLong();
+ return new LocationTime(time, elapsedRealtimeNanos);
+ }
+
+ public LocationTime[] newArray(int size) {
+ return new LocationTime[size];
+ }
+ };
+}
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index c2a06117cf14..2cef2f24c6ae 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -64,6 +64,7 @@ import android.location.INetInitiatedListener;
import android.location.Location;
import android.location.LocationManager;
import android.location.LocationRequest;
+import android.location.LocationTime;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
@@ -2685,6 +2686,19 @@ public class LocationManagerService extends ILocationManager.Stub {
}
@Override
+ public LocationTime getGnssTimeMillis() {
+ synchronized (mLock) {
+ Location location = mLastLocation.get(LocationManager.GPS_PROVIDER);
+ if (location == null) {
+ return null;
+ }
+ long currentNanos = SystemClock.elapsedRealtimeNanos();
+ long deltaMs = (currentNanos - location.getElapsedRealtimeNanos()) / 1000000L;
+ return new LocationTime(location.getTime() + deltaMs, currentNanos);
+ }
+ }
+
+ @Override
public boolean injectLocation(Location location) {
mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
"Location Hardware permission not granted to inject location");