summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/current.txt1
-rw-r--r--core/java/android/companion/CompanionDeviceManager.java43
-rw-r--r--core/java/android/companion/IAssociationRequestCallback.aidl2
-rw-r--r--core/java/android/companion/flags.aconfig10
-rw-r--r--packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionAssociationActivity.java55
-rw-r--r--services/companion/java/com/android/server/companion/association/AssociationRequestsProcessor.java8
6 files changed, 71 insertions, 48 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index 5eeb299de9da..a4d70a09ad4b 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -9824,6 +9824,7 @@ package android.companion {
method public void onAssociationPending(@NonNull android.content.IntentSender);
method @Deprecated public void onDeviceFound(@NonNull android.content.IntentSender);
method public abstract void onFailure(@Nullable CharSequence);
+ method @FlaggedApi("android.companion.association_failure_code") public void onFailure(int);
}
public abstract class CompanionDeviceService extends android.app.Service {
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index b4ad1c8fff12..34cfa584b683 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -21,6 +21,8 @@ import static android.Manifest.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_P
import static android.Manifest.permission.REQUEST_COMPANION_PROFILE_COMPUTER;
import static android.Manifest.permission.REQUEST_COMPANION_PROFILE_WATCH;
+import static java.util.Collections.unmodifiableMap;
+
import android.annotation.CallbackExecutor;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
@@ -56,6 +58,7 @@ import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.UserHandle;
import android.service.notification.NotificationListenerService;
+import android.util.ArrayMap;
import android.util.ExceptionUtils;
import android.util.Log;
import android.util.SparseArray;
@@ -75,6 +78,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.function.BiConsumer;
@@ -119,29 +123,31 @@ public final class CompanionDeviceManager {
* is created successfully.
*/
public static final int RESULT_OK = -1;
-
+ //TODO(b/331459560) Need to update the java doc after API cut for W.
/**
* The result code to propagate back to the user activity, indicates if the association dialog
* is implicitly cancelled.
* E.g. phone is locked, switch to another app or press outside the dialog.
*/
public static final int RESULT_CANCELED = 0;
-
+ //TODO(b/331459560) Need to update the java doc after API cut for W.
/**
* The result code to propagate back to the user activity, indicates the association dialog
* is explicitly declined by the users.
*/
public static final int RESULT_USER_REJECTED = 1;
-
+ //TODO(b/331459560) Need to update the java doc after API cut for W.
/**
* The result code to propagate back to the user activity, indicates the association
* dialog is dismissed if there's no device found after 20 seconds.
*/
public static final int RESULT_DISCOVERY_TIMEOUT = 2;
-
+ //TODO(b/331459560) Need to update the java doc after API cut for W.
/**
* The result code to propagate back to the user activity, indicates the internal error
* in CompanionDeviceManager.
+ * E.g. Missing necessary permissions or duplicate {@link AssociationRequest}s when create the
+ * {@link AssociationInfo}.
*/
public static final int RESULT_INTERNAL_ERROR = 3;
@@ -368,12 +374,22 @@ public final class CompanionDeviceManager {
*/
public void onAssociationCreated(@NonNull AssociationInfo associationInfo) {}
+ //TODO(b/331459560): Add deprecated and remove abstract after API cut for W.
/**
* Invoked if the association could not be created.
*
* @param error error message.
*/
public abstract void onFailure(@Nullable CharSequence error);
+
+ /**
+ * Invoked if the association could not be created.
+ *
+ * @param resultCode indicate the particular reason why the association
+ * could not be created.
+ */
+ @FlaggedApi(Flags.FLAG_ASSOCIATION_FAILURE_CODE)
+ public void onFailure(@ResultCode int resultCode) {}
}
private final ICompanionDeviceManager mService;
@@ -1803,8 +1819,12 @@ public final class CompanionDeviceManager {
}
@Override
- public void onFailure(CharSequence error) throws RemoteException {
- execute(mCallback::onFailure, error);
+ public void onFailure(@ResultCode int resultCode) {
+ if (Flags.associationFailureCode()) {
+ execute(mCallback::onFailure, resultCode);
+ }
+
+ execute(mCallback::onFailure, RESULT_CODE_TO_REASON.get(resultCode));
}
private <T> void execute(Consumer<T> callback, T arg) {
@@ -1988,4 +2008,15 @@ public final class CompanionDeviceManager {
}
}
}
+
+ private static final Map<Integer, String> RESULT_CODE_TO_REASON;
+ static {
+ final Map<Integer, String> map = new ArrayMap<>();
+ map.put(RESULT_CANCELED, REASON_CANCELED);
+ map.put(RESULT_USER_REJECTED, REASON_USER_REJECTED);
+ map.put(RESULT_DISCOVERY_TIMEOUT, REASON_DISCOVERY_TIMEOUT);
+ map.put(RESULT_INTERNAL_ERROR, REASON_INTERNAL_ERROR);
+
+ RESULT_CODE_TO_REASON = unmodifiableMap(map);
+ }
}
diff --git a/core/java/android/companion/IAssociationRequestCallback.aidl b/core/java/android/companion/IAssociationRequestCallback.aidl
index 8cc2a7194e08..b1be30a1288c 100644
--- a/core/java/android/companion/IAssociationRequestCallback.aidl
+++ b/core/java/android/companion/IAssociationRequestCallback.aidl
@@ -25,5 +25,5 @@ interface IAssociationRequestCallback {
oneway void onAssociationCreated(in AssociationInfo associationInfo);
- oneway void onFailure(in CharSequence error);
+ oneway void onFailure(in int resultCode);
} \ No newline at end of file
diff --git a/core/java/android/companion/flags.aconfig b/core/java/android/companion/flags.aconfig
index fd4ba83b02e3..ee9114f74092 100644
--- a/core/java/android/companion/flags.aconfig
+++ b/core/java/android/companion/flags.aconfig
@@ -53,4 +53,12 @@ flag {
namespace: "companion"
description: "Unpair with an associated bluetooth device"
bug: "322237619"
-} \ No newline at end of file
+}
+
+flag {
+ name: "association_failure_code"
+ is_exported: true
+ namespace: "companion"
+ description: "Enable association failure code API"
+ bug: "331459560"
+}
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionAssociationActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionAssociationActivity.java
index 5770c5104dee..66ab81bf02b1 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionAssociationActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionAssociationActivity.java
@@ -16,10 +16,7 @@
package com.android.companiondevicemanager;
-import static android.companion.CompanionDeviceManager.REASON_CANCELED;
-import static android.companion.CompanionDeviceManager.REASON_DISCOVERY_TIMEOUT;
-import static android.companion.CompanionDeviceManager.REASON_INTERNAL_ERROR;
-import static android.companion.CompanionDeviceManager.REASON_USER_REJECTED;
+import static android.companion.CompanionDeviceManager.RESULT_CANCELED;
import static android.companion.CompanionDeviceManager.RESULT_DISCOVERY_TIMEOUT;
import static android.companion.CompanionDeviceManager.RESULT_INTERNAL_ERROR;
import static android.companion.CompanionDeviceManager.RESULT_USER_REJECTED;
@@ -234,8 +231,7 @@ public class CompanionAssociationActivity extends FragmentActivity implements
boolean forCancelDialog = intent.getBooleanExtra(EXTRA_FORCE_CANCEL_CONFIRMATION, false);
if (forCancelDialog) {
Slog.i(TAG, "Cancelling the user confirmation");
- cancel(/* discoveryTimeOut */ false, /* userRejected */ false,
- /* internalError */ false);
+ cancel(RESULT_CANCELED);
return;
}
@@ -243,8 +239,14 @@ public class CompanionAssociationActivity extends FragmentActivity implements
// yet). We can only "process" one request at a time.
final IAssociationRequestCallback appCallback = IAssociationRequestCallback.Stub
.asInterface(intent.getExtras().getBinder(EXTRA_APPLICATION_CALLBACK));
+
+ if (appCallback == null) {
+ return;
+ }
+ Slog.e(TAG, "More than one AssociationRequests are processing.");
+
try {
- requireNonNull(appCallback).onFailure("Busy.");
+ appCallback.onFailure(RESULT_INTERNAL_ERROR);
} catch (RemoteException ignore) {
}
}
@@ -255,8 +257,7 @@ public class CompanionAssociationActivity extends FragmentActivity implements
// TODO: handle config changes without cancelling.
if (!isDone()) {
- cancel(/* discoveryTimeOut */ false,
- /* userRejected */ false, /* internalError */ false); // will finish()
+ cancel(RESULT_CANCELED); // will finish()
}
}
@@ -330,8 +331,7 @@ public class CompanionAssociationActivity extends FragmentActivity implements
&& CompanionDeviceDiscoveryService.getScanResult().getValue().isEmpty()) {
synchronized (LOCK) {
if (sDiscoveryStarted) {
- cancel(/* discoveryTimeOut */ true,
- /* userRejected */ false, /* internalError */ false);
+ cancel(RESULT_DISCOVERY_TIMEOUT);
}
}
}
@@ -371,7 +371,7 @@ public class CompanionAssociationActivity extends FragmentActivity implements
mCdmServiceReceiver.send(RESULT_CODE_ASSOCIATION_APPROVED, data);
}
- private void cancel(boolean discoveryTimeout, boolean userRejected, boolean internalError) {
+ private void cancel(int failureCode) {
if (isDone()) {
Slog.w(TAG, "Already done: " + (mApproved ? "Approved" : "Cancelled"));
return;
@@ -379,35 +379,19 @@ public class CompanionAssociationActivity extends FragmentActivity implements
mCancelled = true;
// Stop discovery service if it was used.
- if (!mRequest.isSelfManaged() || discoveryTimeout) {
+ if (!mRequest.isSelfManaged()) {
CompanionDeviceDiscoveryService.stop(this);
}
- final String cancelReason;
- final int resultCode;
- if (userRejected) {
- cancelReason = REASON_USER_REJECTED;
- resultCode = RESULT_USER_REJECTED;
- } else if (discoveryTimeout) {
- cancelReason = REASON_DISCOVERY_TIMEOUT;
- resultCode = RESULT_DISCOVERY_TIMEOUT;
- } else if (internalError) {
- cancelReason = REASON_INTERNAL_ERROR;
- resultCode = RESULT_INTERNAL_ERROR;
- } else {
- cancelReason = REASON_CANCELED;
- resultCode = CompanionDeviceManager.RESULT_CANCELED;
- }
-
// First send callback to the app directly...
try {
- Slog.i(TAG, "Sending onFailure to app due to reason=" + cancelReason);
- mAppCallback.onFailure(cancelReason);
+ Slog.i(TAG, "Sending onFailure to app due to failureCode=" + failureCode);
+ mAppCallback.onFailure(failureCode);
} catch (RemoteException ignore) {
}
// ... then set result and finish ("sending" onActivityResult()).
- setResultAndFinish(null, resultCode);
+ setResultAndFinish(null, failureCode);
}
private void setResultAndFinish(@Nullable AssociationInfo association, int resultCode) {
@@ -452,8 +436,7 @@ public class CompanionAssociationActivity extends FragmentActivity implements
}
} catch (PackageManager.NameNotFoundException e) {
Slog.e(TAG, "Package u" + userId + "/" + packageName + " not found.");
- cancel(/* discoveryTimeout */ false,
- /* userRejected */ false, /* internalError */ true);
+ cancel(RESULT_INTERNAL_ERROR);
return;
}
@@ -637,7 +620,7 @@ public class CompanionAssociationActivity extends FragmentActivity implements
// Disable the button, to prevent more clicks.
v.setEnabled(false);
- cancel(/* discoveryTimeout */ false, /* userRejected */ true, /* internalError */ false);
+ cancel(RESULT_USER_REJECTED);
}
private void onShowHelperDialog(View view) {
@@ -763,7 +746,7 @@ public class CompanionAssociationActivity extends FragmentActivity implements
@Override
public void onShowHelperDialogFailed() {
- cancel(/* discoveryTimeout */ false, /* userRejected */ false, /* internalError */ true);
+ cancel(RESULT_INTERNAL_ERROR);
}
@Override
diff --git a/services/companion/java/com/android/server/companion/association/AssociationRequestsProcessor.java b/services/companion/java/com/android/server/companion/association/AssociationRequestsProcessor.java
index 3fbd8560b82c..b3a2da40ff4d 100644
--- a/services/companion/java/com/android/server/companion/association/AssociationRequestsProcessor.java
+++ b/services/companion/java/com/android/server/companion/association/AssociationRequestsProcessor.java
@@ -19,7 +19,6 @@ package com.android.server.companion.association;
import static android.app.PendingIntent.FLAG_CANCEL_CURRENT;
import static android.app.PendingIntent.FLAG_IMMUTABLE;
import static android.app.PendingIntent.FLAG_ONE_SHOT;
-import static android.companion.CompanionDeviceManager.REASON_INTERNAL_ERROR;
import static android.companion.CompanionDeviceManager.RESULT_INTERNAL_ERROR;
import static android.content.ComponentName.createRelative;
import static android.content.pm.PackageManager.FEATURE_WATCH;
@@ -183,7 +182,7 @@ public class AssociationRequestsProcessor {
String errorMessage = "3p apps are not allowed to create associations on watch.";
Slog.e(TAG, errorMessage);
try {
- callback.onFailure(errorMessage);
+ callback.onFailure(RESULT_INTERNAL_ERROR);
} catch (RemoteException e) {
// ignored
}
@@ -252,8 +251,9 @@ public class AssociationRequestsProcessor {
} catch (SecurityException e) {
// Since, at this point the caller is our own UI, we need to catch the exception on
// forward it back to the application via the callback.
+ Slog.e(TAG, e.getMessage());
try {
- callback.onFailure(e.getMessage());
+ callback.onFailure(RESULT_INTERNAL_ERROR);
} catch (RemoteException ignore) {
}
return;
@@ -378,7 +378,7 @@ public class AssociationRequestsProcessor {
// Send the association back via the app's callback
if (callback != null) {
try {
- callback.onFailure(REASON_INTERNAL_ERROR);
+ callback.onFailure(RESULT_INTERNAL_ERROR);
} catch (RemoteException ignore) {
}
}