Loading quickstep/src/com/android/launcher3/uioverrides/flags/DevOptionsUiHelper.kt +17 −16 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading Loading @@ -241,7 +239,7 @@ class DevOptionsUiHelper(c: Context, attr: AttributeSet?) : PreferenceGroup(c, a private fun DebugInfo<Boolean>.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<Int>.getIntValueAsString() = Loading @@ -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 } Loading @@ -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) } } Loading Loading @@ -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)) Loading Loading @@ -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) Loading Loading @@ -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) } } } Loading Loading @@ -512,7 +513,7 @@ class DevOptionsUiHelper(c: Context, attr: AttributeSet?) : PreferenceGroup(c, a info.providerName.className, info.spanX, info.spanY, userType userType, ) } } Loading @@ -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( Loading @@ -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) } } } Loading src/com/android/launcher3/LauncherSettings.java +14 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } } } src/com/android/launcher3/model/ModelDbController.java +16 −13 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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), Loading @@ -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; } } Loading tests/multivalentTests/src/com/android/launcher3/util/TestUtil.java +5 −9 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); } /** Loading Loading
quickstep/src/com/android/launcher3/uioverrides/flags/DevOptionsUiHelper.kt +17 −16 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading Loading @@ -241,7 +239,7 @@ class DevOptionsUiHelper(c: Context, attr: AttributeSet?) : PreferenceGroup(c, a private fun DebugInfo<Boolean>.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<Int>.getIntValueAsString() = Loading @@ -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 } Loading @@ -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) } } Loading Loading @@ -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)) Loading Loading @@ -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) Loading Loading @@ -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) } } } Loading Loading @@ -512,7 +513,7 @@ class DevOptionsUiHelper(c: Context, attr: AttributeSet?) : PreferenceGroup(c, a info.providerName.className, info.spanX, info.spanY, userType userType, ) } } Loading @@ -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( Loading @@ -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) } } } Loading
src/com/android/launcher3/LauncherSettings.java +14 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } } }
src/com/android/launcher3/model/ModelDbController.java +16 −13 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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), Loading @@ -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; } } Loading
tests/multivalentTests/src/com/android/launcher3/util/TestUtil.java +5 −9 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); } /** Loading