Loading src/com/android/launcher3/model/BgDataModel.java +1 −2 Original line number Diff line number Diff line Loading @@ -297,8 +297,7 @@ public class BgDataModel { .filter(wi -> wi.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT) .map(ShortcutKey::fromItemInfo), // Pending shortcuts ItemInstallQueue.INSTANCE.get(context).getPendingShortcuts() .stream().filter(si -> si.user.equals(user))) ItemInstallQueue.INSTANCE.get(context).getPendingShortcuts(user)) .collect(groupingBy(ShortcutKey::getPackageName, mapping(ShortcutKey::getId, Collectors.toSet()))); Loading src/com/android/launcher3/model/ItemInstallQueue.java +63 −140 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ import static android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID; import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION; import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET; import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT; import static com.android.launcher3.LauncherSettings.Favorites.PROFILE_ID; import static com.android.launcher3.model.data.AppInfo.makeLaunchIntent; import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; Loading @@ -30,11 +29,9 @@ import android.appwidget.AppWidgetProviderInfo; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.LauncherActivityInfo; import android.content.pm.LauncherApps; import android.content.pm.ShortcutInfo; import android.os.Process; import android.os.UserHandle; import android.util.Log; import android.util.Pair; Loading @@ -47,27 +44,19 @@ import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherAppWidgetProviderInfo; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.Utilities; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.LauncherAppWidgetInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.pm.UserCache; import com.android.launcher3.shortcuts.ShortcutKey; import com.android.launcher3.shortcuts.ShortcutRequest; import com.android.launcher3.util.MainThreadInitializedObject; import com.android.launcher3.util.PersistedItemArray; import com.android.launcher3.util.Preconditions; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONStringer; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; /** * Class to maintain a queue of pending items to be added to the workspace. Loading @@ -79,7 +68,6 @@ public class ItemInstallQueue { public static final int FLAG_DRAG_AND_DROP = 4; private static final String TAG = "InstallShortcutReceiver"; private static final boolean DBG = false; // The set of shortcuts that are pending install private static final String APPS_PENDING_INSTALL = "apps_to_install"; Loading @@ -90,24 +78,34 @@ public class ItemInstallQueue { public static MainThreadInitializedObject<ItemInstallQueue> INSTANCE = new MainThreadInitializedObject<>(ItemInstallQueue::new); private final PersistedItemArray<PendingInstallShortcutInfo> mStorage = new PersistedItemArray<>(APPS_PENDING_INSTALL); private final Context mContext; // Determines whether to defer installing shortcuts immediately until // processAllPendingInstalls() is called. private int mInstallQueueDisabledFlags = 0; // Only accessed on worker thread private List<PendingInstallShortcutInfo> mItems; private ItemInstallQueue(Context context) { mContext = context; } @WorkerThread private void ensureQueueLoaded() { Preconditions.assertWorkerThread(); if (mItems == null) { mItems = mStorage.read(mContext, this::decode); } } @WorkerThread private void addToQueue(PendingInstallShortcutInfo info) { String encoded = info.encodeToString(mContext); SharedPreferences prefs = Utilities.getPrefs(mContext); Set<String> strings = prefs.getStringSet(APPS_PENDING_INSTALL, null); strings = (strings != null) ? new HashSet<>(strings) : new HashSet<>(1); strings.add(encoded); prefs.edit().putStringSet(APPS_PENDING_INSTALL, strings).apply(); ensureQueueLoaded(); mItems.add(info); mStorage.write(mContext, mItems); } @WorkerThread Loading @@ -117,28 +115,21 @@ public class ItemInstallQueue { // Launcher not loaded return; } ArrayList<Pair<ItemInfo, Object>> installQueue = new ArrayList<>(); SharedPreferences prefs = Utilities.getPrefs(mContext); Set<String> strings = prefs.getStringSet(APPS_PENDING_INSTALL, null); if (DBG) Log.d(TAG, "Getting and clearing APPS_PENDING_INSTALL: " + strings); if (strings == null) { ensureQueueLoaded(); if (mItems.isEmpty()) { return; } for (String encoded : strings) { PendingInstallShortcutInfo info = decode(encoded, mContext); if (info == null) { continue; } List<Pair<ItemInfo, Object>> installQueue = mItems.stream() .map(info -> info.getItemInfo(mContext)) .collect(Collectors.toList()); // Generate a shortcut info to add into the model installQueue.add(info.getItemInfo(mContext)); } prefs.edit().remove(APPS_PENDING_INSTALL).apply(); // Add the items and clear queue if (!installQueue.isEmpty()) { launcher.getModel().addAndBindAddedWorkspaceItems(installQueue); } mItems.clear(); mStorage.getFile(mContext).delete(); } /** Loading @@ -149,34 +140,12 @@ public class ItemInstallQueue { if (packageNames.isEmpty()) { return; } Preconditions.assertWorkerThread(); SharedPreferences sp = Utilities.getPrefs(mContext); Set<String> strings = sp.getStringSet(APPS_PENDING_INSTALL, null); if (DBG) { Log.d(TAG, "APPS_PENDING_INSTALL: " + strings + ", removing packages: " + packageNames); } if (strings == null || ((Collection) strings).isEmpty()) { return; } Set<String> newStrings = new HashSet<>(strings); Iterator<String> newStringsIter = newStrings.iterator(); while (newStringsIter.hasNext()) { String encoded = newStringsIter.next(); try { Decoder decoder = new Decoder(encoded, mContext); if (packageNames.contains(getIntentPackage(decoder.intent)) && user.equals(decoder.user)) { newStringsIter.remove(); } } catch (JSONException | URISyntaxException e) { Log.d(TAG, "Exception reading shortcut to add: " + e); newStringsIter.remove(); ensureQueueLoaded(); if (mItems.removeIf(item -> item.user.equals(user) && packageNames.contains(getIntentPackage(item.intent)))) { mStorage.write(mContext, mItems); } } sp.edit().putStringSet(APPS_PENDING_INSTALL, newStrings).apply(); } /** * Adds an item to the install queue Loading @@ -200,28 +169,14 @@ public class ItemInstallQueue { } /** * Returns all pending shorts in the queue * Returns a stream of all pending shortcuts in the queue */ @WorkerThread public HashSet<ShortcutKey> getPendingShortcuts() { HashSet<ShortcutKey> result = new HashSet<>(); Set<String> strings = Utilities.getPrefs(mContext).getStringSet(APPS_PENDING_INSTALL, null); if (strings == null || ((Collection) strings).isEmpty()) { return result; } for (String encoded : strings) { try { Decoder decoder = new Decoder(encoded, mContext); if (decoder.optInt(Favorites.ITEM_TYPE, -1) == ITEM_TYPE_DEEP_SHORTCUT) { result.add(ShortcutKey.fromIntent(decoder.intent, decoder.user)); } } catch (JSONException | URISyntaxException e) { Log.d(TAG, "Exception reading shortcut to add: " + e); } } return result; public Stream<ShortcutKey> getPendingShortcuts(UserHandle user) { ensureQueueLoaded(); return mItems.stream() .filter(item -> item.itemType == ITEM_TYPE_DEEP_SHORTCUT && user.equals(item.user)) .map(item -> ShortcutKey.fromIntent(item.intent, user)); } private void queuePendingShortcutInfo(PendingInstallShortcutInfo info) { Loading Loading @@ -293,19 +248,9 @@ public class ItemInstallQueue { providerInfo = info; } public String encodeToString(Context context) { try { return new JSONStringer() .object() .key(Favorites.ITEM_TYPE).value(itemType) .key(Favorites.INTENT).value(intent.toUri(0)) .key(PROFILE_ID).value( UserCache.INSTANCE.get(context).getSerialNumberForUser(user)) .endObject().toString(); } catch (JSONException e) { Log.d(TAG, "Exception when adding shortcut: " + e); return null; } @Override public Intent getIntent() { return intent; } public Pair<ItemInfo, Object> getItemInfo(Context context) { Loading Loading @@ -365,16 +310,13 @@ public class ItemInstallQueue { ? intent.getPackage() : intent.getComponent().getPackageName(); } private static PendingInstallShortcutInfo decode(String encoded, Context context) { try { Decoder decoder = new Decoder(encoded, context); switch (decoder.optInt(Favorites.ITEM_TYPE, -1)) { private PendingInstallShortcutInfo decode(int itemType, UserHandle user, Intent intent) { switch (itemType) { case Favorites.ITEM_TYPE_APPLICATION: return new PendingInstallShortcutInfo( decoder.intent.getPackage(), decoder.user); return new PendingInstallShortcutInfo(intent.getPackage(), user); case Favorites.ITEM_TYPE_DEEP_SHORTCUT: { List<ShortcutInfo> si = ShortcutKey.fromIntent(decoder.intent, decoder.user) .buildRequest(context) List<ShortcutInfo> si = ShortcutKey.fromIntent(intent, user) .buildRequest(mContext) .query(ShortcutRequest.ALL); if (si.isEmpty()) { return null; Loading @@ -383,11 +325,11 @@ public class ItemInstallQueue { } } case Favorites.ITEM_TYPE_APPWIDGET: { int widgetId = decoder.intent.getIntExtra(EXTRA_APPWIDGET_ID, 0); int widgetId = intent.getIntExtra(EXTRA_APPWIDGET_ID, 0); AppWidgetProviderInfo info = AppWidgetManager.getInstance(context).getAppWidgetInfo(widgetId); if (info == null || !info.provider.equals(decoder.intent.getComponent()) || !info.getProfile().equals(decoder.user)) { AppWidgetManager.getInstance(mContext).getAppWidgetInfo(widgetId); if (info == null || !info.provider.equals(intent.getComponent()) || !info.getProfile().equals(user)) { return null; } return new PendingInstallShortcutInfo(info, widgetId); Loading @@ -395,25 +337,6 @@ public class ItemInstallQueue { default: Log.e(TAG, "Unknown item type"); } } catch (JSONException | URISyntaxException e) { Log.d(TAG, "Exception reading shortcut to add: " + e); } return null; } private static class Decoder extends JSONObject { public final Intent intent; public final UserHandle user; private Decoder(String encoded, Context context) throws JSONException, URISyntaxException { super(encoded); intent = Intent.parseUri(getString(Favorites.INTENT), 0); user = has(PROFILE_ID) ? UserCache.INSTANCE.get(context).getUserForSerialNumber(getLong(PROFILE_ID)) : Process.myUserHandle(); if (user == null || intent == null) { throw new JSONException("Invalid data"); } } } } src/com/android/launcher3/util/PersistedItemArray.java +9 −5 Original line number Diff line number Diff line Loading @@ -68,8 +68,7 @@ public class PersistedItemArray<T extends ItemInfo> { */ @WorkerThread public void write(Context context, List<T> items) { AtomicFile file = new AtomicFile(context.getFileStreamPath(mFileName)); AtomicFile file = getFile(context); FileOutputStream fos; try { fos = file.startWrite(); Loading Loading @@ -124,9 +123,7 @@ public class PersistedItemArray<T extends ItemInfo> { @WorkerThread public List<T> read(Context context, ItemFactory<T> factory, LongFunction<UserHandle> userFn) { List<T> result = new ArrayList<>(); AtomicFile file = new AtomicFile(context.getFileStreamPath(mFileName)); try (FileInputStream fis = file.openRead()) { try (FileInputStream fis = getFile(context).openRead()) { XmlPullParser parser = Xml.newPullParser(); parser.setInput(new InputStreamReader(fis, StandardCharsets.UTF_8)); Loading Loading @@ -166,6 +163,13 @@ public class PersistedItemArray<T extends ItemInfo> { return result; } /** * Returns the underlying file used for persisting data */ public AtomicFile getFile(Context context) { return new AtomicFile(context.getFileStreamPath(mFileName)); } /** * Interface to create an ItemInfo during parsing */ Loading Loading
src/com/android/launcher3/model/BgDataModel.java +1 −2 Original line number Diff line number Diff line Loading @@ -297,8 +297,7 @@ public class BgDataModel { .filter(wi -> wi.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT) .map(ShortcutKey::fromItemInfo), // Pending shortcuts ItemInstallQueue.INSTANCE.get(context).getPendingShortcuts() .stream().filter(si -> si.user.equals(user))) ItemInstallQueue.INSTANCE.get(context).getPendingShortcuts(user)) .collect(groupingBy(ShortcutKey::getPackageName, mapping(ShortcutKey::getId, Collectors.toSet()))); Loading
src/com/android/launcher3/model/ItemInstallQueue.java +63 −140 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ import static android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID; import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION; import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET; import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT; import static com.android.launcher3.LauncherSettings.Favorites.PROFILE_ID; import static com.android.launcher3.model.data.AppInfo.makeLaunchIntent; import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; Loading @@ -30,11 +29,9 @@ import android.appwidget.AppWidgetProviderInfo; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.LauncherActivityInfo; import android.content.pm.LauncherApps; import android.content.pm.ShortcutInfo; import android.os.Process; import android.os.UserHandle; import android.util.Log; import android.util.Pair; Loading @@ -47,27 +44,19 @@ import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherAppWidgetProviderInfo; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.Utilities; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.LauncherAppWidgetInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.pm.UserCache; import com.android.launcher3.shortcuts.ShortcutKey; import com.android.launcher3.shortcuts.ShortcutRequest; import com.android.launcher3.util.MainThreadInitializedObject; import com.android.launcher3.util.PersistedItemArray; import com.android.launcher3.util.Preconditions; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONStringer; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; /** * Class to maintain a queue of pending items to be added to the workspace. Loading @@ -79,7 +68,6 @@ public class ItemInstallQueue { public static final int FLAG_DRAG_AND_DROP = 4; private static final String TAG = "InstallShortcutReceiver"; private static final boolean DBG = false; // The set of shortcuts that are pending install private static final String APPS_PENDING_INSTALL = "apps_to_install"; Loading @@ -90,24 +78,34 @@ public class ItemInstallQueue { public static MainThreadInitializedObject<ItemInstallQueue> INSTANCE = new MainThreadInitializedObject<>(ItemInstallQueue::new); private final PersistedItemArray<PendingInstallShortcutInfo> mStorage = new PersistedItemArray<>(APPS_PENDING_INSTALL); private final Context mContext; // Determines whether to defer installing shortcuts immediately until // processAllPendingInstalls() is called. private int mInstallQueueDisabledFlags = 0; // Only accessed on worker thread private List<PendingInstallShortcutInfo> mItems; private ItemInstallQueue(Context context) { mContext = context; } @WorkerThread private void ensureQueueLoaded() { Preconditions.assertWorkerThread(); if (mItems == null) { mItems = mStorage.read(mContext, this::decode); } } @WorkerThread private void addToQueue(PendingInstallShortcutInfo info) { String encoded = info.encodeToString(mContext); SharedPreferences prefs = Utilities.getPrefs(mContext); Set<String> strings = prefs.getStringSet(APPS_PENDING_INSTALL, null); strings = (strings != null) ? new HashSet<>(strings) : new HashSet<>(1); strings.add(encoded); prefs.edit().putStringSet(APPS_PENDING_INSTALL, strings).apply(); ensureQueueLoaded(); mItems.add(info); mStorage.write(mContext, mItems); } @WorkerThread Loading @@ -117,28 +115,21 @@ public class ItemInstallQueue { // Launcher not loaded return; } ArrayList<Pair<ItemInfo, Object>> installQueue = new ArrayList<>(); SharedPreferences prefs = Utilities.getPrefs(mContext); Set<String> strings = prefs.getStringSet(APPS_PENDING_INSTALL, null); if (DBG) Log.d(TAG, "Getting and clearing APPS_PENDING_INSTALL: " + strings); if (strings == null) { ensureQueueLoaded(); if (mItems.isEmpty()) { return; } for (String encoded : strings) { PendingInstallShortcutInfo info = decode(encoded, mContext); if (info == null) { continue; } List<Pair<ItemInfo, Object>> installQueue = mItems.stream() .map(info -> info.getItemInfo(mContext)) .collect(Collectors.toList()); // Generate a shortcut info to add into the model installQueue.add(info.getItemInfo(mContext)); } prefs.edit().remove(APPS_PENDING_INSTALL).apply(); // Add the items and clear queue if (!installQueue.isEmpty()) { launcher.getModel().addAndBindAddedWorkspaceItems(installQueue); } mItems.clear(); mStorage.getFile(mContext).delete(); } /** Loading @@ -149,34 +140,12 @@ public class ItemInstallQueue { if (packageNames.isEmpty()) { return; } Preconditions.assertWorkerThread(); SharedPreferences sp = Utilities.getPrefs(mContext); Set<String> strings = sp.getStringSet(APPS_PENDING_INSTALL, null); if (DBG) { Log.d(TAG, "APPS_PENDING_INSTALL: " + strings + ", removing packages: " + packageNames); } if (strings == null || ((Collection) strings).isEmpty()) { return; } Set<String> newStrings = new HashSet<>(strings); Iterator<String> newStringsIter = newStrings.iterator(); while (newStringsIter.hasNext()) { String encoded = newStringsIter.next(); try { Decoder decoder = new Decoder(encoded, mContext); if (packageNames.contains(getIntentPackage(decoder.intent)) && user.equals(decoder.user)) { newStringsIter.remove(); } } catch (JSONException | URISyntaxException e) { Log.d(TAG, "Exception reading shortcut to add: " + e); newStringsIter.remove(); ensureQueueLoaded(); if (mItems.removeIf(item -> item.user.equals(user) && packageNames.contains(getIntentPackage(item.intent)))) { mStorage.write(mContext, mItems); } } sp.edit().putStringSet(APPS_PENDING_INSTALL, newStrings).apply(); } /** * Adds an item to the install queue Loading @@ -200,28 +169,14 @@ public class ItemInstallQueue { } /** * Returns all pending shorts in the queue * Returns a stream of all pending shortcuts in the queue */ @WorkerThread public HashSet<ShortcutKey> getPendingShortcuts() { HashSet<ShortcutKey> result = new HashSet<>(); Set<String> strings = Utilities.getPrefs(mContext).getStringSet(APPS_PENDING_INSTALL, null); if (strings == null || ((Collection) strings).isEmpty()) { return result; } for (String encoded : strings) { try { Decoder decoder = new Decoder(encoded, mContext); if (decoder.optInt(Favorites.ITEM_TYPE, -1) == ITEM_TYPE_DEEP_SHORTCUT) { result.add(ShortcutKey.fromIntent(decoder.intent, decoder.user)); } } catch (JSONException | URISyntaxException e) { Log.d(TAG, "Exception reading shortcut to add: " + e); } } return result; public Stream<ShortcutKey> getPendingShortcuts(UserHandle user) { ensureQueueLoaded(); return mItems.stream() .filter(item -> item.itemType == ITEM_TYPE_DEEP_SHORTCUT && user.equals(item.user)) .map(item -> ShortcutKey.fromIntent(item.intent, user)); } private void queuePendingShortcutInfo(PendingInstallShortcutInfo info) { Loading Loading @@ -293,19 +248,9 @@ public class ItemInstallQueue { providerInfo = info; } public String encodeToString(Context context) { try { return new JSONStringer() .object() .key(Favorites.ITEM_TYPE).value(itemType) .key(Favorites.INTENT).value(intent.toUri(0)) .key(PROFILE_ID).value( UserCache.INSTANCE.get(context).getSerialNumberForUser(user)) .endObject().toString(); } catch (JSONException e) { Log.d(TAG, "Exception when adding shortcut: " + e); return null; } @Override public Intent getIntent() { return intent; } public Pair<ItemInfo, Object> getItemInfo(Context context) { Loading Loading @@ -365,16 +310,13 @@ public class ItemInstallQueue { ? intent.getPackage() : intent.getComponent().getPackageName(); } private static PendingInstallShortcutInfo decode(String encoded, Context context) { try { Decoder decoder = new Decoder(encoded, context); switch (decoder.optInt(Favorites.ITEM_TYPE, -1)) { private PendingInstallShortcutInfo decode(int itemType, UserHandle user, Intent intent) { switch (itemType) { case Favorites.ITEM_TYPE_APPLICATION: return new PendingInstallShortcutInfo( decoder.intent.getPackage(), decoder.user); return new PendingInstallShortcutInfo(intent.getPackage(), user); case Favorites.ITEM_TYPE_DEEP_SHORTCUT: { List<ShortcutInfo> si = ShortcutKey.fromIntent(decoder.intent, decoder.user) .buildRequest(context) List<ShortcutInfo> si = ShortcutKey.fromIntent(intent, user) .buildRequest(mContext) .query(ShortcutRequest.ALL); if (si.isEmpty()) { return null; Loading @@ -383,11 +325,11 @@ public class ItemInstallQueue { } } case Favorites.ITEM_TYPE_APPWIDGET: { int widgetId = decoder.intent.getIntExtra(EXTRA_APPWIDGET_ID, 0); int widgetId = intent.getIntExtra(EXTRA_APPWIDGET_ID, 0); AppWidgetProviderInfo info = AppWidgetManager.getInstance(context).getAppWidgetInfo(widgetId); if (info == null || !info.provider.equals(decoder.intent.getComponent()) || !info.getProfile().equals(decoder.user)) { AppWidgetManager.getInstance(mContext).getAppWidgetInfo(widgetId); if (info == null || !info.provider.equals(intent.getComponent()) || !info.getProfile().equals(user)) { return null; } return new PendingInstallShortcutInfo(info, widgetId); Loading @@ -395,25 +337,6 @@ public class ItemInstallQueue { default: Log.e(TAG, "Unknown item type"); } } catch (JSONException | URISyntaxException e) { Log.d(TAG, "Exception reading shortcut to add: " + e); } return null; } private static class Decoder extends JSONObject { public final Intent intent; public final UserHandle user; private Decoder(String encoded, Context context) throws JSONException, URISyntaxException { super(encoded); intent = Intent.parseUri(getString(Favorites.INTENT), 0); user = has(PROFILE_ID) ? UserCache.INSTANCE.get(context).getUserForSerialNumber(getLong(PROFILE_ID)) : Process.myUserHandle(); if (user == null || intent == null) { throw new JSONException("Invalid data"); } } } }
src/com/android/launcher3/util/PersistedItemArray.java +9 −5 Original line number Diff line number Diff line Loading @@ -68,8 +68,7 @@ public class PersistedItemArray<T extends ItemInfo> { */ @WorkerThread public void write(Context context, List<T> items) { AtomicFile file = new AtomicFile(context.getFileStreamPath(mFileName)); AtomicFile file = getFile(context); FileOutputStream fos; try { fos = file.startWrite(); Loading Loading @@ -124,9 +123,7 @@ public class PersistedItemArray<T extends ItemInfo> { @WorkerThread public List<T> read(Context context, ItemFactory<T> factory, LongFunction<UserHandle> userFn) { List<T> result = new ArrayList<>(); AtomicFile file = new AtomicFile(context.getFileStreamPath(mFileName)); try (FileInputStream fis = file.openRead()) { try (FileInputStream fis = getFile(context).openRead()) { XmlPullParser parser = Xml.newPullParser(); parser.setInput(new InputStreamReader(fis, StandardCharsets.UTF_8)); Loading Loading @@ -166,6 +163,13 @@ public class PersistedItemArray<T extends ItemInfo> { return result; } /** * Returns the underlying file used for persisting data */ public AtomicFile getFile(Context context) { return new AtomicFile(context.getFileStreamPath(mFileName)); } /** * Interface to create an ItemInfo during parsing */ Loading