1 /* 2 * Copyright (C) 2022 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 17 package com.android.server.appwidget; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.appwidget.AppWidgetProviderInfo; 22 import android.content.ComponentName; 23 import android.os.Build; 24 import android.text.TextUtils; 25 import android.util.SizeF; 26 import android.util.Slog; 27 28 import com.android.modules.utils.TypedXmlPullParser; 29 import com.android.modules.utils.TypedXmlSerializer; 30 31 import java.io.IOException; 32 import java.util.ArrayList; 33 import java.util.Arrays; 34 import java.util.List; 35 import java.util.Objects; 36 import java.util.stream.Collectors; 37 38 /** 39 * @hide 40 */ 41 public class AppWidgetXmlUtil { 42 43 private static final String TAG = "AppWidgetXmlUtil"; 44 45 private static final String ATTR_MIN_WIDTH = "min_width"; 46 private static final String ATTR_MIN_HEIGHT = "min_height"; 47 private static final String ATTR_MIN_RESIZE_WIDTH = "min_resize_width"; 48 private static final String ATTR_MIN_RESIZE_HEIGHT = "min_resize_height"; 49 private static final String ATTR_MAX_RESIZE_WIDTH = "max_resize_width"; 50 private static final String ATTR_MAX_RESIZE_HEIGHT = "max_resize_height"; 51 private static final String ATTR_TARGET_CELL_WIDTH = "target_cell_width"; 52 private static final String ATTR_TARGET_CELL_HEIGHT = "target_cell_height"; 53 private static final String ATTR_UPDATE_PERIOD_MILLIS = "update_period_millis"; 54 private static final String ATTR_INITIAL_LAYOUT = "initial_layout"; 55 private static final String ATTR_INITIAL_KEYGUARD_LAYOUT = "initial_keyguard_layout"; 56 private static final String ATTR_CONFIGURE = "configure"; 57 private static final String ATTR_LABEL = "label"; 58 private static final String ATTR_ICON = "icon"; 59 private static final String ATTR_PREVIEW_IMAGE = "preview_image"; 60 private static final String ATTR_PREVIEW_LAYOUT = "preview_layout"; 61 private static final String ATTR_AUTO_ADVANCED_VIEW_ID = "auto_advance_view_id"; 62 private static final String ATTR_RESIZE_MODE = "resize_mode"; 63 private static final String ATTR_WIDGET_CATEGORY = "widget_category"; 64 private static final String ATTR_WIDGET_FEATURES = "widget_features"; 65 private static final String ATTR_DESCRIPTION_RES = "description_res"; 66 private static final String ATTR_PROVIDER_INHERITANCE = "provider_inheritance"; 67 private static final String ATTR_OS_FINGERPRINT = "os_fingerprint"; 68 private static final String SIZE_SEPARATOR = ","; 69 70 /** 71 * @hide 72 */ writeAppWidgetProviderInfoLocked(@onNull final TypedXmlSerializer out, @NonNull final AppWidgetProviderInfo info)73 public static void writeAppWidgetProviderInfoLocked(@NonNull final TypedXmlSerializer out, 74 @NonNull final AppWidgetProviderInfo info) throws IOException { 75 Objects.requireNonNull(out); 76 Objects.requireNonNull(info); 77 out.attributeInt(null, ATTR_MIN_WIDTH, info.minWidth); 78 out.attributeInt(null, ATTR_MIN_HEIGHT, info.minHeight); 79 out.attributeInt(null, ATTR_MIN_RESIZE_WIDTH, info.minResizeWidth); 80 out.attributeInt(null, ATTR_MIN_RESIZE_HEIGHT, info.minResizeHeight); 81 out.attributeInt(null, ATTR_MAX_RESIZE_WIDTH, info.maxResizeWidth); 82 out.attributeInt(null, ATTR_MAX_RESIZE_HEIGHT, info.maxResizeHeight); 83 out.attributeInt(null, ATTR_TARGET_CELL_WIDTH, info.targetCellWidth); 84 out.attributeInt(null, ATTR_TARGET_CELL_HEIGHT, info.targetCellHeight); 85 out.attributeInt(null, ATTR_UPDATE_PERIOD_MILLIS, info.updatePeriodMillis); 86 out.attributeInt(null, ATTR_INITIAL_LAYOUT, info.initialLayout); 87 out.attributeInt(null, ATTR_INITIAL_KEYGUARD_LAYOUT, info.initialKeyguardLayout); 88 if (info.configure != null) { 89 out.attribute(null, ATTR_CONFIGURE, info.configure.flattenToShortString()); 90 } 91 if (info.label != null) { 92 out.attribute(null, ATTR_LABEL, info.label); 93 } 94 out.attributeInt(null, ATTR_ICON, info.icon); 95 out.attributeInt(null, ATTR_PREVIEW_IMAGE, info.previewImage); 96 out.attributeInt(null, ATTR_PREVIEW_LAYOUT, info.previewLayout); 97 out.attributeInt(null, ATTR_AUTO_ADVANCED_VIEW_ID, info.autoAdvanceViewId); 98 out.attributeInt(null, ATTR_RESIZE_MODE, info.resizeMode); 99 out.attributeInt(null, ATTR_WIDGET_CATEGORY, info.widgetCategory); 100 out.attributeInt(null, ATTR_WIDGET_FEATURES, info.widgetFeatures); 101 out.attributeInt(null, ATTR_DESCRIPTION_RES, info.descriptionRes); 102 out.attributeBoolean(null, ATTR_PROVIDER_INHERITANCE, info.isExtendedFromAppWidgetProvider); 103 out.attribute(null, ATTR_OS_FINGERPRINT, Build.FINGERPRINT); 104 } 105 106 /** 107 * @hide 108 */ 109 @Nullable readAppWidgetProviderInfoLocked( @onNull final TypedXmlPullParser parser)110 public static AppWidgetProviderInfo readAppWidgetProviderInfoLocked( 111 @NonNull final TypedXmlPullParser parser) { 112 Objects.requireNonNull(parser); 113 final String fingerprint = parser.getAttributeValue(null, ATTR_OS_FINGERPRINT); 114 if (!Build.FINGERPRINT.equals(fingerprint)) { 115 return null; 116 } 117 final AppWidgetProviderInfo info = new AppWidgetProviderInfo(); 118 info.minWidth = parser.getAttributeInt(null, ATTR_MIN_WIDTH, 0); 119 info.minHeight = parser.getAttributeInt(null, ATTR_MIN_HEIGHT, 0); 120 info.minResizeWidth = parser.getAttributeInt(null, ATTR_MIN_RESIZE_WIDTH, 0); 121 info.minResizeHeight = parser.getAttributeInt(null, ATTR_MIN_RESIZE_HEIGHT, 0); 122 info.maxResizeWidth = parser.getAttributeInt(null, ATTR_MAX_RESIZE_WIDTH, 0); 123 info.maxResizeHeight = parser.getAttributeInt(null, ATTR_MAX_RESIZE_HEIGHT, 0); 124 info.targetCellWidth = parser.getAttributeInt(null, ATTR_TARGET_CELL_WIDTH, 0); 125 info.targetCellHeight = parser.getAttributeInt(null, ATTR_TARGET_CELL_HEIGHT, 0); 126 info.updatePeriodMillis = parser.getAttributeInt(null, ATTR_UPDATE_PERIOD_MILLIS, 0); 127 info.initialLayout = parser.getAttributeInt(null, ATTR_INITIAL_LAYOUT, 0); 128 info.initialKeyguardLayout = parser.getAttributeInt( 129 null, ATTR_INITIAL_KEYGUARD_LAYOUT, 0); 130 final String configure = parser.getAttributeValue(null, ATTR_CONFIGURE); 131 if (!TextUtils.isEmpty(configure)) { 132 info.configure = ComponentName.unflattenFromString(configure); 133 } 134 info.label = parser.getAttributeValue(null, ATTR_LABEL); 135 info.icon = parser.getAttributeInt(null, ATTR_ICON, 0); 136 info.previewImage = parser.getAttributeInt(null, ATTR_PREVIEW_IMAGE, 0); 137 info.previewLayout = parser.getAttributeInt(null, ATTR_PREVIEW_LAYOUT, 0); 138 info.autoAdvanceViewId = parser.getAttributeInt(null, ATTR_AUTO_ADVANCED_VIEW_ID, 0); 139 info.resizeMode = parser.getAttributeInt(null, ATTR_RESIZE_MODE, 0); 140 info.widgetCategory = parser.getAttributeInt(null, ATTR_WIDGET_CATEGORY, 0); 141 info.widgetFeatures = parser.getAttributeInt(null, ATTR_WIDGET_FEATURES, 0); 142 info.descriptionRes = parser.getAttributeInt(null, ATTR_DESCRIPTION_RES, 0); 143 info.isExtendedFromAppWidgetProvider = parser.getAttributeBoolean(null, 144 ATTR_PROVIDER_INHERITANCE, false); 145 return info; 146 } 147 148 @NonNull serializeWidgetSizes(@onNull List<SizeF> sizes)149 static String serializeWidgetSizes(@NonNull List<SizeF> sizes) { 150 return sizes.stream().map(SizeF::toString) 151 .collect(Collectors.joining(SIZE_SEPARATOR)); 152 } 153 154 @Nullable deserializeWidgetSizesStr(@ullable String sizesStr)155 static ArrayList<SizeF> deserializeWidgetSizesStr(@Nullable String sizesStr) { 156 if (sizesStr == null || sizesStr.isEmpty()) { 157 return null; 158 } 159 try { 160 return Arrays.stream(sizesStr.split(SIZE_SEPARATOR)) 161 .map(SizeF::parseSizeF) 162 .collect(Collectors.toCollection(ArrayList::new)); 163 } catch (NumberFormatException e) { 164 Slog.e(TAG, "Error parsing widget sizes", e); 165 return null; 166 } 167 } 168 } 169