Snap for 9406096 from 50cd81ffd52a5843203b437f3437e126da459795 to tm-qpr2-release
Change-Id: Ia8b735edb974e2c2a541400b19986fd68fac4f9d
diff --git a/res/values/strings.xml b/res/values/strings.xml
index c238961..0faf2e1 100755
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -399,4 +399,10 @@
<!-- Label for a button which lets user try to open their photos. [CHAR LIMIT=40] -->
<string name="open_my_photos">Open My Photos</string>
+
+ <!--
+ Name of the authority corresponding to a ContentProvider in system UI that can provide remote
+ rendering of a preview of the lock screen.
+ -->
+ <string name="lock_screen_preview_provider_authority" translatable="false">com.android.systemui.keyguard.quickaffordance</string>
</resources>
diff --git a/src/com/android/wallpaper/model/WallpaperSectionController.java b/src/com/android/wallpaper/model/WallpaperSectionController.java
index 7963015..12babbd 100644
--- a/src/com/android/wallpaper/model/WallpaperSectionController.java
+++ b/src/com/android/wallpaper/model/WallpaperSectionController.java
@@ -59,6 +59,7 @@
import com.android.wallpaper.picker.MyPhotosStarter;
import com.android.wallpaper.picker.WallpaperSectionView;
import com.android.wallpaper.picker.WorkspaceSurfaceHolderCallback;
+import com.android.wallpaper.util.PreviewUtils;
import com.android.wallpaper.util.ResourceUtils;
import com.android.wallpaper.util.WallpaperConnection;
import com.android.wallpaper.util.WallpaperSurfaceCallback;
@@ -164,7 +165,9 @@
mWorkspaceSurface = mHomePreviewCard.findViewById(R.id.workspace_surface);
mHomePreviewProgress = mHomePreviewCard.findViewById(R.id.wallpaper_preview_spinner);
mWorkspaceSurfaceCallback = new WorkspaceSurfaceHolderCallback(
- mWorkspaceSurface, mAppContext);
+ mWorkspaceSurface,
+ new PreviewUtils(
+ mAppContext, mAppContext.getString(R.string.grid_control_metadata_name)));
mHomeWallpaperSurface = mHomePreviewCard.findViewById(R.id.wallpaper_surface);
Future<ColorInfo> colorFuture = CompletableFuture.completedFuture(
diff --git a/src/com/android/wallpaper/picker/DisplayAspectRatioFrameLayout.kt b/src/com/android/wallpaper/picker/DisplayAspectRatioFrameLayout.kt
new file mode 100644
index 0000000..a2f1c67
--- /dev/null
+++ b/src/com/android/wallpaper/picker/DisplayAspectRatioFrameLayout.kt
@@ -0,0 +1,58 @@
+/*
+ * 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 com.android.wallpaper.picker
+
+import android.content.Context
+import android.util.AttributeSet
+import android.widget.FrameLayout
+import androidx.core.view.children
+import com.android.wallpaper.util.ScreenSizeCalculator
+
+/**
+ * [FrameLayout] that sizes its children using a fixed aspect ratio that is the same as that of the
+ * display.
+ */
+class DisplayAspectRatioFrameLayout(
+ context: Context,
+ attrs: AttributeSet?,
+) : FrameLayout(context, attrs) {
+
+ override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec)
+ val screenAspectRatio = ScreenSizeCalculator.getInstance().getScreenAspectRatio(context)
+ // We're always forcing the width based on the height. This will only work if the
+ // DisplayAspectRatioFrameLayout is allowed to stretch to fill its parent (for example if
+ // the parent is a vertical LinearLayout and the DisplayAspectRatioFrameLayout has a height
+ // if 0 and a weight of 1.
+ //
+ // If you need to use this class to force the height dimension based on the width instead,
+ // you will need to flip the logic below.
+ children.forEach { child ->
+ child.measure(
+ MeasureSpec.makeMeasureSpec(
+ (child.measuredHeight / screenAspectRatio).toInt(),
+ MeasureSpec.EXACTLY
+ ),
+ MeasureSpec.makeMeasureSpec(
+ child.measuredHeight,
+ MeasureSpec.EXACTLY,
+ ),
+ )
+ }
+ }
+}
diff --git a/src/com/android/wallpaper/picker/PreviewFragment.java b/src/com/android/wallpaper/picker/PreviewFragment.java
index e1eaca2..e9e78c8 100755
--- a/src/com/android/wallpaper/picker/PreviewFragment.java
+++ b/src/com/android/wallpaper/picker/PreviewFragment.java
@@ -58,6 +58,7 @@
import com.android.wallpaper.module.WallpaperPreferences;
import com.android.wallpaper.module.WallpaperSetter;
import com.android.wallpaper.util.FullScreenAnimation;
+import com.android.wallpaper.util.PreviewUtils;
import com.android.wallpaper.util.ResourceUtils;
import com.android.wallpaper.widget.BottomActionBar;
import com.android.wallpaper.widget.BottomActionBar.BottomSheetContent;
@@ -317,7 +318,11 @@
protected WorkspaceSurfaceHolderCallback createWorkspaceSurfaceCallback(
SurfaceView workspaceSurface) {
- return new WorkspaceSurfaceHolderCallback(workspaceSurface, getContext());
+ return new WorkspaceSurfaceHolderCallback(
+ workspaceSurface,
+ new PreviewUtils(
+ getContext(),
+ getContext().getString(R.string.grid_control_metadata_name)));
}
@Override
diff --git a/src/com/android/wallpaper/picker/WorkspaceSurfaceHolderCallback.java b/src/com/android/wallpaper/picker/WorkspaceSurfaceHolderCallback.java
index 2661923..bb4c0d3 100644
--- a/src/com/android/wallpaper/picker/WorkspaceSurfaceHolderCallback.java
+++ b/src/com/android/wallpaper/picker/WorkspaceSurfaceHolderCallback.java
@@ -16,7 +16,6 @@
package com.android.wallpaper.picker;
import android.app.WallpaperColors;
-import android.content.Context;
import android.os.Bundle;
import android.os.Message;
import android.os.RemoteException;
@@ -27,7 +26,6 @@
import androidx.annotation.Nullable;
-import com.android.wallpaper.R;
import com.android.wallpaper.util.PreviewUtils;
import com.android.wallpaper.util.SurfaceViewUtils;
@@ -60,9 +58,12 @@
private WorkspaceRenderListener mListener;
private boolean mNeedsToCleanUp;
+ @Nullable private final Bundle mExtras;
- public WorkspaceSurfaceHolderCallback(SurfaceView workspaceSurface, Context context) {
- this(workspaceSurface, context, false);
+ public WorkspaceSurfaceHolderCallback(
+ SurfaceView workspaceSurface,
+ PreviewUtils previewUtils) {
+ this(workspaceSurface, previewUtils, false, null);
}
/**
@@ -73,12 +74,33 @@
* the surface is created and wallpaper colors are set via
* {@link #setWallpaperColors(WallpaperColors)}
*/
- public WorkspaceSurfaceHolderCallback(SurfaceView workspaceSurface, Context context,
+ public WorkspaceSurfaceHolderCallback(
+ SurfaceView workspaceSurface,
+ PreviewUtils previewUtils,
boolean shouldUseWallpaperColors) {
+ this(
+ workspaceSurface,
+ previewUtils,
+ shouldUseWallpaperColors,
+ null);
+ }
+
+ public WorkspaceSurfaceHolderCallback(
+ SurfaceView workspaceSurface,
+ PreviewUtils previewUtils,
+ @Nullable Bundle extras) {
+ this(workspaceSurface, previewUtils, false, extras);
+ }
+
+ private WorkspaceSurfaceHolderCallback(
+ SurfaceView workspaceSurface,
+ PreviewUtils previewUtils,
+ boolean shouldUseWallpaperColors,
+ @Nullable Bundle extras) {
mWorkspaceSurface = workspaceSurface;
- mPreviewUtils = new PreviewUtils(context,
- context.getString(R.string.grid_control_metadata_name));
+ mPreviewUtils = previewUtils;
mShouldUseWallpaperColors = shouldUseWallpaperColors;
+ mExtras = extras;
}
@Override
@@ -96,7 +118,7 @@
*
* @param colors WallpaperColors extracted from the current wallpaper preview, or {@code null}
* if none are available.
- * @see #WorkspaceSurfaceHolderCallback(SurfaceView, Context, boolean)
+ * @see #WorkspaceSurfaceHolderCallback(SurfaceView, PreviewUtils, boolean)
*/
public void setWallpaperColors(@Nullable WallpaperColors colors) {
if (!mShouldUseWallpaperColors) {
@@ -141,6 +163,27 @@
public void surfaceDestroyed(SurfaceHolder holder) {
}
+ /**
+ * Sends a message to the remote renderer.
+ *
+ * @param what An ID for the message (the remote side can pick this up through
+ * {@link Message#what}.
+ * @param bundle The data of the message (the remote side can pick this up through
+ * {@link Message#getData()}.
+ */
+ public void send(final int what, @Nullable Bundle bundle) {
+ if (mCallback != null) {
+ try {
+ final Message message = new Message();
+ message.what = what;
+ message.setData(bundle);
+ mCallback.replyTo.send(message);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Couldn't send message to workspace preview", e);
+ }
+ }
+ }
+
public void cleanUp() {
if (mCallback != null) {
try {
@@ -170,7 +213,7 @@
+ "crash");
return;
}
- Bundle request = SurfaceViewUtils.createSurfaceViewRequest(workspaceSurface);
+ Bundle request = SurfaceViewUtils.createSurfaceViewRequest(workspaceSurface, mExtras);
if (mWallpaperColors != null) {
request.putParcelable(KEY_WALLPAPER_COLORS, mWallpaperColors);
}
diff --git a/src/com/android/wallpaper/util/PreviewUtils.java b/src/com/android/wallpaper/util/PreviewUtils.java
deleted file mode 100644
index 0b8977a..0000000
--- a/src/com/android/wallpaper/util/PreviewUtils.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2020 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.wallpaper.util;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ProviderInfo;
-import android.content.pm.ResolveInfo;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.text.TextUtils;
-
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-/** Util class for wallpaper preview. */
-public class PreviewUtils {
-
- private static final String PREVIEW = "preview";
- private static final String METHOD_GET_PREVIEW = "get_preview";
- private static final ExecutorService sExecutorService = Executors.newSingleThreadExecutor();
-
- private final Context mContext;
- private final String mProviderAuthority;
- private ProviderInfo mProviderInfo;
-
- public PreviewUtils(Context context, String authorityMetadataKey) {
- mContext = context;
- Intent homeIntent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME);
-
- ResolveInfo info = context.getPackageManager().resolveActivity(homeIntent,
- PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA);
- if (info != null && info.activityInfo != null && info.activityInfo.metaData != null) {
- mProviderAuthority = info.activityInfo.metaData.getString(authorityMetadataKey);
- } else {
- mProviderAuthority = null;
- }
-
- mProviderInfo = TextUtils.isEmpty(mProviderAuthority) ? null
- : mContext.getPackageManager().resolveContentProvider(mProviderAuthority, 0);
- if (mProviderInfo != null && !TextUtils.isEmpty(mProviderInfo.readPermission)) {
- if (context.checkSelfPermission(mProviderInfo.readPermission)
- != PackageManager.PERMISSION_GRANTED) {
- mProviderInfo = null;
- }
- }
- }
-
- /**
- * Render preview under the current grid option.
- * @param bundle request options to pass on the call
- * @param callback to receive the results, it will be called on the main thread.
- */
- public void renderPreview(Bundle bundle, WorkspacePreviewCallback callback) {
- sExecutorService.submit(() -> {
- Bundle result = mContext.getContentResolver().call(getUri(PREVIEW),
- METHOD_GET_PREVIEW, null, bundle);
- new Handler(Looper.getMainLooper()).post(() -> callback.onPreviewRendered(result));
- });
- }
-
- /** Easy way to generate a Uri with the provider info from this class. */
- public Uri getUri(String path) {
- return new Uri.Builder()
- .scheme(ContentResolver.SCHEME_CONTENT)
- .authority(mProviderInfo.authority)
- .appendPath(path)
- .build();
- }
-
- /** Return whether preview is supported. */
- public boolean supportsPreview() {
- return mProviderInfo != null;
- }
-
- /**
- * Callback for a call to the provider to render preview
- */
- public interface WorkspacePreviewCallback {
- /**
- * Called with the result from the provider.
- */
- void onPreviewRendered(Bundle resultBundle);
- }
-}
diff --git a/src/com/android/wallpaper/util/PreviewUtils.kt b/src/com/android/wallpaper/util/PreviewUtils.kt
new file mode 100644
index 0000000..a2e0275
--- /dev/null
+++ b/src/com/android/wallpaper/util/PreviewUtils.kt
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2020 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.wallpaper.util
+
+import android.content.ContentResolver
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.content.pm.ProviderInfo
+import android.net.Uri
+import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
+import android.text.TextUtils
+import java.util.concurrent.Executors
+
+/** Util class for wallpaper preview. */
+class PreviewUtils(
+ private val context: Context,
+ authorityMetadataKey: String? = null,
+ authority: String? = null,
+) {
+ /** Callback for a call to the provider to render preview */
+ interface WorkspacePreviewCallback {
+ /** Called with the result from the provider. */
+ fun onPreviewRendered(resultBundle: Bundle?)
+ }
+
+ private var providerInfo: ProviderInfo?
+
+ constructor(
+ context: Context,
+ authorityMetadataKey: String,
+ ) : this(
+ context = context,
+ authorityMetadataKey = authorityMetadataKey,
+ authority = null,
+ )
+
+ init {
+ val providerAuthority =
+ authority ?: homeAuthority(context, checkNotNull(authorityMetadataKey))
+
+ providerInfo =
+ if (!TextUtils.isEmpty(providerAuthority)) {
+ context.packageManager.resolveContentProvider(
+ providerAuthority,
+ 0,
+ )
+ } else {
+ null
+ }
+
+ providerInfo?.let {
+ if (!TextUtils.isEmpty(it.readPermission)) {
+ if (
+ context.checkSelfPermission(it.readPermission) !=
+ PackageManager.PERMISSION_GRANTED
+ ) {
+ providerInfo = null
+ }
+ }
+ }
+ }
+
+ /**
+ * Render preview under the current grid option.
+ *
+ * @param bundle request options to pass on the call.
+ * @param callback to receive the results, it will be called on the main thread.
+ */
+ fun renderPreview(bundle: Bundle?, callback: WorkspacePreviewCallback) {
+ EXECUTOR_SERVICE.submit {
+ val result =
+ context.contentResolver.call(
+ getUri(PREVIEW),
+ METHOD_GET_PREVIEW,
+ null,
+ bundle,
+ )
+ Handler(Looper.getMainLooper()).post { callback.onPreviewRendered(result) }
+ }
+ }
+
+ /** Easy way to generate a Uri with the provider info from this class. */
+ fun getUri(path: String?): Uri {
+ return Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(checkNotNull(providerInfo).authority)
+ .appendPath(path)
+ .build()
+ }
+
+ /** Return whether preview is supported. */
+ fun supportsPreview(): Boolean {
+ return providerInfo != null
+ }
+
+ companion object {
+ private const val PREVIEW = "preview"
+ private const val METHOD_GET_PREVIEW = "get_preview"
+ private val EXECUTOR_SERVICE = Executors.newSingleThreadExecutor()
+
+ private fun homeAuthority(context: Context, authorityMetadataKey: String): String? {
+ val homeIntent = Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME)
+ val info =
+ context.packageManager.resolveActivity(
+ homeIntent,
+ PackageManager.MATCH_DEFAULT_ONLY or PackageManager.GET_META_DATA,
+ )
+
+ return info?.activityInfo?.metaData?.getString(authorityMetadataKey)
+ }
+ }
+}
diff --git a/src/com/android/wallpaper/util/SurfaceViewUtils.java b/src/com/android/wallpaper/util/SurfaceViewUtils.java
index 1656b1b..1b74f77 100644
--- a/src/com/android/wallpaper/util/SurfaceViewUtils.java
+++ b/src/com/android/wallpaper/util/SurfaceViewUtils.java
@@ -20,6 +20,8 @@
import android.view.SurfaceControlViewHost;
import android.view.SurfaceView;
+import androidx.annotation.Nullable;
+
/** Util class to generate surface view requests and parse responses */
public class SurfaceViewUtils {
@@ -32,11 +34,21 @@
/** Create a surface view request. */
public static Bundle createSurfaceViewRequest(SurfaceView surfaceView) {
+ return createSurfaceViewRequest(surfaceView, null);
+ }
+
+ /** Create a surface view request. */
+ public static Bundle createSurfaceViewRequest(
+ SurfaceView surfaceView,
+ @Nullable Bundle extras) {
Bundle bundle = new Bundle();
bundle.putBinder(KEY_HOST_TOKEN, surfaceView.getHostToken());
bundle.putInt(KEY_DISPLAY_ID, surfaceView.getDisplay().getDisplayId());
bundle.putInt(KEY_VIEW_WIDTH, surfaceView.getWidth());
bundle.putInt(KEY_VIEW_HEIGHT, surfaceView.getHeight());
+ if (extras != null) {
+ bundle.putAll(extras);
+ }
return bundle;
}