Skip to content

Commit

Permalink
WIP: proper multi-user support. works, but missing some app names and…
Browse files Browse the repository at this point in the history
… icons
  • Loading branch information
infinity0 committed Aug 28, 2023
1 parent 9a0864c commit 1d8fe53
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 47 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ android {
//applicationId "dev.ukanth.ufirewall.donate"
minSdkVersion 21
targetSdkVersion 33
versionCode 20230814
versionName "3.6"
versionCode 20230827
versionName "3.6.1"
//buildConfigField 'boolean', 'DONATE', 'true'
}

Expand Down
138 changes: 98 additions & 40 deletions app/src/main/java/dev/ukanth/ufirewall/Api.java
Original file line number Diff line number Diff line change
Expand Up @@ -1415,21 +1415,15 @@ public static List<PackageInfoData> getApps(Context ctx, GetAppList appList) {
}
}
//use pm list packages -f -U --user 10
int pkgManagerFlags = PackageManager.GET_META_DATA;
// it's useless to iterate over uninstalled packages if we don't support multi-profile apps
if (G.supportDual()) {
pkgManagerFlags |= PackageManager.GET_UNINSTALLED_PACKAGES;
}
int pkgManagerFlags = PackageManager.GET_META_DATA | PackageManager.GET_UNINSTALLED_PACKAGES;
PackageManager pkgmanager = ctx.getPackageManager();
List<ApplicationInfo> installed = pkgmanager.getInstalledApplications(pkgManagerFlags);
SparseArray<PackageInfoData> syncMap = new SparseArray<>();
Editor edit = cachePrefs.edit();
boolean changed = false;
String name;
String cachekey;
String cacheLabel = "cache.label.";
PackageInfoData app;
ApplicationInfo apinfo;

Date install = new Date();
install.setTime(System.currentTimeMillis() - (180000));
Expand All @@ -1440,48 +1434,57 @@ public static List<PackageInfoData> getApps(Context ctx, GetAppList appList) {
packagesForUser = getPackagesForUser(listOfUids);
}

for (int i = 0; i < installed.size(); i++) {
//for (ApplicationInfo apinfo : installed) {
//List<ApplicationInfo> installed = pkgmanager.getInstalledApplications(pkgManagerFlags);
/*List<PkgInfo> pkginfos = new ArrayList();
for (ApplicationInfo apinfo : installed) {
List<Integer> uids = new ArrayList();
String label = pkgmanager.getApplicationLabel(apinfo).toString();
uids.add(apinfo.uid);
pkginfos.add(new PkgInfo(apinfo.packageName, label, uids, apinfo.sourceDir, (apinfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0));
}*/
List<PkgInfo> pkginfos = getPackagesShell(pkgmanager);

for (PkgInfo pkg : pkginfos) {
Log.i(TAG, "Processing app info: " + pkg.packageName);
count = count + 1;
apinfo = installed.get(i);

if (appList != null) {
appList.doProgress(count);
}

boolean firstseen = false;
app = syncMap.get(apinfo.uid);
app = syncMap.get(pkg.uid);
// filter applications which are not allowed to access the Internet
if (app == null && PackageManager.PERMISSION_GRANTED != pkgmanager.checkPermission(Manifest.permission.INTERNET, apinfo.packageName) && !showAllApps()) {
// dumpsys package check-permission <package> android.permission.INTERNET <uid>
// contrary to help text, package goes first!
if (app == null && PackageManager.PERMISSION_GRANTED != pkgmanager.checkPermission(Manifest.permission.INTERNET, pkg.packageName) && !showAllApps()) {
continue;
}
// try to get the application label from our cache - getApplicationLabel() is horribly slow!!!!
cachekey = cacheLabel + apinfo.packageName;
cachekey = cacheLabel + pkg.packageName + Integer.toString(pkg.uid);
name = prefs.getString(cachekey, "");
if (name.length() == 0 || isRecentlyInstalled(apinfo.packageName)) {
if (name.length() == 0 || isRecentlyInstalled(pkg.packageName)) {
// get label and put on cache
name = pkgmanager.getApplicationLabel(apinfo).toString();
name = pkg.packageLabel + " / user " + Integer.toString(pkg.user_id);
edit.putString(cachekey, name);
changed = true;
firstseen = true;
}
if (app == null) {
app = new PackageInfoData();
app.uid = apinfo.uid;
app.installTime = new File(apinfo.sourceDir).lastModified();
app.uid = pkg.uid;
app.installTime = new File(pkg.sourceDir).lastModified();
app.names = new ArrayList<String>();
app.names.add(name);
app.appinfo = apinfo;
if (app.appinfo != null && (app.appinfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
if (!pkg.isSystem) {
//user app
app.appType = 1;
} else {
//system app
app.appType = 0;
}
app.pkgName = apinfo.packageName;
if ((apinfo.flags & ApplicationInfo.FLAG_INSTALLED) != 0)
syncMap.put(apinfo.uid, app);
app.pkgName = pkg.packageName;
syncMap.put(app.uid, app);
} else {
app.names.add(name);
}
Expand Down Expand Up @@ -1509,12 +1512,12 @@ public static List<PackageInfoData> getApps(Context ctx, GetAppList appList) {
if (G.enableTor() && !app.selected_tor && Collections.binarySearch(selected_tor, app.uid) >= 0) {
app.selected_tor = true;
}
if (G.supportDual()) {
/*if (G.supportDual()) {
checkPartOfMultiUser(apinfo, name, listOfUids, packagesForUser, multiUserAppsMap);
}
}*/
}

if (G.supportDual()) {
/*if (G.supportDual()) {
//run through multi user map
for (int i = 0; i < multiUserAppsMap.size(); i++) {
app = multiUserAppsMap.valueAt(i);
Expand All @@ -1541,7 +1544,7 @@ public static List<PackageInfoData> getApps(Context ctx, GetAppList appList) {
}
syncMap.put(app.uid, app);
}
}
}*/

List<PackageInfoData> specialData = getSpecialData();

Expand Down Expand Up @@ -1636,7 +1639,7 @@ public static List<PackageInfoData> getSpecialData() {
return specialData;
}

private static void checkPartOfMultiUser(ApplicationInfo apinfo, String name, List<Integer> uid1, HashMap<Integer,String> pkgs, SparseArray<PackageInfoData> syncMap) {
/*private static void checkPartOfMultiUser(ApplicationInfo apinfo, String name, List<Integer> uid1, HashMap<Integer,String> pkgs, SparseArray<PackageInfoData> syncMap) {
try {
for (Integer integer : uid1) {
int appUid = Integer.parseInt(integer + "" + apinfo.uid + "");
Expand Down Expand Up @@ -1666,7 +1669,7 @@ private static void checkPartOfMultiUser(ApplicationInfo apinfo, String name, Li
} catch (Exception e) {
Log.e(TAG, e.getMessage(), e);
}
}
}*/

private static boolean packagesExistForUserUid(HashMap<Integer,String> pkgs, int appUid) {
if(pkgs.containsKey(appUid)){
Expand Down Expand Up @@ -1694,6 +1697,52 @@ public static HashMap<Integer, String> getPackagesForUser(List<Integer> userProf
return listApps.size() > 0 ? listApps : null;
}

private static final Pattern pmfU = Pattern.compile("package:(.*)=(.*?) uid:(.*)", Pattern.MULTILINE);

public static List<PkgInfo> pkgInfoFromPm(PackageManager mgr, String item, boolean isSystem) {
List<PkgInfo> infos = new ArrayList();
Matcher matcher = pmfU.matcher(item);
if (matcher.find() && matcher.groupCount() > 0) {
String sourceDir = matcher.group(1);
String packageName = matcher.group(2);
String packageLabel = null;
try {
ApplicationInfo info = mgr.getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES);
packageLabel = mgr.getApplicationLabel(info).toString();
} catch (NameNotFoundException e) {
// test later for null
}
String[] uids = matcher.group(3).split(",");
for (String uid: uids) {
int uidi = Integer.parseInt(uid);
int user = uidi / 100000;
infos.add(new PkgInfo(packageName, (packageLabel == null)? packageName: packageLabel, uidi, user, sourceDir, isSystem));
}
} else {
Log.i(TAG, "could not parse pm output: " + item);
}
return infos;
}

public static List<PkgInfo> getPackagesShell(PackageManager mgr) {
List<PkgInfo> pkginfos = new ArrayList();
Shell.Result result;
List<String> out;
// user packages
result = Shell.cmd("pm list packages -f -U -3").exec();
out = result.getOut();
for (String item : out) {
pkginfos.addAll(pkgInfoFromPm(mgr, item, false));
}
// system packages
result = Shell.cmd("pm list packages -f -U -s").exec();
out = result.getOut();
for (String item : out) {
pkginfos.addAll(pkgInfoFromPm(mgr, item, true));
}
return pkginfos;
}

private static boolean isRecentlyInstalled(String packageName) {
boolean isRecent = false;
if (recentlyInstalled != null && recentlyInstalled.contains(packageName)) {
Expand Down Expand Up @@ -2755,7 +2804,7 @@ public static boolean loadSharedPreferencesFromFile(Context ctx, StringBuilder b
public static void probeLogTarget(final Context ctx) {

}

@SuppressLint("InlinedApi")
public static void showInstalledAppDetails(Context context, String packageName) {
final String SCHEME = "package";
Expand Down Expand Up @@ -3244,6 +3293,23 @@ protected Integer doInBackground(Object... params) {

}

public static final class PkgInfo {
public String packageName;
public String packageLabel;
public int uid; // uid for the app
public int user_id; // android user_id for the user
public String sourceDir;
public boolean isSystem;
public PkgInfo(String packageName, String packageLabel, int uid, int user_id, String sourceDir, boolean isSystem) {
this.packageName = packageName;
this.packageLabel = packageLabel;
this.uid = uid;
this.user_id = user_id;
this.sourceDir = sourceDir;
this.isSystem = isSystem;
}
}

/**
* Small structure to hold an application info
*/
Expand All @@ -3263,7 +3329,7 @@ public static final class PackageInfoData {
public String pkgName;

/**
* Application Type
* Application Type. 0 for system, 1 for user, 2 for core.
*/
public int appType;

Expand Down Expand Up @@ -3299,10 +3365,6 @@ public static final class PackageInfoData {
* toString cache
*/
public String tostr;
/**
* application info
*/
public ApplicationInfo appinfo;
/**
* cached application icon
*/
Expand Down Expand Up @@ -3350,9 +3412,6 @@ public boolean equals(Object o) {
@Override
public int hashCode() {
int result = 17;
if (appinfo != null) {
result = 31 * result + appinfo.hashCode();
}
result = 31 * result + uid;
result = 31 * result + pkgName.hashCode();
return result;
Expand All @@ -3379,13 +3438,12 @@ public String toString() {
public String toStringWithUID() {
if (tostr == null) {
StringBuilder s = new StringBuilder();
s.append("[ ");
s.append(uid);
s.append(" ] ");
for (int i = 0; i < names.size(); i++) {
if (i != 0) s.append(", ");
s.append(names.get(i));
}
s.append(" / ");
s.append(uid);
s.append("\n");
tostr = s.toString();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,11 @@ public View getView(final int position, View convertView, ViewGroup parent) {
holder.text.setOnClickListener(v -> StartAppDetailActivityIntent(v,holder,id));


ApplicationInfo info = holder.app.appinfo;
if (info != null && (info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
if (holder.app.appType == 1) {
//user app
holder.text.setTextColor(G.userColor());
} else {
//system app
//system or core app
holder.text.setTextColor(G.sysColor());
}

Expand All @@ -158,7 +157,7 @@ public View getView(final int position, View convertView, ViewGroup parent) {
holder.icon.setImageDrawable(context.getDrawable(R.drawable.ic_unknown));
} else {
holder.icon.setImageDrawable(holder.app.cached_icon);
if (!holder.app.icon_loaded && info != null) {
if (!holder.app.icon_loaded) {
// this icon has not been loaded yet - load it on a
// separated thread
try {
Expand Down Expand Up @@ -398,7 +397,8 @@ protected View doInBackground(Object... params) {
final PackageManager pkgMgr = (PackageManager) params[1];
final View viewToUpdate = (View) params[2];
if (!app.icon_loaded) {
Drawable d = new ScaleDrawable(pkgMgr.getApplicationIcon(app.appinfo), 0, 32, 32).getDrawable();
ApplicationInfo info = pkgMgr.getApplicationInfo(app.pkgName, PackageManager.GET_UNINSTALLED_PACKAGES);
Drawable d = new ScaleDrawable(pkgMgr.getApplicationIcon(info), 0, 32, 32).getDrawable();
d.setBounds(0, 0, 32, 32);
app.cached_icon = d;
app.icon_loaded = true;
Expand Down

0 comments on commit 1d8fe53

Please sign in to comment.