// AppIDFromString returns the app id (or base uid) for a given uid, stripping out the user id from it. // (ie. "10001" -> 10001,nil; "u0a25" -> 10025,nil; "text" -> 0,error func AppIDFromString(uid string) (int32, error) { // The empty string is a valid/expected value to pass through here. if uid == "" { return 0, nil } if m, result := parseutils.SubexpNames(abrUIDRE, uid); m { i, err := strconv.Atoi(result["appId"]) if err != nil { fmt.Printf("Error getting app id from string: %v\n", err) return 0, err } // These are types defined and formatted in frameworks/base/core/java/android/os/UserHandle.java switch result["aidType"] { case "i": // Isolated UID return int32(i) + firstIsolatedUID, nil case "a": // appId >= firstApplicationUID return int32(i) + firstApplicationUID, nil case "s": // Unmodified app ID return int32(i), nil default: return int32(i), fmt.Errorf("unknown appIdType: %s", result["aidType"]) } } i, err := strconv.Atoi(uid) if err != nil { fmt.Printf("Error getting app id from string: %v\n", err) return 0, err } return AppID(int32(i)), nil }
func sdkVersion(input string) (int, error) { // Found in the System Properties section of a bug report. re := regexp.MustCompile(`.*\[ro.build.version.sdk\]:\s+\[(?P<sdkVersion>\d+)\].*`) if match, result := parseutils.SubexpNames(re, input); match { return strconv.Atoi(result["sdkVersion"]) } return -1, errors.New("unable to find device SDK version") }
// modelName returns the device's model name (ie. Nexus 5). func modelName(input string) string { // Found in the System Properties section of a bug report. re := regexp.MustCompile(`.*\[ro.product.model\]:\s+\[(?P<modelName>.*)\].*`) if match, result := parseutils.SubexpNames(re, input); match { return result["modelName"] } // We should only get to this point in the case of a bad (malformed) bug report. return "unknown device" }
// extractAppsFromAppOpsDump looks at the app ops service dump from a bug report // and extracts package names and their UIDs from the dump. It returns a mapping of // the package name to the PackageInfo object. func extractAppsFromAppOpsDump(s string) (map[string]*usagepb.PackageInfo, []error) { pkgs := make(map[string]*usagepb.PackageInfo) var errs []error inAppOpsSection := false var curUID int32 var err error Loop: for _, line := range strings.Split(s, "\n") { line = strings.TrimSpace(line) if m, result := parseutils.SubexpNames(serviceDumpRE, line); m { switch in := result["service"] == "appops"; { case inAppOpsSection && !in: // Just exited the App Ops section break Loop case in: inAppOpsSection = true continue Loop default: // Random section continue Loop } } if !inAppOpsSection { continue } if m, result := parseutils.SubexpNames(uidRE, line); m { curUID, err = AppIDFromString(result["uid"]) if err != nil { errs = append(errs, err) } } if m, result := parseutils.SubexpNames(appOpsPackageRE, line); m { pkg := result["package"] pkgs[pkg] = &usagepb.PackageInfo{ PkgName: proto.String(pkg), Uid: proto.Int32(curUID), } } } return pkgs, errs }
func extractBuildFingerprint(input string) string { // A regular expression to match any build fingerprint line in the bugreport. re := regexp.MustCompile("Build\\s+fingerprint:\\s+'(?P<build>\\S+)'") var out string for _, line := range strings.Split(input, "\n") { if match, result := parseutils.SubexpNames(re, line); match { out = result["build"] break } } return out }
// extractAppsFromPackageDump looks at the package service dump from a bug report // and extracts as much application info from the dump. It returns a mapping of // the package name to the PackageInfo object. func extractAppsFromPackageDump(s string) (map[string]*usagepb.PackageInfo, []error) { pkgs := make(map[string]*usagepb.PackageInfo) var errs []error var inPackageDumpSection, inCurrentSection bool var curPkg *usagepb.PackageInfo Loop: for _, line := range strings.Split(s, "\n") { line = strings.TrimSpace(line) if m, result := parseutils.SubexpNames(serviceDumpRE, line); m { switch in := result["service"] == "package"; { case inPackageDumpSection && !in: // Just exited package dump section break Loop case in: inPackageDumpSection = true continue Loop default: // Random section continue Loop } } if !inPackageDumpSection { continue } switch line { case "Packages:": inCurrentSection = true continue Loop case "Hidden system packages:": inCurrentSection = false break Loop } if !inCurrentSection { continue } if m, result := parseutils.SubexpNames(packageDumpPackageRE, line); m { if curPkg != nil { pkgs[curPkg.GetPkgName()] = curPkg } curPkg = &usagepb.PackageInfo{ PkgName: proto.String(result["package"]), } } else if m, result := parseutils.SubexpNames(userIDRE, line); m { if curPkg == nil { errs = append(errs, errors.New("found userId line before package line")) continue } uid, err := AppIDFromString(result["uid"]) if err != nil { errs = append(errs, err) } curPkg.Uid = proto.Int32(uid) } else if m, result := parseutils.SubexpNames(packageDumpVersionCodeRE, line); m { if curPkg == nil { errs = append(errs, errors.New("found versionCode line before package line")) continue } vc, err := strconv.Atoi(result["versionCode"]) if err != nil { errs = append(errs, fmt.Errorf("error getting version code from string: %v\n", err)) continue } curPkg.VersionCode = proto.Int32(int32(vc)) } else if m, result := parseutils.SubexpNames(packageDumpVersionNameRE, line); m { if curPkg == nil { errs = append(errs, errors.New("found versionName line before package line")) continue } curPkg.VersionName = proto.String(result["versionName"]) } else if m, result := parseutils.SubexpNames(firstInstallTimeRE, line); m { if curPkg == nil { errs = append(errs, errors.New("found firstInstallTime line before package line")) continue } t, err := time.Parse(timeFormat, result["time"]) if err != nil { errs = append(errs, err) } curPkg.FirstInstallTime = proto.Int64(t.UnixNano() / int64(time.Millisecond)) } else if m, result := parseutils.SubexpNames(lastUpdateTimeRE, line); m { if curPkg == nil { errs = append(errs, errors.New("found lastUpdateTime line before package line")) continue } t, err := time.Parse(timeFormat, result["time"]) if err != nil { errs = append(errs, err) } curPkg.LastUpdateTime = proto.Int64(t.UnixNano() / int64(time.Millisecond)) } } if curPkg != nil { pkgs[curPkg.GetPkgName()] = curPkg } return pkgs, errs }