diff --git a/lib/common/mobile/android/android-application-manager.ts b/lib/common/mobile/android/android-application-manager.ts index 2d94de1da1..7b3f79fdb7 100644 --- a/lib/common/mobile/android/android-application-manager.ts +++ b/lib/common/mobile/android/android-application-manager.ts @@ -42,8 +42,51 @@ export class AndroidApplicationManager extends ApplicationManagerBase { } public async getInstalledApplications(): Promise { - const result = - (await this.adb.executeShellCommand(["pm", "list", "packages"])) || ""; + let result = ""; + try { + result = await this.adb.executeShellCommand(["pm", "list", "packages"]); + } catch (err) { + /** + * on some devices (Samsung) listing packages is prevented by a permission error + * notably, some system apps (bloatware) is installed under user 150 + * and listing these packages results in a permission error. + * if this happens, we have to first list all the users, and then loop through + * all the users and trying to list packages for that specific user, ignoring + * any errors. These are all then concatenated together and parsed normally. + * This is a slower operation, so we only do it in case listing failed in the first place. + */ + const userIDs: string[] = []; + const users = await this.adb.executeShellCommand(["pm", "list", "users"]); + /** + * Users: + * UserInfo{0:Owner:c13} running + */ + + const userIDRegex = /UserInfo{(\d+)[:}]/; + users.split(EOL).forEach((line: string) => { + const [, userID] = line.match(userIDRegex) ?? []; + + if (userID) { + userIDs.push(userID); + } + }); + + for (let id of userIDs) { + try { + result += + EOL + + (await this.adb.executeShellCommand([ + "pm", + "list", + "packages", + "--user", + id, + ])); + } catch (err) { + // ignore - likely permission denied. + } + } + } const regex = /package:(.+)/; return result .split(EOL)