Added a new "incidentReportApprover" permission protection flag.

This gives the ONE app installed on the system the permission to
authorize the sharing of incident and bug reports with an app.

Currently that app is PermissionController.  Package Manager
enforces that there is only one installed, and refused to boot
if that isn't the case.

Bug: 123543706
Test: bit GooglePermissionControllerTest:*
Change-Id: I76a7fad0ea36359bbb0ff09669df46202d059dab
This commit is contained in:
Joe Onorato
2018-12-18 10:40:04 -08:00
parent f5e95eff50
commit 5a15b55107
16 changed files with 92 additions and 0 deletions

View File

@@ -18,6 +18,7 @@ package android {
field public static final String ALLOCATE_AGGRESSIVE = "android.permission.ALLOCATE_AGGRESSIVE";
field public static final String ALLOW_ANY_CODEC_FOR_PLAYBACK = "android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK";
field public static final String AMBIENT_WALLPAPER = "android.permission.AMBIENT_WALLPAPER";
field public static final String APPROVE_INCIDENT_REPORTS = "android.permission.APPROVE_INCIDENT_REPORTS";
field public static final String BACKUP = "android.permission.BACKUP";
field public static final String BIND_ATTENTION_SERVICE = "android.permission.BIND_ATTENTION_SERVICE";
field public static final String BIND_AUGMENTED_AUTOFILL_SERVICE = "android.permission.BIND_AUGMENTED_AUTOFILL_SERVICE";
@@ -1489,6 +1490,7 @@ package android.content.pm {
method @NonNull public android.content.pm.dex.ArtManager getArtManager();
method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public abstract String getDefaultBrowserPackageNameAsUser(int);
method @Nullable @RequiresPermission(android.Manifest.permission.SET_HARMFUL_APP_WARNINGS) public CharSequence getHarmfulAppWarning(@NonNull String);
method public String getIncidentReportApproverPackageName();
method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackagesAsUser(int, int);
method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_INSTANT_APPS) public abstract android.graphics.drawable.Drawable getInstantAppIcon(String);
method public abstract android.content.ComponentName getInstantAppInstallerComponent();
@@ -1610,6 +1612,7 @@ package android.content.pm {
field public static final int FLAG_REMOVED = 2; // 0x2
field public static final int PROTECTION_FLAG_CONFIGURATOR = 524288; // 0x80000
field public static final int PROTECTION_FLAG_DOCUMENTER = 262144; // 0x40000
field public static final int PROTECTION_FLAG_INCIDENT_REPORT_APPROVER = 1048576; // 0x100000
field public static final int PROTECTION_FLAG_OEM = 16384; // 0x4000
field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000
field public static final int PROTECTION_FLAG_WELLBEING = 131072; // 0x20000

View File

@@ -4,6 +4,7 @@ package android {
public static final class Manifest.permission {
field public static final String ACCESS_NOTIFICATIONS = "android.permission.ACCESS_NOTIFICATIONS";
field public static final String ACTIVITY_EMBEDDING = "android.permission.ACTIVITY_EMBEDDING";
field public static final String APPROVE_INCIDENT_REPORTS = "android.permission.APPROVE_INCIDENT_REPORTS";
field public static final String BRIGHTNESS_SLIDER_USAGE = "android.permission.BRIGHTNESS_SLIDER_USAGE";
field public static final String CHANGE_APP_IDLE_STATE = "android.permission.CHANGE_APP_IDLE_STATE";
field public static final String CLEAR_APP_USER_DATA = "android.permission.CLEAR_APP_USER_DATA";
@@ -413,6 +414,7 @@ package android.content.pm {
public abstract class PackageManager {
method public abstract boolean arePermissionsIndividuallyControlled();
method @RequiresPermission("android.permission.INTERACT_ACROSS_USERS_FULL") public abstract String getDefaultBrowserPackageNameAsUser(int);
method public String getIncidentReportApproverPackageName();
method public abstract int getInstallReason(String, @NonNull android.os.UserHandle);
method public abstract java.util.List<android.content.pm.ApplicationInfo> getInstalledApplicationsAsUser(int, int);
method @RequiresPermission("android.permission.INTERACT_ACROSS_USERS_FULL") public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackagesAsUser(int, int);
@@ -434,6 +436,7 @@ package android.content.pm {
public class PermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
field public static final int PROTECTION_FLAG_CONFIGURATOR = 524288; // 0x80000
field public static final int PROTECTION_FLAG_DOCUMENTER = 262144; // 0x40000
field public static final int PROTECTION_FLAG_INCIDENT_REPORT_APPROVER = 1048576; // 0x100000
field public static final int PROTECTION_FLAG_OEM = 16384; // 0x4000
field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000
field public static final int PROTECTION_FLAG_VENDOR_PRIVILEGED = 32768; // 0x8000

View File

@@ -3025,6 +3025,15 @@ public class ApplicationPackageManager extends PackageManager {
}
}
@Override
public String getIncidentReportApproverPackageName() {
try {
return mPM.getIncidentReportApproverPackageName();
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
}
@Override
public boolean isPackageStateProtected(String packageName, int userId) {
try {

View File

@@ -688,6 +688,8 @@ interface IPackageManager {
String getContentCaptureServicePackageName();
String getIncidentReportApproverPackageName();
boolean isPackageStateProtected(String packageName, int userId);
void sendDeviceCustomizationReadyBroadcast();

View File

@@ -6743,6 +6743,19 @@ public abstract class PackageManager {
"getContentCaptureServicePackageName not implemented in subclass");
}
/**
* @return the incident report approver app package name, or null if it's not defined
* by the OEM.
*
* @hide
*/
@SystemApi
@TestApi
public String getIncidentReportApproverPackageName() {
throw new UnsupportedOperationException(
"getIncidentReportApproverPackageName not implemented in subclass");
}
/**
* @return whether a given package's state is protected, e.g. package cannot be disabled,
* suspended, hidden or force stopped.

View File

@@ -56,6 +56,7 @@ public abstract class PackageManagerInternal {
public static final int PACKAGE_WELLBEING = 7;
public static final int PACKAGE_DOCUMENTER = 8;
public static final int PACKAGE_CONFIGURATOR = 9;
public static final int PACKAGE_INCIDENT_REPORT_APPROVER = 10;
@IntDef(value = {
PACKAGE_SYSTEM,
PACKAGE_SETUP_WIZARD,
@@ -67,6 +68,7 @@ public abstract class PackageManagerInternal {
PACKAGE_WELLBEING,
PACKAGE_DOCUMENTER,
PACKAGE_CONFIGURATOR,
PACKAGE_INCIDENT_REPORT_APPROVER,
})
@Retention(RetentionPolicy.SOURCE)
public @interface KnownPackage {}

View File

@@ -213,6 +213,16 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
@TestApi
public static final int PROTECTION_FLAG_CONFIGURATOR = 0x80000;
/**
* Additional flag for {${link #protectionLevel}, corresponding
* to the <code>incident_report_approver</code> value of
* {@link android.R.attr#protectionLevel}.
*
* @hide
*/
@SystemApi
@TestApi
public static final int PROTECTION_FLAG_INCIDENT_REPORT_APPROVER = 0x100000;
/** @hide */
@IntDef(flag = true, prefix = { "PROTECTION_FLAG_" }, value = {
@@ -233,6 +243,7 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
PROTECTION_FLAG_WELLBEING,
PROTECTION_FLAG_DOCUMENTER,
PROTECTION_FLAG_CONFIGURATOR,
PROTECTION_FLAG_INCIDENT_REPORT_APPROVER,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ProtectionFlags {}
@@ -431,6 +442,9 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
if ((level & PROTECTION_FLAG_CONFIGURATOR) != 0) {
protLevel += "|configurator";
}
if ((level & PermissionInfo.PROTECTION_FLAG_INCIDENT_REPORT_APPROVER) != 0) {
protLevel += "|incidentReportApprover";
}
return protLevel;
}

View File

@@ -115,6 +115,7 @@
<protected-broadcast android:name="android.app.action.BUGREPORT_FAILED" />
<protected-broadcast android:name="android.app.action.BUGREPORT_SHARE" />
<protected-broadcast android:name="android.app.action.SHOW_DEVICE_MONITORING_DIALOG" />
<protected-broadcast android:name="android.intent.action.PENDING_INCIDENT_REPORTS_CHANGED" />
<protected-broadcast android:name="android.appwidget.action.APPWIDGET_UPDATE_OPTIONS" />
<protected-broadcast android:name="android.appwidget.action.APPWIDGET_DELETED" />
@@ -2798,6 +2799,15 @@
<permission android:name="android.permission.SIGNAL_PERSISTENT_PROCESSES"
android:protectionLevel="signature|privileged|development" />
<!-- @hide @SystemApi @TestApi
Allow an application to approve incident and bug reports to be
shared off-device. There can be only one application installed on the
device with this permission, and since this is a privileged permission, it
must be in priv-app.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.APPROVE_INCIDENT_REPORTS"
android:protectionLevel="signature|incidentReportApprover" />
<!-- ==================================== -->
<!-- Private permissions -->
<!-- ==================================== -->

View File

@@ -277,6 +277,9 @@
<!-- Additional flag from base permission type: this permission automatically
granted to device configurator -->
<flag name="configurator" value="0x80000" />
<!-- Additional flag from base permission type: this permission designates the app
that will approve the sharing of incident reports. -->
<flag name="incidentReportApprover" value="0x100000" />
</attr>
<!-- Flags indicating more context for a permission group. -->

View File

@@ -3493,6 +3493,13 @@
-->
<string name="config_defaultAttentionService" translatable="false"></string>
<!-- The package name for the incident report approver app.
This app is usually PermissionController or an app that replaces it. When
a bugreport or incident report with EXPLICT-level sharing flags is going to be
shared, this app will be sent the PENDING_INCIDENT_REPORTS_CHANGED broadcast.
-->
<string name="config_incidentReportApproverPackage" translatable="false">com.android.permissioncontroller</string>
<!-- The package name for the system's content capture service.
This service must be trusted, as it can be activated without explicit consent of the user.
If no service with the specified name exists on the device, content capture will be

View File

@@ -3580,4 +3580,6 @@
<!-- For Attention Service -->
<java-symbol type="integer" name="config_attentionMaximumExtension" />
<java-symbol type="integer" name="config_attentionApiTimeout" />
<java-symbol type="string" name="config_incidentReportApproverPackage" />
</resources>

View File

@@ -141,6 +141,7 @@ applications that come with the platform
<permission name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS"/>
<permission name="android.permission.GET_APP_OPS_STATS"/>
<permission name="android.permission.UPDATE_APP_OPS_STATS"/>
<permission name="android.permission.APPROVE_INCIDENT_REPORTS"/>
</privapp-permissions>
<privapp-permissions package="com.android.phone">

View File

@@ -1350,6 +1350,7 @@ public class PackageManagerService extends IPackageManager.Stub
final @Nullable String mDocumenterPackage;
final @Nullable String mConfiguratorPackage;
final @Nullable String mAppPredictionServicePackage;
final @Nullable String mIncidentReportApproverPackage;
final @NonNull String mServicesSystemSharedLibraryPackageName;
final @NonNull String mSharedSystemSharedLibraryPackageName;
@@ -2879,6 +2880,7 @@ public class PackageManagerService extends IPackageManager.Stub
mConfiguratorPackage =
mContext.getString(R.string.config_deviceConfiguratorPackageName);
mAppPredictionServicePackage = getAppPredictionServicePackageName();
mIncidentReportApproverPackage = getIncidentReportApproverPackageName();
// Now that we know all of the shared libraries, update all clients to have
// the correct library paths.
@@ -20112,6 +20114,10 @@ public class PackageManagerService extends IPackageManager.Stub
return contentCaptureServiceName.substring(0, separatorIndex);
}
public String getIncidentReportApproverPackageName() {
return mContext.getString(R.string.config_incidentReportApproverPackage);
}
@Override
public void setApplicationEnabledSetting(String appPackageName,
int newState, int flags, int userId, String callingPackage) {
@@ -23275,6 +23281,8 @@ public class PackageManagerService extends IPackageManager.Stub
return mDocumenterPackage;
case PackageManagerInternal.PACKAGE_CONFIGURATOR:
return mConfiguratorPackage;
case PackageManagerInternal.PACKAGE_INCIDENT_REPORT_APPROVER:
return mIncidentReportApproverPackage;
}
return null;
}

View File

@@ -251,6 +251,9 @@ public final class BasePermission {
return (protectionLevel & PermissionInfo.PROTECTION_FLAG_CONFIGURATOR)
!= 0;
}
public boolean isIncidentReportApprover() {
return (protectionLevel & PermissionInfo.PROTECTION_FLAG_INCIDENT_REPORT_APPROVER) != 0;
}
public void transfer(@NonNull String origPackageName, @NonNull String newPackageName) {
if (!origPackageName.equals(sourcePackageName)) {

View File

@@ -1716,6 +1716,14 @@ public class PermissionManagerService {
// this app is the documenter, then it gets the permission.
allowed = true;
}
if (!allowed && bp.isIncidentReportApprover()
&& pkg.packageName.equals(mPackageManagerInt.getKnownPackageName(
PackageManagerInternal.PACKAGE_INCIDENT_REPORT_APPROVER,
UserHandle.USER_SYSTEM))) {
// If this permission is to be granted to the incident report approver and
// this app is the incident report approver, then it gets the permission.
allowed = true;
}
}
return allowed;
}

View File

@@ -1151,6 +1151,10 @@ public class IPackageManagerStub implements IPackageManager {
return null;
}
public String getIncidentReportApproverPackageName() throws RemoteException {
return null;
}
@Override
public boolean isPackageStateProtected(String packageName, int userId) throws RemoteException {
return false;