Android: Keep folder and shortcut grants, re-take the folders we use

Pruning now only runs when the config was really read: when the memory
stick isn't reachable at startup (an unmounted SD card, or right after
boot), NativeInit falls back to defaults and the recent list is empty, so
every recent game's grant looked unused and was released.

Grants for the memory stick, the Games tab folder and pinned folders are
re-taken at every startup. That moves their persisted time up, so they're
the last the system drops if we ever reach its limit. The new time is
written out with the next grant change, which is also the only time the
system prunes.

Home screen shortcuts can't be enumerated, so the 64 most recently
created or launched are remembered in a new [Shortcuts] section of
ppsspp.ini, and their grants are kept. ShortcutActivity runs without the
config loaded, so it queues them in SharedPreferences until the next
startup saves them.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-10-23 13:54:31 +02:00
1 parent 020e39baa9
commit 8e146f4c24
7 files changed
+205 -32

No files matched your search

+39 -1
View File
@@ -1397,7 +1397,8 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
bSaveSettings = true;
IniFile iniFile;
if (!iniFile.Load(iniFilename_)) {
loadedFromFile_ = iniFile.Load(iniFilename_);
if (!loadedFromFile_) {
WARN_LOG(Log::Config, "Failed to read '%s'. Setting main config to default.", iniFilename_.c_str());
// Continue anyway to initialize the config.
}
@@ -1449,6 +1450,18 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
}
}
vShortcutUris.clear();
if (const Section *shortcuts = iniFile.GetSection("Shortcuts")) {
for (int i = 0; i < MAX_SHORTCUT_URIS; i++) {
char keyName[64];
snprintf(keyName, sizeof(keyName), "Uri%d", i);
std::string uri;
if (shortcuts->Get(keyName, &uri) && !uri.empty()) {
vShortcutUris.push_back(uri);
}
}
}
// Default values for post process shaders
bool postShadersInitialized = iniFile.HasSection("PostShaderList");
Section *postShaderChain = iniFile.GetOrCreateSection("PostShaderList");
@@ -1573,6 +1586,18 @@ bool Config::Save(const char *saveReason) {
pinnedPaths->Set(keyName, vPinnedPaths[i]);
}
if (vShortcutUris.empty()) {
iniFile.DeleteSection("Shortcuts");
} else {
Section *shortcuts = iniFile.GetOrCreateSection("Shortcuts");
shortcuts->Clear();
for (size_t i = 0; i < vShortcutUris.size(); ++i) {
char keyName[64];
snprintf(keyName, sizeof(keyName), "Uri%d", (int)i);
shortcuts->Set(keyName, vShortcutUris[i]);
}
}
if (!IsGameSpecific()) {
// These settings can be game specific, and so are handled in SaveGameConfig().
@@ -1841,6 +1866,19 @@ void Config::DismissUpgrade() {
sUpgradeMessage.clear();
}
bool Config::AddShortcutUri(std::string_view uri) {
auto iter = std::find(vShortcutUris.begin(), vShortcutUris.end(), uri);
const bool added = iter == vShortcutUris.end();
if (!added) {
vShortcutUris.erase(iter);
}
vShortcutUris.insert(vShortcutUris.begin(), std::string(uri));
if ((int)vShortcutUris.size() > MAX_SHORTCUT_URIS) {
vShortcutUris.resize(MAX_SHORTCUT_URIS);
}
return added;
}
void Config::SetSearchPath(const Path &searchPath) {
searchPath_ = searchPath;
}