diff options
| author | 2024-10-29 17:15:31 +0000 | |
|---|---|---|
| committer | 2024-10-29 17:15:31 +0000 | |
| commit | 02244c6d374d2a748d930e8e25a2568cedd975ed (patch) | |
| tree | fd09500b76ee3c693aaa4724dbcda853dba10ea4 | |
| parent | e01bd63547de3b923436f8390c0857cdd6da6238 (diff) | |
| parent | 2d347e9c6633b56319c5a7ed42e4e67f48c88ef6 (diff) | |
Merge "Revert "Save generated previews in AppWidgetService"" into main
| -rw-r--r-- | core/java/android/appwidget/flags.aconfig | 2 | ||||
| -rw-r--r-- | core/proto/android/service/appwidget.proto | 13 | ||||
| -rw-r--r-- | services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java | 440 |
3 files changed, 16 insertions, 439 deletions
diff --git a/core/java/android/appwidget/flags.aconfig b/core/java/android/appwidget/flags.aconfig index e5c94fccfe28..3839b5fa2599 100644 --- a/core/java/android/appwidget/flags.aconfig +++ b/core/java/android/appwidget/flags.aconfig @@ -55,7 +55,7 @@ flag { name: "remote_views_proto" namespace: "app_widgets" description: "Enable support for persisting RemoteViews previews to Protobuf" - bug: "364420494" + bug: "306546610" } flag { diff --git a/core/proto/android/service/appwidget.proto b/core/proto/android/service/appwidget.proto index fb907196bfc7..97350ef90eec 100644 --- a/core/proto/android/service/appwidget.proto +++ b/core/proto/android/service/appwidget.proto @@ -20,8 +20,6 @@ package android.service.appwidget; option java_multiple_files = true; option java_outer_classname = "AppWidgetServiceProto"; -import "frameworks/base/core/proto/android/widget/remoteviews.proto"; - // represents the object holding the dump info of the app widget service message AppWidgetServiceDumpProto { repeated WidgetProto widgets = 1; // the array of bound widgets @@ -40,14 +38,3 @@ message WidgetProto { optional int32 maxHeight = 9; optional bool restoreCompleted = 10; } - -// represents a set of widget previews for a particular provider -message GeneratedPreviewsProto { - repeated Preview previews = 1; - - // represents a particular RemoteViews preview, which may be set for multiple categories - message Preview { - repeated int32 widget_categories = 1; - optional android.widget.RemoteViewsProto views = 2; - } -}
\ No newline at end of file diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java index 35998d9a1fd4..f6ac706c4985 100644 --- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java +++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java @@ -17,7 +17,6 @@ package com.android.server.appwidget; import static android.appwidget.flags.Flags.remoteAdapterConversion; -import static android.appwidget.flags.Flags.remoteViewsProto; import static android.appwidget.flags.Flags.removeAppWidgetServiceIoFromCriticalPath; import static android.appwidget.flags.Flags.securityPolicyInteractAcrossUsers; import static android.appwidget.flags.Flags.supportResumeRestoreAfterReboot; @@ -32,7 +31,6 @@ import static com.android.server.appwidget.AppWidgetXmlUtil.serializeWidgetSizes import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME; import android.Manifest; -import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.PermissionName; @@ -106,7 +104,6 @@ import android.os.UserHandle; import android.os.UserManager; import android.provider.DeviceConfig; import android.service.appwidget.AppWidgetServiceDumpProto; -import android.service.appwidget.GeneratedPreviewsProto; import android.service.appwidget.WidgetProto; import android.text.TextUtils; import android.util.ArrayMap; @@ -125,9 +122,7 @@ import android.util.SparseIntArray; import android.util.SparseLongArray; import android.util.TypedValue; import android.util.Xml; -import android.util.proto.ProtoInputStream; import android.util.proto.ProtoOutputStream; -import android.util.proto.ProtoUtils; import android.view.Display; import android.view.View; import android.widget.RemoteViews; @@ -139,7 +134,6 @@ import com.android.internal.app.UnlaunchableAppActivity; import com.android.internal.appwidget.IAppWidgetHost; import com.android.internal.appwidget.IAppWidgetService; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; -import com.android.internal.infra.AndroidFuture; import com.android.internal.os.BackgroundThread; import com.android.internal.os.SomeArgs; import com.android.internal.util.ArrayUtils; @@ -227,10 +221,6 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku // XML attribute for widget ids that are pending deletion. // See {@link Provider#pendingDeletedWidgetIds}. private static final String PENDING_DELETED_IDS_ATTR = "pending_deleted_ids"; - // Name of service directory in /data/system_ce/<user>/ - private static final String APPWIDGET_CE_DATA_DIRNAME = "appwidget"; - // Name of previews directory in /data/system_ce/<user>/appwidget/ - private static final String WIDGET_PREVIEWS_DIRNAME = "previews"; // Hard limit of number of hosts an app can create, note that the app that hosts the widgets // can have multiple instances of {@link AppWidgetHost}, typically in respect to different @@ -326,9 +316,6 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku // Handler to the background thread that saves states to disk. private Handler mSaveStateHandler; - // Handler to the background thread that saves generated previews to disk. All operations that - // modify saved previews must be run on this Handler. - private Handler mSavePreviewsHandler; // Handler to the foreground thread that handles broadcasts related to user // and package events, as well as various internal events within // AppWidgetService. @@ -372,7 +359,6 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku } else { mSaveStateHandler = BackgroundThread.getHandler(); } - mSavePreviewsHandler = new Handler(BackgroundThread.get().getLooper()); final ServiceThread serviceThread = new ServiceThread(TAG, android.os.Process.THREAD_PRIORITY_FOREGROUND, false /* allowIo */); serviceThread.start(); @@ -392,9 +378,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku SystemUiDeviceConfigFlags.GENERATED_PREVIEW_API_MAX_PROVIDERS, DEFAULT_GENERATED_PREVIEW_MAX_PROVIDERS); mGeneratedPreviewsApiCounter = new ApiCounter(generatedPreviewResetInterval, - generatedPreviewMaxCallsPerInterval, - // Set a limit on the number of providers if storing them in memory. - remoteViewsProto() ? Integer.MAX_VALUE : generatedPreviewsMaxProviders); + generatedPreviewMaxCallsPerInterval, generatedPreviewsMaxProviders); DeviceConfig.addOnPropertiesChangedListener(NAMESPACE_SYSTEMUI, new HandlerExecutor(mCallbackHandler), this::handleSystemUiDeviceConfigChange); @@ -660,14 +644,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku for (int i = 0; i < providerCount; i++) { Provider provider = mProviders.get(i); if (provider.id.uid == clearedUid) { - if (remoteViewsProto()) { - changed |= clearGeneratedPreviewsAsync(provider); - } else { - changed |= provider.clearGeneratedPreviewsLocked(); - } - if (DEBUG) { - Slog.e(TAG, "clearPreviewsForUidLocked " + provider + " changed " + changed); - } + changed |= provider.clearGeneratedPreviewsLocked(); } } return changed; @@ -3269,9 +3246,6 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku deleteWidgetsLocked(provider, UserHandle.USER_ALL); mProviders.remove(provider); mGeneratedPreviewsApiCounter.remove(provider.id); - if (remoteViewsProto()) { - clearGeneratedPreviewsAsync(provider); - } // no need to send the DISABLE broadcast, since the receiver is gone anyway cancelBroadcastsLocked(provider); @@ -3850,14 +3824,6 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku } catch (IOException e) { Slog.w(TAG, "Failed to read state: " + e); } - - if (remoteViewsProto()) { - try { - loadGeneratedPreviewCategoriesLocked(profileId); - } catch (IOException e) { - Slog.w(TAG, "Failed to read preview categories: " + e); - } - } } if (version >= 0) { @@ -4627,12 +4593,6 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku keep.add(providerId); // Use the new AppWidgetProviderInfo. provider.setPartialInfoLocked(info); - // Clear old previews - if (remoteViewsProto()) { - clearGeneratedPreviewsAsync(provider); - } else { - provider.clearGeneratedPreviewsLocked(); - } // If it's enabled final int M = provider.widgets.size(); if (M > 0) { @@ -4924,7 +4884,6 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku mSecurityPolicy.enforceCallFromPackage(callingPackage); ensureWidgetCategoryCombinationIsValid(widgetCategory); - AndroidFuture<RemoteViews> result = null; synchronized (mLock) { ensureGroupStateLoadedLocked(profileId); final int providerCount = mProviders.size(); @@ -4958,23 +4917,10 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku callingPackage); if (providerIsInCallerProfile && !shouldFilterAppAccess && (providerIsInCallerPackage || hasBindAppWidgetPermission)) { - if (remoteViewsProto()) { - result = getGeneratedPreviewsAsync(provider, widgetCategory); - } else { - return provider.getGeneratedPreviewLocked(widgetCategory); - } + return provider.getGeneratedPreviewLocked(widgetCategory); } } } - - if (result != null) { - try { - return result.get(); - } catch (Exception e) { - Slog.e(TAG, "Failed to get generated previews Future result", e); - return null; - } - } // Either the provider does not exist or the caller does not have permission to access its // previews. return null; @@ -5004,12 +4950,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku providerComponent + " is not a valid AppWidget provider"); } if (mGeneratedPreviewsApiCounter.tryApiCall(providerId)) { - if (remoteViewsProto()) { - setGeneratedPreviewsAsync(provider, widgetCategories, preview); - } else { - provider.setGeneratedPreviewLocked(widgetCategories, preview); - scheduleNotifyGroupHostsForProvidersChangedLocked(userId); - } + provider.setGeneratedPreviewLocked(widgetCategories, preview); + scheduleNotifyGroupHostsForProvidersChangedLocked(userId); return true; } return false; @@ -5037,361 +4979,11 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku throw new IllegalArgumentException( providerComponent + " is not a valid AppWidget provider"); } - - if (remoteViewsProto()) { - removeGeneratedPreviewsAsync(provider, widgetCategories); - } else { - final boolean changed = provider.removeGeneratedPreviewLocked(widgetCategories); - if (changed) scheduleNotifyGroupHostsForProvidersChangedLocked(userId); - } - } - } - - /** - * Return previews for the specified provider from a background thread. The result of the future - * is nullable. - */ - @FlaggedApi(android.appwidget.flags.Flags.FLAG_REMOTE_VIEWS_PROTO) - @NonNull - private AndroidFuture<RemoteViews> getGeneratedPreviewsAsync( - @NonNull Provider provider, @AppWidgetProviderInfo.CategoryFlags int widgetCategory) { - AndroidFuture<RemoteViews> result = new AndroidFuture<>(); - mSavePreviewsHandler.post(() -> { - SparseArray<RemoteViews> previews = loadGeneratedPreviews(provider); - for (int i = 0; i < previews.size(); i++) { - if ((widgetCategory & previews.keyAt(i)) != 0) { - result.complete(previews.valueAt(i)); - return; - } - } - result.complete(null); - }); - return result; - } - - /** - * Set previews for the specified provider on a background thread. - */ - @FlaggedApi(android.appwidget.flags.Flags.FLAG_REMOTE_VIEWS_PROTO) - private void setGeneratedPreviewsAsync(@NonNull Provider provider, int widgetCategories, - @NonNull RemoteViews preview) { - mSavePreviewsHandler.post(() -> { - SparseArray<RemoteViews> previews = loadGeneratedPreviews(provider); - for (int flag : Provider.WIDGET_CATEGORY_FLAGS) { - if ((widgetCategories & flag) != 0) { - previews.put(flag, preview); - } - } - saveGeneratedPreviews(provider, previews, /* notify= */ true); - }); - } - - /** - * Remove previews for the specified provider on a background thread. - */ - @FlaggedApi(android.appwidget.flags.Flags.FLAG_REMOTE_VIEWS_PROTO) - private void removeGeneratedPreviewsAsync(@NonNull Provider provider, int widgetCategories) { - mSavePreviewsHandler.post(() -> { - SparseArray<RemoteViews> previews = loadGeneratedPreviews(provider); - boolean changed = false; - for (int flag : Provider.WIDGET_CATEGORY_FLAGS) { - if ((widgetCategories & flag) != 0) { - changed |= previews.removeReturnOld(flag) != null; - } - } - if (changed) { - saveGeneratedPreviews(provider, previews, /* notify= */ true); - } - }); - } - - /** - * Clear previews for the specified provider on a background thread. Returns true if changed - * (i.e. there are previews to clear). If returns true, the caller should schedule a providers - * changed notification. - */ - @FlaggedApi(android.appwidget.flags.Flags.FLAG_REMOTE_VIEWS_PROTO) - private boolean clearGeneratedPreviewsAsync(@NonNull Provider provider) { - mSavePreviewsHandler.post(() -> { - saveGeneratedPreviews(provider, /* previews= */ null, /* notify= */ false); - }); - return provider.info.generatedPreviewCategories != 0; - } - - private void checkSavePreviewsThread() { - if (DEBUG && !mSavePreviewsHandler.getLooper().isCurrentThread()) { - throw new IllegalStateException("Only modify previews on the background thread"); + final boolean changed = provider.removeGeneratedPreviewLocked(widgetCategories); + if (changed) scheduleNotifyGroupHostsForProvidersChangedLocked(userId); } } - /** - * Load previews from file for the given provider. If there are no previews, returns an empty - * SparseArray. Else, returns a SparseArray of the previews mapped by widget category. - */ - @FlaggedApi(android.appwidget.flags.Flags.FLAG_REMOTE_VIEWS_PROTO) - @NonNull - private SparseArray<RemoteViews> loadGeneratedPreviews(@NonNull Provider provider) { - checkSavePreviewsThread(); - try { - AtomicFile previewsFile = getWidgetPreviewsFile(provider); - if (!previewsFile.exists()) { - return new SparseArray<>(); - } - ProtoInputStream input = new ProtoInputStream(previewsFile.readFully()); - SparseArray<RemoteViews> entries = readGeneratedPreviewsFromProto(input); - SparseArray<RemoteViews> singleCategoryKeyedEntries = new SparseArray<>(); - for (int i = 0; i < entries.size(); i++) { - int widgetCategories = entries.keyAt(i); - RemoteViews preview = entries.valueAt(i); - for (int flag : Provider.WIDGET_CATEGORY_FLAGS) { - if ((widgetCategories & flag) != 0) { - singleCategoryKeyedEntries.put(flag, preview); - } - } - } - return singleCategoryKeyedEntries; - } catch (IOException e) { - Slog.e(TAG, "Failed to load generated previews for " + provider, e); - return new SparseArray<>(); - } - } - - /** - * This is called when loading profile/group state to populate - * AppWidgetProviderInfo.generatedPreviewCategories based on what previews are saved. - * - * This is the only time previews are read while not on mSavePreviewsHandler. It happens once - * per profile during initialization, before any calls to get/set/removeWidgetPreviewAsync - * happen for that profile. - */ - @FlaggedApi(android.appwidget.flags.Flags.FLAG_REMOTE_VIEWS_PROTO) - @GuardedBy("mLock") - private void loadGeneratedPreviewCategoriesLocked(int profileId) throws IOException { - for (Provider provider : mProviders) { - if (provider.id.getProfile().getIdentifier() != profileId) { - continue; - } - AtomicFile previewsFile = getWidgetPreviewsFile(provider); - if (!previewsFile.exists()) { - continue; - } - ProtoInputStream input = new ProtoInputStream(previewsFile.readFully()); - provider.info.generatedPreviewCategories = readGeneratedPreviewCategoriesFromProto( - input); - if (DEBUG) { - Slog.i(TAG, TextUtils.formatSimple( - "loadGeneratedPreviewCategoriesLocked %d %s categories %d", profileId, - provider, provider.info.generatedPreviewCategories)); - } - } - } - - /** - * Save the given previews into storage. - * - * @param provider Provider for which to save previews - * @param previews Previews to save. If null or empty, clears any saved previews for this - * provider. - * @param notify If true, then this function will notify hosts of updated provider info. - */ - @FlaggedApi(android.appwidget.flags.Flags.FLAG_REMOTE_VIEWS_PROTO) - private void saveGeneratedPreviews(@NonNull Provider provider, - @Nullable SparseArray<RemoteViews> previews, boolean notify) { - checkSavePreviewsThread(); - AtomicFile file = null; - FileOutputStream stream = null; - try { - file = getWidgetPreviewsFile(provider); - if (previews == null || previews.size() == 0) { - if (file.exists()) { - if (DEBUG) { - Slog.i(TAG, "Deleting widget preview file " + file); - } - file.delete(); - } - } else { - if (DEBUG) { - Slog.i(TAG, "Writing widget preview file " + file); - } - ProtoOutputStream out = new ProtoOutputStream(); - writePreviewsToProto(out, previews); - stream = file.startWrite(); - stream.write(out.getBytes()); - file.finishWrite(stream); - } - - synchronized (mLock) { - provider.updateGeneratedPreviewCategoriesLocked(previews); - if (notify) { - scheduleNotifyGroupHostsForProvidersChangedLocked(provider.getUserId()); - } - } - } catch (IOException e) { - if (file != null && stream != null) { - file.failWrite(stream); - } - Slog.w(TAG, "Failed to save widget previews for provider " + provider.id.componentName); - } - } - - - /** - * Write the given previews as a GeneratedPreviewsProto to the output stream. - */ - @FlaggedApi(android.appwidget.flags.Flags.FLAG_REMOTE_VIEWS_PROTO) - private void writePreviewsToProto(@NonNull ProtoOutputStream out, - @NonNull SparseArray<RemoteViews> generatedPreviews) { - // Collect RemoteViews mapped by hashCode in order to avoid writing duplicates. - SparseArray<Pair<Integer, RemoteViews>> previewsToWrite = new SparseArray<>(); - for (int i = 0; i < generatedPreviews.size(); i++) { - int widgetCategory = generatedPreviews.keyAt(i); - RemoteViews views = generatedPreviews.valueAt(i); - if (!previewsToWrite.contains(views.hashCode())) { - previewsToWrite.put(views.hashCode(), new Pair<>(widgetCategory, views)); - } else { - Pair<Integer, RemoteViews> entry = previewsToWrite.get(views.hashCode()); - previewsToWrite.put(views.hashCode(), - Pair.create(entry.first | widgetCategory, views)); - } - } - - for (int i = 0; i < previewsToWrite.size(); i++) { - final long token = out.start(GeneratedPreviewsProto.PREVIEWS); - Pair<Integer, RemoteViews> entry = previewsToWrite.valueAt(i); - out.write(GeneratedPreviewsProto.Preview.WIDGET_CATEGORIES, entry.first); - final long viewsToken = out.start(GeneratedPreviewsProto.Preview.VIEWS); - entry.second.writePreviewToProto(mContext, out); - out.end(viewsToken); - out.end(token); - } - } - - /** - * Read a GeneratedPreviewsProto message from the input stream. - */ - @FlaggedApi(android.appwidget.flags.Flags.FLAG_REMOTE_VIEWS_PROTO) - @NonNull - private SparseArray<RemoteViews> readGeneratedPreviewsFromProto(@NonNull ProtoInputStream input) - throws IOException { - SparseArray<RemoteViews> entries = new SparseArray<>(); - while (input.nextField() != ProtoInputStream.NO_MORE_FIELDS) { - switch (input.getFieldNumber()) { - case (int) GeneratedPreviewsProto.PREVIEWS: - final long token = input.start(GeneratedPreviewsProto.PREVIEWS); - Pair<Integer, RemoteViews> entry = readSinglePreviewFromProto(input, - /* skipViews= */ false); - entries.put(entry.first, entry.second); - input.end(token); - break; - default: - Slog.w(TAG, "Unknown field while reading GeneratedPreviewsProto! " - + ProtoUtils.currentFieldToString(input)); - } - } - return entries; - } - - /** - * Read the widget categories from GeneratedPreviewsProto and return an int representing the - * combined widget categories of all the previews. - */ - @FlaggedApi(android.appwidget.flags.Flags.FLAG_REMOTE_VIEWS_PROTO) - @AppWidgetProviderInfo.CategoryFlags - private int readGeneratedPreviewCategoriesFromProto(@NonNull ProtoInputStream input) - throws IOException { - int widgetCategories = 0; - while (input.nextField() != ProtoInputStream.NO_MORE_FIELDS) { - switch (input.getFieldNumber()) { - case (int) GeneratedPreviewsProto.PREVIEWS: - final long token = input.start(GeneratedPreviewsProto.PREVIEWS); - Pair<Integer, RemoteViews> entry = readSinglePreviewFromProto(input, - /* skipViews= */ true); - widgetCategories |= entry.first; - input.end(token); - break; - default: - Slog.w(TAG, "Unknown field while reading GeneratedPreviewsProto! " - + ProtoUtils.currentFieldToString(input)); - } - } - return widgetCategories; - } - - /** - * Read a single GeneratedPreviewsProto.Preview message from the input stream, and returns a - * pair of widget category and corresponding RemoteViews. If skipViews is true, this function - * will only read widget categories and the returned RemoteViews will be null. - */ - @FlaggedApi(android.appwidget.flags.Flags.FLAG_REMOTE_VIEWS_PROTO) - @NonNull - private Pair<Integer, RemoteViews> readSinglePreviewFromProto(@NonNull ProtoInputStream input, - boolean skipViews) throws IOException { - int widgetCategories = 0; - RemoteViews views = null; - while (input.nextField() != ProtoInputStream.NO_MORE_FIELDS) { - switch (input.getFieldNumber()) { - case (int) GeneratedPreviewsProto.Preview.VIEWS: - if (skipViews) { - // ProtoInputStream will skip over the nested message when nextField() is - // called. - continue; - } - final long token = input.start(GeneratedPreviewsProto.Preview.VIEWS); - try { - views = RemoteViews.createPreviewFromProto(mContext, input); - } catch (Exception e) { - Slog.e(TAG, "Unable to deserialize RemoteViews", e); - } - input.end(token); - break; - case (int) GeneratedPreviewsProto.Preview.WIDGET_CATEGORIES: - widgetCategories = input.readInt( - GeneratedPreviewsProto.Preview.WIDGET_CATEGORIES); - break; - default: - Slog.w(TAG, "Unknown field while reading GeneratedPreviewsProto! " - + ProtoUtils.currentFieldToString(input)); - } - } - return Pair.create(widgetCategories, views); - } - - /** - * Returns the file in which all generated previews for this provider are stored. This will be - * a path of the form: - * {@literal /data/system_ce/<userId>/appwidget/previews/<package>-<class>-<uid>.binpb} - * - * This function will not create the file if it does not already exist. - */ - @NonNull - private static AtomicFile getWidgetPreviewsFile(@NonNull Provider provider) throws IOException { - int userId = provider.getUserId(); - File previewsDirectory = getWidgetPreviewsDirectory(userId); - File providerPreviews = Environment.buildPath(previewsDirectory, - TextUtils.formatSimple("%s-%s-%d.binpb", provider.id.componentName.getPackageName(), - provider.id.componentName.getClassName(), provider.id.uid)); - return new AtomicFile(providerPreviews); - } - - /** - * Returns the widget previews directory for the given user, creating it if it does not exist. - * This will be a path of the form: - * {@literal /data/system_ce/<userId>/appwidget/previews} - */ - @NonNull - private static File getWidgetPreviewsDirectory(int userId) throws IOException { - File dataSystemCeDirectory = Environment.getDataSystemCeDirectory(userId); - File previewsDirectory = Environment.buildPath(dataSystemCeDirectory, - APPWIDGET_CE_DATA_DIRNAME, WIDGET_PREVIEWS_DIRNAME); - if (!previewsDirectory.exists()) { - if (!previewsDirectory.mkdirs()) { - throw new IOException("Unable to create widget preview directory " - + previewsDirectory.getPath()); - } - } - return previewsDirectory; - } - private static void ensureWidgetCategoryCombinationIsValid(int widgetCategories) { int validCategories = AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN | AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD @@ -5823,11 +5415,11 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku AppWidgetManager.META_DATA_APPWIDGET_PROVIDER); } if (newInfo != null) { - newInfo.generatedPreviewCategories = info.generatedPreviewCategories; info = newInfo; if (DEBUG) { Objects.requireNonNull(info); } + updateGeneratedPreviewCategoriesLocked(); } } mInfoParsed = true; @@ -5884,7 +5476,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku generatedPreviews.put(flag, preview); } } - updateGeneratedPreviewCategoriesLocked(generatedPreviews); + updateGeneratedPreviewCategoriesLocked(); } @GuardedBy("this.mLock") @@ -5896,7 +5488,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku } } if (changed) { - updateGeneratedPreviewCategoriesLocked(generatedPreviews); + updateGeneratedPreviewCategoriesLocked(); } return changed; } @@ -5905,19 +5497,17 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku public boolean clearGeneratedPreviewsLocked() { if (generatedPreviews.size() > 0) { generatedPreviews.clear(); - updateGeneratedPreviewCategoriesLocked(generatedPreviews); + updateGeneratedPreviewCategoriesLocked(); return true; } return false; } + @GuardedBy("this.mLock") - private void updateGeneratedPreviewCategoriesLocked( - @Nullable SparseArray<RemoteViews> previews) { + private void updateGeneratedPreviewCategoriesLocked() { info.generatedPreviewCategories = 0; - if (previews != null) { - for (int i = 0; i < previews.size(); i++) { - info.generatedPreviewCategories |= previews.keyAt(i); - } + for (int i = 0; i < generatedPreviews.size(); i++) { + info.generatedPreviewCategories |= generatedPreviews.keyAt(i); } } |