Add PbA branding to clipboard

Bug: 213357911

Test: Manually on Raven
Change-Id: If9944393fe64c7f94a5be139a538833d91ae98fe
This commit is contained in:
Yi-an Chen
2022-06-01 11:24:06 -07:00
parent e9ff71ec1b
commit edfc44079c
6 changed files with 168 additions and 14 deletions

View File

@@ -0,0 +1,53 @@
/*
* Copyright (C) 2022 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.
*/
package android.util;
import android.content.Context;
import android.content.res.Resources;
import android.provider.DeviceConfig;
/**
* Util class for whether we should show the safety protection resources.
*
* @hide
*/
public class SafetyProtectionUtils {
private static final String SAFETY_PROTECTION_RESOURCES_ENABLED = "safety_protection_enabled";
/**
* Determines whether we should show the safety protection resources.
* We show the resources only if
* (1) the feature flag safety_protection_enabled is enabled and
* (2) the config value config_safetyProtectionEnabled is enabled/true and
* (3) the resources exist (currently the resources only exist on GMS devices)
*
* TODO: make this an API in U
*
* @hide
*/
public static boolean shouldShowSafetyProtectionResources(Context context) {
return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
SAFETY_PROTECTION_RESOURCES_ENABLED, false)
&& context.getResources().getBoolean(
Resources.getSystem()
.getIdentifier("config_safetyProtectionEnabled",
"bool", "android"))
&& context.getDrawable(android.R.drawable.ic_safety_protection) != null
&& context.getString(android.R.string.safety_protection_display_text) != null
&& !context.getString(android.R.string.safety_protection_display_text).isEmpty();
}
}

View File

@@ -32,6 +32,7 @@ import android.compat.annotation.EnabledAfter;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
@@ -494,19 +495,39 @@ public class Toast {
*/
public static Toast makeText(@NonNull Context context, @Nullable Looper looper,
@NonNull CharSequence text, @Duration int duration) {
if (Compatibility.isChangeEnabled(CHANGE_TEXT_TOASTS_IN_THE_SYSTEM)) {
Toast result = new Toast(context, looper);
result.mText = text;
result.mDuration = duration;
return result;
} else {
Toast result = new Toast(context, looper);
View v = ToastPresenter.getTextToastView(context, text);
result.mNextView = v;
result.mDuration = duration;
Toast result = new Toast(context, looper);
return result;
if (Compatibility.isChangeEnabled(CHANGE_TEXT_TOASTS_IN_THE_SYSTEM)) {
result.mText = text;
} else {
result.mNextView = ToastPresenter.getTextToastView(context, text);
}
result.mDuration = duration;
return result;
}
/**
* Make a standard toast with an icon to display using the specified looper.
* If looper is null, Looper.myLooper() is used.
*
* The toast will be a custom view that's rendered by the app (instead of by SystemUI).
* In Android version R and above, non-system apps can only render the toast
* when it's in the foreground.
*
* @hide
*/
public static Toast makeCustomToastWithIcon(@NonNull Context context, @Nullable Looper looper,
@NonNull CharSequence text, @Duration int duration, @NonNull Drawable icon) {
if (icon == null) {
throw new IllegalArgumentException("Drawable icon should not be null "
+ "for makeCustomToastWithIcon");
}
Toast result = new Toast(context, looper);
result.mNextView = ToastPresenter.getTextToastViewWithIcon(context, text, icon);
result.mDuration = duration;
return result;
}
/**

View File

@@ -25,6 +25,7 @@ import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
@@ -55,6 +56,8 @@ public class ToastPresenter {
@VisibleForTesting
public static final int TEXT_TOAST_LAYOUT = R.layout.transient_notification;
@VisibleForTesting
public static final int TEXT_TOAST_LAYOUT_WITH_ICON = R.layout.transient_notification_with_icon;
/**
* Returns the default text toast view for message {@code text}.
@@ -66,6 +69,24 @@ public class ToastPresenter {
return view;
}
/**
* Returns the default icon text toast view for message {@code text} and the icon {@code icon}.
*/
public static View getTextToastViewWithIcon(Context context, CharSequence text, Drawable icon) {
if (icon == null) {
return getTextToastView(context, text);
}
View view = LayoutInflater.from(context).inflate(TEXT_TOAST_LAYOUT_WITH_ICON, null);
TextView textView = view.findViewById(com.android.internal.R.id.message);
textView.setText(text);
ImageView imageView = view.findViewById(com.android.internal.R.id.icon);
if (imageView != null) {
imageView.setImageDrawable(icon);
}
return view;
}
private final Context mContext;
private final Resources mResources;
private final WindowManager mWindowManager;

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2022 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:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:maxWidth="@dimen/toast_width"
android:background="?android:attr/toastFrameBackground"
android:elevation="@dimen/toast_elevation"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:paddingStart="16dp"
android:paddingEnd="16dp">
<ImageView
android:id="@android:id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@android:id/message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="2"
android:paddingTop="12dp"
android:paddingBottom="12dp"
android:textAppearance="@style/TextAppearance.Toast"/>
</LinearLayout>

View File

@@ -1574,6 +1574,7 @@
<java-symbol type="layout" name="time_picker_dialog" />
<java-symbol type="layout" name="tooltip" />
<java-symbol type="layout" name="transient_notification" />
<java-symbol type="layout" name="transient_notification_with_icon" />
<java-symbol type="layout" name="voice_interaction_session" />
<java-symbol type="layout" name="web_text_view_dropdown" />
<java-symbol type="layout" name="webview_find" />

View File

@@ -43,6 +43,7 @@ import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -63,6 +64,7 @@ import android.provider.DeviceConfig;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.SafetyProtectionUtils;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -1181,9 +1183,19 @@ public class ClipboardService extends SystemService {
String message =
getContext().getString(R.string.pasted_from_clipboard, callingAppLabel);
Slog.i(TAG, message);
Toast.makeText(
getContext(), UiThread.get().getLooper(), message, Toast.LENGTH_SHORT)
.show();
Toast toastToShow;
if (SafetyProtectionUtils.shouldShowSafetyProtectionResources(getContext())) {
Drawable safetyProtectionIcon = getContext()
.getDrawable(R.drawable.ic_safety_protection);
toastToShow = Toast.makeCustomToastWithIcon(getContext(),
UiThread.get().getLooper(), message,
Toast.LENGTH_SHORT, safetyProtectionIcon);
} else {
toastToShow = Toast.makeText(
getContext(), UiThread.get().getLooper(), message,
Toast.LENGTH_SHORT);
}
toastToShow.show();
} catch (PackageManager.NameNotFoundException e) {
// do nothing
}