Loading services/core/java/com/android/server/ServiceWatcher.java +30 −24 Original line number Diff line number Diff line Loading @@ -80,10 +80,16 @@ public class ServiceWatcher implements ServiceConnection { default void onError() {} } /** Function to run on binder interface when first bound. */ public interface OnBindRunner { /** Called to run client code with the binder. */ void run(IBinder binder, ComponentName service) throws RemoteException; } /** * Information on the service ServiceWatcher has selected as the best option for binding. */ public static final class ServiceInfo implements Comparable<ServiceInfo> { private static final class ServiceInfo implements Comparable<ServiceInfo> { public static final ServiceInfo NONE = new ServiceInfo(Integer.MIN_VALUE, null, UserHandle.USER_NULL, false); Loading Loading @@ -179,25 +185,25 @@ public class ServiceWatcher implements ServiceConnection { private final Handler mHandler; private final Intent mIntent; @Nullable private final BinderRunner mOnBind; @Nullable private final OnBindRunner mOnBind; @Nullable private final Runnable mOnUnbind; // read/write from handler thread only private int mCurrentUserId; // write from handler thread only, read anywhere private volatile ServiceInfo mServiceInfo; private volatile ServiceInfo mTargetService; private volatile IBinder mBinder; public ServiceWatcher(Context context, String action, @Nullable BinderRunner onBind, @Nullable Runnable onUnbind, @Nullable OnBindRunner onBind, @Nullable Runnable onUnbind, @BoolRes int enableOverlayResId, @StringRes int nonOverlayPackageResId) { this(context, FgThread.getHandler(), action, onBind, onUnbind, enableOverlayResId, nonOverlayPackageResId); } public ServiceWatcher(Context context, Handler handler, String action, @Nullable BinderRunner onBind, @Nullable Runnable onUnbind, @Nullable OnBindRunner onBind, @Nullable Runnable onUnbind, @BoolRes int enableOverlayResId, @StringRes int nonOverlayPackageResId) { mContext = context; mHandler = handler; Loading @@ -214,7 +220,7 @@ public class ServiceWatcher implements ServiceConnection { mCurrentUserId = UserHandle.USER_NULL; mServiceInfo = ServiceInfo.NONE; mTargetService = ServiceInfo.NONE; mBinder = null; } Loading Loading @@ -304,7 +310,7 @@ public class ServiceWatcher implements ServiceConnection { } } if (forceRebind || !bestServiceInfo.equals(mServiceInfo)) { if (forceRebind || !bestServiceInfo.equals(mTargetService)) { rebind(bestServiceInfo); } } Loading @@ -312,32 +318,32 @@ public class ServiceWatcher implements ServiceConnection { private void rebind(ServiceInfo newServiceInfo) { Preconditions.checkState(Looper.myLooper() == mHandler.getLooper()); if (!mServiceInfo.equals(ServiceInfo.NONE)) { if (!mTargetService.equals(ServiceInfo.NONE)) { if (D) { Log.i(TAG, "[" + mIntent.getAction() + "] unbinding from " + mServiceInfo); Log.i(TAG, "[" + mIntent.getAction() + "] unbinding from " + mTargetService); } mContext.unbindService(this); onServiceDisconnected(mServiceInfo.component); mServiceInfo = ServiceInfo.NONE; onServiceDisconnected(mTargetService.component); mTargetService = ServiceInfo.NONE; } mServiceInfo = newServiceInfo; if (mServiceInfo.equals(ServiceInfo.NONE)) { mTargetService = newServiceInfo; if (mTargetService.equals(ServiceInfo.NONE)) { return; } Preconditions.checkState(mServiceInfo.component != null); Preconditions.checkState(mTargetService.component != null); if (D) { Log.i(TAG, getLogPrefix() + " binding to " + mServiceInfo); Log.i(TAG, getLogPrefix() + " binding to " + mTargetService); } Intent bindIntent = new Intent(mIntent).setComponent(mServiceInfo.component); Intent bindIntent = new Intent(mIntent).setComponent(mTargetService.component); if (!mContext.bindServiceAsUser(bindIntent, this, BIND_AUTO_CREATE | BIND_NOT_FOREGROUND | BIND_NOT_VISIBLE, mHandler, UserHandle.of(mServiceInfo.userId))) { mServiceInfo = ServiceInfo.NONE; mHandler, UserHandle.of(mTargetService.userId))) { mTargetService = ServiceInfo.NONE; Log.e(TAG, getLogPrefix() + " unexpected bind failure - retrying later"); mHandler.postDelayed(() -> onBestServiceChanged(false), RETRY_DELAY_MS); } Loading @@ -355,11 +361,11 @@ public class ServiceWatcher implements ServiceConnection { mBinder = binder; if (mOnBind != null) { try { mOnBind.run(binder); mOnBind.run(binder, component); } catch (RuntimeException | RemoteException e) { // binders may propagate some specific non-RemoteExceptions from the other side // through the binder as well - we cannot allow those to crash the system server Log.e(TAG, getLogPrefix() + " exception running on " + mServiceInfo, e); Log.e(TAG, getLogPrefix() + " exception running on " + component, e); } } } Loading Loading @@ -406,7 +412,7 @@ public class ServiceWatcher implements ServiceConnection { void onPackageChanged(String packageName) { // force a rebind if the changed package was the currently connected package onBestServiceChanged(packageName.equals(mServiceInfo.getPackageName())); onBestServiceChanged(packageName.equals(mTargetService.getPackageName())); } /** Loading @@ -425,7 +431,7 @@ public class ServiceWatcher implements ServiceConnection { } catch (RuntimeException | RemoteException e) { // binders may propagate some specific non-RemoteExceptions from the other side // through the binder as well - we cannot allow those to crash the system server Log.e(TAG, getLogPrefix() + " exception running on " + mServiceInfo, e); Log.e(TAG, getLogPrefix() + " exception running on " + mTargetService, e); runner.onError(); } }); Loading @@ -437,14 +443,14 @@ public class ServiceWatcher implements ServiceConnection { @Override public String toString() { return mServiceInfo.toString(); return mTargetService.toString(); } /** * Dump for debugging. */ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("service=" + mServiceInfo); pw.println("target service=" + mTargetService); pw.println("connected=" + (mBinder != null)); } } services/core/java/com/android/server/location/HardwareActivityRecognitionProxy.java +2 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server.location; import android.annotation.Nullable; import android.content.ComponentName; import android.content.Context; import android.hardware.location.ActivityRecognitionHardware; import android.hardware.location.IActivityRecognitionHardwareClient; Loading Loading @@ -77,7 +78,7 @@ public class HardwareActivityRecognitionProxy { return mServiceWatcher.register(); } private void onBind(IBinder binder) throws RemoteException { private void onBind(IBinder binder, ComponentName service) throws RemoteException { String descriptor = binder.getInterfaceDescriptor(); if (IActivityRecognitionHardwareWatcher.class.getCanonicalName().equals(descriptor)) { Loading services/core/java/com/android/server/location/LocationProviderProxy.java +19 −8 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.location; import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR; import android.annotation.Nullable; import android.content.ComponentName; import android.content.Context; import android.location.Location; import android.location.util.identity.CallerIdentity; Loading @@ -32,10 +33,12 @@ import com.android.internal.location.ILocationProvider; import com.android.internal.location.ILocationProviderManager; import com.android.internal.location.ProviderProperties; import com.android.internal.location.ProviderRequest; import com.android.internal.util.ArrayUtils; import com.android.server.ServiceWatcher; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.Objects; /** * Proxy for ILocationProvider implementations. Loading Loading @@ -65,6 +68,8 @@ public class LocationProviderProxy extends AbstractLocationProvider { @GuardedBy("mLock") Proxy mProxy; @GuardedBy("mLock") @Nullable ComponentName mService; private volatile ProviderRequest mRequest; Loading @@ -86,11 +91,12 @@ public class LocationProviderProxy extends AbstractLocationProvider { return mServiceWatcher.register(); } private void onBind(IBinder binder) throws RemoteException { private void onBind(IBinder binder, ComponentName service) throws RemoteException { ILocationProvider provider = ILocationProvider.Stub.asInterface(binder); synchronized (mLock) { mProxy = new Proxy(); mService = service; provider.setLocationProviderManager(mProxy); ProviderRequest request = mRequest; Loading @@ -103,6 +109,7 @@ public class LocationProviderProxy extends AbstractLocationProvider { private void onUnbind() { synchronized (mLock) { mProxy = null; mService = null; setState(State.EMPTY_STATE); } } Loading @@ -111,16 +118,16 @@ public class LocationProviderProxy extends AbstractLocationProvider { public void onSetRequest(ProviderRequest request) { mRequest = request; mServiceWatcher.runOnBinder(binder -> { ILocationProvider service = ILocationProvider.Stub.asInterface(binder); service.setRequest(request, request.workSource); ILocationProvider provider = ILocationProvider.Stub.asInterface(binder); provider.setRequest(request, request.workSource); }); } @Override public void onExtraCommand(int uid, int pid, String command, Bundle extras) { mServiceWatcher.runOnBinder(binder -> { ILocationProvider service = ILocationProvider.Stub.asInterface(binder); service.sendExtraCommand(command, extras); ILocationProvider provider = ILocationProvider.Stub.asInterface(binder); provider.sendExtraCommand(command, extras); }); } Loading @@ -129,12 +136,14 @@ public class LocationProviderProxy extends AbstractLocationProvider { mServiceWatcher.dump(fd, pw, args); } private static String guessPackageName(Context context, int uid) { private static String guessPackageName(Context context, int uid, String packageName) { String[] packageNames = context.getPackageManager().getPackagesForUid(uid); if (packageNames == null || packageNames.length == 0) { // illegal state exception will propagate back through binders throw new IllegalStateException( "location provider from uid " + uid + " has no package information"); } else if (ArrayUtils.contains(packageNames, packageName)) { return packageName; } else { return packageNames[0]; } Loading @@ -154,7 +163,8 @@ public class LocationProviderProxy extends AbstractLocationProvider { CallerIdentity identity; if (packageName == null) { packageName = guessPackageName(mContext, Binder.getCallingUid()); packageName = guessPackageName(mContext, Binder.getCallingUid(), Objects.requireNonNull(mService).getPackageName()); // unsafe is ok since the package is coming direct from the package manager here identity = CallerIdentity.fromBinderUnsafe(packageName, attributionTag); } else { Loading @@ -175,7 +185,8 @@ public class LocationProviderProxy extends AbstractLocationProvider { // if no identity is set yet, set it now if (getIdentity() == null) { String packageName = guessPackageName(mContext, Binder.getCallingUid()); String packageName = guessPackageName(mContext, Binder.getCallingUid(), Objects.requireNonNull(mService).getPackageName()); // unsafe is ok since the package is coming direct from the package manager here setIdentity(CallerIdentity.fromBinderUnsafe(packageName, null)); } Loading services/core/java/com/android/server/location/geofence/GeofenceProxy.java +1 −1 Original line number Diff line number Diff line Loading @@ -63,7 +63,7 @@ public final class GeofenceProxy { private GeofenceProxy(Context context, IGpsGeofenceHardware gpsGeofence) { mGpsGeofenceHardware = Objects.requireNonNull(gpsGeofence); mServiceWatcher = new ServiceWatcher(context, SERVICE_ACTION, this::updateGeofenceHardware, null, (binder, service) -> updateGeofenceHardware(binder), null, com.android.internal.R.bool.config_enableGeofenceOverlay, com.android.internal.R.string.config_geofenceProviderPackageName); Loading Loading
services/core/java/com/android/server/ServiceWatcher.java +30 −24 Original line number Diff line number Diff line Loading @@ -80,10 +80,16 @@ public class ServiceWatcher implements ServiceConnection { default void onError() {} } /** Function to run on binder interface when first bound. */ public interface OnBindRunner { /** Called to run client code with the binder. */ void run(IBinder binder, ComponentName service) throws RemoteException; } /** * Information on the service ServiceWatcher has selected as the best option for binding. */ public static final class ServiceInfo implements Comparable<ServiceInfo> { private static final class ServiceInfo implements Comparable<ServiceInfo> { public static final ServiceInfo NONE = new ServiceInfo(Integer.MIN_VALUE, null, UserHandle.USER_NULL, false); Loading Loading @@ -179,25 +185,25 @@ public class ServiceWatcher implements ServiceConnection { private final Handler mHandler; private final Intent mIntent; @Nullable private final BinderRunner mOnBind; @Nullable private final OnBindRunner mOnBind; @Nullable private final Runnable mOnUnbind; // read/write from handler thread only private int mCurrentUserId; // write from handler thread only, read anywhere private volatile ServiceInfo mServiceInfo; private volatile ServiceInfo mTargetService; private volatile IBinder mBinder; public ServiceWatcher(Context context, String action, @Nullable BinderRunner onBind, @Nullable Runnable onUnbind, @Nullable OnBindRunner onBind, @Nullable Runnable onUnbind, @BoolRes int enableOverlayResId, @StringRes int nonOverlayPackageResId) { this(context, FgThread.getHandler(), action, onBind, onUnbind, enableOverlayResId, nonOverlayPackageResId); } public ServiceWatcher(Context context, Handler handler, String action, @Nullable BinderRunner onBind, @Nullable Runnable onUnbind, @Nullable OnBindRunner onBind, @Nullable Runnable onUnbind, @BoolRes int enableOverlayResId, @StringRes int nonOverlayPackageResId) { mContext = context; mHandler = handler; Loading @@ -214,7 +220,7 @@ public class ServiceWatcher implements ServiceConnection { mCurrentUserId = UserHandle.USER_NULL; mServiceInfo = ServiceInfo.NONE; mTargetService = ServiceInfo.NONE; mBinder = null; } Loading Loading @@ -304,7 +310,7 @@ public class ServiceWatcher implements ServiceConnection { } } if (forceRebind || !bestServiceInfo.equals(mServiceInfo)) { if (forceRebind || !bestServiceInfo.equals(mTargetService)) { rebind(bestServiceInfo); } } Loading @@ -312,32 +318,32 @@ public class ServiceWatcher implements ServiceConnection { private void rebind(ServiceInfo newServiceInfo) { Preconditions.checkState(Looper.myLooper() == mHandler.getLooper()); if (!mServiceInfo.equals(ServiceInfo.NONE)) { if (!mTargetService.equals(ServiceInfo.NONE)) { if (D) { Log.i(TAG, "[" + mIntent.getAction() + "] unbinding from " + mServiceInfo); Log.i(TAG, "[" + mIntent.getAction() + "] unbinding from " + mTargetService); } mContext.unbindService(this); onServiceDisconnected(mServiceInfo.component); mServiceInfo = ServiceInfo.NONE; onServiceDisconnected(mTargetService.component); mTargetService = ServiceInfo.NONE; } mServiceInfo = newServiceInfo; if (mServiceInfo.equals(ServiceInfo.NONE)) { mTargetService = newServiceInfo; if (mTargetService.equals(ServiceInfo.NONE)) { return; } Preconditions.checkState(mServiceInfo.component != null); Preconditions.checkState(mTargetService.component != null); if (D) { Log.i(TAG, getLogPrefix() + " binding to " + mServiceInfo); Log.i(TAG, getLogPrefix() + " binding to " + mTargetService); } Intent bindIntent = new Intent(mIntent).setComponent(mServiceInfo.component); Intent bindIntent = new Intent(mIntent).setComponent(mTargetService.component); if (!mContext.bindServiceAsUser(bindIntent, this, BIND_AUTO_CREATE | BIND_NOT_FOREGROUND | BIND_NOT_VISIBLE, mHandler, UserHandle.of(mServiceInfo.userId))) { mServiceInfo = ServiceInfo.NONE; mHandler, UserHandle.of(mTargetService.userId))) { mTargetService = ServiceInfo.NONE; Log.e(TAG, getLogPrefix() + " unexpected bind failure - retrying later"); mHandler.postDelayed(() -> onBestServiceChanged(false), RETRY_DELAY_MS); } Loading @@ -355,11 +361,11 @@ public class ServiceWatcher implements ServiceConnection { mBinder = binder; if (mOnBind != null) { try { mOnBind.run(binder); mOnBind.run(binder, component); } catch (RuntimeException | RemoteException e) { // binders may propagate some specific non-RemoteExceptions from the other side // through the binder as well - we cannot allow those to crash the system server Log.e(TAG, getLogPrefix() + " exception running on " + mServiceInfo, e); Log.e(TAG, getLogPrefix() + " exception running on " + component, e); } } } Loading Loading @@ -406,7 +412,7 @@ public class ServiceWatcher implements ServiceConnection { void onPackageChanged(String packageName) { // force a rebind if the changed package was the currently connected package onBestServiceChanged(packageName.equals(mServiceInfo.getPackageName())); onBestServiceChanged(packageName.equals(mTargetService.getPackageName())); } /** Loading @@ -425,7 +431,7 @@ public class ServiceWatcher implements ServiceConnection { } catch (RuntimeException | RemoteException e) { // binders may propagate some specific non-RemoteExceptions from the other side // through the binder as well - we cannot allow those to crash the system server Log.e(TAG, getLogPrefix() + " exception running on " + mServiceInfo, e); Log.e(TAG, getLogPrefix() + " exception running on " + mTargetService, e); runner.onError(); } }); Loading @@ -437,14 +443,14 @@ public class ServiceWatcher implements ServiceConnection { @Override public String toString() { return mServiceInfo.toString(); return mTargetService.toString(); } /** * Dump for debugging. */ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("service=" + mServiceInfo); pw.println("target service=" + mTargetService); pw.println("connected=" + (mBinder != null)); } }
services/core/java/com/android/server/location/HardwareActivityRecognitionProxy.java +2 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server.location; import android.annotation.Nullable; import android.content.ComponentName; import android.content.Context; import android.hardware.location.ActivityRecognitionHardware; import android.hardware.location.IActivityRecognitionHardwareClient; Loading Loading @@ -77,7 +78,7 @@ public class HardwareActivityRecognitionProxy { return mServiceWatcher.register(); } private void onBind(IBinder binder) throws RemoteException { private void onBind(IBinder binder, ComponentName service) throws RemoteException { String descriptor = binder.getInterfaceDescriptor(); if (IActivityRecognitionHardwareWatcher.class.getCanonicalName().equals(descriptor)) { Loading
services/core/java/com/android/server/location/LocationProviderProxy.java +19 −8 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.location; import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR; import android.annotation.Nullable; import android.content.ComponentName; import android.content.Context; import android.location.Location; import android.location.util.identity.CallerIdentity; Loading @@ -32,10 +33,12 @@ import com.android.internal.location.ILocationProvider; import com.android.internal.location.ILocationProviderManager; import com.android.internal.location.ProviderProperties; import com.android.internal.location.ProviderRequest; import com.android.internal.util.ArrayUtils; import com.android.server.ServiceWatcher; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.Objects; /** * Proxy for ILocationProvider implementations. Loading Loading @@ -65,6 +68,8 @@ public class LocationProviderProxy extends AbstractLocationProvider { @GuardedBy("mLock") Proxy mProxy; @GuardedBy("mLock") @Nullable ComponentName mService; private volatile ProviderRequest mRequest; Loading @@ -86,11 +91,12 @@ public class LocationProviderProxy extends AbstractLocationProvider { return mServiceWatcher.register(); } private void onBind(IBinder binder) throws RemoteException { private void onBind(IBinder binder, ComponentName service) throws RemoteException { ILocationProvider provider = ILocationProvider.Stub.asInterface(binder); synchronized (mLock) { mProxy = new Proxy(); mService = service; provider.setLocationProviderManager(mProxy); ProviderRequest request = mRequest; Loading @@ -103,6 +109,7 @@ public class LocationProviderProxy extends AbstractLocationProvider { private void onUnbind() { synchronized (mLock) { mProxy = null; mService = null; setState(State.EMPTY_STATE); } } Loading @@ -111,16 +118,16 @@ public class LocationProviderProxy extends AbstractLocationProvider { public void onSetRequest(ProviderRequest request) { mRequest = request; mServiceWatcher.runOnBinder(binder -> { ILocationProvider service = ILocationProvider.Stub.asInterface(binder); service.setRequest(request, request.workSource); ILocationProvider provider = ILocationProvider.Stub.asInterface(binder); provider.setRequest(request, request.workSource); }); } @Override public void onExtraCommand(int uid, int pid, String command, Bundle extras) { mServiceWatcher.runOnBinder(binder -> { ILocationProvider service = ILocationProvider.Stub.asInterface(binder); service.sendExtraCommand(command, extras); ILocationProvider provider = ILocationProvider.Stub.asInterface(binder); provider.sendExtraCommand(command, extras); }); } Loading @@ -129,12 +136,14 @@ public class LocationProviderProxy extends AbstractLocationProvider { mServiceWatcher.dump(fd, pw, args); } private static String guessPackageName(Context context, int uid) { private static String guessPackageName(Context context, int uid, String packageName) { String[] packageNames = context.getPackageManager().getPackagesForUid(uid); if (packageNames == null || packageNames.length == 0) { // illegal state exception will propagate back through binders throw new IllegalStateException( "location provider from uid " + uid + " has no package information"); } else if (ArrayUtils.contains(packageNames, packageName)) { return packageName; } else { return packageNames[0]; } Loading @@ -154,7 +163,8 @@ public class LocationProviderProxy extends AbstractLocationProvider { CallerIdentity identity; if (packageName == null) { packageName = guessPackageName(mContext, Binder.getCallingUid()); packageName = guessPackageName(mContext, Binder.getCallingUid(), Objects.requireNonNull(mService).getPackageName()); // unsafe is ok since the package is coming direct from the package manager here identity = CallerIdentity.fromBinderUnsafe(packageName, attributionTag); } else { Loading @@ -175,7 +185,8 @@ public class LocationProviderProxy extends AbstractLocationProvider { // if no identity is set yet, set it now if (getIdentity() == null) { String packageName = guessPackageName(mContext, Binder.getCallingUid()); String packageName = guessPackageName(mContext, Binder.getCallingUid(), Objects.requireNonNull(mService).getPackageName()); // unsafe is ok since the package is coming direct from the package manager here setIdentity(CallerIdentity.fromBinderUnsafe(packageName, null)); } Loading
services/core/java/com/android/server/location/geofence/GeofenceProxy.java +1 −1 Original line number Diff line number Diff line Loading @@ -63,7 +63,7 @@ public final class GeofenceProxy { private GeofenceProxy(Context context, IGpsGeofenceHardware gpsGeofence) { mGpsGeofenceHardware = Objects.requireNonNull(gpsGeofence); mServiceWatcher = new ServiceWatcher(context, SERVICE_ACTION, this::updateGeofenceHardware, null, (binder, service) -> updateGeofenceHardware(binder), null, com.android.internal.R.bool.config_enableGeofenceOverlay, com.android.internal.R.string.config_geofenceProviderPackageName); Loading