diff --git a/src/com/android/launcher3/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java index efdd5e15e7..55ede6cecb 100644 --- a/src/com/android/launcher3/AutoInstallsLayout.java +++ b/src/com/android/launcher3/AutoInstallsLayout.java @@ -31,7 +31,6 @@ import android.text.TextUtils; import android.util.ArrayMap; import android.util.AttributeSet; import android.util.Log; -import android.util.Pair; import android.util.Patterns; import android.util.Xml; @@ -45,7 +44,7 @@ import com.android.launcher3.model.data.LauncherAppWidgetInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.qsb.QsbContainerView; import com.android.launcher3.util.IntArray; -import com.android.launcher3.util.PackageManagerHelper; +import com.android.launcher3.util.Partner; import com.android.launcher3.util.Thunk; import com.android.launcher3.widget.LauncherWidgetHolder; @@ -76,19 +75,16 @@ public class AutoInstallsLayout { static AutoInstallsLayout get(Context context, LauncherWidgetHolder appWidgetHolder, LayoutParserCallback callback) { - Pair customizationApkInfo = PackageManagerHelper.findSystemApk( - ACTION_LAUNCHER_CUSTOMIZATION, context.getPackageManager()); - if (customizationApkInfo == null) { + Partner partner = Partner.get(context.getPackageManager(), ACTION_LAUNCHER_CUSTOMIZATION); + if (partner == null) { return null; } - String pkg = customizationApkInfo.first; - Resources targetRes = customizationApkInfo.second; InvariantDeviceProfile grid = LauncherAppState.getIDP(context); // Try with grid size and hotseat count String layoutName = String.format(Locale.ENGLISH, FORMATTED_LAYOUT_RES_WITH_HOSTEAT, grid.numColumns, grid.numRows, grid.numDatabaseHotseatIcons); - int layoutId = targetRes.getIdentifier(layoutName, "xml", pkg); + int layoutId = partner.getXmlResId(layoutName); // Try with only grid size if (layoutId == 0) { @@ -96,21 +92,21 @@ public class AutoInstallsLayout { + " not found. Trying layout without hosteat"); layoutName = String.format(Locale.ENGLISH, FORMATTED_LAYOUT_RES, grid.numColumns, grid.numRows); - layoutId = targetRes.getIdentifier(layoutName, "xml", pkg); + layoutId = partner.getXmlResId(layoutName); } // Try the default layout if (layoutId == 0) { Log.d(TAG, "Formatted layout: " + layoutName + " not found. Trying the default layout"); - layoutId = targetRes.getIdentifier(LAYOUT_RES, "xml", pkg); + layoutId = partner.getXmlResId(LAYOUT_RES); } if (layoutId == 0) { - Log.e(TAG, "Layout definition not found in package: " + pkg); + Log.e(TAG, "Layout definition not found in package: " + partner.getPackageName()); return null; } - return new AutoInstallsLayout(context, appWidgetHolder, callback, targetRes, layoutId, - TAG_WORKSPACE); + return new AutoInstallsLayout(context, appWidgetHolder, callback, partner.getResources(), + layoutId, TAG_WORKSPACE); } // Object Tags diff --git a/src/com/android/launcher3/DefaultLayoutParser.java b/src/com/android/launcher3/DefaultLayoutParser.java index af13beac1d..c69ae4dac8 100644 --- a/src/com/android/launcher3/DefaultLayoutParser.java +++ b/src/com/android/launcher3/DefaultLayoutParser.java @@ -19,6 +19,7 @@ import android.util.Log; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.shortcuts.ShortcutKey; +import com.android.launcher3.util.Partner; import com.android.launcher3.util.Thunk; import com.android.launcher3.widget.LauncherWidgetHolder; @@ -51,6 +52,9 @@ public class DefaultLayoutParser extends AutoInstallsLayout { private static final String ATTR_SHORTCUT_ID = "shortcutId"; private static final String ATTR_PACKAGE_NAME = "packageName"; + public static final String RES_PARTNER_FOLDER = "partner_folder"; + public static final String RES_PARTNER_DEFAULT_LAYOUT = "partner_default_layout"; + // TODO: Remove support for this broadcast, instead use widget options to send bind time options private static final String ACTION_APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE = "com.android.launcher.action.APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE"; @@ -278,10 +282,9 @@ public class DefaultLayoutParser extends AutoInstallsLayout { // Folder contents come from an external XML resource final Partner partner = Partner.get(mPackageManager); if (partner != null) { - final Resources partnerRes = partner.getResources(); - final int resId = partnerRes.getIdentifier(Partner.RES_FOLDER, - "xml", partner.getPackageName()); + final int resId = partner.getXmlResId(RES_PARTNER_FOLDER); if (resId != 0) { + final Resources partnerRes = partner.getResources(); final XmlPullParser partnerParser = partnerRes.getXml(resId); beginDocument(partnerParser, TAG_FOLDER); diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java index 1f97535b4c..594d7cbd82 100644 --- a/src/com/android/launcher3/InvariantDeviceProfile.java +++ b/src/com/android/launcher3/InvariantDeviceProfile.java @@ -60,6 +60,7 @@ import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.DisplayController.Info; import com.android.launcher3.util.IntArray; import com.android.launcher3.util.MainThreadInitializedObject; +import com.android.launcher3.util.Partner; import com.android.launcher3.util.Themes; import com.android.launcher3.util.WindowBounds; import com.android.launcher3.util.window.WindowManagerProxy; @@ -112,6 +113,11 @@ public class InvariantDeviceProfile { static final int INDEX_TWO_PANEL_PORTRAIT = 2; static final int INDEX_TWO_PANEL_LANDSCAPE = 3; + /** These resources are used to override the device profile */ + private static final String RES_GRID_NUM_ROWS = "grid_num_rows"; + private static final String RES_GRID_NUM_COLUMNS = "grid_num_columns"; + private static final String RES_GRID_ICON_SIZE_DP = "grid_icon_size_dp"; + /** * Number of icons per row and column in the workspace. */ @@ -567,8 +573,24 @@ public class InvariantDeviceProfile { */ private void applyPartnerDeviceProfileOverrides(Context context, DisplayMetrics dm) { Partner p = Partner.get(context.getPackageManager()); - if (p != null) { - p.applyInvariantDeviceProfileOverrides(this, dm); + if (p == null) { + return; + } + try { + int numRows = p.getIntValue(RES_GRID_NUM_ROWS, -1); + int numColumns = p.getIntValue(RES_GRID_NUM_COLUMNS, -1); + float iconSizePx = p.getDimenValue(RES_GRID_ICON_SIZE_DP, -1); + + if (numRows > 0 && numColumns > 0) { + this.numRows = numRows; + this.numColumns = numColumns; + } + if (iconSizePx > 0) { + this.iconSize[InvariantDeviceProfile.INDEX_DEFAULT] = + Utilities.dpiFromPx(iconSizePx, dm.densityDpi); + } + } catch (Resources.NotFoundException ex) { + Log.e(TAG, "Invalid Partner grid resource!", ex); } } diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java index d002c2b901..8ddbbaaf2e 100644 --- a/src/com/android/launcher3/LauncherProvider.java +++ b/src/com/android/launcher3/LauncherProvider.java @@ -16,6 +16,7 @@ package com.android.launcher3; +import static com.android.launcher3.DefaultLayoutParser.RES_PARTNER_DEFAULT_LAYOUT; import static com.android.launcher3.provider.LauncherDbUtils.copyTable; import static com.android.launcher3.provider.LauncherDbUtils.dropTable; import static com.android.launcher3.provider.LauncherDbUtils.tableExists; @@ -34,7 +35,6 @@ import android.content.Intent; import android.content.OperationApplicationException; import android.content.SharedPreferences; import android.content.pm.ProviderInfo; -import android.content.res.Resources; import android.database.Cursor; import android.database.DatabaseUtils; import android.database.SQLException; @@ -70,6 +70,7 @@ import com.android.launcher3.util.IntArray; import com.android.launcher3.util.IntSet; import com.android.launcher3.util.NoLocaleSQLiteHelper; import com.android.launcher3.util.PackageManagerHelper; +import com.android.launcher3.util.Partner; import com.android.launcher3.util.Thunk; import com.android.launcher3.widget.LauncherWidgetHolder; @@ -544,13 +545,11 @@ public class LauncherProvider extends ContentProvider { } if (loader == null) { final Partner partner = Partner.get(getContext().getPackageManager()); - if (partner != null && partner.hasDefaultLayout()) { - final Resources partnerRes = partner.getResources(); - int workspaceResId = partnerRes.getIdentifier(Partner.RES_DEFAULT_LAYOUT, - "xml", partner.getPackageName()); + if (partner != null) { + int workspaceResId = partner.getXmlResId(RES_PARTNER_DEFAULT_LAYOUT); if (workspaceResId != 0) { loader = new DefaultLayoutParser(getContext(), widgetHolder, - mOpenHelper, partnerRes, workspaceResId); + mOpenHelper, partner.getResources(), workspaceResId); } } } diff --git a/src/com/android/launcher3/Partner.java b/src/com/android/launcher3/Partner.java deleted file mode 100644 index 2e27f32226..0000000000 --- a/src/com/android/launcher3/Partner.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2014 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; - -import static com.android.launcher3.util.PackageManagerHelper.findSystemApk; - -import android.content.pm.PackageManager; -import android.content.res.Resources; -import android.util.DisplayMetrics; -import android.util.Log; -import android.util.Pair; - -import java.io.File; - -/** - * Utilities to discover and interact with partner customizations. There can - * only be one set of customizations on a device, and it must be bundled with - * the system. - */ -public class Partner { - - static final String TAG = "Launcher.Partner"; - - /** Marker action used to discover partner */ - private static final String - ACTION_PARTNER_CUSTOMIZATION = "com.android.launcher3.action.PARTNER_CUSTOMIZATION"; - - public static final String RES_FOLDER = "partner_folder"; - public static final String RES_WALLPAPERS = "partner_wallpapers"; - public static final String RES_DEFAULT_LAYOUT = "partner_default_layout"; - - public static final String RES_DEFAULT_WALLPAPER_HIDDEN = "default_wallpapper_hidden"; - public static final String RES_SYSTEM_WALLPAPER_DIR = "system_wallpaper_directory"; - - public static final String RES_REQUIRE_FIRST_RUN_FLOW = "requires_first_run_flow"; - - /** These resources are used to override the device profile */ - public static final String RES_GRID_NUM_ROWS = "grid_num_rows"; - public static final String RES_GRID_NUM_COLUMNS = "grid_num_columns"; - public static final String RES_GRID_ICON_SIZE_DP = "grid_icon_size_dp"; - - /** - * Find and return partner details, or {@code null} if none exists. - */ - public static synchronized Partner get(PackageManager pm) { - Pair apkInfo = findSystemApk(ACTION_PARTNER_CUSTOMIZATION, pm); - return apkInfo != null ? new Partner(apkInfo.first, apkInfo.second) : null; - } - - private final String mPackageName; - private final Resources mResources; - - private Partner(String packageName, Resources res) { - mPackageName = packageName; - mResources = res; - } - - public String getPackageName() { - return mPackageName; - } - - public Resources getResources() { - return mResources; - } - - public boolean hasDefaultLayout() { - int defaultLayout = getResources().getIdentifier(Partner.RES_DEFAULT_LAYOUT, - "xml", getPackageName()); - return defaultLayout != 0; - } - - public boolean hasFolder() { - int folder = getResources().getIdentifier(Partner.RES_FOLDER, - "xml", getPackageName()); - return folder != 0; - } - - public boolean hideDefaultWallpaper() { - int resId = getResources().getIdentifier(RES_DEFAULT_WALLPAPER_HIDDEN, "bool", - getPackageName()); - return resId != 0 && getResources().getBoolean(resId); - } - - public File getWallpaperDirectory() { - int resId = getResources().getIdentifier(RES_SYSTEM_WALLPAPER_DIR, "string", - getPackageName()); - return (resId != 0) ? new File(getResources().getString(resId)) : null; - } - - public boolean requiresFirstRunFlow() { - int resId = getResources().getIdentifier(RES_REQUIRE_FIRST_RUN_FLOW, "bool", - getPackageName()); - return resId != 0 && getResources().getBoolean(resId); - } - - public void applyInvariantDeviceProfileOverrides(InvariantDeviceProfile inv, DisplayMetrics dm) { - int numRows = -1; - int numColumns = -1; - float iconSize = -1; - - try { - int resId = getResources().getIdentifier(RES_GRID_NUM_ROWS, - "integer", getPackageName()); - if (resId > 0) { - numRows = getResources().getInteger(resId); - } - - resId = getResources().getIdentifier(RES_GRID_NUM_COLUMNS, - "integer", getPackageName()); - if (resId > 0) { - numColumns = getResources().getInteger(resId); - } - - resId = getResources().getIdentifier(RES_GRID_ICON_SIZE_DP, - "dimen", getPackageName()); - if (resId > 0) { - int px = getResources().getDimensionPixelSize(resId); - iconSize = Utilities.dpiFromPx((float) px, dm.densityDpi); - } - } catch (Resources.NotFoundException ex) { - Log.e(TAG, "Invalid Partner grid resource!", ex); - return; - } - - if (numRows > 0 && numColumns > 0) { - inv.numRows = numRows; - inv.numColumns = numColumns; - } - - if (iconSize > 0) { - inv.iconSize[InvariantDeviceProfile.INDEX_DEFAULT] = iconSize; - } - } -} diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java index 12e8b54547..140440eee2 100644 --- a/src/com/android/launcher3/util/PackageManagerHelper.java +++ b/src/com/android/launcher3/util/PackageManagerHelper.java @@ -16,8 +16,6 @@ package com.android.launcher3.util; -import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; - import android.app.AppOpsManager; import android.content.ActivityNotFoundException; import android.content.ComponentName; @@ -31,7 +29,6 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; -import android.content.res.Resources; import android.graphics.Rect; import android.net.Uri; import android.os.Build; @@ -40,7 +37,6 @@ import android.os.PatternMatcher; import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; -import android.util.Pair; import android.widget.Toast; import androidx.annotation.NonNull; @@ -295,25 +291,6 @@ public class PackageManagerHelper { } } - /** - * Finds a system apk which had a broadcast receiver listening to a particular action. - * @param action intent action used to find the apk - * @return a pair of apk package name and the resources. - */ - public static Pair findSystemApk(String action, PackageManager pm) { - final Intent intent = new Intent(action); - for (ResolveInfo info : pm.queryBroadcastReceivers(intent, MATCH_SYSTEM_ONLY)) { - final String packageName = info.activityInfo.packageName; - try { - final Resources res = pm.getResourcesForApplication(packageName); - return Pair.create(packageName, res); - } catch (NameNotFoundException e) { - Log.w(TAG, "Failed to find resources for " + packageName); - } - } - return null; - } - /** * Returns true if the intent is a valid launch intent for a launcher activity of an app. * This is used to identify shortcuts which are different from the ones exposed by the diff --git a/src/com/android/launcher3/util/Partner.java b/src/com/android/launcher3/util/Partner.java new file mode 100644 index 0000000000..220ab566aa --- /dev/null +++ b/src/com/android/launcher3/util/Partner.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2014 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 static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; + +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.ResolveInfo; +import android.content.res.Resources; +import android.util.Log; +import android.util.Pair; + +/** + * Utilities to discover and interact with partner customizations. There can + * only be one set of customizations on a device, and it must be bundled with + * the system. + */ +public class Partner { + + static final String TAG = "Launcher.Partner"; + + /** Marker action used to discover partner */ + private static final String + ACTION_PARTNER_CUSTOMIZATION = "com.android.launcher3.action.PARTNER_CUSTOMIZATION"; + + /** + * Find and return partner details, or {@code null} if none exists. + */ + public static Partner get(PackageManager pm) { + return get(pm, ACTION_PARTNER_CUSTOMIZATION); + } + + /** + * Find and return partner details, or {@code null} if none exists. + */ + public static Partner get(PackageManager pm, String action) { + Pair apkInfo = findSystemApk(action, pm); + return apkInfo != null ? new Partner(apkInfo.first, apkInfo.second) : null; + } + + private final String mPackageName; + private final Resources mResources; + + private Partner(String packageName, Resources res) { + mPackageName = packageName; + mResources = res; + } + + public String getPackageName() { + return mPackageName; + } + + public Resources getResources() { + return mResources; + } + + /** + * Returns the xml resource Id for the provided name, or 0 is the resource is not found + */ + public int getXmlResId(String layoutName) { + return getResources().getIdentifier(layoutName, "xml", getPackageName()); + } + + /** + * Returns the integer resource value for the provided resource name, + * or default value if the resource name is not present + */ + public int getIntValue(String resName, int defaultValue) { + int resId = getResources().getIdentifier(resName, "integer", getPackageName()); + return resId > 0 ? getResources().getInteger(resId) : defaultValue; + } + + /** + * Returns the dimension value for the provided resource name, + * or default value if the resource name is not present + */ + public float getDimenValue(String resName, int defaultValue) { + int resId = getResources().getIdentifier(resName, "dimen", getPackageName()); + return resId > 0 ? getResources().getDimension(resId) : defaultValue; + } + + /** + * Finds a system apk which had a broadcast receiver listening to a particular action. + * @param action intent action used to find the apk + * @return a pair of apk package name and the resources. + */ + private static Pair findSystemApk(String action, PackageManager pm) { + final Intent intent = new Intent(action); + for (ResolveInfo info : pm.queryBroadcastReceivers(intent, MATCH_SYSTEM_ONLY)) { + final String packageName = info.activityInfo.packageName; + try { + final Resources res = pm.getResourcesForApplication(packageName); + return Pair.create(packageName, res); + } catch (NameNotFoundException e) { + Log.w(TAG, "Failed to find resources for " + packageName); + } + } + return null; + } +}