diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/DevOptionsUiHelper.kt b/quickstep/src/com/android/launcher3/uioverrides/flags/DevOptionsUiHelper.kt index 181cba098f..417bb74470 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/flags/DevOptionsUiHelper.kt +++ b/quickstep/src/com/android/launcher3/uioverrides/flags/DevOptionsUiHelper.kt @@ -35,9 +35,6 @@ import android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS import android.provider.Settings.Secure import android.text.Html import android.util.AttributeSet -import android.util.Base64 -import android.util.Base64.NO_PADDING -import android.util.Base64.NO_WRAP import android.view.inputmethod.EditorInfo import android.widget.TextView import android.widget.Toast @@ -57,9 +54,10 @@ import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_FOLDER -import com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_KEY import com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_LABEL import com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_TAG +import com.android.launcher3.LauncherSettings.Settings.LAYOUT_PROVIDER_KEY +import com.android.launcher3.LauncherSettings.Settings.createBlobProviderKey import com.android.launcher3.R import com.android.launcher3.model.data.FolderInfo import com.android.launcher3.model.data.ItemInfo @@ -241,7 +239,7 @@ class DevOptionsUiHelper(c: Context, attr: AttributeSet?) : PreferenceGroup(c, a private fun DebugInfo.getBoolValue() = DeviceConfigHelper.prefs.getBoolean( this.key, - DeviceConfig.getBoolean(NAMESPACE_LAUNCHER, this.key, this.valueInCode) + DeviceConfig.getBoolean(NAMESPACE_LAUNCHER, this.key, this.valueInCode), ) private fun DebugInfo.getIntValueAsString() = @@ -265,7 +263,7 @@ class DevOptionsUiHelper(c: Context, attr: AttributeSet?) : PreferenceGroup(c, a val pluginPermissionApps = pm.getPackagesHoldingPermissions( arrayOf(PLUGIN_PERMISSION), - PackageManager.MATCH_DISABLED_COMPONENTS + PackageManager.MATCH_DISABLED_COMPONENTS, ) .map { it.packageName } @@ -274,7 +272,7 @@ class DevOptionsUiHelper(c: Context, attr: AttributeSet?) : PreferenceGroup(c, a pm.queryIntentServices( Intent(action), PackageManager.MATCH_DISABLED_COMPONENTS or - PackageManager.GET_RESOLVED_FILTER + PackageManager.GET_RESOLVED_FILTER, ) .filter { pluginPermissionApps.contains(it.serviceInfo.packageName) } } @@ -316,7 +314,7 @@ class DevOptionsUiHelper(c: Context, attr: AttributeSet?) : PreferenceGroup(c, a infoList.forEach { manager.pluginEnabler.setDisabled( it.serviceInfo.componentName, - disabledState + disabledState, ) } manager.notifyChange(Intent(Intent.ACTION_PACKAGE_CHANGED, pluginUri)) @@ -387,12 +385,12 @@ class DevOptionsUiHelper(c: Context, attr: AttributeSet?) : PreferenceGroup(c, a addOnboardPref( "All Apps Bounce", HOME_BOUNCE_SEEN.sharedPrefKey, - HOME_BOUNCE_COUNT.sharedPrefKey + HOME_BOUNCE_COUNT.sharedPrefKey, ) addOnboardPref( "Hybrid Hotseat Education", HOTSEAT_DISCOVERY_TIP_COUNT.sharedPrefKey, - HOTSEAT_LONGPRESS_TIP_SEEN.sharedPrefKey + HOTSEAT_LONGPRESS_TIP_SEEN.sharedPrefKey, ) addOnboardPref("Taskbar Education", TASKBAR_EDU_TOOLTIP_STEP.sharedPrefKey) addOnboardPref("Taskbar Search Education", TASKBAR_SEARCH_EDU_SEEN.sharedPrefKey) @@ -470,13 +468,16 @@ class DevOptionsUiHelper(c: Context, attr: AttributeSet?) : PreferenceGroup(c, a session.allowPublicAccess() session.commit(ORDERED_BG_EXECUTOR) { - val key = Base64.encodeToString(digest, NO_WRAP or NO_PADDING) - Secure.putString(resolver, LAYOUT_DIGEST_KEY, key) + Secure.putString( + resolver, + LAYOUT_PROVIDER_KEY, + createBlobProviderKey(digest), + ) MODEL_EXECUTOR.submit { model.modelDbController.createEmptyDB() }.get() MAIN_EXECUTOR.submit { model.forceReload() }.get() MODEL_EXECUTOR.submit {}.get() - Secure.putString(resolver, LAYOUT_DIGEST_KEY, null) + Secure.putString(resolver, LAYOUT_PROVIDER_KEY, null) } } } @@ -512,7 +513,7 @@ class DevOptionsUiHelper(c: Context, attr: AttributeSet?) : PreferenceGroup(c, a info.providerName.className, info.spanX, info.spanY, - userType + userType, ) } } @@ -520,7 +521,7 @@ class DevOptionsUiHelper(c: Context, attr: AttributeSet?) : PreferenceGroup(c, a private fun createUriPickerIntent( action: String, executor: Executor, - callback: (uri: Uri) -> Unit + callback: (uri: Uri) -> Unit, ): Intent { val pendingIntent = PendingIntent( @@ -532,7 +533,7 @@ class DevOptionsUiHelper(c: Context, attr: AttributeSet?) : PreferenceGroup(c, a allowlistToken: IBinder?, finishedReceiver: IIntentReceiver?, requiredPermission: String?, - options: Bundle? + options: Bundle?, ) { intent.data?.let { uri -> executor.execute { callback(uri) } } } diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java index 87ac193397..1d2d1611de 100644 --- a/src/com/android/launcher3/LauncherSettings.java +++ b/src/com/android/launcher3/LauncherSettings.java @@ -16,8 +16,12 @@ package com.android.launcher3; +import static android.util.Base64.NO_PADDING; +import static android.util.Base64.NO_WRAP; + import android.database.sqlite.SQLiteDatabase; import android.provider.BaseColumns; +import android.util.Base64; import androidx.annotation.NonNull; @@ -354,8 +358,17 @@ public class LauncherSettings { * Launcher settings */ public static final class Settings { - public static final String LAYOUT_DIGEST_KEY = "launcher3.layout.provider.blob"; + public static final String LAYOUT_PROVIDER_KEY = "launcher3.layout.provider"; public static final String LAYOUT_DIGEST_LABEL = "launcher-layout"; public static final String LAYOUT_DIGEST_TAG = "ignore"; + public static final String BLOB_KEY_PREFIX = "blob://"; + + /** + * Creates a key to be used for {@link #LAYOUT_PROVIDER_KEY} + * @param digest byte[] representing the message digest for the blob handle + */ + public static String createBlobProviderKey(byte[] digest) { + return BLOB_KEY_PREFIX + Base64.encodeToString(digest, NO_WRAP | NO_PADDING); + } } } diff --git a/src/com/android/launcher3/model/ModelDbController.java b/src/com/android/launcher3/model/ModelDbController.java index da1a221d5d..5d66d16ad8 100644 --- a/src/com/android/launcher3/model/ModelDbController.java +++ b/src/com/android/launcher3/model/ModelDbController.java @@ -25,7 +25,8 @@ import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE; import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APP_PAIR; import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME; import static com.android.launcher3.LauncherSettings.Favorites.addTableToDb; -import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_KEY; +import static com.android.launcher3.LauncherSettings.Settings.BLOB_KEY_PREFIX; +import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_PROVIDER_KEY; import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_LABEL; import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_TAG; import static com.android.launcher3.provider.LauncherDbUtils.tableExists; @@ -548,9 +549,15 @@ public class ModelDbController { private AutoInstallsLayout createWorkspaceLoaderFromAppRestriction( LauncherWidgetHolder widgetHolder) { ContentResolver cr = mContext.getContentResolver(); - String blobHandlerDigest = Settings.Secure.getString(cr, LAYOUT_DIGEST_KEY); - if (!TextUtils.isEmpty(blobHandlerDigest)) { + String systemLayoutProvider = Settings.Secure.getString(cr, LAYOUT_PROVIDER_KEY); + if (TextUtils.isEmpty(systemLayoutProvider)) { + return null; + } + + // Try the blob store first + if (systemLayoutProvider.startsWith(BLOB_KEY_PREFIX)) { BlobStoreManager blobManager = mContext.getSystemService(BlobStoreManager.class); + String blobHandlerDigest = systemLayoutProvider.substring(BLOB_KEY_PREFIX.length()); try (InputStream in = new ParcelFileDescriptor.AutoCloseInputStream( blobManager.openBlob(BlobHandle.createWithSha256( Base64.decode(blobHandlerDigest, NO_WRAP | NO_PADDING), @@ -562,25 +569,21 @@ public class ModelDbController { } } - String authority = Settings.Secure.getString(cr, "launcher3.layout.provider"); - if (TextUtils.isEmpty(authority)) { - return null; - } - + // Try contentProvider based provider PackageManager pm = mContext.getPackageManager(); - ProviderInfo pi = pm.resolveContentProvider(authority, 0); + ProviderInfo pi = pm.resolveContentProvider(systemLayoutProvider, 0); if (pi == null) { - Log.e(TAG, "No provider found for authority " + authority); + Log.e(TAG, "No provider found for authority " + systemLayoutProvider); return null; } - Uri uri = getLayoutUri(authority, mContext); + Uri uri = getLayoutUri(systemLayoutProvider, mContext); try (InputStream in = cr.openInputStream(uri)) { - Log.d(TAG, "Loading layout from " + authority); + Log.d(TAG, "Loading layout from " + systemLayoutProvider); Resources res = pm.getResourcesForApplication(pi.applicationInfo); return getAutoInstallsLayoutFromIS(in, widgetHolder, SourceResources.wrap(res)); } catch (Exception e) { - Log.e(TAG, "Error getting layout stream from: " + authority , e); + Log.e(TAG, "Error getting layout stream from: " + systemLayoutProvider , e); return null; } } diff --git a/tests/multivalentTests/src/com/android/launcher3/util/TestUtil.java b/tests/multivalentTests/src/com/android/launcher3/util/TestUtil.java index 64035da5a5..ce682f1076 100644 --- a/tests/multivalentTests/src/com/android/launcher3/util/TestUtil.java +++ b/tests/multivalentTests/src/com/android/launcher3/util/TestUtil.java @@ -15,14 +15,12 @@ */ package com.android.launcher3.util; -import static android.util.Base64.NO_PADDING; -import static android.util.Base64.NO_WRAP; - import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; -import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_KEY; import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_LABEL; import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_TAG; +import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_PROVIDER_KEY; +import static com.android.launcher3.LauncherSettings.Settings.createBlobProviderKey; import static org.junit.Assert.assertTrue; @@ -42,7 +40,6 @@ import android.os.Process; import android.os.UserHandle; import android.provider.Settings; import android.system.OsConstants; -import android.util.Base64; import android.util.Log; import androidx.test.uiautomator.UiDevice; @@ -169,13 +166,12 @@ public class TestUtil { session.commit(AsyncTask.THREAD_POOL_EXECUTOR, i -> wait.countDown()); } - String key = Base64.encodeToString(digest, NO_WRAP | NO_PADDING); - grantWriteSecurePermission(); - Settings.Secure.putString(context.getContentResolver(), LAYOUT_DIGEST_KEY, key); + Settings.Secure.putString( + context.getContentResolver(), LAYOUT_PROVIDER_KEY, createBlobProviderKey(digest)); wait.await(); return () -> - Settings.Secure.putString(context.getContentResolver(), LAYOUT_DIGEST_KEY, null); + Settings.Secure.putString(context.getContentResolver(), LAYOUT_PROVIDER_KEY, null); } /**