1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.wallpaper.util 17 18 import android.content.ContentResolver 19 import android.content.Context 20 import android.content.Intent 21 import android.content.pm.PackageManager 22 import android.content.pm.ProviderInfo 23 import android.net.Uri 24 import android.os.Bundle 25 import android.os.Handler 26 import android.os.Looper 27 import android.os.Message 28 import android.text.TextUtils 29 import java.util.concurrent.Executors 30 31 /** Util class for wallpaper preview. */ 32 class PreviewUtils( 33 private val context: Context, 34 authorityMetadataKey: String? = null, 35 authority: String? = null, 36 ) { 37 /** Callback for a call to the provider to render preview */ 38 interface WorkspacePreviewCallback { 39 /** Called with the result from the provider. */ onPreviewRenderednull40 fun onPreviewRendered(resultBundle: Bundle?) 41 } 42 43 private var providerInfo: ProviderInfo? 44 45 constructor( 46 context: Context, 47 authorityMetadataKey: String, 48 ) : this( 49 context = context.applicationContext, 50 authorityMetadataKey = authorityMetadataKey, 51 authority = null, 52 ) 53 54 init { 55 val providerAuthority = 56 authority ?: homeAuthority(context, checkNotNull(authorityMetadataKey)) ?: "" 57 58 providerInfo = 59 if (!TextUtils.isEmpty(providerAuthority)) { 60 context.packageManager.resolveContentProvider( 61 providerAuthority, 62 0, 63 ) 64 } else { 65 null 66 } 67 68 providerInfo?.let { 69 if (!TextUtils.isEmpty(it.readPermission)) { 70 if ( 71 context.checkSelfPermission(it.readPermission) != 72 PackageManager.PERMISSION_GRANTED 73 ) { 74 providerInfo = null 75 } 76 } 77 } 78 } 79 80 /** 81 * Render preview under the current grid option. 82 * 83 * @param bundle request options to pass on the call. 84 * @param callback to receive the results, it will be called on the main thread. 85 */ renderPreviewnull86 fun renderPreview(bundle: Bundle?, callback: WorkspacePreviewCallback) { 87 EXECUTOR_SERVICE.submit { 88 val result = 89 context.contentResolver.call( 90 getUri(PREVIEW), 91 METHOD_GET_PREVIEW, 92 null, 93 bundle, 94 ) 95 Handler(Looper.getMainLooper()).post { callback.onPreviewRendered(result) } 96 } 97 } 98 99 /** Cleans up the preview on the renderer side */ cleanUpnull100 fun cleanUp(workspaceCallback: Message?) { 101 // Send any message to clean up the corresponding preview on the renderer side. 102 workspaceCallback?.replyTo?.send(workspaceCallback) 103 } 104 105 /** Easy way to generate a Uri with the provider info from this class. */ getUrinull106 fun getUri(path: String?): Uri { 107 return Uri.Builder() 108 .scheme(ContentResolver.SCHEME_CONTENT) 109 .authority(checkNotNull(providerInfo).authority) 110 .appendPath(path) 111 .build() 112 } 113 114 /** Return whether preview is supported. */ supportsPreviewnull115 fun supportsPreview(): Boolean { 116 return providerInfo != null 117 } 118 119 companion object { 120 private const val PREVIEW = "preview" 121 private const val METHOD_GET_PREVIEW = "get_preview" 122 private val EXECUTOR_SERVICE = Executors.newSingleThreadExecutor() 123 homeAuthoritynull124 private fun homeAuthority(context: Context, authorityMetadataKey: String): String? { 125 val homeIntent = Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME) 126 val info = 127 context.packageManager.resolveActivity( 128 homeIntent, 129 PackageManager.MATCH_DEFAULT_ONLY or PackageManager.GET_META_DATA, 130 ) 131 132 return info?.activityInfo?.metaData?.getString(authorityMetadataKey) 133 } 134 } 135 } 136