Merge "Add callback to ImageActionUtils for unresolved intents"
diff --git a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
index 6502526..bc38739 100644
--- a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
+++ b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
@@ -50,7 +50,6 @@
 import androidx.annotation.VisibleForTesting;
 
 import com.android.launcher3.BaseActivity;
-import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.views.ArrowTipView;
@@ -76,7 +75,7 @@
     public static final String ACTIONS_ERROR_CODE = "niu_actions_app_error_code";
     public static final int ERROR_PERMISSIONS_STRUCTURE = 1;
     public static final int ERROR_PERMISSIONS_SCREENSHOT = 2;
-    private static final String NIU_ACTIONS_CONFIRMED = "launcher_go.niu_actions_confirmed";
+    public static final String NIU_ACTIONS_CONFIRMED = "launcher_go.niu_actions_confirmed";
     private static final String ASSIST_SETTINGS_ARGS_BUNDLE = ":settings:show_fragment_args";
     private static final String ASSIST_SETTINGS_ARGS_KEY = ":settings:fragment_args_key";
     private static final String ASSIST_SETTINGS_PREFERENCE_KEY = "default_assist";
@@ -87,10 +86,11 @@
 
     @Retention(SOURCE)
     @IntDef({PRIVACY_CONFIRMATION, ASSISTANT_NOT_SELECTED, ASSISTANT_NOT_SUPPORTED})
-    private @interface DialogType{}
-    private static final int PRIVACY_CONFIRMATION = 0;
-    private static final int ASSISTANT_NOT_SELECTED = 1;
-    private static final int ASSISTANT_NOT_SUPPORTED = 2;
+    @VisibleForTesting
+    public @interface DialogType{}
+    public static final int PRIVACY_CONFIRMATION = 0;
+    public static final int ASSISTANT_NOT_SELECTED = 1;
+    public static final int ASSISTANT_NOT_SUPPORTED = 2;
 
     private AssistContentRequester mContentRequester;
 
@@ -211,7 +211,8 @@
             Intent intent = createNIUIntent(actionType);
             // Only add and send the image if the appropriate permissions are held
             if (mAssistStructurePermitted && mAssistScreenshotPermitted) {
-                mImageApi.shareAsDataWithExplicitIntent(/* crop */ null, intent);
+                mImageApi.shareAsDataWithExplicitIntent(/* crop */ null, intent,
+                        () -> showDialog(actionType, ASSISTANT_NOT_SUPPORTED));
             } else {
                 // If both permissions are disabled, the structure error code takes priority
                 // The user must enable that one before they can enable screenshots
@@ -301,7 +302,6 @@
             mImageApi = imageActionsApi;
         }
 
-        // TODO (b/192406446): Test that these dialogs are shown at the appropriate times
         private void showDialog(String action, @DialogType int type) {
             switch (type) {
                 case PRIVACY_CONFIRMATION:
@@ -334,7 +334,7 @@
                                 int bodyTextID, int button1TextID,
                                 View.OnClickListener button1Callback, int button2TextID,
                                 View.OnClickListener button2Callback) {
-            BaseDraggingActivity activity = BaseActivity.fromContext(getActionsView().getContext());
+            BaseActivity activity = BaseActivity.fromContext(getActionsView().getContext());
             LayoutInflater inflater = LayoutInflater.from(activity);
             View view = inflater.inflate(R.layout.niu_actions_dialog, /* root */ null);
 
@@ -368,6 +368,11 @@
             mDialog.cancel();
         }
 
+        @VisibleForTesting
+        public OverlayDialogGo getDialog() {
+            return mDialog;
+        }
+
         private void onDialogClickSettings(View v) {
             mDialog.dismiss();
 
@@ -401,7 +406,11 @@
         }
     }
 
-    private static final class OverlayDialogGo extends AlertDialog {
+    /**
+     * Basic modal dialog for various user prompts
+     */
+    @VisibleForTesting
+    public static final class OverlayDialogGo extends AlertDialog {
         private final String mAction;
         private final @DialogType int mType;
 
diff --git a/quickstep/src/com/android/quickstep/ImageActionsApi.java b/quickstep/src/com/android/quickstep/ImageActionsApi.java
index 8cb64c2..154848d 100644
--- a/quickstep/src/com/android/quickstep/ImageActionsApi.java
+++ b/quickstep/src/com/android/quickstep/ImageActionsApi.java
@@ -64,20 +64,23 @@
      */
     @UiThread
     public void shareWithExplicitIntent(@Nullable Rect crop, Intent intent) {
-        addImageAndSendIntent(crop, intent, false);
+        addImageAndSendIntent(crop, intent, false, null /* exceptionCallback */);
     }
 
     /**
      * Share the image this api was constructed with using the provided intent. The implementation
      * should set the intent's data field to the URI pointing to the image.
+     * @param exceptionCallback An optional callback to be called when the intent can't be resolved
      */
     @UiThread
-    public void shareAsDataWithExplicitIntent(@Nullable Rect crop, Intent intent) {
-        addImageAndSendIntent(crop, intent, true);
+    public void shareAsDataWithExplicitIntent(@Nullable Rect crop, Intent intent,
+            @Nullable Runnable exceptionCallback) {
+        addImageAndSendIntent(crop, intent, true, exceptionCallback);
     }
 
     @UiThread
-    private void addImageAndSendIntent(@Nullable Rect crop, Intent intent, boolean setData) {
+    private void addImageAndSendIntent(@Nullable Rect crop, Intent intent, boolean setData,
+            @Nullable Runnable exceptionCallback) {
         if (mBitmapSupplier.get() == null) {
             Log.e(TAG, "No snapshot available, not starting share.");
             return;
@@ -92,7 +95,7 @@
                         intentForUri.putExtra(EXTRA_STREAM, uri);
                     }
                     return new Intent[]{intentForUri};
-                }, TAG));
+                }, TAG, exceptionCallback));
     }
 
     /**
diff --git a/quickstep/src/com/android/quickstep/util/ImageActionUtils.java b/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
index de7dbd6..51a9915 100644
--- a/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
+++ b/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
@@ -154,6 +154,18 @@
     @WorkerThread
     public static void persistBitmapAndStartActivity(Context context, Bitmap bitmap, Rect crop,
             Intent intent, BiFunction<Uri, Intent, Intent[]> uriToIntentMap, String tag) {
+        persistBitmapAndStartActivity(context, bitmap, crop, intent, uriToIntentMap, tag,
+                (Runnable) null);
+    }
+
+    /**
+     * Starts activity based on given intent created from image uri.
+     * @param exceptionCallback An optional callback to be called when the intent can't be resolved
+     */
+    @WorkerThread
+    public static void persistBitmapAndStartActivity(Context context, Bitmap bitmap, Rect crop,
+            Intent intent, BiFunction<Uri, Intent, Intent[]> uriToIntentMap, String tag,
+            Runnable exceptionCallback) {
         Intent[] intents = uriToIntentMap.apply(getImageUri(bitmap, crop, context, tag), intent);
 
         try {
@@ -165,6 +177,9 @@
             }
         } catch (ActivityNotFoundException e) {
             Log.e(TAG, "No activity found to receive image intent");
+            if (exceptionCallback != null) {
+                exceptionCallback.run();
+            }
         }
     }