diff options
author | 2025-02-19 15:45:59 -0800 | |
---|---|---|
committer | 2025-02-20 10:16:56 -0800 | |
commit | 3fd385c1cd5b4dcc7f086f20b82dca684581a89b (patch) | |
tree | e1e048a74501a9d52c2a873d32446661db92534a | |
parent | 91547eb4d234c2f76b41028a58345fb59c464486 (diff) |
Moving grid customization provider to Dagger
Bug: 361850561
Test: Presubmit
Flag: EXEMPT dagger
Change-Id: I0ebc2a614b9448e5de97d3dda43d98b951989689
-rw-r--r-- | Android.bp | 9 | ||||
-rw-r--r-- | AndroidManifest-common.xml | 2 | ||||
-rw-r--r-- | src/com/android/launcher3/dagger/LauncherBaseAppComponent.java | 3 | ||||
-rw-r--r-- | src/com/android/launcher3/graphics/GridCustomizationsProxy.java (renamed from src/com/android/launcher3/graphics/GridCustomizationsProvider.java) | 96 | ||||
-rw-r--r-- | src/com/android/launcher3/graphics/LauncherCustomizationProvider.kt | 29 | ||||
-rw-r--r-- | src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java | 2 | ||||
-rw-r--r-- | src/com/android/launcher3/testing/TestInformationProvider.java | 69 | ||||
-rw-r--r-- | src/com/android/launcher3/util/ContentProviderProxy.kt | 86 |
8 files changed, 196 insertions, 100 deletions
diff --git a/Android.bp b/Android.bp index 1e1e0ad6cc..a4a058fce0 100644 --- a/Android.bp +++ b/Android.bp @@ -455,6 +455,9 @@ android_app { extra_check_modules: ["Launcher3LintChecker"], baseline_filename: "lint-baseline.xml", }, + kotlincflags: [ + "-Xjvm-default=all", + ], } // Library with all the dependencies for building quickstep @@ -519,6 +522,9 @@ android_library { min_sdk_version: "current", // TODO(b/319712088): re-enable use_resource_processor use_resource_processor: false, + kotlincflags: [ + "-Xjvm-default=all", + ], } // Library with all the source code and dependencies for building Quickstep @@ -552,6 +558,9 @@ android_library { min_sdk_version: "current", // TODO(b/319712088): re-enable use_resource_processor use_resource_processor: false, + kotlincflags: [ + "-Xjvm-default=all", + ], } // Build rule for Quickstep app. diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml index 80d2eaca23..fe57da11fc 100644 --- a/AndroidManifest-common.xml +++ b/AndroidManifest-common.xml @@ -136,7 +136,7 @@ TODO: Add proper permissions --> <provider - android:name="com.android.launcher3.graphics.GridCustomizationsProvider" + android:name="com.android.launcher3.graphics.LauncherCustomizationProvider" android:authorities="${applicationId}.grid_control" android:exported="true" /> diff --git a/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java b/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java index 31d0da08db..f6acda46a1 100644 --- a/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java +++ b/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java @@ -20,6 +20,7 @@ import android.content.Context; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.LauncherPrefs; +import com.android.launcher3.graphics.GridCustomizationsProxy; import com.android.launcher3.graphics.ThemeManager; import com.android.launcher3.icons.LauncherIcons.IconPool; import com.android.launcher3.model.ItemInstallQueue; @@ -75,6 +76,8 @@ public interface LauncherBaseAppComponent { InvariantDeviceProfile getIDP(); IconPool getIconPool(); + GridCustomizationsProxy getGridCustomizationsProxy(); + /** Builder for LauncherBaseAppComponent. */ interface Builder { @BindsInstance Builder appContext(@ApplicationContext Context context); diff --git a/src/com/android/launcher3/graphics/GridCustomizationsProvider.java b/src/com/android/launcher3/graphics/GridCustomizationsProxy.java index 12c65c72cd..01c9d7ec4f 100644 --- a/src/com/android/launcher3/graphics/GridCustomizationsProvider.java +++ b/src/com/android/launcher3/graphics/GridCustomizationsProxy.java @@ -22,7 +22,6 @@ import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import static java.util.Objects.requireNonNullElse; -import android.content.ContentProvider; import android.content.ContentValues; import android.content.Context; import android.content.pm.PackageManager; @@ -45,9 +44,13 @@ import com.android.launcher3.InvariantDeviceProfile.GridOption; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherModel; import com.android.launcher3.LauncherPrefs; +import com.android.launcher3.dagger.ApplicationContext; +import com.android.launcher3.dagger.LauncherAppSingleton; import com.android.launcher3.model.BgDataModel; import com.android.launcher3.shapes.IconShapeModel; import com.android.launcher3.shapes.ShapesProvider; +import com.android.launcher3.util.ContentProviderProxy.ProxyProvider; +import com.android.launcher3.util.DaggerSingletonTracker; import com.android.launcher3.util.Executors; import com.android.launcher3.util.Preconditions; import com.android.launcher3.util.RunnableList; @@ -62,6 +65,8 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; +import javax.inject.Inject; + /** * Exposes various launcher grid options and allows the caller to change them. * APIs: @@ -76,7 +81,7 @@ import java.util.concurrent.ExecutionException; * rows: number of rows in the grid * cols: number of columns in the grid * preview_count: number of previews available for this grid option. The preview uri - * looks like /preview/<grid-name>/<preview index starting with 0> + * looks like /preview/[grid-name]/[preview index starting with 0] * is_default: true if this grid option is currently set to the system * * /get_preview: Open a file stream for the grid preview @@ -85,7 +90,8 @@ import java.util.concurrent.ExecutionException; * shape_key: key of the shape to apply * name: key of the grid to apply */ -public class GridCustomizationsProvider extends ContentProvider { +@LauncherAppSingleton +public class GridCustomizationsProxy implements ProxyProvider { private static final String TAG = "GridCustomizationsProvider"; @@ -132,17 +138,31 @@ public class GridCustomizationsProvider extends ContentProvider { private final Set<PreviewLifecycleObserver> mActivePreviews = Collections.newSetFromMap(new ConcurrentHashMap<>()); - @Override - public boolean onCreate() { - return true; + private final Context mContext; + private final ThemeManager mThemeManager; + private final LauncherPrefs mPrefs; + private final InvariantDeviceProfile mIdp; + + @Inject + GridCustomizationsProxy( + @ApplicationContext Context context, + ThemeManager themeManager, + LauncherPrefs prefs, + InvariantDeviceProfile idp, + DaggerSingletonTracker lifeCycle + ) { + mContext = context; + mThemeManager = themeManager; + mPrefs = prefs; + mIdp = idp; + lifeCycle.addCloseable(() -> mActivePreviews.forEach(PreviewLifecycleObserver::binderDied)); } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { - Context context = getContext(); String path = uri.getPath(); - if (context == null || path == null) { + if (path == null) { return null; } @@ -151,8 +171,7 @@ public class GridCustomizationsProvider extends ContentProvider { if (Flags.newCustomizationPickerUi()) { MatrixCursor cursor = new MatrixCursor(new String[]{ KEY_SHAPE_KEY, KEY_SHAPE_TITLE, KEY_PATH, KEY_IS_DEFAULT}); - String currentShapePath = - ThemeManager.INSTANCE.get(context).getIconState().getIconMask(); + String currentShapePath = mThemeManager.getIconState().getIconMask(); Optional<IconShapeModel> selectedShape = ShapesProvider.INSTANCE.getIconShapes() .values() .stream() @@ -180,8 +199,7 @@ public class GridCustomizationsProvider extends ContentProvider { MatrixCursor cursor = new MatrixCursor(new String[]{ KEY_NAME, KEY_GRID_TITLE, KEY_ROWS, KEY_COLS, KEY_PREVIEW_COUNT, KEY_IS_DEFAULT, KEY_GRID_ICON_ID}); - InvariantDeviceProfile idp = InvariantDeviceProfile.INSTANCE.get(getContext()); - List<GridOption> gridOptionList = idp.parseAllGridOptions(getContext()); + List<GridOption> gridOptionList = mIdp.parseAllGridOptions(mContext); if (com.android.launcher3.Flags.oneGridSpecs()) { gridOptionList.sort(Comparator .comparingInt((GridOption option) -> option.numColumns) @@ -194,8 +212,8 @@ public class GridCustomizationsProvider extends ContentProvider { .add(KEY_ROWS, gridOption.numRows) .add(KEY_COLS, gridOption.numColumns) .add(KEY_PREVIEW_COUNT, 1) - .add(KEY_IS_DEFAULT, idp.numColumns == gridOption.numColumns - && idp.numRows == gridOption.numRows) + .add(KEY_IS_DEFAULT, mIdp.numColumns == gridOption.numColumns + && mIdp.numRows == gridOption.numRows) .add(KEY_GRID_ICON_ID, gridOption.gridIconId); } return cursor; @@ -203,8 +221,7 @@ public class GridCustomizationsProvider extends ContentProvider { case GET_ICON_THEMED: case ICON_THEMED: { MatrixCursor cursor = new MatrixCursor(new String[]{BOOLEAN_VALUE}); - cursor.newRow().add(BOOLEAN_VALUE, - ThemeManager.INSTANCE.get(getContext()).isMonoThemeEnabled() ? 1 : 0); + cursor.newRow().add(BOOLEAN_VALUE, mThemeManager.isMonoThemeEnabled() ? 1 : 0); return cursor; } default: @@ -213,38 +230,21 @@ public class GridCustomizationsProvider extends ContentProvider { } @Override - public String getType(Uri uri) { - return "vnd.android.cursor.dir/launcher_grid"; - } - - @Override - public Uri insert(Uri uri, ContentValues initialValues) { - return null; - } - - @Override - public int delete(Uri uri, String selection, String[] selectionArgs) { - return 0; - } - - @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { String path = uri.getPath(); - Context context = getContext(); - if (path == null || context == null) { + if (path == null) { return 0; } switch (path) { case KEY_DEFAULT_GRID: { if (Flags.newCustomizationPickerUi()) { - LauncherPrefs.INSTANCE.get(context).put(PREF_ICON_SHAPE, + mPrefs.put(PREF_ICON_SHAPE, requireNonNullElse(values.getAsString(KEY_SHAPE_KEY), "")); } String gridName = values.getAsString(KEY_NAME); - InvariantDeviceProfile idp = InvariantDeviceProfile.INSTANCE.get(context); // Verify that this is a valid grid option GridOption match = null; - for (GridOption option : idp.parseAllGridOptions(context)) { + for (GridOption option : mIdp.parseAllGridOptions(mContext)) { String name = option.name; if (name != null && name.equals(gridName)) { match = option; @@ -255,23 +255,22 @@ public class GridCustomizationsProvider extends ContentProvider { return 0; } - idp.setCurrentGrid(context, gridName); + mIdp.setCurrentGrid(mContext, gridName); if (Flags.newCustomizationPickerUi()) { try { // Wait for device profile to be fully reloaded and applied to the launcher - loadModelSync(context); + loadModelSync(mContext); } catch (ExecutionException | InterruptedException e) { Log.e(TAG, "Fail to load model", e); } } - context.getContentResolver().notifyChange(uri, null); + mContext.getContentResolver().notifyChange(uri, null); return 1; } case ICON_THEMED: case SET_ICON_THEMED: { - ThemeManager.INSTANCE.get(context) - .setMonoThemeEnabled(values.getAsBoolean(BOOLEAN_VALUE)); - context.getContentResolver().notifyChange(uri, null); + mThemeManager.setMonoThemeEnabled(values.getAsBoolean(BOOLEAN_VALUE)); + mContext.getContentResolver().notifyChange(uri, null); return 1; } default: @@ -298,12 +297,7 @@ public class GridCustomizationsProvider extends ContentProvider { @Override public Bundle call(@NonNull String method, String arg, Bundle extras) { - Context context = getContext(); - if (context == null) { - return null; - } - - if (context.checkPermission("android.permission.BIND_WALLPAPER", + if (mContext.checkPermission("android.permission.BIND_WALLPAPER", Binder.getCallingPid(), Binder.getCallingUid()) != PackageManager.PERMISSION_GRANTED) { return null; @@ -317,14 +311,10 @@ public class GridCustomizationsProvider extends ContentProvider { } private synchronized Bundle getPreview(Bundle request) { - Context context = getContext(); - if (context == null) { - return null; - } RunnableList lifeCycleTracker = new RunnableList(); try { PreviewSurfaceRenderer renderer = new PreviewSurfaceRenderer( - getContext(), lifeCycleTracker, request); + mContext, lifeCycleTracker, request); PreviewLifecycleObserver observer = new PreviewLifecycleObserver(lifeCycleTracker, renderer); diff --git a/src/com/android/launcher3/graphics/LauncherCustomizationProvider.kt b/src/com/android/launcher3/graphics/LauncherCustomizationProvider.kt new file mode 100644 index 0000000000..c949e2ec17 --- /dev/null +++ b/src/com/android/launcher3/graphics/LauncherCustomizationProvider.kt @@ -0,0 +1,29 @@ +/* + * 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.launcher3.graphics + +import android.content.Context +import android.net.Uri +import com.android.launcher3.dagger.LauncherComponentProvider.appComponent +import com.android.launcher3.util.ContentProviderProxy + +/** Provider for various Launcher customizations exposed via a ContentProvider API */ +class LauncherCustomizationProvider : ContentProviderProxy() { + + override fun getProxy(ctx: Context): ProxyProvider? = ctx.appComponent.gridCustomizationsProxy + + override fun getType(uri: Uri) = "vnd.android.cursor.dir/launcher_grid" +} diff --git a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java index f0d670e59a..6fe5804da6 100644 --- a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java +++ b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java @@ -124,7 +124,7 @@ public class PreviewSurfaceRenderer { if (Flags.newCustomizationPickerUi()) { updateColorOverrides(bundle); } - mHideQsb = bundle.getBoolean(GridCustomizationsProvider.KEY_HIDE_BOTTOM_ROW); + mHideQsb = bundle.getBoolean(GridCustomizationsProxy.KEY_HIDE_BOTTOM_ROW); mHostToken = bundle.getBinder(KEY_HOST_TOKEN); mWidth = bundle.getInt(KEY_VIEW_WIDTH); diff --git a/src/com/android/launcher3/testing/TestInformationProvider.java b/src/com/android/launcher3/testing/TestInformationProvider.java index 17b472a473..4b592e7627 100644 --- a/src/com/android/launcher3/testing/TestInformationProvider.java +++ b/src/com/android/launcher3/testing/TestInformationProvider.java @@ -16,61 +16,40 @@ package com.android.launcher3.testing; -import android.content.ContentProvider; -import android.content.ContentValues; -import android.database.Cursor; -import android.net.Uri; +import android.content.Context; import android.os.Bundle; import android.util.Log; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.android.launcher3.Utilities; +import com.android.launcher3.util.ContentProviderProxy; -public class TestInformationProvider extends ContentProvider { +public class TestInformationProvider extends ContentProviderProxy { private static final String TAG = "TestInformationProvider"; + @Nullable @Override - public boolean onCreate() { - return true; - } - - @Override - public int update(Uri uri, ContentValues contentValues, String s, String[] strings) { - return 0; - } - - @Override - public int delete(Uri uri, String s, String[] strings) { - return 0; - } - - @Override - public Uri insert(Uri uri, ContentValues contentValues) { - return null; - } - - @Override - public String getType(Uri uri) { - return null; - } - - @Override - public Cursor query(Uri uri, String[] strings, String s, String[] strings1, String s1) { - return null; - } - - @Override - public Bundle call(String method, String arg, Bundle extras) { + public ProxyProvider getProxy(@NonNull Context context) { if (Utilities.isRunningInTestHarness()) { - TestInformationHandler handler = TestInformationHandler.newInstance(getContext()); - handler.init(getContext()); - - Bundle response = handler.call(method, arg, extras); - if (response == null) { - Log.e(TAG, "Couldn't handle method: " + method + "; current handler=" - + handler.getClass().getSimpleName()); - } - return response; + return new ProxyProvider() { + @Nullable + @Override + public Bundle call(@NonNull String method, @Nullable String arg, + @Nullable Bundle extras) { + TestInformationHandler handler = TestInformationHandler.newInstance(context); + handler.init(context); + + Bundle response = handler.call(method, arg, extras); + if (response == null) { + Log.e(TAG, "Couldn't handle method: " + method + "; current handler=" + + handler.getClass().getSimpleName()); + } + return response; + } + }; } return null; } diff --git a/src/com/android/launcher3/util/ContentProviderProxy.kt b/src/com/android/launcher3/util/ContentProviderProxy.kt new file mode 100644 index 0000000000..db693db7ff --- /dev/null +++ b/src/com/android/launcher3/util/ContentProviderProxy.kt @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2025 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.launcher3.util + +import android.content.ContentProvider +import android.content.ContentValues +import android.content.Context +import android.database.Cursor +import android.net.Uri +import android.os.Bundle + +/** Wrapper around [ContentProvider] which allows delegating all calls to an interface */ +abstract class ContentProviderProxy : ContentProvider() { + + override fun onCreate() = true + + override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?): Int = + checkGetProxy()?.delete(uri, selection, selectionArgs) ?: 0 + + /** Do not route this call through proxy as it doesn't generally require initializing objects */ + override fun getType(uri: Uri): String? = null + + override fun insert(uri: Uri, values: ContentValues?): Uri? = + checkGetProxy()?.insert(uri, values) + + override fun query( + uri: Uri, + projection: Array<out String>?, + selection: String?, + selectionArgs: Array<out String>?, + sortOrder: String?, + ): Cursor? = checkGetProxy()?.query(uri, projection, selection, selectionArgs, sortOrder) + + override fun update( + uri: Uri, + values: ContentValues?, + selection: String?, + selectionArgs: Array<out String>?, + ): Int = checkGetProxy()?.update(uri, values, selection, selectionArgs) ?: 0 + + override fun call(method: String, arg: String?, extras: Bundle?): Bundle? = + checkGetProxy()?.call(method, arg, extras) + + private fun checkGetProxy(): ProxyProvider? = context?.let { getProxy(it) } + + abstract fun getProxy(ctx: Context): ProxyProvider? + + /** Interface for handling the actual content provider calls */ + interface ProxyProvider { + + fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?): Int = 0 + + fun insert(uri: Uri, values: ContentValues?): Uri? = null + + fun query( + uri: Uri, + projection: Array<out String>?, + selection: String?, + selectionArgs: Array<out String>?, + sortOrder: String?, + ): Cursor? = null + + fun update( + uri: Uri, + values: ContentValues?, + selection: String?, + selectionArgs: Array<out String>?, + ): Int = 0 + + fun call(method: String, arg: String?, extras: Bundle?): Bundle? = null + } +} |