Loading core/java/com/android/internal/app/procstats/AssociationState.java +14 −1 Original line number Diff line number Diff line Loading @@ -445,8 +445,18 @@ public final class AssociationState { } } public boolean hasProcess(String procName) { final int NSRC = mSources.size(); for (int isrc = 0; isrc < NSRC; isrc++) { if (mSources.keyAt(isrc).mProcess.equals(procName)) { return true; } } return false; } public void dumpStats(PrintWriter pw, String prefix, String prefixInner, String headerPrefix, long now, long totalTime, boolean dumpDetails, boolean dumpAll) { long now, long totalTime, String reqPackage, boolean dumpDetails, boolean dumpAll) { if (dumpAll) { pw.print(prefix); pw.print("mNumActive="); Loading @@ -456,6 +466,9 @@ public final class AssociationState { for (int isrc = 0; isrc < NSRC; isrc++) { final SourceKey key = mSources.keyAt(isrc); final SourceState src = mSources.valueAt(isrc); if (reqPackage != null && !reqPackage.equals(key.mProcess)) { continue; } pw.print(prefixInner); pw.print("<- "); pw.print(key.mProcess); Loading core/java/com/android/internal/app/procstats/ProcessStats.java +20 −5 Original line number Diff line number Diff line Loading @@ -1475,6 +1475,7 @@ public final class ProcessStats implements Parcelable { final int NSRVS = pkgState.mServices.size(); final int NASCS = pkgState.mAssociations.size(); final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName); boolean onlyAssociations = false; if (!pkgMatch) { boolean procMatch = false; for (int iproc = 0; iproc < NPROCS; iproc++) { Loading @@ -1485,9 +1486,20 @@ public final class ProcessStats implements Parcelable { } } if (!procMatch) { // Check if this app has any associations with the requested // package, so that if so we print those. for (int iasc = 0; iasc < NASCS; iasc++) { AssociationState asc = pkgState.mAssociations.valueAt(iasc); if (asc.hasProcess(reqPackage)) { onlyAssociations = true; break; } } if (!onlyAssociations) { continue; } } } if (NPROCS > 0 || NSRVS > 0 || NASCS > 0) { if (!printedHeader) { if (sepNeeded) pw.println(); Loading @@ -1503,7 +1515,7 @@ public final class ProcessStats implements Parcelable { pw.print(vers); pw.println(":"); } if ((section & REPORT_PKG_PROC_STATS) != 0) { if ((section & REPORT_PKG_PROC_STATS) != 0 && !onlyAssociations) { if (!dumpSummary || dumpAll) { for (int iproc = 0; iproc < NPROCS; iproc++) { ProcessState proc = pkgState.mProcesses.valueAt(iproc); Loading Loading @@ -1550,7 +1562,7 @@ public final class ProcessStats implements Parcelable { now, totalTime); } } if ((section & REPORT_PKG_SVC_STATS) != 0) { if ((section & REPORT_PKG_SVC_STATS) != 0 && !onlyAssociations) { for (int isvc = 0; isvc < NSRVS; isvc++) { ServiceState svc = pkgState.mServices.valueAt(isvc); if (!pkgMatch && !reqPackage.equals(svc.getProcessName())) { Loading Loading @@ -1579,8 +1591,10 @@ public final class ProcessStats implements Parcelable { for (int iasc = 0; iasc < NASCS; iasc++) { AssociationState asc = pkgState.mAssociations.valueAt(iasc); if (!pkgMatch && !reqPackage.equals(asc.getProcessName())) { if (!onlyAssociations || !asc.hasProcess(reqPackage)) { continue; } } if (activeOnly && !asc.isInUse()) { pw.print(" (Not active association: "); pw.print(pkgState.mAssociations.keyAt(iasc)); Loading @@ -1597,7 +1611,8 @@ public final class ProcessStats implements Parcelable { pw.print(" Process: "); pw.println(asc.getProcessName()); asc.dumpStats(pw, " ", " ", " ", now, totalTime, dumpDetails, dumpAll); now, totalTime, onlyAssociations ? reqPackage : null, dumpDetails, dumpAll); } } } Loading core/java/com/android/server/SystemConfig.java +442 −294 File changed.Preview size limit exceeded, changes collapsed. Show changes services/core/java/com/android/server/am/ActiveServices.java +18 −5 Original line number Diff line number Diff line Loading @@ -2019,6 +2019,13 @@ public final class ActiveServices { ComponentName className = new ComponentName( sInfo.applicationInfo.packageName, sInfo.name); ComponentName name = comp != null ? comp : className; if (!mAm.validateAssociationAllowedLocked(callingPackage, callingUid, name.getPackageName(), sInfo.applicationInfo.uid)) { String msg = "association not allowed between packages " + callingPackage + " and " + r.packageName; Slog.w(TAG, "Service lookup failed: " + msg); return new ServiceLookupResult(null, msg); } if ((sInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) != 0) { if (isBindExternal) { if (!sInfo.exported) { Loading Loading @@ -2099,6 +2106,17 @@ public final class ActiveServices { } } if (r != null) { if (!mAm.validateAssociationAllowedLocked(callingPackage, callingUid, r.packageName, r.appInfo.uid)) { String msg = "association not allowed between packages " + callingPackage + " and " + r.packageName; Slog.w(TAG, "Service lookup failed: " + msg); return new ServiceLookupResult(null, msg); } if (!mAm.mIntentFirewall.checkService(r.name, service, callingUid, callingPid, resolvedType, r.appInfo)) { return new ServiceLookupResult(null, "blocked by firewall"); } if (mAm.checkComponentPermission(r.permission, callingPid, callingUid, r.appInfo.uid, r.exported) != PERMISSION_GRANTED) { if (!r.exported) { Loading @@ -2125,11 +2143,6 @@ public final class ActiveServices { return null; } } if (!mAm.mIntentFirewall.checkService(r.name, service, callingUid, callingPid, resolvedType, r.appInfo)) { return null; } return new ServiceLookupResult(r, null); } return null; Loading services/core/java/com/android/server/am/ActivityManagerService.java +116 −0 Original line number Diff line number Diff line Loading @@ -657,6 +657,12 @@ public class ActivityManagerService extends IActivityManager.Stub */ ArraySet<String> mBackgroundLaunchBroadcasts; /** * When an app has restrictions on the other apps that can have associations with it, * it appears here with a set of the allowed apps. */ ArrayMap<String, ArraySet<String>> mAllowedAssociations; /** * All of the processes we currently have running organized by pid. * The keys are the pid running the application. Loading Loading @@ -2396,6 +2402,34 @@ public class ActivityManagerService extends IActivityManager.Stub return mBackgroundLaunchBroadcasts; } boolean validateAssociationAllowedLocked(String pkg1, int uid1, String pkg2, int uid2) { if (mAllowedAssociations == null) { mAllowedAssociations = SystemConfig.getInstance().getAllowedAssociations(); } // Interactions with the system uid are always allowed, since that is the core system // that everyone needs to be able to interact with. if (UserHandle.getAppId(uid1) == SYSTEM_UID) { return true; } if (UserHandle.getAppId(uid2) == SYSTEM_UID) { return true; } // We won't allow this association if either pkg1 or pkg2 has a limit on the // associations that are allowed with it, and the other package is not explicitly // specified as one of those associations. ArraySet<String> pkgs = mAllowedAssociations.get(pkg1); if (pkgs != null) { if (!pkgs.contains(pkg2)) { return false; } } pkgs = mAllowedAssociations.get(pkg2); if (pkgs != null) { return pkgs.contains(pkg1); } return true; } @Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { Loading Loading @@ -6264,6 +6298,21 @@ public class ActivityManagerService extends IActivityManager.Stub return state != 'Z' && state != 'X' && state != 'x' && state != 'K'; } private String checkContentProviderAssociation(ProcessRecord callingApp, int callingUid, ProviderInfo cpi) { if (callingApp == null) { return validateAssociationAllowedLocked(cpi.packageName, cpi.applicationInfo.uid, null, callingUid) ? null : "<null>"; } for (int i = callingApp.pkgList.size() - 1; i >= 0; i--) { if (!validateAssociationAllowedLocked(callingApp.pkgList.keyAt(i), callingApp.uid, cpi.packageName, cpi.applicationInfo.uid)) { return cpi.packageName; } } return null; } private ContentProviderHolder getContentProviderImpl(IApplicationThread caller, String name, IBinder token, int callingUid, String callingTag, boolean stable, int userId) { Loading Loading @@ -6335,6 +6384,11 @@ public class ActivityManagerService extends IActivityManager.Stub String msg; if (r != null && cpr.canRunHere(r)) { if ((msg = checkContentProviderAssociation(r, callingUid, cpi)) != null) { throw new SecurityException("Content provider lookup " + cpr.name.flattenToShortString() + " failed: association not allowed with package " + msg); } checkTime(startTime, "getContentProviderImpl: before checkContentProviderPermission"); if ((msg = checkContentProviderPermissionLocked(cpi, r, userId, checkCrossUser)) Loading Loading @@ -6364,6 +6418,11 @@ public class ActivityManagerService extends IActivityManager.Stub } catch (RemoteException e) { } if ((msg = checkContentProviderAssociation(r, callingUid, cpi)) != null) { throw new SecurityException("Content provider lookup " + cpr.name.flattenToShortString() + " failed: association not allowed with package " + msg); } checkTime(startTime, "getContentProviderImpl: before checkContentProviderPermission"); if ((msg = checkContentProviderPermissionLocked(cpi, r, userId, checkCrossUser)) Loading Loading @@ -6461,6 +6520,11 @@ public class ActivityManagerService extends IActivityManager.Stub checkTime(startTime, "getContentProviderImpl: got app info for user"); String msg; if ((msg = checkContentProviderAssociation(r, callingUid, cpi)) != null) { throw new SecurityException("Content provider lookup " + cpr.name.flattenToShortString() + " failed: association not allowed with package " + msg); } checkTime(startTime, "getContentProviderImpl: before checkContentProviderPermission"); if ((msg = checkContentProviderPermissionLocked(cpi, r, userId, !singleton)) != null) { Loading Loading @@ -9206,6 +9270,12 @@ public class ActivityManagerService extends IActivityManager.Stub if (dumpAll) { pw.println("-------------------------------------------------------------------------------"); } dumpAllowedAssociationsLocked(fd, pw, args, opti, dumpAll, dumpPackage); pw.println(); if (dumpAll) { pw.println("-------------------------------------------------------------------------------"); } mPendingIntentController.dumpPendingIntents(pw, dumpAll, dumpPackage); pw.println(); Loading Loading @@ -9474,6 +9544,14 @@ public class ActivityManagerService extends IActivityManager.Stub System.gc(); pw.println(BinderInternal.nGetBinderProxyCount(Integer.parseInt(uid))); } } else if ("allowed-associations".equals(cmd)) { if (opti < args.length) { dumpPackage = args[opti]; opti++; } synchronized (this) { dumpAllowedAssociationsLocked(fd, pw, args, opti, true, dumpPackage); } } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) { if (opti < args.length) { dumpPackage = args[opti]; Loading Loading @@ -10824,6 +10902,44 @@ public class ActivityManagerService extends IActivityManager.Stub proto.end(handlerToken); } void dumpAllowedAssociationsLocked(FileDescriptor fd, PrintWriter pw, String[] args, int opti, boolean dumpAll, String dumpPackage) { boolean needSep = false; boolean printedAnything = false; pw.println("ACTIVITY MANAGER ALLOWED ASSOCIATION STATE (dumpsys activity allowed-associations)"); boolean printed = false; if (mAllowedAssociations != null) { for (int i = 0; i < mAllowedAssociations.size(); i++) { final String pkg = mAllowedAssociations.keyAt(i); final ArraySet<String> asc = mAllowedAssociations.valueAt(i); boolean printedHeader = false; for (int j = 0; j < asc.size(); j++) { if (dumpPackage == null || pkg.equals(dumpPackage) || asc.valueAt(j).equals(dumpPackage)) { if (!printed) { pw.println(" Allowed associations (by restricted package):"); printed = true; needSep = true; printedAnything = true; } if (!printedHeader) { pw.print(" * "); pw.print(pkg); pw.println(":"); printedHeader = true; } pw.print(" Allow: "); pw.println(asc.valueAt(j)); } } } } if (!printed) { pw.println(" (No association restrictions)"); } } void dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args, int opti, boolean dumpAll, String dumpPackage) { boolean needSep = false; Loading Loading
core/java/com/android/internal/app/procstats/AssociationState.java +14 −1 Original line number Diff line number Diff line Loading @@ -445,8 +445,18 @@ public final class AssociationState { } } public boolean hasProcess(String procName) { final int NSRC = mSources.size(); for (int isrc = 0; isrc < NSRC; isrc++) { if (mSources.keyAt(isrc).mProcess.equals(procName)) { return true; } } return false; } public void dumpStats(PrintWriter pw, String prefix, String prefixInner, String headerPrefix, long now, long totalTime, boolean dumpDetails, boolean dumpAll) { long now, long totalTime, String reqPackage, boolean dumpDetails, boolean dumpAll) { if (dumpAll) { pw.print(prefix); pw.print("mNumActive="); Loading @@ -456,6 +466,9 @@ public final class AssociationState { for (int isrc = 0; isrc < NSRC; isrc++) { final SourceKey key = mSources.keyAt(isrc); final SourceState src = mSources.valueAt(isrc); if (reqPackage != null && !reqPackage.equals(key.mProcess)) { continue; } pw.print(prefixInner); pw.print("<- "); pw.print(key.mProcess); Loading
core/java/com/android/internal/app/procstats/ProcessStats.java +20 −5 Original line number Diff line number Diff line Loading @@ -1475,6 +1475,7 @@ public final class ProcessStats implements Parcelable { final int NSRVS = pkgState.mServices.size(); final int NASCS = pkgState.mAssociations.size(); final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName); boolean onlyAssociations = false; if (!pkgMatch) { boolean procMatch = false; for (int iproc = 0; iproc < NPROCS; iproc++) { Loading @@ -1485,9 +1486,20 @@ public final class ProcessStats implements Parcelable { } } if (!procMatch) { // Check if this app has any associations with the requested // package, so that if so we print those. for (int iasc = 0; iasc < NASCS; iasc++) { AssociationState asc = pkgState.mAssociations.valueAt(iasc); if (asc.hasProcess(reqPackage)) { onlyAssociations = true; break; } } if (!onlyAssociations) { continue; } } } if (NPROCS > 0 || NSRVS > 0 || NASCS > 0) { if (!printedHeader) { if (sepNeeded) pw.println(); Loading @@ -1503,7 +1515,7 @@ public final class ProcessStats implements Parcelable { pw.print(vers); pw.println(":"); } if ((section & REPORT_PKG_PROC_STATS) != 0) { if ((section & REPORT_PKG_PROC_STATS) != 0 && !onlyAssociations) { if (!dumpSummary || dumpAll) { for (int iproc = 0; iproc < NPROCS; iproc++) { ProcessState proc = pkgState.mProcesses.valueAt(iproc); Loading Loading @@ -1550,7 +1562,7 @@ public final class ProcessStats implements Parcelable { now, totalTime); } } if ((section & REPORT_PKG_SVC_STATS) != 0) { if ((section & REPORT_PKG_SVC_STATS) != 0 && !onlyAssociations) { for (int isvc = 0; isvc < NSRVS; isvc++) { ServiceState svc = pkgState.mServices.valueAt(isvc); if (!pkgMatch && !reqPackage.equals(svc.getProcessName())) { Loading Loading @@ -1579,8 +1591,10 @@ public final class ProcessStats implements Parcelable { for (int iasc = 0; iasc < NASCS; iasc++) { AssociationState asc = pkgState.mAssociations.valueAt(iasc); if (!pkgMatch && !reqPackage.equals(asc.getProcessName())) { if (!onlyAssociations || !asc.hasProcess(reqPackage)) { continue; } } if (activeOnly && !asc.isInUse()) { pw.print(" (Not active association: "); pw.print(pkgState.mAssociations.keyAt(iasc)); Loading @@ -1597,7 +1611,8 @@ public final class ProcessStats implements Parcelable { pw.print(" Process: "); pw.println(asc.getProcessName()); asc.dumpStats(pw, " ", " ", " ", now, totalTime, dumpDetails, dumpAll); now, totalTime, onlyAssociations ? reqPackage : null, dumpDetails, dumpAll); } } } Loading
core/java/com/android/server/SystemConfig.java +442 −294 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/core/java/com/android/server/am/ActiveServices.java +18 −5 Original line number Diff line number Diff line Loading @@ -2019,6 +2019,13 @@ public final class ActiveServices { ComponentName className = new ComponentName( sInfo.applicationInfo.packageName, sInfo.name); ComponentName name = comp != null ? comp : className; if (!mAm.validateAssociationAllowedLocked(callingPackage, callingUid, name.getPackageName(), sInfo.applicationInfo.uid)) { String msg = "association not allowed between packages " + callingPackage + " and " + r.packageName; Slog.w(TAG, "Service lookup failed: " + msg); return new ServiceLookupResult(null, msg); } if ((sInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) != 0) { if (isBindExternal) { if (!sInfo.exported) { Loading Loading @@ -2099,6 +2106,17 @@ public final class ActiveServices { } } if (r != null) { if (!mAm.validateAssociationAllowedLocked(callingPackage, callingUid, r.packageName, r.appInfo.uid)) { String msg = "association not allowed between packages " + callingPackage + " and " + r.packageName; Slog.w(TAG, "Service lookup failed: " + msg); return new ServiceLookupResult(null, msg); } if (!mAm.mIntentFirewall.checkService(r.name, service, callingUid, callingPid, resolvedType, r.appInfo)) { return new ServiceLookupResult(null, "blocked by firewall"); } if (mAm.checkComponentPermission(r.permission, callingPid, callingUid, r.appInfo.uid, r.exported) != PERMISSION_GRANTED) { if (!r.exported) { Loading @@ -2125,11 +2143,6 @@ public final class ActiveServices { return null; } } if (!mAm.mIntentFirewall.checkService(r.name, service, callingUid, callingPid, resolvedType, r.appInfo)) { return null; } return new ServiceLookupResult(r, null); } return null; Loading
services/core/java/com/android/server/am/ActivityManagerService.java +116 −0 Original line number Diff line number Diff line Loading @@ -657,6 +657,12 @@ public class ActivityManagerService extends IActivityManager.Stub */ ArraySet<String> mBackgroundLaunchBroadcasts; /** * When an app has restrictions on the other apps that can have associations with it, * it appears here with a set of the allowed apps. */ ArrayMap<String, ArraySet<String>> mAllowedAssociations; /** * All of the processes we currently have running organized by pid. * The keys are the pid running the application. Loading Loading @@ -2396,6 +2402,34 @@ public class ActivityManagerService extends IActivityManager.Stub return mBackgroundLaunchBroadcasts; } boolean validateAssociationAllowedLocked(String pkg1, int uid1, String pkg2, int uid2) { if (mAllowedAssociations == null) { mAllowedAssociations = SystemConfig.getInstance().getAllowedAssociations(); } // Interactions with the system uid are always allowed, since that is the core system // that everyone needs to be able to interact with. if (UserHandle.getAppId(uid1) == SYSTEM_UID) { return true; } if (UserHandle.getAppId(uid2) == SYSTEM_UID) { return true; } // We won't allow this association if either pkg1 or pkg2 has a limit on the // associations that are allowed with it, and the other package is not explicitly // specified as one of those associations. ArraySet<String> pkgs = mAllowedAssociations.get(pkg1); if (pkgs != null) { if (!pkgs.contains(pkg2)) { return false; } } pkgs = mAllowedAssociations.get(pkg2); if (pkgs != null) { return pkgs.contains(pkg1); } return true; } @Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { Loading Loading @@ -6264,6 +6298,21 @@ public class ActivityManagerService extends IActivityManager.Stub return state != 'Z' && state != 'X' && state != 'x' && state != 'K'; } private String checkContentProviderAssociation(ProcessRecord callingApp, int callingUid, ProviderInfo cpi) { if (callingApp == null) { return validateAssociationAllowedLocked(cpi.packageName, cpi.applicationInfo.uid, null, callingUid) ? null : "<null>"; } for (int i = callingApp.pkgList.size() - 1; i >= 0; i--) { if (!validateAssociationAllowedLocked(callingApp.pkgList.keyAt(i), callingApp.uid, cpi.packageName, cpi.applicationInfo.uid)) { return cpi.packageName; } } return null; } private ContentProviderHolder getContentProviderImpl(IApplicationThread caller, String name, IBinder token, int callingUid, String callingTag, boolean stable, int userId) { Loading Loading @@ -6335,6 +6384,11 @@ public class ActivityManagerService extends IActivityManager.Stub String msg; if (r != null && cpr.canRunHere(r)) { if ((msg = checkContentProviderAssociation(r, callingUid, cpi)) != null) { throw new SecurityException("Content provider lookup " + cpr.name.flattenToShortString() + " failed: association not allowed with package " + msg); } checkTime(startTime, "getContentProviderImpl: before checkContentProviderPermission"); if ((msg = checkContentProviderPermissionLocked(cpi, r, userId, checkCrossUser)) Loading Loading @@ -6364,6 +6418,11 @@ public class ActivityManagerService extends IActivityManager.Stub } catch (RemoteException e) { } if ((msg = checkContentProviderAssociation(r, callingUid, cpi)) != null) { throw new SecurityException("Content provider lookup " + cpr.name.flattenToShortString() + " failed: association not allowed with package " + msg); } checkTime(startTime, "getContentProviderImpl: before checkContentProviderPermission"); if ((msg = checkContentProviderPermissionLocked(cpi, r, userId, checkCrossUser)) Loading Loading @@ -6461,6 +6520,11 @@ public class ActivityManagerService extends IActivityManager.Stub checkTime(startTime, "getContentProviderImpl: got app info for user"); String msg; if ((msg = checkContentProviderAssociation(r, callingUid, cpi)) != null) { throw new SecurityException("Content provider lookup " + cpr.name.flattenToShortString() + " failed: association not allowed with package " + msg); } checkTime(startTime, "getContentProviderImpl: before checkContentProviderPermission"); if ((msg = checkContentProviderPermissionLocked(cpi, r, userId, !singleton)) != null) { Loading Loading @@ -9206,6 +9270,12 @@ public class ActivityManagerService extends IActivityManager.Stub if (dumpAll) { pw.println("-------------------------------------------------------------------------------"); } dumpAllowedAssociationsLocked(fd, pw, args, opti, dumpAll, dumpPackage); pw.println(); if (dumpAll) { pw.println("-------------------------------------------------------------------------------"); } mPendingIntentController.dumpPendingIntents(pw, dumpAll, dumpPackage); pw.println(); Loading Loading @@ -9474,6 +9544,14 @@ public class ActivityManagerService extends IActivityManager.Stub System.gc(); pw.println(BinderInternal.nGetBinderProxyCount(Integer.parseInt(uid))); } } else if ("allowed-associations".equals(cmd)) { if (opti < args.length) { dumpPackage = args[opti]; opti++; } synchronized (this) { dumpAllowedAssociationsLocked(fd, pw, args, opti, true, dumpPackage); } } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) { if (opti < args.length) { dumpPackage = args[opti]; Loading Loading @@ -10824,6 +10902,44 @@ public class ActivityManagerService extends IActivityManager.Stub proto.end(handlerToken); } void dumpAllowedAssociationsLocked(FileDescriptor fd, PrintWriter pw, String[] args, int opti, boolean dumpAll, String dumpPackage) { boolean needSep = false; boolean printedAnything = false; pw.println("ACTIVITY MANAGER ALLOWED ASSOCIATION STATE (dumpsys activity allowed-associations)"); boolean printed = false; if (mAllowedAssociations != null) { for (int i = 0; i < mAllowedAssociations.size(); i++) { final String pkg = mAllowedAssociations.keyAt(i); final ArraySet<String> asc = mAllowedAssociations.valueAt(i); boolean printedHeader = false; for (int j = 0; j < asc.size(); j++) { if (dumpPackage == null || pkg.equals(dumpPackage) || asc.valueAt(j).equals(dumpPackage)) { if (!printed) { pw.println(" Allowed associations (by restricted package):"); printed = true; needSep = true; printedAnything = true; } if (!printedHeader) { pw.print(" * "); pw.print(pkg); pw.println(":"); printedHeader = true; } pw.print(" Allow: "); pw.println(asc.valueAt(j)); } } } } if (!printed) { pw.println(" (No association restrictions)"); } } void dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args, int opti, boolean dumpAll, String dumpPackage) { boolean needSep = false; Loading