diff options
author | Eugene Susla <eugenesusla@google.com> | 2017-03-14 10:26:10 -0700 |
---|---|---|
committer | Eugene Susla <eugenesusla@google.com> | 2017-03-24 14:03:17 -0700 |
commit | a38fbf63fd2a29884637a59387643c801ed4f663 (patch) | |
tree | 17a41c27bc5b8d2e3dd296bf49df2911f65285a0 /services/print | |
parent | cf0341ec5db251ef3030524c7ca8e51cef45cc40 (diff) |
Unbind from service on app killed and dedup association requests
1. Listen to calling package binder death stopping the scanning on that.
2. Don't restart scanning when a request with the same values was made.
Bug: 30932767
Test: 1.:
- Using a test app start scanning and kill the app.
- In debug mode ensure that DeviceDiscoveryService#stopScan gets triggered
2.:
- Start scanning and rotate the device while device chooser is visible
- Ensure no visible loss of state is happening
Change-Id: If126a2c963da90172a956fbd88e6b3dcd7ac8b01
Diffstat (limited to 'services/print')
-rw-r--r-- | services/print/java/com/android/server/print/CompanionDeviceManagerService.java | 77 |
1 files changed, 69 insertions, 8 deletions
diff --git a/services/print/java/com/android/server/print/CompanionDeviceManagerService.java b/services/print/java/com/android/server/print/CompanionDeviceManagerService.java index 9356dacc29f8..7790698d02e9 100644 --- a/services/print/java/com/android/server/print/CompanionDeviceManagerService.java +++ b/services/print/java/com/android/server/print/CompanionDeviceManagerService.java @@ -20,6 +20,7 @@ package com.android.server.print; import static com.android.internal.util.Preconditions.checkNotNull; import android.Manifest; +import android.annotation.CheckResult; import android.annotation.Nullable; import android.companion.AssociationRequest; import android.companion.CompanionDeviceManager; @@ -36,8 +37,11 @@ import android.content.pm.PackageManager; import android.net.NetworkPolicyManager; import android.os.Binder; import android.os.Environment; +import android.os.Handler; import android.os.IBinder; import android.os.IDeviceIdleController; +import android.os.IInterface; +import android.os.Parcel; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; @@ -68,11 +72,13 @@ import java.util.concurrent.ConcurrentMap; import java.util.function.Function; //TODO move to own package! -//TODO un/linkToDeath & onBinderDied - unbind //TODO onStop schedule unbind in 5 seconds -//TODO Prune association on app uninstall +//TODO make sure APIs are only callable from currently focused app +//TODO schedule stopScan on activity destroy(except if configuration change) +//TODO on associate called again after configuration change -> replace old callback with new +//TODO avoid leaking calling activity in IFindDeviceCallback (see PrintManager#print for example) /** @hide */ -public class CompanionDeviceManagerService extends SystemService { +public class CompanionDeviceManagerService extends SystemService implements Binder.DeathRecipient { private static final ComponentName SERVICE_TO_BIND_TO = ComponentName.createRelative( CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME, @@ -90,6 +96,8 @@ public class CompanionDeviceManagerService extends SystemService { private final CompanionDeviceManagerImpl mImpl; private final ConcurrentMap<Integer, AtomicFile> mUidToStorage = new ConcurrentHashMap<>(); private IDeviceIdleController mIdleController; + private IFindDeviceCallback mFindDeviceCallback; + private ServiceConnection mServiceConnection; public CompanionDeviceManagerService(Context context) { super(context); @@ -125,7 +133,51 @@ public class CompanionDeviceManagerService extends SystemService { publishBinderService(Context.COMPANION_DEVICE_SERVICE, mImpl); } + @Override + public void binderDied() { + Handler.getMain().post(this::handleBinderDied); + } + + private void handleBinderDied() { + mServiceConnection = unbind(mServiceConnection); + mFindDeviceCallback = unlinkToDeath(mFindDeviceCallback, this, 0); + } + + /** + * Usage: {@code a = unlinkToDeath(a, deathRecipient, flags); } + */ + @Nullable + @CheckResult + private static <T extends IInterface> T unlinkToDeath(T iinterface, + IBinder.DeathRecipient deathRecipient, int flags) { + if (iinterface != null) { + iinterface.asBinder().unlinkToDeath(deathRecipient, flags); + } + return null; + } + + @Nullable + @CheckResult + private ServiceConnection unbind(@Nullable ServiceConnection conn) { + if (conn != null) { + getContext().unbindService(conn); + } + return null; + } + class CompanionDeviceManagerImpl extends ICompanionDeviceManager.Stub { + + @Override + public boolean onTransact(int code, Parcel data, Parcel reply, int flags) + throws RemoteException { + try { + return super.onTransact(code, data, reply, flags); + } catch (Throwable e) { + Slog.e(LOG_TAG, "Error during IPC", e); + throw ExceptionUtils.propagate(e, RemoteException.class); + } + } + @Override public void associate( AssociationRequest request, @@ -135,14 +187,14 @@ public class CompanionDeviceManagerService extends SystemService { Slog.i(LOG_TAG, "associate(request = " + request + ", callback = " + callback + ", callingPackage = " + callingPackage + ")"); } - checkNotNull(request); - checkNotNull(callback); + checkNotNull(request, "Request cannot be null"); + checkNotNull(callback, "Callback cannot be null"); final long callingIdentity = Binder.clearCallingIdentity(); try { //TODO bindServiceAsUser getContext().bindService( new Intent().setComponent(SERVICE_TO_BIND_TO), - getServiceConnection(request, callback, callingPackage), + createServiceConnection(request, callback, callingPackage), Context.BIND_AUTO_CREATE); } finally { Binder.restoreCallingIdentity(callingIdentity); @@ -168,11 +220,11 @@ public class CompanionDeviceManagerService extends SystemService { return UserHandle.getUserId(Binder.getCallingUid()); } - private ServiceConnection getServiceConnection( + private ServiceConnection createServiceConnection( final AssociationRequest request, final IFindDeviceCallback findDeviceCallback, final String callingPackage) { - return new ServiceConnection() { + mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { if (DEBUG) { @@ -180,6 +232,14 @@ public class CompanionDeviceManagerService extends SystemService { "onServiceConnected(name = " + name + ", service = " + service + ")"); } + mFindDeviceCallback = findDeviceCallback; + try { + mFindDeviceCallback.asBinder().linkToDeath( + CompanionDeviceManagerService.this, 0); + } catch (RemoteException e) { + handleBinderDied(); + return; + } try { ICompanionDeviceDiscoveryService.Stub .asInterface(service) @@ -198,6 +258,7 @@ public class CompanionDeviceManagerService extends SystemService { if (DEBUG) Slog.i(LOG_TAG, "onServiceDisconnected(name = " + name + ")"); } }; + return mServiceConnection; } private ICompanionDeviceDiscoveryServiceCallback.Stub getServiceCallback() { |