Merge "Update GNSS listener maps when clients die abnormally."
This commit is contained in:
@@ -67,6 +67,7 @@ import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.IInterface;
|
||||
import android.os.PowerManager;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
@@ -109,6 +110,7 @@ import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
|
||||
import com.android.server.location.LocationRequestStatistics.PackageStatistics;
|
||||
import com.android.server.location.MockProvider;
|
||||
import com.android.server.location.PassiveProvider;
|
||||
import com.android.server.location.RemoteListenerHelper;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
@@ -121,6 +123,8 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* The service class that manages LocationProviders and issues location
|
||||
@@ -225,11 +229,14 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
private final ArraySet<String> mIgnoreSettingsPackageWhitelist = new ArraySet<>();
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private final ArrayMap<IBinder, CallerIdentity> mGnssMeasurementsListeners = new ArrayMap<>();
|
||||
|
||||
private final ArrayMap<IBinder, LinkedListener<IGnssMeasurementsListener>>
|
||||
mGnssMeasurementsListeners = new ArrayMap<>();
|
||||
@GuardedBy("mLock")
|
||||
private final ArrayMap<IBinder, CallerIdentity>
|
||||
private final ArrayMap<IBinder, LinkedListener<IGnssNavigationMessageListener>>
|
||||
mGnssNavigationMessageListeners = new ArrayMap<>();
|
||||
@GuardedBy("mLock")
|
||||
private final ArrayMap<IBinder, LinkedListener<IGnssStatusListener>>
|
||||
mGnssStatusListeners = new ArrayMap<>();
|
||||
|
||||
// current active user on the device - other users are denied location data
|
||||
private int mCurrentUserId = UserHandle.USER_SYSTEM;
|
||||
@@ -243,7 +250,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
@GuardedBy("mLock")
|
||||
private IBatchedLocationCallback mGnssBatchingCallback;
|
||||
@GuardedBy("mLock")
|
||||
private LinkedCallback mGnssBatchingDeathCallback;
|
||||
private LinkedListener<IBatchedLocationCallback> mGnssBatchingDeathCallback;
|
||||
@GuardedBy("mLock")
|
||||
private boolean mGnssBatchingInProgress = false;
|
||||
|
||||
@@ -485,7 +492,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
&& record.mIsForegroundUid != foreground) {
|
||||
if (D) {
|
||||
Log.d(TAG, "request from uid " + uid + " is now "
|
||||
+ (foreground ? "foreground" : "background)"));
|
||||
+ foregroundAsString(foreground));
|
||||
}
|
||||
record.updateForeground(foreground);
|
||||
|
||||
@@ -499,44 +506,48 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
applyRequirementsLocked(provider);
|
||||
}
|
||||
|
||||
for (Entry<IBinder, CallerIdentity> entry : mGnssMeasurementsListeners.entrySet()) {
|
||||
CallerIdentity callerIdentity = entry.getValue();
|
||||
if (callerIdentity.mUid == uid) {
|
||||
if (D) {
|
||||
Log.d(TAG, "gnss measurements listener from uid " + uid
|
||||
+ " is now " + (foreground ? "foreground" : "background)"));
|
||||
}
|
||||
if (foreground || isThrottlingExemptLocked(entry.getValue())) {
|
||||
mGnssMeasurementsProvider.addListener(
|
||||
IGnssMeasurementsListener.Stub.asInterface(entry.getKey()),
|
||||
callerIdentity);
|
||||
} else {
|
||||
mGnssMeasurementsProvider.removeListener(
|
||||
IGnssMeasurementsListener.Stub.asInterface(entry.getKey()));
|
||||
}
|
||||
}
|
||||
}
|
||||
updateGnssDataProviderOnUidImportanceChangedLocked(mGnssMeasurementsListeners,
|
||||
mGnssMeasurementsProvider, IGnssMeasurementsListener.Stub::asInterface,
|
||||
uid, foreground);
|
||||
|
||||
for (Entry<IBinder, CallerIdentity> entry : mGnssNavigationMessageListeners.entrySet()) {
|
||||
CallerIdentity callerIdentity = entry.getValue();
|
||||
if (callerIdentity.mUid == uid) {
|
||||
if (D) {
|
||||
Log.d(TAG, "gnss navigation message listener from uid "
|
||||
+ uid + " is now "
|
||||
+ (foreground ? "foreground" : "background)"));
|
||||
}
|
||||
if (foreground || isThrottlingExemptLocked(entry.getValue())) {
|
||||
mGnssNavigationMessageProvider.addListener(
|
||||
IGnssNavigationMessageListener.Stub.asInterface(entry.getKey()),
|
||||
callerIdentity);
|
||||
} else {
|
||||
mGnssNavigationMessageProvider.removeListener(
|
||||
IGnssNavigationMessageListener.Stub.asInterface(entry.getKey()));
|
||||
}
|
||||
updateGnssDataProviderOnUidImportanceChangedLocked(mGnssNavigationMessageListeners,
|
||||
mGnssNavigationMessageProvider, IGnssNavigationMessageListener.Stub::asInterface,
|
||||
uid, foreground);
|
||||
|
||||
updateGnssDataProviderOnUidImportanceChangedLocked(mGnssStatusListeners,
|
||||
mGnssStatusProvider, IGnssStatusListener.Stub::asInterface, uid, foreground);
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private <TListener extends IInterface> void updateGnssDataProviderOnUidImportanceChangedLocked(
|
||||
ArrayMap<IBinder, ? extends LinkedListenerBase> gnssDataListeners,
|
||||
RemoteListenerHelper<TListener> gnssDataProvider,
|
||||
Function<IBinder, TListener> mapBinderToListener, int uid, boolean foreground) {
|
||||
for (Entry<IBinder, ? extends LinkedListenerBase> entry : gnssDataListeners.entrySet()) {
|
||||
LinkedListenerBase linkedListener = entry.getValue();
|
||||
CallerIdentity callerIdentity = linkedListener.mCallerIdentity;
|
||||
if (callerIdentity.mUid != uid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (D) {
|
||||
Log.d(TAG, linkedListener.mListenerName + " from uid "
|
||||
+ uid + " is now " + foregroundAsString(foreground));
|
||||
}
|
||||
|
||||
TListener listener = mapBinderToListener.apply(entry.getKey());
|
||||
if (foreground || isThrottlingExemptLocked(callerIdentity)) {
|
||||
gnssDataProvider.addListener(listener, callerIdentity);
|
||||
} else {
|
||||
gnssDataProvider.removeListener(listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String foregroundAsString(boolean foreground) {
|
||||
return foreground ? "foreground" : "background";
|
||||
}
|
||||
|
||||
private static boolean isImportanceForeground(int importance) {
|
||||
return importance <= FOREGROUND_IMPORTANCE_CUTOFF;
|
||||
}
|
||||
@@ -1218,9 +1229,8 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
* A wrapper class holding either an ILocationListener or a PendingIntent to receive
|
||||
* location updates.
|
||||
*/
|
||||
private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
|
||||
private final class Receiver extends LinkedListenerBase implements PendingIntent.OnFinished {
|
||||
private static final long WAKELOCK_TIMEOUT_MILLIS = 60 * 1000;
|
||||
final CallerIdentity mCallerIdentity;
|
||||
private final int mAllowedResolutionLevel; // resolution level allowed to receiver
|
||||
|
||||
private final ILocationListener mListener;
|
||||
@@ -1240,6 +1250,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
|
||||
private Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
|
||||
String packageName, WorkSource workSource, boolean hideFromAppOps) {
|
||||
super(new CallerIdentity(uid, pid, packageName), "LocationListener");
|
||||
mListener = listener;
|
||||
mPendingIntent = intent;
|
||||
if (listener != null) {
|
||||
@@ -1248,7 +1259,6 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
mKey = intent;
|
||||
}
|
||||
mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
|
||||
mCallerIdentity = new CallerIdentity(uid, pid, packageName);
|
||||
if (workSource != null && workSource.isEmpty()) {
|
||||
workSource = null;
|
||||
}
|
||||
@@ -1486,7 +1496,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
|
||||
@Override
|
||||
public void binderDied() {
|
||||
if (D) Log.d(TAG, "Location listener died");
|
||||
if (D) Log.d(TAG, "Remote " + mListenerName + " died.");
|
||||
|
||||
synchronized (mLock) {
|
||||
removeUpdatesLocked(this);
|
||||
@@ -1617,53 +1627,59 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
return false;
|
||||
}
|
||||
|
||||
CallerIdentity callerIdentity = new CallerIdentity(Binder.getCallingUid(),
|
||||
Binder.getCallingPid(), packageName);
|
||||
synchronized (mLock) {
|
||||
mGnssBatchingCallback = callback;
|
||||
mGnssBatchingDeathCallback = new LinkedCallback(callback);
|
||||
try {
|
||||
callback.asBinder().linkToDeath(mGnssBatchingDeathCallback, 0 /* flags */);
|
||||
} catch (RemoteException e) {
|
||||
// if the remote process registering the listener is already dead, just swallow the
|
||||
// exception and return
|
||||
Log.e(TAG, "Remote listener already died.", e);
|
||||
mGnssBatchingDeathCallback = new LinkedListener<>(callback,
|
||||
"BatchedLocationCallback", callerIdentity,
|
||||
(IBatchedLocationCallback listener) -> {
|
||||
stopGnssBatch();
|
||||
removeGnssBatchingCallback();
|
||||
});
|
||||
if (!linkToListenerDeathNotificationLocked(callback.asBinder(),
|
||||
mGnssBatchingDeathCallback)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private class LinkedCallback implements IBinder.DeathRecipient {
|
||||
private final IBatchedLocationCallback mCallback;
|
||||
private abstract static class LinkedListenerBase implements IBinder.DeathRecipient {
|
||||
protected final CallerIdentity mCallerIdentity;
|
||||
protected final String mListenerName;
|
||||
|
||||
private LinkedCallback(@NonNull IBatchedLocationCallback callback) {
|
||||
mCallback = callback;
|
||||
private LinkedListenerBase(@NonNull CallerIdentity callerIdentity,
|
||||
@NonNull String listenerName) {
|
||||
mCallerIdentity = callerIdentity;
|
||||
mListenerName = listenerName;
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public IBatchedLocationCallback getUnderlyingListener() {
|
||||
return mCallback;
|
||||
private static class LinkedListener<TListener> extends LinkedListenerBase {
|
||||
private final TListener mListener;
|
||||
private final Consumer<TListener> mBinderDeathCallback;
|
||||
|
||||
private LinkedListener(@NonNull TListener listener, String listenerName,
|
||||
@NonNull CallerIdentity callerIdentity,
|
||||
@NonNull Consumer<TListener> binderDeathCallback) {
|
||||
super(callerIdentity, listenerName);
|
||||
mListener = listener;
|
||||
mBinderDeathCallback = binderDeathCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void binderDied() {
|
||||
Log.d(TAG, "Remote Batching Callback died: " + mCallback);
|
||||
stopGnssBatch();
|
||||
removeGnssBatchingCallback();
|
||||
if (D) Log.d(TAG, "Remote " + mListenerName + " died.");
|
||||
mBinderDeathCallback.accept(mListener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeGnssBatchingCallback() {
|
||||
synchronized (mLock) {
|
||||
try {
|
||||
mGnssBatchingCallback.asBinder().unlinkToDeath(mGnssBatchingDeathCallback,
|
||||
0 /* flags */);
|
||||
} catch (NoSuchElementException e) {
|
||||
// if the death callback isn't connected (it should be...), log error, swallow the
|
||||
// exception and return
|
||||
Log.e(TAG, "Couldn't unlink death callback.", e);
|
||||
}
|
||||
unlinkFromListenerDeathNotificationLocked(mGnssBatchingCallback.asBinder(),
|
||||
mGnssBatchingDeathCallback);
|
||||
mGnssBatchingCallback = null;
|
||||
mGnssBatchingDeathCallback = null;
|
||||
}
|
||||
@@ -2264,10 +2280,8 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
if (receiver == null) {
|
||||
receiver = new Receiver(listener, null, pid, uid, packageName, workSource,
|
||||
hideFromAppOps);
|
||||
try {
|
||||
receiver.getListener().asBinder().linkToDeath(receiver, 0);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "linkToDeath failed:", e);
|
||||
if (!linkToListenerDeathNotificationLocked(receiver.getListener().asBinder(),
|
||||
receiver)) {
|
||||
return null;
|
||||
}
|
||||
mReceivers.put(binder, receiver);
|
||||
@@ -2482,7 +2496,8 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver)));
|
||||
|
||||
if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
|
||||
receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
|
||||
unlinkFromListenerDeathNotificationLocked(receiver.getListener().asBinder(),
|
||||
receiver);
|
||||
receiver.clearPendingBroadcastsLocked();
|
||||
}
|
||||
|
||||
@@ -2694,18 +2709,52 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerGnssStatusCallback(IGnssStatusListener callback, String packageName) {
|
||||
public boolean registerGnssStatusCallback(IGnssStatusListener listener, String packageName) {
|
||||
if (!hasGnssPermissions(packageName) || mGnssStatusProvider == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return mGnssStatusProvider.addListener(callback, new CallerIdentity(Binder.getCallingUid(),
|
||||
Binder.getCallingPid(), packageName));
|
||||
CallerIdentity callerIdentity = new CallerIdentity(Binder.getCallingUid(),
|
||||
Binder.getCallingPid(), packageName);
|
||||
LinkedListener<IGnssStatusListener> linkedListener = new LinkedListener<>(listener,
|
||||
"GnssStatusListener", callerIdentity, this::unregisterGnssStatusCallback);
|
||||
IBinder binder = listener.asBinder();
|
||||
synchronized (mLock) {
|
||||
if (!linkToListenerDeathNotificationLocked(binder, linkedListener)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mGnssStatusListeners.put(binder, linkedListener);
|
||||
long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
if (isThrottlingExemptLocked(callerIdentity)
|
||||
|| isImportanceForeground(
|
||||
mActivityManager.getPackageImportance(packageName))) {
|
||||
mGnssStatusProvider.addListener(listener, callerIdentity);
|
||||
}
|
||||
return true;
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterGnssStatusCallback(IGnssStatusListener callback) {
|
||||
mGnssStatusProvider.removeListener(callback);
|
||||
public void unregisterGnssStatusCallback(IGnssStatusListener listener) {
|
||||
if (mGnssStatusProvider == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
IBinder binder = listener.asBinder();
|
||||
synchronized (mLock) {
|
||||
LinkedListener<IGnssStatusListener> linkedListener =
|
||||
mGnssStatusListeners.remove(binder);
|
||||
if (linkedListener == null) {
|
||||
return;
|
||||
}
|
||||
unlinkFromListenerDeathNotificationLocked(binder, linkedListener);
|
||||
mGnssStatusProvider.removeListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2715,22 +2764,75 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
return false;
|
||||
}
|
||||
|
||||
CallerIdentity callerIdentity = new CallerIdentity(Binder.getCallingUid(),
|
||||
Binder.getCallingPid(), packageName);
|
||||
LinkedListener<IGnssMeasurementsListener> linkedListener = new LinkedListener<>(listener,
|
||||
"GnssMeasurementsListener", callerIdentity, this::removeGnssMeasurementsListener);
|
||||
IBinder binder = listener.asBinder();
|
||||
synchronized (mLock) {
|
||||
CallerIdentity callerIdentity = new CallerIdentity(Binder.getCallingUid(),
|
||||
Binder.getCallingPid(), packageName);
|
||||
mGnssMeasurementsListeners.put(listener.asBinder(), callerIdentity);
|
||||
if (!linkToListenerDeathNotificationLocked(binder, linkedListener)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mGnssMeasurementsListeners.put(binder, linkedListener);
|
||||
long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
if (isThrottlingExemptLocked(callerIdentity)
|
||||
|| isImportanceForeground(
|
||||
mActivityManager.getPackageImportance(packageName))) {
|
||||
return mGnssMeasurementsProvider.addListener(listener, callerIdentity);
|
||||
mGnssMeasurementsProvider.addListener(listener, callerIdentity);
|
||||
}
|
||||
return true;
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
|
||||
if (mGnssMeasurementsProvider == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
IBinder binder = listener.asBinder();
|
||||
synchronized (mLock) {
|
||||
LinkedListener<IGnssMeasurementsListener> linkedListener =
|
||||
mGnssMeasurementsListeners.remove(binder);
|
||||
if (linkedListener == null) {
|
||||
return;
|
||||
}
|
||||
unlinkFromListenerDeathNotificationLocked(binder, linkedListener);
|
||||
mGnssMeasurementsProvider.removeListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean linkToListenerDeathNotificationLocked(IBinder binder,
|
||||
LinkedListenerBase linkedListener) {
|
||||
try {
|
||||
binder.linkToDeath(linkedListener, 0 /* flags */);
|
||||
return true;
|
||||
} catch (RemoteException e) {
|
||||
// if the remote process registering the listener is already dead, just swallow the
|
||||
// exception and return
|
||||
Log.w(TAG, "Could not link " + linkedListener.mListenerName + " death callback.",
|
||||
e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean unlinkFromListenerDeathNotificationLocked(IBinder binder,
|
||||
LinkedListenerBase linkedListener) {
|
||||
try {
|
||||
binder.unlinkToDeath(linkedListener, 0 /* flags */);
|
||||
return true;
|
||||
} catch (NoSuchElementException e) {
|
||||
// if the death callback isn't connected (it should be...), log error,
|
||||
// swallow the exception and return
|
||||
Log.w(TAG, "Could not unlink " + linkedListener.mListenerName + " death callback.",
|
||||
e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2758,53 +2860,54 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
return mGnssMeasurementsProvider.getGnssCapabilities();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
|
||||
if (mGnssMeasurementsProvider == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized (mLock) {
|
||||
mGnssMeasurementsListeners.remove(listener.asBinder());
|
||||
mGnssMeasurementsProvider.removeListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addGnssNavigationMessageListener(
|
||||
IGnssNavigationMessageListener listener,
|
||||
String packageName) {
|
||||
IGnssNavigationMessageListener listener, String packageName) {
|
||||
if (!hasGnssPermissions(packageName) || mGnssNavigationMessageProvider == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CallerIdentity callerIdentity = new CallerIdentity(Binder.getCallingUid(),
|
||||
Binder.getCallingPid(), packageName);
|
||||
LinkedListener<IGnssNavigationMessageListener> linkedListener =
|
||||
new LinkedListener<>(listener, "GnssNavigationMessageListener", callerIdentity,
|
||||
this::removeGnssNavigationMessageListener);
|
||||
IBinder binder = listener.asBinder();
|
||||
synchronized (mLock) {
|
||||
CallerIdentity callerIdentity = new CallerIdentity(Binder.getCallingUid(),
|
||||
Binder.getCallingPid(), packageName);
|
||||
if (!linkToListenerDeathNotificationLocked(binder, linkedListener)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mGnssNavigationMessageListeners.put(listener.asBinder(), callerIdentity);
|
||||
mGnssNavigationMessageListeners.put(binder, linkedListener);
|
||||
long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
if (isThrottlingExemptLocked(callerIdentity)
|
||||
|| isImportanceForeground(
|
||||
mActivityManager.getPackageImportance(packageName))) {
|
||||
return mGnssNavigationMessageProvider.addListener(listener, callerIdentity);
|
||||
mGnssNavigationMessageProvider.addListener(listener, callerIdentity);
|
||||
}
|
||||
return true;
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
|
||||
if (mGnssNavigationMessageProvider != null) {
|
||||
synchronized (mLock) {
|
||||
mGnssNavigationMessageListeners.remove(listener.asBinder());
|
||||
mGnssNavigationMessageProvider.removeListener(listener);
|
||||
if (mGnssNavigationMessageProvider == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
IBinder binder = listener.asBinder();
|
||||
synchronized (mLock) {
|
||||
LinkedListener<IGnssNavigationMessageListener> linkedListener =
|
||||
mGnssNavigationMessageListeners.remove(binder);
|
||||
if (linkedListener == null) {
|
||||
return;
|
||||
}
|
||||
unlinkFromListenerDeathNotificationLocked(binder, linkedListener);
|
||||
mGnssNavigationMessageProvider.removeListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3368,18 +3471,14 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
pw.println(" " + record);
|
||||
}
|
||||
}
|
||||
|
||||
pw.println(" Active GnssMeasurement Listeners:");
|
||||
for (CallerIdentity callerIdentity : mGnssMeasurementsListeners.values()) {
|
||||
pw.println(" " + callerIdentity.mPid + " " + callerIdentity.mUid + " "
|
||||
+ callerIdentity.mPackageName + ": "
|
||||
+ isThrottlingExemptLocked(callerIdentity));
|
||||
}
|
||||
dumpGnssDataListenersLocked(pw, mGnssMeasurementsListeners);
|
||||
pw.println(" Active GnssNavigationMessage Listeners:");
|
||||
for (CallerIdentity callerIdentity : mGnssNavigationMessageListeners.values()) {
|
||||
pw.println(" " + callerIdentity.mPid + " " + callerIdentity.mUid + " "
|
||||
+ callerIdentity.mPackageName + ": "
|
||||
+ isThrottlingExemptLocked(callerIdentity));
|
||||
}
|
||||
dumpGnssDataListenersLocked(pw, mGnssNavigationMessageListeners);
|
||||
pw.println(" Active GnssStatus Listeners:");
|
||||
dumpGnssDataListenersLocked(pw, mGnssStatusListeners);
|
||||
|
||||
pw.println(" Historical Records by Provider:");
|
||||
for (Map.Entry<PackageProviderKey, PackageStatistics> entry
|
||||
: mRequestStatistics.statistics.entrySet()) {
|
||||
@@ -3432,4 +3531,15 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private void dumpGnssDataListenersLocked(PrintWriter pw,
|
||||
ArrayMap<IBinder, ? extends LinkedListenerBase> gnssDataListeners) {
|
||||
for (LinkedListenerBase listener : gnssDataListeners.values()) {
|
||||
CallerIdentity callerIdentity = listener.mCallerIdentity;
|
||||
pw.println(" " + callerIdentity.mPid + " " + callerIdentity.mUid + " "
|
||||
+ callerIdentity.mPackageName + ": "
|
||||
+ isThrottlingExemptLocked(callerIdentity));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,9 +31,11 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A helper class, that handles operations in remote listeners, and tracks for remote process death.
|
||||
* A helper class that handles operations in remote listeners.
|
||||
*
|
||||
* @param <TListener> the type of GNSS data listener.
|
||||
*/
|
||||
abstract class RemoteListenerHelper<TListener extends IInterface> {
|
||||
public abstract class RemoteListenerHelper<TListener extends IInterface> {
|
||||
|
||||
protected static final int RESULT_SUCCESS = 0;
|
||||
protected static final int RESULT_NOT_AVAILABLE = 1;
|
||||
@@ -46,7 +48,7 @@ abstract class RemoteListenerHelper<TListener extends IInterface> {
|
||||
protected final Handler mHandler;
|
||||
private final String mTag;
|
||||
|
||||
private final Map<IBinder, LinkedListener> mListenerMap = new HashMap<>();
|
||||
private final Map<IBinder, IdentifiedListener> mListenerMap = new HashMap<>();
|
||||
|
||||
protected final Context mContext;
|
||||
protected final AppOpsManager mAppOps;
|
||||
@@ -71,24 +73,21 @@ abstract class RemoteListenerHelper<TListener extends IInterface> {
|
||||
return mIsRegistered;
|
||||
}
|
||||
|
||||
public boolean addListener(@NonNull TListener listener, CallerIdentity callerIdentity) {
|
||||
/**
|
||||
* Adds GNSS data listener {@code listener} with caller identify {@code callerIdentify}.
|
||||
*/
|
||||
public void addListener(@NonNull TListener listener, CallerIdentity callerIdentity) {
|
||||
Preconditions.checkNotNull(listener, "Attempted to register a 'null' listener.");
|
||||
IBinder binder = listener.asBinder();
|
||||
LinkedListener deathListener = new LinkedListener(listener, callerIdentity);
|
||||
synchronized (mListenerMap) {
|
||||
if (mListenerMap.containsKey(binder)) {
|
||||
// listener already added
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
try {
|
||||
binder.linkToDeath(deathListener, 0 /* flags */);
|
||||
} catch (RemoteException e) {
|
||||
// if the remote process registering the listener is already death, just swallow the
|
||||
// exception and return
|
||||
Log.v(mTag, "Remote listener already died.", e);
|
||||
return false;
|
||||
}
|
||||
mListenerMap.put(binder, deathListener);
|
||||
|
||||
IdentifiedListener identifiedListener = new IdentifiedListener(listener,
|
||||
callerIdentity);
|
||||
mListenerMap.put(binder, identifiedListener);
|
||||
|
||||
// update statuses we already know about, starting from the ones that will never change
|
||||
int result;
|
||||
@@ -107,26 +106,23 @@ abstract class RemoteListenerHelper<TListener extends IInterface> {
|
||||
} else {
|
||||
// at this point if the supported flag is not set, the notification will be sent
|
||||
// asynchronously in the future
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
post(deathListener, getHandlerOperation(result));
|
||||
post(identifiedListener, getHandlerOperation(result));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove GNSS data listener {@code listener}.
|
||||
*/
|
||||
public void removeListener(@NonNull TListener listener) {
|
||||
Preconditions.checkNotNull(listener, "Attempted to remove a 'null' listener.");
|
||||
IBinder binder = listener.asBinder();
|
||||
LinkedListener linkedListener;
|
||||
synchronized (mListenerMap) {
|
||||
linkedListener = mListenerMap.remove(binder);
|
||||
mListenerMap.remove(listener.asBinder());
|
||||
if (mListenerMap.isEmpty()) {
|
||||
tryUnregister();
|
||||
}
|
||||
}
|
||||
if (linkedListener != null) {
|
||||
binder.unlinkToDeath(linkedListener, 0 /* flags */);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract boolean isAvailableInPlatform();
|
||||
@@ -198,14 +194,15 @@ abstract class RemoteListenerHelper<TListener extends IInterface> {
|
||||
}
|
||||
|
||||
private void foreachUnsafe(ListenerOperation<TListener> operation) {
|
||||
for (LinkedListener linkedListener : mListenerMap.values()) {
|
||||
post(linkedListener, operation);
|
||||
for (IdentifiedListener identifiedListener : mListenerMap.values()) {
|
||||
post(identifiedListener, operation);
|
||||
}
|
||||
}
|
||||
|
||||
private void post(LinkedListener linkedListener, ListenerOperation<TListener> operation) {
|
||||
private void post(IdentifiedListener identifiedListener,
|
||||
ListenerOperation<TListener> operation) {
|
||||
if (operation != null) {
|
||||
mHandler.post(new HandlerRunnable(linkedListener, operation));
|
||||
mHandler.post(new HandlerRunnable(identifiedListener, operation));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,35 +256,31 @@ abstract class RemoteListenerHelper<TListener extends IInterface> {
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
private class LinkedListener implements IBinder.DeathRecipient {
|
||||
private class IdentifiedListener {
|
||||
private final TListener mListener;
|
||||
private final CallerIdentity mCallerIdentity;
|
||||
|
||||
LinkedListener(@NonNull TListener listener, CallerIdentity callerIdentity) {
|
||||
private IdentifiedListener(@NonNull TListener listener, CallerIdentity callerIdentity) {
|
||||
mListener = listener;
|
||||
mCallerIdentity = callerIdentity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void binderDied() {
|
||||
Log.d(mTag, "Remote Listener died: " + mListener);
|
||||
removeListener(mListener);
|
||||
}
|
||||
}
|
||||
|
||||
private class HandlerRunnable implements Runnable {
|
||||
private final LinkedListener mLinkedListener;
|
||||
private final IdentifiedListener mIdentifiedListener;
|
||||
private final ListenerOperation<TListener> mOperation;
|
||||
|
||||
HandlerRunnable(LinkedListener linkedListener, ListenerOperation<TListener> operation) {
|
||||
mLinkedListener = linkedListener;
|
||||
private HandlerRunnable(IdentifiedListener identifiedListener,
|
||||
ListenerOperation<TListener> operation) {
|
||||
mIdentifiedListener = identifiedListener;
|
||||
mOperation = operation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
mOperation.execute(mLinkedListener.mListener, mLinkedListener.mCallerIdentity);
|
||||
mOperation.execute(mIdentifiedListener.mListener,
|
||||
mIdentifiedListener.mCallerIdentity);
|
||||
} catch (RemoteException e) {
|
||||
Log.v(mTag, "Error in monitored listener.", e);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user