Skip to content

Commit 432ae75

Browse files
committed
[BatchOps] Enable "Uninstall" option for apps uninstalled without clearing data
Signed-off-by: Muntashir Al-Islam <muntashirakon@riseup.net>
1 parent 06d6368 commit 432ae75

9 files changed

Lines changed: 42 additions & 10 deletions

File tree

app/src/main/java/io/github/muntashirakon/AppManager/compat/ApplicationInfoCompat.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,12 @@ public static boolean isInstalled(@NonNull ApplicationInfo info) {
336336
&& Paths.exists(info.publicSourceDir);
337337
}
338338

339+
public static boolean isOnlyDataInstalled(@NonNull ApplicationInfo info) {
340+
return (info.flags & ApplicationInfo.FLAG_INSTALLED) == 0
341+
&& !(info.processName != null
342+
&& Paths.exists(info.publicSourceDir));
343+
}
344+
339345
public static boolean isTestOnly(@NonNull ApplicationInfo info) {
340346
return (info.flags & ApplicationInfo.FLAG_TEST_ONLY) != 0;
341347
}

app/src/main/java/io/github/muntashirakon/AppManager/db/AppsDb.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@
2323
import io.github.muntashirakon.AppManager.db.entity.FreezeType;
2424
import io.github.muntashirakon.AppManager.db.entity.LogFilter;
2525
import io.github.muntashirakon.AppManager.db.entity.OpHistory;
26+
import io.github.muntashirakon.AppManager.logs.Log;
2627
import io.github.muntashirakon.AppManager.utils.ContextUtils;
2728

28-
@Database(entities = {App.class, LogFilter.class, FileHash.class, Backup.class, OpHistory.class, FmFavorite.class, FreezeType.class}, version = 5)
29+
@Database(entities = {App.class, LogFilter.class, FileHash.class, Backup.class, OpHistory.class, FmFavorite.class, FreezeType.class}, version = 6)
2930
public abstract class AppsDb extends RoomDatabase {
3031
private static AppsDb sAppsDb;
3132

@@ -47,13 +48,24 @@ public void migrate(@NonNull SupportSQLiteDatabase db) {
4748
db.execSQL("CREATE TABLE IF NOT EXISTS `freeze_type` (`package_name` TEXT NOT NULL, `type` INTEGER NOT NULL, PRIMARY KEY(`package_name`))");
4849
}
4950
};
51+
public static final Migration M_5_6 = new Migration(5, 6) {
52+
@Override
53+
public void migrate(@NonNull SupportSQLiteDatabase db) {
54+
db.execSQL("ALTER TABLE `app` ADD COLUMN `is_only_data_installed` INTEGER NOT NULL DEFAULT 0");
55+
}
56+
};
5057

5158
public static AppsDb getInstance() {
5259
if (sAppsDb == null) {
5360
sAppsDb = Room.databaseBuilder(ContextUtils.getContext(), AppsDb.class, "apps.db")
54-
.addMigrations(M_2_3, M_3_4, M_4_5)
61+
.addMigrations(M_2_3, M_3_4, M_4_5, M_5_6)
5562
.fallbackToDestructiveMigrationOnDowngrade()
5663
.build();
64+
try {
65+
sAppsDb.appDao().getAll();
66+
} catch (Throwable th) {
67+
th.printStackTrace();
68+
}
5769
}
5870
return sAppsDb;
5971
}

app/src/main/java/io/github/muntashirakon/AppManager/db/entity/App.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ public class App implements Serializable {
6969
@ColumnInfo(name = "is_installed", defaultValue = "true")
7070
public boolean isInstalled;
7171

72+
@ColumnInfo(name = "is_only_data_installed", defaultValue = "0")
73+
public boolean isOnlyDataInstalled;
74+
7275
@ColumnInfo(name = "is_enabled", defaultValue = "false")
7376
public boolean isEnabled;
7477

@@ -133,6 +136,7 @@ public static App fromPackageInfo(@NonNull Context context, @NonNull PackageInfo
133136
app.uid = applicationInfo.uid;
134137
app.userId = UserHandleHidden.getUserId(app.uid);
135138
app.isInstalled = ApplicationInfoCompat.isInstalled(applicationInfo);
139+
app.isOnlyDataInstalled = ApplicationInfoCompat.isOnlyDataInstalled(applicationInfo);
136140
app.flags = applicationInfo.flags;
137141
app.isEnabled = !FreezeUtils.isFrozen(applicationInfo);
138142
app.packageLabel = ApplicationInfoCompat.loadLabelSafe(applicationInfo, context.getPackageManager()).toString();
@@ -160,6 +164,7 @@ public static App fromBackup(@NonNull Backup backup) {
160164
app.uid = 0;
161165
app.userId = backup.userId;
162166
app.isInstalled = false;
167+
app.isOnlyDataInstalled = false;
163168
if (backup.isSystem) {
164169
app.flags |= ApplicationInfo.FLAG_SYSTEM;
165170
}

app/src/main/java/io/github/muntashirakon/AppManager/main/ApplicationItem.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ public class ApplicationItem extends PackageItemInfo implements IFilterableAppIn
158158
* Whether the app is installed
159159
*/
160160
public boolean isInstalled = true;
161+
public boolean isOnlyDataInstalled = true;
161162
/**
162163
* Whether the app has any activities
163164
*/

app/src/main/java/io/github/muntashirakon/AppManager/main/MainBatchOpsHandler.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
package io.github.muntashirakon.AppManager.main;
44

55
import android.Manifest;
6+
import android.content.pm.ApplicationInfo;
67
import android.os.Build;
78
import android.view.Menu;
89
import android.view.MenuItem;
@@ -75,11 +76,15 @@ public boolean onSelectionChange(int selectionCount) {
7576
// Best case: O(1)
7677
// Worst case: O(n)
7778
boolean areAllInstalled = true;
79+
boolean areAllUninstalledWithoutData = true;
7880
boolean areAllUninstalledSystem = true;
7981
boolean doAllUninstalledhaveBackup = true;
8082
for (ApplicationItem item : selectedItems) {
8183
if (item.isInstalled) continue;
8284
areAllInstalled = false;
85+
if (areAllUninstalledWithoutData) {
86+
areAllUninstalledWithoutData = item.isOnlyDataInstalled;
87+
}
8388
if (!doAllUninstalledhaveBackup && !areAllUninstalledSystem) {
8489
// No need to check further
8590
break;
@@ -93,7 +98,7 @@ public boolean onSelectionChange(int selectionCount) {
9398
}
9499
/* === Enable/Disable === */
95100
// Enable “Uninstall” action iff all selections are installed
96-
mUninstallMenu.setEnabled(nonZeroSelection && areAllInstalled);
101+
mUninstallMenu.setEnabled(nonZeroSelection && (areAllInstalled || areAllUninstalledWithoutData));
97102
mFreezeUnfreezeMenu.setEnabled(nonZeroSelection && areAllInstalled);
98103
mForceStopMenu.setEnabled(nonZeroSelection && areAllInstalled);
99104
mClearDataCacheMenu.setEnabled(nonZeroSelection && areAllInstalled);

app/src/main/java/io/github/muntashirakon/AppManager/main/MainRecyclerAdapter.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,7 @@ private void handleClick(@NonNull ApplicationItem item) {
391391
// The app is already installed, and we were wrong to assume that it was installed.
392392
// Update data before opening it.
393393
item.isInstalled = true;
394+
item.isOnlyDataInstalled = false;
394395
item.userIds = new int[]{UserHandleHidden.myUserId()};
395396
Intent intent = AppDetailsActivity.getIntent(mActivity, item.packageName, UserHandleHidden.myUserId());
396397
mActivity.startActivity(intent);

app/src/main/java/io/github/muntashirakon/AppManager/main/MainViewModel.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,7 @@ private ApplicationItem getNewApplicationItem(@NonNull String packageName, @NonN
718718
}
719719
item.userIds = ArrayUtils.appendInt(item.userIds, app.userId);
720720
item.isInstalled = true;
721+
item.isOnlyDataInstalled = false;
721722
item.openCount += app.openCount;
722723
item.screenTime += app.screenTime;
723724
if (item.lastUsageTime == 0L || item.lastUsageTime < app.lastUsageTime) {
@@ -742,6 +743,7 @@ private ApplicationItem getNewApplicationItem(@NonNull String packageName, @NonN
742743
} else {
743744
item.packageName = app.packageName;
744745
item.isInstalled = false;
746+
item.isOnlyDataInstalled = app.isOnlyDataInstalled;
745747
item.hasKeystore |= app.hasKeystore;
746748
}
747749
}

app/src/main/java/io/github/muntashirakon/AppManager/oneclickops/OneClickOpsViewModel.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
import io.github.muntashirakon.AppManager.users.Users;
4040
import io.github.muntashirakon.AppManager.utils.PackageUtils;
4141
import io.github.muntashirakon.AppManager.utils.ThreadUtils;
42-
import io.github.muntashirakon.io.Paths;
4342

4443
public class OneClickOpsViewModel extends AndroidViewModel {
4544
public static final String TAG = OneClickOpsViewModel.class.getSimpleName();
@@ -236,10 +235,12 @@ public void clearData() {
236235
HashSet<String> packageNames = new HashSet<>();
237236
for (ApplicationInfo applicationInfo : PackageUtils.getAllApplications(MATCH_UNINSTALLED_PACKAGES
238237
| PackageManagerCompat.MATCH_STATIC_SHARED_AND_SDK_LIBRARIES)) {
239-
if (packageNames.contains(applicationInfo.packageName) || isInstalled(applicationInfo)) {
238+
if (packageNames.contains(applicationInfo.packageName)) {
240239
continue;
241240
}
242-
packageNames.add(applicationInfo.packageName);
241+
if (ApplicationInfoCompat.isOnlyDataInstalled(applicationInfo)) {
242+
packageNames.add(applicationInfo.packageName);
243+
}
243244
if (ThreadUtils.isInterrupted()) {
244245
return;
245246
}
@@ -287,8 +288,4 @@ private ItemCount getTrackerCountForApp(@NonNull PackageInfo packageInfo) {
287288
trackerCount.count = ComponentUtils.getTrackerComponentsForPackage(packageInfo).size();
288289
return trackerCount;
289290
}
290-
291-
private boolean isInstalled(@NonNull ApplicationInfo info) {
292-
return info.processName != null && Paths.exists(info.publicSourceDir);
293-
}
294291
}

app/src/main/java/io/github/muntashirakon/AppManager/utils/PackageUtils.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ public static List<ApplicationItem> getInstalledOrBackedUpApplicationsFromDb(@No
170170
}
171171
item.userIds = ArrayUtils.appendInt(item.userIds, app.userId);
172172
item.isInstalled = true;
173+
item.isOnlyDataInstalled = false;
173174
item.openCount += app.openCount;
174175
item.screenTime += app.screenTime;
175176
if (item.lastUsageTime == 0L || item.lastUsageTime < app.lastUsageTime) {
@@ -197,6 +198,7 @@ public static List<ApplicationItem> getInstalledOrBackedUpApplicationsFromDb(@No
197198
item.packageName = app.packageName;
198199
applicationItems.put(app.packageName, item);
199200
item.isInstalled = false;
201+
item.isOnlyDataInstalled = app.isOnlyDataInstalled;
200202
item.hasKeystore |= app.hasKeystore;
201203
}
202204
}
@@ -237,6 +239,7 @@ public static List<ApplicationItem> getInstalledOrBackedUpApplicationsFromDb(@No
237239
item.isUser = !backup.isSystem;
238240
item.isDisabled = false;
239241
item.isInstalled = false;
242+
item.isOnlyDataInstalled = false;
240243
item.hasSplits = backup.hasSplits;
241244
item.hasKeystore = backup.hasKeyStore;
242245
item.generateOtherInfo();

0 commit comments

Comments
 (0)