NIU Actions: Add privacy confirmation dialog
This adds a dialog to inform the user that the NIU Actions buttons need to send data to Google in order to function. The user can accept or reject this. The dialog will block use of the feature until the user accepts.
Bug: 191818216
Test: Manual (Pixel 3A with multiple user profiles)
Test: m -j RunLauncherGoGoogleRoboTests
Change-Id: Iedd056ce239de5269d02a31d28a9778efae34ede
diff --git a/go/quickstep/res/drawable/round_rect_dialog.xml b/go/quickstep/res/drawable/round_rect_dialog.xml
new file mode 100644
index 0000000..bbb7c5b
--- /dev/null
+++ b/go/quickstep/res/drawable/round_rect_dialog.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <corners android:radius="@dimen/modal_dialog_corner_radius" />
+</shape>
diff --git a/go/quickstep/res/layout/niu_actions_confirmation_dialog.xml b/go/quickstep/res/layout/niu_actions_confirmation_dialog.xml
new file mode 100644
index 0000000..db1531a
--- /dev/null
+++ b/go/quickstep/res/layout/niu_actions_confirmation_dialog.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/niu_actions_confirmation_dialog_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal"
+ android:layout_gravity="center">
+
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="1dp"
+ android:layout_weight="1"/>
+
+ <LinearLayout
+ android:layout_width="@dimen/modal_dialog_width"
+ android:layout_height="wrap_content"
+ android:background="@drawable/round_rect_dialog"
+ android:backgroundTint="?attr/modalDialogBackground"
+ android:orientation="vertical"
+ android:layout_gravity="center"
+ android:paddingTop="@dimen/modal_dialog_padding"
+ android:paddingLeft="@dimen/modal_dialog_padding"
+ android:paddingRight="@dimen/modal_dialog_padding"
+ android:paddingBottom="@dimen/modal_dialog_padding_bottom">
+
+ <TextView
+ style="@style/ModalDialogTitle"
+ android:id="@+id/niu_actions_confirmation_header"
+ android:text="@string/niu_actions_confirmation_title"/>
+
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="@dimen/modal_dialog_vertical_spacer"/>
+
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/confirmation_dialog_text_height">
+
+ <TextView
+ style="@style/ModalDialogText"
+ android:id="@+id/niu_actions_confirmation_description"
+ android:text="@string/niu_actions_confirmation_text"/>
+ </ScrollView>
+
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="@dimen/modal_dialog_vertical_spacer"/>
+
+ <LinearLayout
+ android:id="@+id/niu_actions_confirmation_buttons"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal">
+
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:layout_weight="1"/>
+
+ <Button
+ style="@style/ModalDialogButton"
+ android:id="@+id/niu_actions_confirmation_reject"
+ android:text="@string/niu_actions_confirmation_no"/>
+
+ <Button
+ style="@style/ModalDialogButton"
+ android:id="@+id/niu_actions_confirmation_accept"
+ android:text="@string/niu_actions_confirmation_yes"/>
+ </LinearLayout>
+
+ </LinearLayout>
+
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="1dp"
+ android:layout_weight="1" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/go/quickstep/res/values-land/dimens.xml b/go/quickstep/res/values-land/dimens.xml
new file mode 100644
index 0000000..5097016
--- /dev/null
+++ b/go/quickstep/res/values-land/dimens.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+ <!-- Modal Dialogs -->
+ <dimen name="modal_dialog_width">360dp</dimen>
+ <dimen name="confirmation_dialog_text_height">168dp</dimen>
+</resources>
diff --git a/go/quickstep/res/values/attrs.xml b/go/quickstep/res/values/attrs.xml
index 03eab50..cdbdc2a 100644
--- a/go/quickstep/res/values/attrs.xml
+++ b/go/quickstep/res/values/attrs.xml
@@ -19,4 +19,6 @@
<attr name="overviewButtonTextColor" format="color" />
<attr name="overviewButtonIconColor" format="color" />
<attr name="overviewButtonBackgroundColor" format="color" />
+ <!-- Modal dialog theming -->
+ <attr name="modalDialogBackground" format="color" />
</resources>
\ No newline at end of file
diff --git a/go/quickstep/res/values/colors.xml b/go/quickstep/res/values/colors.xml
index ae72ef6..8034be2 100644
--- a/go/quickstep/res/values/colors.xml
+++ b/go/quickstep/res/values/colors.xml
@@ -20,4 +20,7 @@
<color name="go_overview_text_color_dark">#F8F9FA</color>
<color name="go_overview_button_color">#70FFFFFF</color>
<color name="go_overview_button_color_dark">#474747</color>
+ <!-- Modal Dialogs -->
+ <color name="go_modal_dialog_background">#FFFFFF</color>
+ <color name="go_modal_dialog_background_dark">#424242</color>
</resources>
diff --git a/go/quickstep/res/values/dimens.xml b/go/quickstep/res/values/dimens.xml
index 55cd138..0a7ac45 100644
--- a/go/quickstep/res/values/dimens.xml
+++ b/go/quickstep/res/values/dimens.xml
@@ -28,4 +28,12 @@
<dimen name="overview_proactive_row_height">0dp</dimen>
<dimen name="overview_proactive_row_bottom_margin">24dp</dimen>
<dimen name="task_corner_radius_override">28dp</dimen>
+
+ <!-- Modal Dialogs -->
+ <dimen name="modal_dialog_width">288dp</dimen>
+ <dimen name="modal_dialog_padding">24dp</dimen>
+ <dimen name="modal_dialog_padding_bottom">8dp</dimen>
+ <dimen name="modal_dialog_vertical_spacer">12dp</dimen>
+ <dimen name="modal_dialog_corner_radius">8dp</dimen>
+ <dimen name="confirmation_dialog_text_height">216dp</dimen>
</resources>
diff --git a/go/quickstep/res/values/strings.xml b/go/quickstep/res/values/strings.xml
index 61c8cd9..6e9e63e 100644
--- a/go/quickstep/res/values/strings.xml
+++ b/go/quickstep/res/values/strings.xml
@@ -11,4 +11,13 @@
<string name="action_translate">Translate</string>
<!-- Label for a button that triggers Search on a screenshot of the current app. [CHAR_LIMIT=40] -->
<string name="action_search">Lens</string>
+ <!-- ******* NIU Actions First-Run Confirmation Dialog ******* -->
+ <!-- Dialog title -->
+ <string name="niu_actions_confirmation_title">Translate or listen to text on screen</string>
+ <!-- Dialog content -->
+ <string name="niu_actions_confirmation_text">Information such as text on your screen, web addresses, and screenshots may be shared with Google.\n\nTo change what information you share, go to <b>Settings > Apps > Default apps > Digital assistant app</b>.</string>
+ <!-- Label for a button that rejects the feature. [CHAR_LIMIT=40] -->
+ <string name="niu_actions_confirmation_no">CANCEL</string>
+ <!-- Label for a button that accepts the feature. [CHAR_LIMIT=40] -->
+ <string name="niu_actions_confirmation_yes">GOT IT</string>
</resources>
diff --git a/go/quickstep/res/values/styles.xml b/go/quickstep/res/values/styles.xml
index ffe8f46..561531b 100644
--- a/go/quickstep/res/values/styles.xml
+++ b/go/quickstep/res/values/styles.xml
@@ -20,12 +20,14 @@
<item name="overviewButtonTextColor">@color/go_overview_text_color</item>
<item name="overviewButtonIconColor">@color/go_overview_text_color</item>
<item name="overviewButtonBackgroundColor">@color/go_overview_button_color</item>
+ <item name="modalDialogBackground">@color/go_modal_dialog_background</item>
</style>
<style name="AppTheme.Dark" parent="@style/LauncherTheme.Dark">
<item name="overviewButtonTextColor">@color/go_overview_text_color_dark</item>
<item name="overviewButtonIconColor">@color/go_overview_text_color_dark</item>
<item name="overviewButtonBackgroundColor">@color/go_overview_button_color_dark</item>
+ <item name="modalDialogBackground">@color/go_modal_dialog_background_dark</item>
</style>
<!-- Overview -->
@@ -56,4 +58,33 @@
<item name="android:layout_height">wrap_content</item>
<item name="android:orientation">vertical</item>
</style>
+
+ <!-- Modal Dialogs -->
+ <style name="ModalDialogTitle">
+ <item name="android:fontFamily">sans-serif-medium</item>
+ <item name="android:textSize">20sp</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
+ <item name="android:lineHeight">24dp</item>
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_gravity">center_horizontal</item>
+ </style>
+
+ <style name="ModalDialogText">
+ <item name="android:fontFamily">sans-serif-medium</item>
+ <item name="android:textSize">16sp</item>
+ <item name="android:textColor">?android:attr/textColorSecondary</item>
+ <item name="android:lineHeight">24dp</item>
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_gravity">center_horizontal</item>
+ </style>
+
+ <style name="ModalDialogButton" parent="@style/Widget.AppCompat.Button.Borderless">
+ <item name="android:textSize">14sp</item>
+ <item name="android:textColor">?android:attr/colorAccent</item>
+ <item name="android:lineHeight">20dp</item>
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ </style>
</resources>
\ No newline at end of file
diff --git a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
index b823c36..37f5352 100644
--- a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
+++ b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
@@ -20,20 +20,31 @@
import static com.android.quickstep.views.OverviewActionsView.DISABLED_ROTATED;
import android.annotation.SuppressLint;
+import android.app.AlertDialog;
import android.app.assist.AssistContent;
import android.content.ActivityNotFoundException;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
+import android.graphics.Color;
import android.graphics.Matrix;
+import android.graphics.drawable.ColorDrawable;
import android.os.SystemClock;
import android.os.UserManager;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Button;
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.quickstep.util.AssistContentRequester;
import com.android.quickstep.views.OverviewActionsView;
import com.android.quickstep.views.TaskThumbnailView;
@@ -53,6 +64,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";
private static final String TAG = "TaskOverlayFactoryGo";
private AssistContentRequester mContentRequester;
@@ -79,6 +91,9 @@
private boolean mAssistStructurePermitted;
private boolean mAssistScreenshotPermitted;
private AssistContentRequester mFactoryContentRequester;
+ private SharedPreferences mSharedPreferences;
+ private String mPreviousAction;
+ private AlertDialog mConfirmationDialog;
private TaskOverlayGo(TaskThumbnailView taskThumbnailView,
AssistContentRequester assistContentRequester) {
@@ -92,6 +107,12 @@
@Override
public void initOverlay(Task task, ThumbnailData thumbnail, Matrix matrix,
boolean rotated) {
+ if (mConfirmationDialog != null && mConfirmationDialog.isShowing()) {
+ // Redraw the dialog in case the layout changed
+ mConfirmationDialog.dismiss();
+ showConfirmationDialog();
+ }
+
getActionsView().updateDisabledFlags(DISABLED_NO_THUMBNAIL, thumbnail == null);
checkSettings();
if (thumbnail == null || TextUtils.isEmpty(mNIUPackageName)) {
@@ -105,6 +126,7 @@
boolean isAllowedByPolicy = mThumbnailView.isRealSnapshot() && !isManagedProfileTask;
getActionsView().setCallbacks(new OverlayUICallbacksGoImpl(isAllowedByPolicy, task));
mTaskPackageName = task.key.getPackageName();
+ mSharedPreferences = Utilities.getPrefs(mApplicationContext);
if (!mAssistStructurePermitted || !mAssistScreenshotPermitted) {
return;
@@ -131,6 +153,12 @@
* Creates and sends an Intent corresponding to the button that was clicked
*/
private void sendNIUIntent(String actionType) {
+ if (!mSharedPreferences.getBoolean(NIU_ACTIONS_CONFIRMED, false)) {
+ mPreviousAction = actionType;
+ showConfirmationDialog();
+ return;
+ }
+
Intent intent = createNIUIntent(actionType);
// Only add and send the image if the appropriate permissions are held
if (mAssistStructurePermitted && mAssistScreenshotPermitted) {
@@ -218,6 +246,35 @@
public void setImageActionsAPI(ImageActionsApi imageActionsApi) {
mImageApi = imageActionsApi;
}
+
+ private void showConfirmationDialog() {
+ BaseDraggingActivity activity = BaseActivity.fromContext(getActionsView().getContext());
+ LayoutInflater inflater = LayoutInflater.from(activity);
+ View view = inflater.inflate(R.layout.niu_actions_confirmation_dialog, /* root */ null);
+
+ Button acceptButton = view.findViewById(R.id.niu_actions_confirmation_accept);
+ acceptButton.setOnClickListener(this::onNiuActionsConfirmationAccept);
+
+ Button rejectButton = view.findViewById(R.id.niu_actions_confirmation_reject);
+ rejectButton.setOnClickListener(this::onNiuActionsConfirmationReject);
+
+ mConfirmationDialog = new AlertDialog.Builder(activity)
+ .setView(view)
+ .create();
+ mConfirmationDialog.getWindow()
+ .setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
+ mConfirmationDialog.show();
+ }
+
+ private void onNiuActionsConfirmationAccept(View v) {
+ mConfirmationDialog.dismiss();
+ mSharedPreferences.edit().putBoolean(NIU_ACTIONS_CONFIRMED, true).apply();
+ sendNIUIntent(mPreviousAction);
+ }
+
+ private void onNiuActionsConfirmationReject(View v) {
+ mConfirmationDialog.cancel();
+ }
}
/**