Loading packages/SystemUI/res/drawable/clipboard_minimized_background.xml 0 → 100644 +23 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- ~ Copyright (C) 2023 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" xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" android:shape="rectangle"> <solid android:color="?androidprv:attr/colorAccentSecondary"/> <corners android:radius="10dp"/> </shape> packages/SystemUI/res/drawable/ic_content_paste.xml 0 → 100644 +25 −0 Original line number Diff line number Diff line <!-- ~ Copyright (C) 2023 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. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="48dp" android:height="48dp" android:viewportWidth="48" android:viewportHeight="48" android:tint="?attr/colorControlNormal"> <path android:fillColor="@android:color/white" android:pathData="M9,42Q7.7,42 6.85,41.15Q6,40.3 6,39V9Q6,7.7 6.85,6.85Q7.7,6 9,6H19.1Q19.45,4.25 20.825,3.125Q22.2,2 24,2Q25.8,2 27.175,3.125Q28.55,4.25 28.9,6H39Q40.3,6 41.15,6.85Q42,7.7 42,9V39Q42,40.3 41.15,41.15Q40.3,42 39,42ZM9,39H39Q39,39 39,39Q39,39 39,39V9Q39,9 39,9Q39,9 39,9H36V13.5H12V9H9Q9,9 9,9Q9,9 9,9V39Q9,39 9,39Q9,39 9,39ZM24,9Q24.85,9 25.425,8.425Q26,7.85 26,7Q26,6.15 25.425,5.575Q24.85,5 24,5Q23.15,5 22.575,5.575Q22,6.15 22,7Q22,7.85 22.575,8.425Q23.15,9 24,9Z"/> </vector> No newline at end of file packages/SystemUI/res/layout/clipboard_overlay.xml +43 −4 Original line number Diff line number Diff line Loading @@ -125,6 +125,45 @@ android:layout_width="@dimen/clipboard_preview_size" android:layout_height="@dimen/clipboard_preview_size"/> </FrameLayout> <LinearLayout android:id="@+id/minimized_preview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:visibility="gone" android:elevation="7dp" android:padding="8dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="@dimen/overlay_action_container_margin_horizontal" android:layout_marginBottom="@dimen/overlay_action_container_margin_bottom" android:background="@drawable/clipboard_minimized_background"> <ImageView android:src="@drawable/ic_content_paste" android:tint="?attr/overlayButtonTextColor" android:layout_width="24dp" android:layout_height="24dp"/> <ImageView android:src="@*android:drawable/ic_chevron_end" android:tint="?attr/overlayButtonTextColor" android:layout_width="24dp" android:layout_height="24dp" android:paddingEnd="-8dp" android:paddingStart="-4dp"/> </LinearLayout> <androidx.constraintlayout.widget.Barrier android:id="@+id/clipboard_content_top" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:barrierDirection="top" app:constraint_referenced_ids="clipboard_preview,minimized_preview"/> <androidx.constraintlayout.widget.Barrier android:id="@+id/clipboard_content_end" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:barrierDirection="end" app:constraint_referenced_ids="clipboard_preview,minimized_preview"/> <FrameLayout android:id="@+id/dismiss_button" android:layout_width="@dimen/overlay_dismiss_button_tappable_size" Loading @@ -132,10 +171,10 @@ android:elevation="10dp" android:visibility="gone" android:alpha="0" app:layout_constraintStart_toEndOf="@id/clipboard_preview" app:layout_constraintEnd_toEndOf="@id/clipboard_preview" app:layout_constraintTop_toTopOf="@id/clipboard_preview" app:layout_constraintBottom_toTopOf="@id/clipboard_preview" app:layout_constraintStart_toEndOf="@id/clipboard_content_end" app:layout_constraintEnd_toEndOf="@id/clipboard_content_end" app:layout_constraintTop_toTopOf="@id/clipboard_content_top" app:layout_constraintBottom_toTopOf="@id/clipboard_content_top" android:contentDescription="@string/clipboard_dismiss_description"> <ImageView android:id="@+id/dismiss_image" Loading packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java +12 −1 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static android.content.ClipDescription.CLASSIFICATION_COMPLETE; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ENTERED; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_UPDATED; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_TOAST_SHOWN; import static com.android.systemui.flags.Flags.CLIPBOARD_MINIMIZED_LAYOUT; import static com.google.android.setupcompat.util.WizardManagerHelper.SETTINGS_SECURE_USER_SETUP_COMPLETE; Loading @@ -35,6 +36,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.UiEventLogger; import com.android.systemui.CoreStartable; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.flags.FeatureFlags; import javax.inject.Inject; import javax.inject.Provider; Loading @@ -57,6 +59,7 @@ public class ClipboardListener implements private final Provider<ClipboardOverlayController> mOverlayProvider; private final ClipboardToast mClipboardToast; private final ClipboardManager mClipboardManager; private final FeatureFlags mFeatureFlags; private final UiEventLogger mUiEventLogger; private ClipboardOverlay mClipboardOverlay; Loading @@ -65,11 +68,13 @@ public class ClipboardListener implements Provider<ClipboardOverlayController> clipboardOverlayControllerProvider, ClipboardToast clipboardToast, ClipboardManager clipboardManager, FeatureFlags featureFlags, UiEventLogger uiEventLogger) { mContext = context; mOverlayProvider = clipboardOverlayControllerProvider; mClipboardToast = clipboardToast; mClipboardManager = clipboardManager; mFeatureFlags = featureFlags; mUiEventLogger = uiEventLogger; } Loading Loading @@ -107,7 +112,11 @@ public class ClipboardListener implements } else { mUiEventLogger.log(CLIPBOARD_OVERLAY_UPDATED, 0, clipSource); } if (mFeatureFlags.isEnabled(CLIPBOARD_MINIMIZED_LAYOUT)) { mClipboardOverlay.setClipData(clipData, clipSource); } else { mClipboardOverlay.setClipDataLegacy(clipData, clipSource); } mClipboardOverlay.setOnSessionCompleteListener(() -> { // Session is complete, free memory until it's needed again. mClipboardOverlay = null; Loading Loading @@ -150,6 +159,8 @@ public class ClipboardListener implements } interface ClipboardOverlay { void setClipDataLegacy(ClipData clipData, String clipSource); void setClipData(ClipData clipData, String clipSource); void setOnSessionCompleteListener(Runnable runnable); Loading packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardModel.kt 0 → 100644 +101 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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 com.android.systemui.clipboardoverlay import android.content.ClipData import android.content.ClipDescription.EXTRA_IS_SENSITIVE import android.content.Context import android.graphics.Bitmap import android.text.TextUtils import android.util.Log import android.util.Size import com.android.systemui.R import java.io.IOException data class ClipboardModel( val clipData: ClipData?, val source: String, val type: Type = Type.OTHER, val item: ClipData.Item? = null, val isSensitive: Boolean = false, val isRemote: Boolean = false, ) { private var _bitmap: Bitmap? = null fun dataMatches(other: ClipboardModel?): Boolean { if (other == null) { return false } return source == other.source && type == other.type && item?.text == other.item?.text && item?.uri == other.item?.uri && isSensitive == other.isSensitive } fun loadThumbnail(context: Context): Bitmap? { if (_bitmap == null && type == Type.IMAGE && item?.uri != null) { try { val size = context.resources.getDimensionPixelSize(R.dimen.overlay_x_scale) _bitmap = context.contentResolver.loadThumbnail(item.uri, Size(size, size * 4), null) } catch (e: IOException) { Log.e(TAG, "Thumbnail loading failed!", e) } } return _bitmap } internal companion object { private val TAG: String = "ClipboardModel" @JvmStatic fun fromClipData( context: Context, utils: ClipboardOverlayUtils, clipData: ClipData?, source: String ): ClipboardModel { if (clipData == null || clipData.itemCount == 0) { return ClipboardModel(clipData, source) } val sensitive = clipData.description?.extras?.getBoolean(EXTRA_IS_SENSITIVE) ?: false val item = clipData.getItemAt(0)!! val type = getType(context, item) val remote = utils.isRemoteCopy(context, clipData, source) return ClipboardModel(clipData, source, type, item, sensitive, remote) } private fun getType(context: Context, item: ClipData.Item): Type { return if (!TextUtils.isEmpty(item.text)) { Type.TEXT } else if ( item.uri != null && context.contentResolver.getType(item.uri)?.startsWith("image") == true ) { Type.IMAGE } else { Type.OTHER } } } enum class Type { TEXT, IMAGE, OTHER } } Loading
packages/SystemUI/res/drawable/clipboard_minimized_background.xml 0 → 100644 +23 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- ~ Copyright (C) 2023 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" xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" android:shape="rectangle"> <solid android:color="?androidprv:attr/colorAccentSecondary"/> <corners android:radius="10dp"/> </shape>
packages/SystemUI/res/drawable/ic_content_paste.xml 0 → 100644 +25 −0 Original line number Diff line number Diff line <!-- ~ Copyright (C) 2023 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. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="48dp" android:height="48dp" android:viewportWidth="48" android:viewportHeight="48" android:tint="?attr/colorControlNormal"> <path android:fillColor="@android:color/white" android:pathData="M9,42Q7.7,42 6.85,41.15Q6,40.3 6,39V9Q6,7.7 6.85,6.85Q7.7,6 9,6H19.1Q19.45,4.25 20.825,3.125Q22.2,2 24,2Q25.8,2 27.175,3.125Q28.55,4.25 28.9,6H39Q40.3,6 41.15,6.85Q42,7.7 42,9V39Q42,40.3 41.15,41.15Q40.3,42 39,42ZM9,39H39Q39,39 39,39Q39,39 39,39V9Q39,9 39,9Q39,9 39,9H36V13.5H12V9H9Q9,9 9,9Q9,9 9,9V39Q9,39 9,39Q9,39 9,39ZM24,9Q24.85,9 25.425,8.425Q26,7.85 26,7Q26,6.15 25.425,5.575Q24.85,5 24,5Q23.15,5 22.575,5.575Q22,6.15 22,7Q22,7.85 22.575,8.425Q23.15,9 24,9Z"/> </vector> No newline at end of file
packages/SystemUI/res/layout/clipboard_overlay.xml +43 −4 Original line number Diff line number Diff line Loading @@ -125,6 +125,45 @@ android:layout_width="@dimen/clipboard_preview_size" android:layout_height="@dimen/clipboard_preview_size"/> </FrameLayout> <LinearLayout android:id="@+id/minimized_preview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:visibility="gone" android:elevation="7dp" android:padding="8dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="@dimen/overlay_action_container_margin_horizontal" android:layout_marginBottom="@dimen/overlay_action_container_margin_bottom" android:background="@drawable/clipboard_minimized_background"> <ImageView android:src="@drawable/ic_content_paste" android:tint="?attr/overlayButtonTextColor" android:layout_width="24dp" android:layout_height="24dp"/> <ImageView android:src="@*android:drawable/ic_chevron_end" android:tint="?attr/overlayButtonTextColor" android:layout_width="24dp" android:layout_height="24dp" android:paddingEnd="-8dp" android:paddingStart="-4dp"/> </LinearLayout> <androidx.constraintlayout.widget.Barrier android:id="@+id/clipboard_content_top" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:barrierDirection="top" app:constraint_referenced_ids="clipboard_preview,minimized_preview"/> <androidx.constraintlayout.widget.Barrier android:id="@+id/clipboard_content_end" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:barrierDirection="end" app:constraint_referenced_ids="clipboard_preview,minimized_preview"/> <FrameLayout android:id="@+id/dismiss_button" android:layout_width="@dimen/overlay_dismiss_button_tappable_size" Loading @@ -132,10 +171,10 @@ android:elevation="10dp" android:visibility="gone" android:alpha="0" app:layout_constraintStart_toEndOf="@id/clipboard_preview" app:layout_constraintEnd_toEndOf="@id/clipboard_preview" app:layout_constraintTop_toTopOf="@id/clipboard_preview" app:layout_constraintBottom_toTopOf="@id/clipboard_preview" app:layout_constraintStart_toEndOf="@id/clipboard_content_end" app:layout_constraintEnd_toEndOf="@id/clipboard_content_end" app:layout_constraintTop_toTopOf="@id/clipboard_content_top" app:layout_constraintBottom_toTopOf="@id/clipboard_content_top" android:contentDescription="@string/clipboard_dismiss_description"> <ImageView android:id="@+id/dismiss_image" Loading
packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java +12 −1 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static android.content.ClipDescription.CLASSIFICATION_COMPLETE; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ENTERED; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_UPDATED; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_TOAST_SHOWN; import static com.android.systemui.flags.Flags.CLIPBOARD_MINIMIZED_LAYOUT; import static com.google.android.setupcompat.util.WizardManagerHelper.SETTINGS_SECURE_USER_SETUP_COMPLETE; Loading @@ -35,6 +36,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.UiEventLogger; import com.android.systemui.CoreStartable; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.flags.FeatureFlags; import javax.inject.Inject; import javax.inject.Provider; Loading @@ -57,6 +59,7 @@ public class ClipboardListener implements private final Provider<ClipboardOverlayController> mOverlayProvider; private final ClipboardToast mClipboardToast; private final ClipboardManager mClipboardManager; private final FeatureFlags mFeatureFlags; private final UiEventLogger mUiEventLogger; private ClipboardOverlay mClipboardOverlay; Loading @@ -65,11 +68,13 @@ public class ClipboardListener implements Provider<ClipboardOverlayController> clipboardOverlayControllerProvider, ClipboardToast clipboardToast, ClipboardManager clipboardManager, FeatureFlags featureFlags, UiEventLogger uiEventLogger) { mContext = context; mOverlayProvider = clipboardOverlayControllerProvider; mClipboardToast = clipboardToast; mClipboardManager = clipboardManager; mFeatureFlags = featureFlags; mUiEventLogger = uiEventLogger; } Loading Loading @@ -107,7 +112,11 @@ public class ClipboardListener implements } else { mUiEventLogger.log(CLIPBOARD_OVERLAY_UPDATED, 0, clipSource); } if (mFeatureFlags.isEnabled(CLIPBOARD_MINIMIZED_LAYOUT)) { mClipboardOverlay.setClipData(clipData, clipSource); } else { mClipboardOverlay.setClipDataLegacy(clipData, clipSource); } mClipboardOverlay.setOnSessionCompleteListener(() -> { // Session is complete, free memory until it's needed again. mClipboardOverlay = null; Loading Loading @@ -150,6 +159,8 @@ public class ClipboardListener implements } interface ClipboardOverlay { void setClipDataLegacy(ClipData clipData, String clipSource); void setClipData(ClipData clipData, String clipSource); void setOnSessionCompleteListener(Runnable runnable); Loading
packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardModel.kt 0 → 100644 +101 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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 com.android.systemui.clipboardoverlay import android.content.ClipData import android.content.ClipDescription.EXTRA_IS_SENSITIVE import android.content.Context import android.graphics.Bitmap import android.text.TextUtils import android.util.Log import android.util.Size import com.android.systemui.R import java.io.IOException data class ClipboardModel( val clipData: ClipData?, val source: String, val type: Type = Type.OTHER, val item: ClipData.Item? = null, val isSensitive: Boolean = false, val isRemote: Boolean = false, ) { private var _bitmap: Bitmap? = null fun dataMatches(other: ClipboardModel?): Boolean { if (other == null) { return false } return source == other.source && type == other.type && item?.text == other.item?.text && item?.uri == other.item?.uri && isSensitive == other.isSensitive } fun loadThumbnail(context: Context): Bitmap? { if (_bitmap == null && type == Type.IMAGE && item?.uri != null) { try { val size = context.resources.getDimensionPixelSize(R.dimen.overlay_x_scale) _bitmap = context.contentResolver.loadThumbnail(item.uri, Size(size, size * 4), null) } catch (e: IOException) { Log.e(TAG, "Thumbnail loading failed!", e) } } return _bitmap } internal companion object { private val TAG: String = "ClipboardModel" @JvmStatic fun fromClipData( context: Context, utils: ClipboardOverlayUtils, clipData: ClipData?, source: String ): ClipboardModel { if (clipData == null || clipData.itemCount == 0) { return ClipboardModel(clipData, source) } val sensitive = clipData.description?.extras?.getBoolean(EXTRA_IS_SENSITIVE) ?: false val item = clipData.getItemAt(0)!! val type = getType(context, item) val remote = utils.isRemoteCopy(context, clipData, source) return ClipboardModel(clipData, source, type, item, sensitive, remote) } private fun getType(context: Context, item: ClipData.Item): Type { return if (!TextUtils.isEmpty(item.text)) { Type.TEXT } else if ( item.uri != null && context.contentResolver.getType(item.uri)?.startsWith("image") == true ) { Type.IMAGE } else { Type.OTHER } } } enum class Type { TEXT, IMAGE, OTHER } }