Loading location/java/android/location/flags/location.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -166,6 +166,16 @@ flag { } } flag { name: "update_is_in_emergency_before_on_register" namespace: "location" description: "Update isInEmergency before onRegister() without holding a lock" bug: "355384257" metadata { purpose: PURPOSE_BUGFIX } } flag { name: "gnss_assistance_interface_jni" namespace: "location" Loading services/core/java/com/android/server/location/provider/LocationProviderManager.java +42 −25 Original line number Diff line number Diff line Loading @@ -395,6 +395,9 @@ public class LocationProviderManager extends @GuardedBy("mMultiplexerLock") private boolean mIsUsingHighPower; @GuardedBy("mMultiplexerLock") private boolean mIsInEmergency; @Nullable private Location mLastLocation = null; protected Registration(LocationRequest request, CallerIdentity identity, Executor executor, Loading @@ -421,6 +424,24 @@ public class LocationProviderManager extends } } /** Update {@link #mIsInEmergency} by invoking Telephony APIs. **/ public void updateIsInEmergency() { boolean isInEmergency = mEmergencyHelper.isInEmergency(0); synchronized (mMultiplexerLock) { mIsInEmergency = isInEmergency; } } /** * Make sure to call {@link #updateIsInEmergency()} before calling this method to keep * {@link #mIsInEmergency} up-to-date. * * <p>See b/426562854 for more details. {@link #updateIsInEmergency()} is a short term * solution to avoid calling IPC with a lock by caching the state right before onRegister(). * The long term solution should be avoiding any synchronous * {@link EmergencyHelper#isInEmergency()}} and using the asynchronous emergency listeners * instead. */ @GuardedBy("mMultiplexerLock") @Override protected void onRegister() { Loading @@ -435,7 +456,11 @@ public class LocationProviderManager extends // initialization order is important as there are ordering dependencies onLocationPermissionsChanged(); if (Flags.updateIsInEmergencyBeforeOnRegister()) { onBypassLocationPermissionsChanged(mIsInEmergency); } else { onBypassLocationPermissionsChanged(mEmergencyHelper.isInEmergency(0)); } mForeground = mAppForegroundHelper.isAppForeground(getIdentity().getUid()); mProviderLocationRequest = calculateProviderLocationRequest(); mIsUsingHighPower = isUsingHighPower(); Loading Loading @@ -1991,20 +2016,12 @@ public class LocationProviderManager extends identity, new GetCurrentLocationTransport(callback), permissionLevel); synchronized (mMultiplexerLock) { Preconditions.checkState(mState != STATE_STOPPED); final long ident = Binder.clearCallingIdentity(); try { putRegistration(callback.asBinder(), registration); registerAndHandleIdentity(callback.asBinder(), registration, () -> { if (!registration.isActive()) { // if the registration never activated, fail it immediately registration.deliverNull(); } } finally { Binder.restoreCallingIdentity(ident); } } }); ICancellationSignal cancelTransport = CancellationSignal.createTransport(); CancellationSignal.fromTransport(cancelTransport) Loading Loading @@ -2045,16 +2062,7 @@ public class LocationProviderManager extends identity, new LocationListenerTransport(listener), permissionLevel); synchronized (mMultiplexerLock) { Preconditions.checkState(mState != STATE_STOPPED); final long ident = Binder.clearCallingIdentity(); try { putRegistration(listener.asBinder(), registration); } finally { Binder.restoreCallingIdentity(ident); } } registerAndHandleIdentity(listener.asBinder(), registration, () -> {}); } public void registerLocationRequest(LocationRequest request, CallerIdentity callerIdentity, Loading @@ -2064,12 +2072,21 @@ public class LocationProviderManager extends callerIdentity, new LocationPendingIntentTransport(mContext, pendingIntent), permissionLevel); registerAndHandleIdentity(pendingIntent, registration, () -> {}); } private <T> void registerAndHandleIdentity(T key, Registration registration, Runnable postRegistrationRunnable) { if (Flags.updateIsInEmergencyBeforeOnRegister()) { registration.updateIsInEmergency(); } synchronized (mMultiplexerLock) { Preconditions.checkState(mState != STATE_STOPPED); final long identity = Binder.clearCallingIdentity(); try { putRegistration(pendingIntent, registration); putRegistration(key, registration); postRegistrationRunnable.run(); } finally { Binder.restoreCallingIdentity(identity); } Loading Loading
location/java/android/location/flags/location.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -166,6 +166,16 @@ flag { } } flag { name: "update_is_in_emergency_before_on_register" namespace: "location" description: "Update isInEmergency before onRegister() without holding a lock" bug: "355384257" metadata { purpose: PURPOSE_BUGFIX } } flag { name: "gnss_assistance_interface_jni" namespace: "location" Loading
services/core/java/com/android/server/location/provider/LocationProviderManager.java +42 −25 Original line number Diff line number Diff line Loading @@ -395,6 +395,9 @@ public class LocationProviderManager extends @GuardedBy("mMultiplexerLock") private boolean mIsUsingHighPower; @GuardedBy("mMultiplexerLock") private boolean mIsInEmergency; @Nullable private Location mLastLocation = null; protected Registration(LocationRequest request, CallerIdentity identity, Executor executor, Loading @@ -421,6 +424,24 @@ public class LocationProviderManager extends } } /** Update {@link #mIsInEmergency} by invoking Telephony APIs. **/ public void updateIsInEmergency() { boolean isInEmergency = mEmergencyHelper.isInEmergency(0); synchronized (mMultiplexerLock) { mIsInEmergency = isInEmergency; } } /** * Make sure to call {@link #updateIsInEmergency()} before calling this method to keep * {@link #mIsInEmergency} up-to-date. * * <p>See b/426562854 for more details. {@link #updateIsInEmergency()} is a short term * solution to avoid calling IPC with a lock by caching the state right before onRegister(). * The long term solution should be avoiding any synchronous * {@link EmergencyHelper#isInEmergency()}} and using the asynchronous emergency listeners * instead. */ @GuardedBy("mMultiplexerLock") @Override protected void onRegister() { Loading @@ -435,7 +456,11 @@ public class LocationProviderManager extends // initialization order is important as there are ordering dependencies onLocationPermissionsChanged(); if (Flags.updateIsInEmergencyBeforeOnRegister()) { onBypassLocationPermissionsChanged(mIsInEmergency); } else { onBypassLocationPermissionsChanged(mEmergencyHelper.isInEmergency(0)); } mForeground = mAppForegroundHelper.isAppForeground(getIdentity().getUid()); mProviderLocationRequest = calculateProviderLocationRequest(); mIsUsingHighPower = isUsingHighPower(); Loading Loading @@ -1991,20 +2016,12 @@ public class LocationProviderManager extends identity, new GetCurrentLocationTransport(callback), permissionLevel); synchronized (mMultiplexerLock) { Preconditions.checkState(mState != STATE_STOPPED); final long ident = Binder.clearCallingIdentity(); try { putRegistration(callback.asBinder(), registration); registerAndHandleIdentity(callback.asBinder(), registration, () -> { if (!registration.isActive()) { // if the registration never activated, fail it immediately registration.deliverNull(); } } finally { Binder.restoreCallingIdentity(ident); } } }); ICancellationSignal cancelTransport = CancellationSignal.createTransport(); CancellationSignal.fromTransport(cancelTransport) Loading Loading @@ -2045,16 +2062,7 @@ public class LocationProviderManager extends identity, new LocationListenerTransport(listener), permissionLevel); synchronized (mMultiplexerLock) { Preconditions.checkState(mState != STATE_STOPPED); final long ident = Binder.clearCallingIdentity(); try { putRegistration(listener.asBinder(), registration); } finally { Binder.restoreCallingIdentity(ident); } } registerAndHandleIdentity(listener.asBinder(), registration, () -> {}); } public void registerLocationRequest(LocationRequest request, CallerIdentity callerIdentity, Loading @@ -2064,12 +2072,21 @@ public class LocationProviderManager extends callerIdentity, new LocationPendingIntentTransport(mContext, pendingIntent), permissionLevel); registerAndHandleIdentity(pendingIntent, registration, () -> {}); } private <T> void registerAndHandleIdentity(T key, Registration registration, Runnable postRegistrationRunnable) { if (Flags.updateIsInEmergencyBeforeOnRegister()) { registration.updateIsInEmergency(); } synchronized (mMultiplexerLock) { Preconditions.checkState(mState != STATE_STOPPED); final long identity = Binder.clearCallingIdentity(); try { putRegistration(pendingIntent, registration); putRegistration(key, registration); postRegistrationRunnable.run(); } finally { Binder.restoreCallingIdentity(identity); } Loading