diff options
author | Jonathan Scott <scottjonathan@google.com> | 2021-09-21 16:37:41 +0100 |
---|---|---|
committer | Jonathan Scott <scottjonathan@google.com> | 2021-09-21 16:37:41 +0100 |
commit | 1ea704c05a6f6120da0bba83663c28e4b69f02d7 (patch) | |
tree | 0bb6d94ce4a1e4dc54aad2bf353e9b7aa41935bf | |
parent | 2c546635a49710ebb6970b6ef455c27db8651128 (diff) | |
download | connectedappssdk-1ea704c05a6f6120da0bba83663c28e4b69f02d7.tar.gz |
Make Connected Apps SDK use only a single broadcast receiver.
This will be followed up with b/200687824
Test: atest CtsDevicePolicyTestCases
Fixes: 199188569
Fixes: 196845483
Fixes: 194696998
Change-Id: I21dadca9c5c3cead9e3376ea97f15f60b56cb9e1
2 files changed, 37 insertions, 6 deletions
diff --git a/sdk/src/main/java/com/google/android/enterprise/connectedapps/AbstractProfileConnector.java b/sdk/src/main/java/com/google/android/enterprise/connectedapps/AbstractProfileConnector.java index ae24257..cc71c7b 100644 --- a/sdk/src/main/java/com/google/android/enterprise/connectedapps/AbstractProfileConnector.java +++ b/sdk/src/main/java/com/google/android/enterprise/connectedapps/AbstractProfileConnector.java @@ -110,7 +110,6 @@ public abstract class AbstractProfileConnector /* availabilityListener= */ this, scheduledExecutorService, availabilityRestrictions); - crossProfileSender.beginMonitoringAvailabilityChanges(); } return crossProfileSender; } diff --git a/sdk/src/main/java/com/google/android/enterprise/connectedapps/CrossProfileSender.java b/sdk/src/main/java/com/google/android/enterprise/connectedapps/CrossProfileSender.java index fe34d09..9cc287b 100644 --- a/sdk/src/main/java/com/google/android/enterprise/connectedapps/CrossProfileSender.java +++ b/sdk/src/main/java/com/google/android/enterprise/connectedapps/CrossProfileSender.java @@ -18,6 +18,9 @@ package com.google.android.enterprise.connectedapps; import static com.google.android.enterprise.connectedapps.CrossProfileSDKUtilities.filterUsersByAvailabilityRestrictions; import static com.google.android.enterprise.connectedapps.CrossProfileSDKUtilities.selectUserHandleToBind; +import static java.util.Collections.newSetFromMap; +import static java.util.Collections.synchronizedSet; + import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; @@ -27,6 +30,7 @@ import android.content.ServiceConnection; import android.content.pm.CrossProfileApps; import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; +import android.os.Bundle; import android.os.IBinder; import android.os.Looper; import android.os.Parcel; @@ -41,8 +45,13 @@ import com.google.android.enterprise.connectedapps.internal.CrossProfileParcelCa import com.google.android.enterprise.connectedapps.internal.ParcelCallReceiver; import com.google.android.enterprise.connectedapps.internal.ParcelUtilities; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Objects; +import java.util.Set; +import java.util.WeakHashMap; import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ScheduledExecutorService; @@ -238,6 +247,11 @@ public class CrossProfileSender { @Nullable private volatile ScheduledFuture<Void> automaticDisconnectionFuture; private final AvailabilityRestrictions availabilityRestrictions; + // This is synchronized which isn't massively performant but it only gets accessed once straight + // after creating a Sender, and once each time availability changes + private static final Set<CrossProfileSender> senders = + synchronizedSet(newSetFromMap(new WeakHashMap<>())); + private boolean isManuallyManagingConnection = false; private ConcurrentLinkedDeque<OngoingCrossProfileCall> ongoingCrossProfileCalls = new ConcurrentLinkedDeque<>(); @@ -277,13 +291,18 @@ public class CrossProfileSender { canUseReflectedApis = ReflectionUtilities.canUseReflectedApis(); this.scheduledExecutorService = scheduledExecutorService; this.availabilityRestrictions = availabilityRestrictions; + + senders.add(this); + beginMonitoringAvailabilityChanges(); } - private final BroadcastReceiver profileAvailabilityReceiver = + private static final BroadcastReceiver profileAvailabilityReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - checkAvailability(); + for (CrossProfileSender sender : senders) { + sender.scheduledExecutorService.execute(sender::checkAvailability); + } } }; @@ -370,7 +389,13 @@ public class CrossProfileSender { return null; } - void beginMonitoringAvailabilityChanges() { + private static final AtomicBoolean isMonitoringAvailabilityChanges = new AtomicBoolean(false); + + private void beginMonitoringAvailabilityChanges() { + if (isMonitoringAvailabilityChanges.getAndSet(true)) { + return; + } + IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNLOCKED); filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE); @@ -593,10 +618,17 @@ public class CrossProfileSender { * @throws UnavailableProfileException if a connection is not already established */ public Parcel call(long crossProfileTypeIdentifier, int methodIdentifier, Parcel params) - throws UnavailableProfileException { + throws UnavailableProfileException { try { return callWithExceptions(crossProfileTypeIdentifier, methodIdentifier, params); - } catch (UnavailableProfileException | RuntimeException e) { + } catch (UnavailableProfileException | RuntimeException | Error e) { + StackTraceElement[] remoteStack = e.getStackTrace(); + StackTraceElement[] localStack = Thread.currentThread().getStackTrace(); + StackTraceElement[] totalStack = + Arrays.copyOf(remoteStack, remoteStack.length + localStack.length - 1); + // We cut off the first element of localStack as it is just getting the stack trace + System.arraycopy(localStack, 1, totalStack, remoteStack.length, localStack.length - 1); + e.setStackTrace(totalStack); throw e; } catch (Throwable e) { throw new UnavailableProfileException("Unexpected checked exception", e); |