Project import generated by Copybara.
GitOrigin-RevId: e94def3f29fe23446b4f16a161673e1a2f36c816
diff --git a/browser/src/main/java/androidx/browser/trusted/ConnectionHolder.java b/browser/src/main/java/androidx/browser/trusted/ConnectionHolder.java
index d00de95..c94a75f 100644
--- a/browser/src/main/java/androidx/browser/trusted/ConnectionHolder.java
+++ b/browser/src/main/java/androidx/browser/trusted/ConnectionHolder.java
@@ -46,16 +46,16 @@
@NonNull private final WrapperFactory mWrapperFactory;
private int mState = STATE_AWAITING_CONNECTION;
- @Nullable private TrustedWebActivityServiceWrapper mService;
- @NonNull private List<Completer<TrustedWebActivityServiceWrapper>> mCompleters =
+ @Nullable private TrustedWebActivityServiceConnection mService;
+ @NonNull private List<Completer<TrustedWebActivityServiceConnection>> mCompleters =
new ArrayList<>();
@Nullable private Exception mCancellationException;
- /** A class that creates the TrustedWebActivityServiceWrapper. Allows mocking in tests. */
+ /** A class that creates the TrustedWebActivityServiceConnection. Allows mocking in tests. */
static class WrapperFactory {
@NonNull
- TrustedWebActivityServiceWrapper create(ComponentName name, IBinder iBinder) {
- return new TrustedWebActivityServiceWrapper(
+ TrustedWebActivityServiceConnection create(ComponentName name, IBinder iBinder) {
+ return new TrustedWebActivityServiceConnection(
ITrustedWebActivityService.Stub.asInterface(iBinder), name);
}
}
@@ -81,7 +81,7 @@
@MainThread
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
mService = mWrapperFactory.create(componentName, iBinder);
- for (Completer<TrustedWebActivityServiceWrapper> completer : mCompleters) {
+ for (Completer<TrustedWebActivityServiceConnection> completer : mCompleters) {
completer.set(mService);
}
mCompleters.clear();
@@ -105,7 +105,7 @@
*/
@MainThread
public void cancel(@NonNull Exception exception) {
- for (Completer<TrustedWebActivityServiceWrapper> completer : mCompleters) {
+ for (Completer<TrustedWebActivityServiceConnection> completer : mCompleters) {
completer.setException(exception);
}
mCompleters.clear();
@@ -117,12 +117,12 @@
/**
* Returns a future that will:
* - be unset if a connection is still pending and set once open.
- * - be set to a {@link TrustedWebActivityServiceWrapper} if a connection is open.
+ * - be set to a {@link TrustedWebActivityServiceConnection} if a connection is open.
* - be set to an exception if the connection failed or has been closed.
*/
@MainThread
@NonNull
- public ListenableFuture<TrustedWebActivityServiceWrapper> getServiceWrapper() {
+ public ListenableFuture<TrustedWebActivityServiceConnection> getServiceWrapper() {
// Using CallbackToFutureAdapter and storing the completers gives us some additional safety
// checks over using Futures ourselves (such as failing the Future if the completer is
// garbage collected).
diff --git a/browser/src/main/java/androidx/browser/trusted/NotificationApiHelperForM.java b/browser/src/main/java/androidx/browser/trusted/NotificationApiHelperForM.java
index 325eca0..cc1d732 100644
--- a/browser/src/main/java/androidx/browser/trusted/NotificationApiHelperForM.java
+++ b/browser/src/main/java/androidx/browser/trusted/NotificationApiHelperForM.java
@@ -20,6 +20,7 @@
import android.os.Build;
import android.os.Parcelable;
+import android.support.annotation.NonNull;
import android.support.annotation.RequiresApi;
import android.support.annotation.RestrictTo;
@@ -40,6 +41,7 @@
* being verified on earlier Jellybean builds.
*/
@RequiresApi(Build.VERSION_CODES.M)
+ @NonNull
static Parcelable[] getActiveNotifications(NotificationManager manager) {
return manager.getActiveNotifications();
}
diff --git a/browser/src/main/java/androidx/browser/trusted/TrustedWebActivityService.java b/browser/src/main/java/androidx/browser/trusted/TrustedWebActivityService.java
index e4a152f..6e67822 100644
--- a/browser/src/main/java/androidx/browser/trusted/TrustedWebActivityService.java
+++ b/browser/src/main/java/androidx/browser/trusted/TrustedWebActivityService.java
@@ -35,15 +35,17 @@
import android.os.StrictMode;
import android.support.customtabs.trusted.ITrustedWebActivityService;
+import android.support.annotation.BinderThread;
import android.support.annotation.CallSuper;
+import android.support.annotation.MainThread;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RestrictTo;
-import androidx.browser.trusted.TrustedWebActivityServiceWrapper.ActiveNotificationsArgs;
-import androidx.browser.trusted.TrustedWebActivityServiceWrapper.CancelNotificationArgs;
-import androidx.browser.trusted.TrustedWebActivityServiceWrapper.NotificationsEnabledArgs;
-import androidx.browser.trusted.TrustedWebActivityServiceWrapper.NotifyNotificationArgs;
-import androidx.browser.trusted.TrustedWebActivityServiceWrapper.ResultArgs;
+import androidx.browser.trusted.TrustedWebActivityServiceConnection.ActiveNotificationsArgs;
+import androidx.browser.trusted.TrustedWebActivityServiceConnection.CancelNotificationArgs;
+import androidx.browser.trusted.TrustedWebActivityServiceConnection.NotificationsEnabledArgs;
+import androidx.browser.trusted.TrustedWebActivityServiceConnection.NotifyNotificationArgs;
+import androidx.browser.trusted.TrustedWebActivityServiceConnection.ResultArgs;
import android.support.v4.app.NotificationManagerCompat;
import java.util.Arrays;
@@ -81,13 +83,16 @@
* Alternatively for greater customization, TrustedWebActivityService can be extended and
* overridden. In this case the manifest entry should be updated to point to the extending class.
* <p>
- * As this is an AIDL Service, calls to {@link #getSmallIconId},
- * {@link #notifyNotificationWithChannel} and {@link #cancelNotification} can occur on different
- * Binder threads, so overriding implementations need to be thread-safe.
+ * As this is an AIDL Service, calls may come in from different Binder threads, so overriding
+ * implementations need to be thread safe [1].
* <p>
* For security, the TrustedWebActivityService will check that whatever connects to it is the
* Trusted Web Activity provider that it was previously verified with (through
* {@link #setVerifiedProvider}).
+ * This is because we don't want to allow any app on the users device to connect to this Service
+ * be able to make it display notifications.
+ *
+ * [1]: https://developer.android.com/guide/components/aidl.html
*/
public class TrustedWebActivityService extends Service {
/** An Intent Action used by the provider to find the TrustedWebActivityService or subclass. */
@@ -102,11 +107,13 @@
public static final String META_DATA_NAME_SMALL_ICON =
"android.support.customtabs.trusted.SMALL_ICON";
- /** The key to use to store a Bitmap to return from the {@link #getSmallIconBitmap()} method. */
+ /**
+ * The key to use to store a Bitmap to return from the {@link #onGetSmallIconBitmap()} method.
+ */
public static final String KEY_SMALL_ICON_BITMAP =
"android.support.customtabs.trusted.SMALL_ICON_BITMAP";
- /** Used as a return value of {@link #getSmallIconId} when the icon is not provided. */
+ /** Used as a return value of {@link #onGetSmallIconId} when the icon is not provided. */
public static final int SMALL_ICON_NOT_SET = -1;
private static final String PREFS_FILE = "TrustedWebActivityVerifiedProvider";
@@ -125,7 +132,7 @@
NotificationsEnabledArgs args = NotificationsEnabledArgs.fromBundle(bundle);
boolean result =
- TrustedWebActivityService.this.areNotificationsEnabled(args.channelName);
+ TrustedWebActivityService.this.onAreNotificationsEnabled(args.channelName);
return new ResultArgs(result).toBundle();
}
@@ -136,7 +143,7 @@
NotifyNotificationArgs args = NotifyNotificationArgs.fromBundle(bundle);
- boolean success = TrustedWebActivityService.this.notifyNotificationWithChannel(
+ boolean success = TrustedWebActivityService.this.onNotifyNotificationWithChannel(
args.platformTag, args.platformId, args.notification, args.channelName);
return new ResultArgs(success).toBundle();
@@ -148,7 +155,7 @@
CancelNotificationArgs args = CancelNotificationArgs.fromBundle(bundle);
- TrustedWebActivityService.this.cancelNotification(args.platformTag, args.platformId);
+ TrustedWebActivityService.this.onCancelNotification(args.platformTag, args.platformId);
}
@Override
@@ -156,21 +163,21 @@
checkCaller();
return new ActiveNotificationsArgs(
- TrustedWebActivityService.this.getActiveNotifications()).toBundle();
+ TrustedWebActivityService.this.onGetActiveNotifications()).toBundle();
}
@Override
public int getSmallIconId() {
checkCaller();
- return TrustedWebActivityService.this.getSmallIconId();
+ return TrustedWebActivityService.this.onGetSmallIconId();
}
@Override
public Bundle getSmallIconBitmap() {
checkCaller();
- return TrustedWebActivityService.this.getSmallIconBitmap();
+ return TrustedWebActivityService.this.onGetSmallIconBitmap();
}
private void checkCaller() {
@@ -206,6 +213,7 @@
*/
@Override
@CallSuper
+ @MainThread
public void onCreate() {
super.onCreate();
mNotificationManager =
@@ -217,7 +225,8 @@
* @param channelName The name of the notification channel to be used on Android O+.
* @return Whether notifications are enabled.
*/
- public boolean areNotificationsEnabled(@NonNull String channelName) {
+ @BinderThread
+ public boolean onAreNotificationsEnabled(@NonNull String channelName) {
ensureOnCreateCalled();
if (!NotificationManagerCompat.from(this).areNotificationsEnabled()) return false;
@@ -241,7 +250,8 @@
* @return Whether the notification was successfully displayed (the channel/app may be blocked
* by the user).
*/
- public boolean notifyNotificationWithChannel(@NonNull String platformTag, int platformId,
+ @BinderThread
+ public boolean onNotifyNotificationWithChannel(@NonNull String platformTag, int platformId,
@NonNull Notification notification, @NonNull String channelName) {
ensureOnCreateCalled();
@@ -268,7 +278,8 @@
* @param platformId The notification id, see
* {@link NotificationManager#cancel(String, int)}.
*/
- public void cancelNotification(@NonNull String platformTag, int platformId) {
+ @BinderThread
+ public void onCancelNotification(@NonNull String platformTag, int platformId) {
ensureOnCreateCalled();
mNotificationManager.cancel(platformTag, platformId);
}
@@ -281,13 +292,15 @@
*
* @hide
*/
+ @NonNull
+ @BinderThread
@RestrictTo(RestrictTo.Scope.LIBRARY)
- public Parcelable[] getActiveNotifications() {
+ public Parcelable[] onGetActiveNotifications() {
ensureOnCreateCalled();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return NotificationApiHelperForM.getActiveNotifications(mNotificationManager);
}
- throw new IllegalStateException("getActiveNotifications cannot be called pre-M.");
+ throw new IllegalStateException("onGetActiveNotifications cannot be called pre-M.");
}
/**
@@ -295,8 +308,9 @@
* @return A Bundle that may contain a Bitmap contained with key {@link #KEY_SMALL_ICON_BITMAP}.
* The bundle may be empty if the client app does not provide a small icon.
*/
- public @NonNull Bundle getSmallIconBitmap() {
- int id = getSmallIconId();
+ @BinderThread
+ public @NonNull Bundle onGetSmallIconBitmap() {
+ int id = onGetSmallIconId();
Bundle bundle = new Bundle();
if (id == SMALL_ICON_NOT_SET) {
return bundle;
@@ -315,7 +329,8 @@
* service section of the manifest.
* @return A resource id for the small icon, or {@link #SMALL_ICON_NOT_SET} if not found.
*/
- public int getSmallIconId() {
+ @BinderThread
+ public int onGetSmallIconId() {
try {
ServiceInfo info = getPackageManager().getServiceInfo(
new ComponentName(this, getClass()), PackageManager.GET_META_DATA);
@@ -332,11 +347,13 @@
@Override
@Nullable
+ @MainThread
public final IBinder onBind(@Nullable Intent intent) {
return mBinder;
}
@Override
+ @MainThread
public final boolean onUnbind(@Nullable Intent intent) {
mVerifiedUid = -1;
@@ -379,7 +396,7 @@
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY)
- public static final void setVerifiedProviderSynchronouslyForTesting(Context context,
+ public static final void setVerifiedProviderSynchronouslyForTesting(@NonNull Context context,
@Nullable String provider) {
String providerEmptyChecked = (provider == null || provider.isEmpty()) ? null : provider;
diff --git a/browser/src/main/java/androidx/browser/trusted/TrustedWebActivityServiceWrapper.java b/browser/src/main/java/androidx/browser/trusted/TrustedWebActivityServiceConnection.java
similarity index 96%
rename from browser/src/main/java/androidx/browser/trusted/TrustedWebActivityServiceWrapper.java
rename to browser/src/main/java/androidx/browser/trusted/TrustedWebActivityServiceConnection.java
index 3719bc9..b088802 100644
--- a/browser/src/main/java/androidx/browser/trusted/TrustedWebActivityServiceWrapper.java
+++ b/browser/src/main/java/androidx/browser/trusted/TrustedWebActivityServiceConnection.java
@@ -31,16 +31,16 @@
import android.support.annotation.RestrictTo;
/**
- * TrustedWebActivityServiceWrapper is used by a Trusted Web Activity provider to wrap calls to
+ * TrustedWebActivityServiceConnection is used by a Trusted Web Activity provider to wrap calls to
* the {@link TrustedWebActivityService} in the client app.
* All of these calls except {@link #getComponentName()} forward over IPC
* to corresponding calls on {@link TrustedWebActivityService}, eg {@link #getSmallIconId()}
- * forwards to {@link TrustedWebActivityService#getSmallIconId()}.
+ * forwards to {@link TrustedWebActivityService#onGetSmallIconId()}.
* <p>
* These IPC calls are synchronous, though the {@link TrustedWebActivityService} method may hit the
* disk. Therefore it is recommended to call them on a background thread (without StrictMode).
*/
-public class TrustedWebActivityServiceWrapper {
+public final class TrustedWebActivityServiceConnection {
// Inputs.
private static final String KEY_PLATFORM_TAG =
"android.support.customtabs.trusted.PLATFORM_TAG";
@@ -65,7 +65,7 @@
private final ITrustedWebActivityService mService;
private final ComponentName mComponentName;
- TrustedWebActivityServiceWrapper(@NonNull ITrustedWebActivityService service,
+ TrustedWebActivityServiceConnection(@NonNull ITrustedWebActivityService service,
@NonNull ComponentName componentName) {
mService = service;
mComponentName = componentName;
@@ -133,6 +133,7 @@
*/
@RestrictTo(RestrictTo.Scope.LIBRARY)
@RequiresApi(Build.VERSION_CODES.M)
+ @NonNull
public Parcelable[] getActiveNotifications() {
try {
Bundle notifications = mService.getActiveNotifications();
@@ -158,7 +159,7 @@
/**
* Requests a bitmap of a small icon to be used for the notification
* small icon. The bitmap is decoded on the side of Trusted Web Activity client using
- * the resource id from {@link TrustedWebActivityService#getSmallIconId}.
+ * the resource id from {@link TrustedWebActivityService#onGetSmallIconId}.
* @return A {@link Bitmap} to be used for the small icon.
* @throws SecurityException If verification with the TrustedWebActivityService fails.
*/
diff --git a/browser/src/main/java/androidx/browser/trusted/TrustedWebActivityServiceConnectionManager.java b/browser/src/main/java/androidx/browser/trusted/TrustedWebActivityServiceConnectionPool.java
similarity index 94%
rename from browser/src/main/java/androidx/browser/trusted/TrustedWebActivityServiceConnectionManager.java
rename to browser/src/main/java/androidx/browser/trusted/TrustedWebActivityServiceConnectionPool.java
index 9cdb10e..f7380a9 100644
--- a/browser/src/main/java/androidx/browser/trusted/TrustedWebActivityServiceConnectionManager.java
+++ b/browser/src/main/java/androidx/browser/trusted/TrustedWebActivityServiceConnectionPool.java
@@ -43,7 +43,7 @@
import java.util.concurrent.atomic.AtomicReference;
/**
- * A TrustedWebActivityServiceConnectionManager will be used by a Trusted Web Activity provider and
+ * A TrustedWebActivityServiceConnectionPool will be used by a Trusted Web Activity provider and
* takes care of connecting to and communicating with {@link TrustedWebActivityService}s.
* <p>
* Trusted Web Activity client apps are registered with {@link #registerClient}, associating a
@@ -53,8 +53,8 @@
* <p>
* To interact with a {@link TrustedWebActivityService}, call {@link #connect}.
*/
-public final class TrustedWebActivityServiceConnectionManager {
- private static final String TAG = "TWAConnectionManager";
+public final class TrustedWebActivityServiceConnectionPool {
+ private static final String TAG = "TWAConnectionPool";
private static final String PREFS_FILE = "TrustedWebActivityVerifiedPackages";
@SuppressWarnings("WeakerAccess") /* synthetic access */
@@ -104,11 +104,7 @@
}
}
- /**
- * Creates a TrustedWebActivityServiceConnectionManager.
- * @param context A Context used for accessing SharedPreferences.
- */
- public TrustedWebActivityServiceConnectionManager(@NonNull Context context) {
+ private TrustedWebActivityServiceConnectionPool(@NonNull Context context) {
mContext = context.getApplicationContext();
// Asynchronously try to load (and therefore cache) the preferences.
@@ -121,6 +117,15 @@
}
/**
+ * Creates a TrustedWebActivityServiceConnectionPool.
+ * @param context A Context used for accessing SharedPreferences.
+ */
+ @NonNull
+ public static TrustedWebActivityServiceConnectionPool create(@NonNull Context context) {
+ return new TrustedWebActivityServiceConnectionPool(context);
+ }
+
+ /**
* Connects to the appropriate {@link TrustedWebActivityService} or uses an existing connection
* if available and runs code once connected.
* <p>
@@ -140,7 +145,7 @@
* @param executor The {@link Executor} to connect to the Service on if a new connection is
* required.
* @return A {@link ListenableFuture} for the resulting
- * {@link TrustedWebActivityServiceWrapper}. This may be set to an
+ * {@link TrustedWebActivityServiceConnection}. This may be set to an
* {@link IllegalArgumentException} if no service exists for the scope (you can check
* for this beforehand by calling {@link #serviceExistsForScope(Uri, String)}. It may
* be set to a {@link SecurityException} if the Service does not accept connections from
@@ -149,7 +154,7 @@
*/
@MainThread
@NonNull
- public ListenableFuture<TrustedWebActivityServiceWrapper> connect(
+ public ListenableFuture<TrustedWebActivityServiceConnection> connect(
@NonNull final Uri scope, @NonNull String origin, @NonNull Executor executor) {
// If we have an existing connection, use it.
ConnectionHolder connection = mConnections.get(scope);