diff options
| author | 2019-03-15 14:13:59 -0700 | |
|---|---|---|
| committer | 2019-03-20 16:10:08 -0700 | |
| commit | f113333b98385fcea5a7f5e596d2cd34ada05f1d (patch) | |
| tree | ed420778b0802cb8f37cd06a1c3a07cc7496ec4a | |
| parent | 72aa96ffb26fa264083a94e96828468225f1b6a0 (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.txt | 1 | ||||
| -rw-r--r-- | core/java/android/os/SystemClock.java | 31 | ||||
| -rw-r--r-- | location/java/android/location/ILocationManager.aidl | 2 | ||||
| -rw-r--r-- | location/java/android/location/LocationTime.aidl | 19 | ||||
| -rw-r--r-- | location/java/android/location/LocationTime.java | 73 | ||||
| -rw-r--r-- | services/core/java/com/android/server/LocationManagerService.java | 14 |
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"); |